feat(modulo): add early work on Wizard GUI

This commit is contained in:
Federico Terzi 2021-06-12 21:24:15 +02:00
parent 5e3491e238
commit 2a9c64d685
10 changed files with 1698 additions and 0 deletions

View File

@ -113,6 +113,8 @@ fn build_native() {
.file("src/sys/form/form.cpp") .file("src/sys/form/form.cpp")
.file("src/sys/search/search.cpp") .file("src/sys/search/search.cpp")
.file("src/sys/common/common.cpp") .file("src/sys/common/common.cpp")
.file("src/sys/wizard/wizard.cpp")
.file("src/sys/wizard/wizard_gui.cpp")
.flag("/EHsc") .flag("/EHsc")
.include(wx_include_dir) .include(wx_include_dir)
.include(wx_include_msvc_dir) .include(wx_include_msvc_dir)

View File

@ -22,4 +22,5 @@ extern crate lazy_static;
pub mod form; pub mod form;
pub mod search; pub mod search;
pub mod wizard;
mod sys; mod sys;

View File

@ -130,4 +130,7 @@ extern "C" {
); );
pub(crate) fn update_items(app: *const c_void, items: *const SearchItem, itemCount: c_int); pub(crate) fn update_items(app: *const c_void, items: *const SearchItem, itemCount: c_int);
// WIZARD
pub(crate) fn interop_show_wizard();
} }

View File

@ -19,6 +19,7 @@
pub mod form; pub mod form;
pub mod search; pub mod search;
pub mod wizard;
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
#[allow(dead_code)] #[allow(dead_code)]

View File

@ -0,0 +1,172 @@
/*
* This file is part of modulo.
*
* Copyright (C) 2020-2021 Federico Terzi
*
* modulo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* modulo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with modulo. If not, see <https://www.gnu.org/licenses/>.
*/
use std::ffi::CStr;
use std::os::raw::{c_char, c_int, c_void};
pub mod types {
// #[derive(Debug)]
// pub struct Search {
// pub title: String,
// pub icon: Option<String>,
// pub items: Vec<SearchItem>,
// }
}
#[allow(dead_code)]
mod interop {
use super::types;
use super::super::interop::*;
use std::ffi::{c_void, CString};
// pub(crate) struct OwnedSearch {
// title: CString,
// icon_path: CString,
// items: Vec<OwnedSearchItem>,
// pub(crate) interop_items: Vec<SearchItem>,
// _interop: Box<SearchMetadata>,
// }
// impl Interoperable for OwnedSearch {
// fn as_ptr(&self) -> *const c_void {
// &(*self._interop) as *const SearchMetadata as *const c_void
// }
// }
// impl From<&types::Search> for OwnedSearch {
// fn from(search: &types::Search) -> Self {
// let title =
// CString::new(search.title.clone()).expect("unable to convert search title to CString");
// let items: Vec<OwnedSearchItem> = search.items.iter().map(|item| item.into()).collect();
// let interop_items: Vec<SearchItem> = items.iter().map(|item| item.to_search_item()).collect();
// let icon_path = if let Some(icon_path) = search.icon.as_ref() {
// icon_path.clone()
// } else {
// "".to_owned()
// };
// let icon_path = CString::new(icon_path).expect("unable to convert search icon to CString");
// let icon_path_ptr = if search.icon.is_some() {
// icon_path.as_ptr()
// } else {
// std::ptr::null()
// };
// let _interop = Box::new(SearchMetadata {
// iconPath: icon_path_ptr,
// windowTitle: title.as_ptr(),
// });
// Self {
// title,
// items,
// icon_path,
// interop_items,
// _interop,
// }
// }
// }
// pub(crate) struct OwnedSearchItem {
// id: CString,
// label: CString,
// trigger: CString,
// }
// impl OwnedSearchItem {
// fn to_search_item(&self) -> SearchItem {
// SearchItem {
// id: self.id.as_ptr(),
// label: self.label.as_ptr(),
// trigger: self.trigger.as_ptr(),
// }
// }
// }
// impl From<&types::SearchItem> for OwnedSearchItem {
// fn from(item: &types::SearchItem) -> Self {
// let id = CString::new(item.id.clone()).expect("unable to convert item id to CString");
// let label =
// CString::new(item.label.clone()).expect("unable to convert item label to CString");
// let trigger = if let Some(trigger) = item.trigger.as_deref() {
// CString::new(trigger.to_string()).expect("unable to convert item trigger to CString")
// } else {
// CString::new("".to_string()).expect("unable to convert item trigger to CString")
// };
// Self { id, label, trigger }
// }
// }
}
// struct SearchData {
// owned_search: interop::OwnedSearch,
// items: Vec<types::SearchItem>,
// algorithm: Box<dyn Fn(&str, &[types::SearchItem]) -> Vec<usize>>,
// }
pub fn show() {
use super::interop::*;
// extern "C" fn search_callback(query: *const c_char, app: *const c_void, data: *const c_void) {
// let query = unsafe { CStr::from_ptr(query) };
// let query = query.to_string_lossy().to_string();
// let search_data = data as *const SearchData;
// let search_data = unsafe { &*search_data };
// let indexes = (*search_data.algorithm)(&query, &search_data.items);
// let items: Vec<SearchItem> = indexes
// .into_iter()
// .map(|index| search_data.owned_search.interop_items[index])
// .collect();
// unsafe {
// update_items(app, items.as_ptr(), items.len() as c_int);
// }
// }
// let mut result: Option<String> = None;
// extern "C" fn result_callback(id: *const c_char, result: *mut c_void) {
// let id = unsafe { CStr::from_ptr(id) };
// let id = id.to_string_lossy().to_string();
// let result: *mut Option<String> = result as *mut Option<String>;
// unsafe {
// *result = Some(id);
// }
// }
unsafe {
interop_show_wizard(
// metadata,
// search_callback,
// &search_data as *const SearchData as *const c_void,
// result_callback,
// &mut result as *mut Option<String> as *mut c_void,
);
}
//result
}

View File

@ -0,0 +1,78 @@
/*
* This file is part of modulo.
*
* Copyright (C) 2020-2021 Federico Terzi
*
* modulo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* modulo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with modulo. If not, see <https://www.gnu.org/licenses/>.
*/
#define _UNICODE
#include "../common/common.h"
#include "../interop/interop.h"
#include "./wizard_gui.h"
#include <vector>
#include <memory>
#include <unordered_map>
// App Code
class WizardApp : public wxApp
{
public:
virtual bool OnInit();
};
class DerivedFrame : public WizardFrame
{
protected:
void welcome_start_clicked(wxCommandEvent &event);
public:
DerivedFrame(wxWindow *parent);
};
DerivedFrame::DerivedFrame(wxWindow *parent)
: WizardFrame(parent)
{
}
void DerivedFrame::welcome_start_clicked(wxCommandEvent &event)
{
this->m_simplebook->ChangeSelection(2);
}
bool WizardApp::OnInit()
{
DerivedFrame *frame = new DerivedFrame(NULL);
//setFrameIcon(formMetadata->iconPath, frame);
frame->Show(true);
Activate(frame);
return true;
}
extern "C" void interop_show_wizard()
{
// Setup high DPI support on Windows
#ifdef __WXMSW__
SetProcessDPIAware();
#endif
wxApp::SetInstance(new WizardApp());
int argc = 0;
wxEntry(argc, (char **)nullptr);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#define _UNICODE
#include "wizard_gui.h"
///////////////////////////////////////////////////////////////////////////
WizardFrame::WizardFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer( wxVERTICAL );
m_simplebook = new wxSimplebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
welcome_panel = new wxPanel( m_simplebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
welcome_panel->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
wxBoxSizer* bSizer2;
bSizer2 = new wxBoxSizer( wxVERTICAL );
welcome_title_text = new wxStaticText( welcome_panel, wxID_ANY, wxT("Welcome to Espanso!"), wxDefaultPosition, wxDefaultSize, 0 );
welcome_title_text->Wrap( -1 );
welcome_title_text->SetFont( wxFont( 18, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
bSizer2->Add( welcome_title_text, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP, 20 );
welcome_version_text = new wxStaticText( welcome_panel, wxID_ANY, wxT("(version 1.2.3)"), wxDefaultPosition, wxDefaultSize, 0 );
welcome_version_text->Wrap( -1 );
bSizer2->Add( welcome_version_text, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
welcome_description_text = new wxStaticText( welcome_panel, wxID_ANY, wxT("This wizard will help you to quickly get started with the tool"), wxDefaultPosition, wxDefaultSize, 0 );
welcome_description_text->Wrap( -1 );
bSizer2->Add( welcome_description_text, 0, wxALL, 20 );
bSizer2->Add( 0, 0, 1, wxEXPAND, 5 );
welcome_start_button = new wxButton( welcome_panel, wxID_ANY, wxT("Start"), wxDefaultPosition, wxDefaultSize, 0 );
welcome_start_button->SetDefault();
bSizer2->Add( welcome_start_button, 0, wxALIGN_RIGHT|wxALL, 10 );
welcome_panel->SetSizer( bSizer2 );
welcome_panel->Layout();
bSizer2->Fit( welcome_panel );
m_simplebook->AddPage( welcome_panel, wxT("a page"), false );
legacy_version_panel = new wxPanel( m_simplebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
legacy_version_panel->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
wxBoxSizer* bSizer21;
bSizer21 = new wxBoxSizer( wxVERTICAL );
legacy_version_title = new wxStaticText( legacy_version_panel, wxID_ANY, wxT("Legacy version detected"), wxDefaultPosition, wxDefaultSize, 0 );
legacy_version_title->Wrap( -1 );
legacy_version_title->SetFont( wxFont( 18, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
bSizer21->Add( legacy_version_title, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_LEFT|wxTOP, 20 );
legacy_version_description = new wxStaticText( legacy_version_panel, wxID_ANY, wxT("A legacy espanso process has been detected and prevents the new version from working correctly.\n\nPlease terminate and uninstall the old espanso version to proceed.\n\nFor more information, see: \n"), wxDefaultPosition, wxDefaultSize, 0 );
legacy_version_description->Wrap( -1 );
bSizer21->Add( legacy_version_description, 0, wxLEFT|wxRIGHT|wxTOP, 20 );
legacy_version_docs_link = new wxHyperlinkCtrl( legacy_version_panel, wxID_ANY, wxT("https://espanso.org/migration#uninstall"), wxT("https://espanso.org/migration#uninstall"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
bSizer21->Add( legacy_version_docs_link, 0, wxLEFT|wxRIGHT, 20 );
bSizer21->Add( 0, 0, 1, wxEXPAND, 5 );
legacy_version_continue_button = new wxButton( legacy_version_panel, wxID_ANY, wxT("Continue"), wxDefaultPosition, wxDefaultSize, 0 );
legacy_version_continue_button->SetDefault();
legacy_version_continue_button->Enable( false );
bSizer21->Add( legacy_version_continue_button, 0, wxALIGN_RIGHT|wxALL, 10 );
legacy_version_panel->SetSizer( bSizer21 );
legacy_version_panel->Layout();
bSizer21->Fit( legacy_version_panel );
m_simplebook->AddPage( legacy_version_panel, wxT("a page"), false );
migrate_panel = new wxPanel( m_simplebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
migrate_panel->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
wxBoxSizer* bSizer211;
bSizer211 = new wxBoxSizer( wxVERTICAL );
migrate_title = new wxStaticText( migrate_panel, wxID_ANY, wxT("Migrate configuration"), wxDefaultPosition, wxDefaultSize, 0 );
migrate_title->Wrap( -1 );
migrate_title->SetFont( wxFont( 18, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
bSizer211->Add( migrate_title, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_LEFT|wxTOP, 20 );
migrate_description = new wxStaticText( migrate_panel, wxID_ANY, wxT("The new version uses a slightly different configuration format that powers some exciting new features.\n\nTo ease the transition, espanso offers two possible choices:\n\n - Automatically backup the old configuration in the Documents folder and migrate to the new format (recommended).\n - Use compatibility mode without changing the configs.\n\nKeep in mind that:\n\n - Compatibility mode does not support all new espanso features\n - You can always migrate the configs later\n\nFor more information, see:\n\n"), wxDefaultPosition, wxDefaultSize, 0 );
migrate_description->Wrap( -1 );
bSizer211->Add( migrate_description, 0, wxLEFT|wxRIGHT|wxTOP, 20 );
migrate_link = new wxHyperlinkCtrl( migrate_panel, wxID_ANY, wxT("https://espanso.org/migration"), wxT("https://espanso.org/migration"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
bSizer211->Add( migrate_link, 0, wxLEFT|wxRIGHT, 20 );
bSizer211->Add( 0, 0, 10, wxEXPAND, 5 );
wxBoxSizer* bSizer8;
bSizer8 = new wxBoxSizer( wxHORIZONTAL );
migrate_compatibility_mode_button = new wxButton( migrate_panel, wxID_ANY, wxT("Use compatibility mode"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer8->Add( migrate_compatibility_mode_button, 0, wxALL, 10 );
bSizer8->Add( 0, 0, 1, wxEXPAND, 5 );
migrate_backup_and_migrate_button = new wxButton( migrate_panel, wxID_ANY, wxT("Backup && Migrate"), wxDefaultPosition, wxDefaultSize, 0 );
migrate_backup_and_migrate_button->SetDefault();
bSizer8->Add( migrate_backup_and_migrate_button, 0, wxALL, 10 );
bSizer211->Add( bSizer8, 1, wxEXPAND, 5 );
migrate_panel->SetSizer( bSizer211 );
migrate_panel->Layout();
bSizer211->Fit( migrate_panel );
m_simplebook->AddPage( migrate_panel, wxT("a page"), false );
bSizer1->Add( m_simplebook, 1, wxEXPAND | wxALL, 5 );
this->SetSizer( bSizer1 );
this->Layout();
this->Centre( wxBOTH );
// Connect Events
welcome_start_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrame::welcome_start_clicked ), NULL, this );
}
WizardFrame::~WizardFrame()
{
// Disconnect Events
welcome_start_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrame::welcome_start_clicked ), NULL, this );
}

View File

@ -0,0 +1,68 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/string.h>
#include <wx/stattext.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/panel.h>
#include <wx/hyperlink.h>
#include <wx/simplebook.h>
#include <wx/frame.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class WizardFrame
///////////////////////////////////////////////////////////////////////////////
class WizardFrame : public wxFrame
{
private:
protected:
wxSimplebook* m_simplebook;
wxPanel* welcome_panel;
wxStaticText* welcome_title_text;
wxStaticText* welcome_version_text;
wxStaticText* welcome_description_text;
wxButton* welcome_start_button;
wxPanel* legacy_version_panel;
wxStaticText* legacy_version_title;
wxStaticText* legacy_version_description;
wxHyperlinkCtrl* legacy_version_docs_link;
wxButton* legacy_version_continue_button;
wxPanel* migrate_panel;
wxStaticText* migrate_title;
wxStaticText* migrate_description;
wxHyperlinkCtrl* migrate_link;
wxButton* migrate_compatibility_mode_button;
wxButton* migrate_backup_and_migrate_button;
// Virtual event handlers, overide them in your derived class
virtual void welcome_start_clicked( wxCommandEvent& event ) { event.Skip(); }
public:
WizardFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Espanso"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 546,572 ), long style = wxCAPTION|wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL );
~WizardFrame();
};

View File

@ -0,0 +1,20 @@
/*
* This file is part of modulo.
*
* Copyright (C) 2020-2021 Federico Terzi
*
* modulo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* modulo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with modulo. If not, see <https://www.gnu.org/licenses/>.
*/
pub use crate::sys::wizard::show;