From 1d10a2293a0eb675a723704ca7cec9b378c48bcb Mon Sep 17 00:00:00 2001 From: bubnikv <bubnikv@gmail.com> Date: Sun, 21 Jan 2018 23:35:00 +0100 Subject: [PATCH] Example implementation of C++ to Perl callbacks using wxWidgets command events. --- lib/Slic3r/GUI/MainFrame.pm | 23 ++++++++++++++++++++--- xs/src/slic3r/GUI/GUI.cpp | 17 ++++++++++++----- xs/src/slic3r/GUI/GUI.hpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 26 +++++++++++++++++++++++--- xs/src/slic3r/GUI/Tab.h | 23 +++++++++++++++-------- xs/xsp/GUI.xsp | 4 ++-- 6 files changed, 73 insertions(+), 22 deletions(-) diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index d75c0e6f8..e6bcf4ec2 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -11,13 +11,19 @@ use List::Util qw(min first); use Slic3r::Geometry qw(X Y); use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedialog :font :icon wxTheApp); -use Wx::Event qw(EVT_CLOSE EVT_MENU EVT_NOTEBOOK_PAGE_CHANGED); +use Wx::Event qw(EVT_CLOSE EVT_COMMAND EVT_MENU EVT_NOTEBOOK_PAGE_CHANGED); use base 'Wx::Frame'; our $qs_last_input_file; our $qs_last_output_file; our $last_config; +# Events to be sent from a C++ Tab implementation: +# 1) To inform about a change of a configuration value. +our $VALUE_CHANGE_EVENT = Wx::NewEventType; +# 2) To inform about a preset selection change or a "modified" status change. +our $PRESETS_CHANGED_EVENT = Wx::NewEventType; + sub new { my ($class, %params) = @_; @@ -151,8 +157,19 @@ sub _init_tabpanel { $panel->AddPage($tab, $tab->title); } -#TODO this is an example of a Slic3r XS interface call to add a new preset editor page to the main view. - Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}, wxTheApp->{app_config}); + #TODO this is an example of a Slic3r XS interface call to add a new preset editor page to the main view. + # The following event is emited by the C++ Tab implementation on config value change. + EVT_COMMAND($self, -1, $VALUE_CHANGE_EVENT, sub { + my ($self, $event) = @_; + print "VALUE_CHANGE_EVENT: ", $event->GetString, "\n"; + }); + # The following event is emited by the C++ Tab implementation on preset selection, + # or when the preset's "modified" status changes. + EVT_COMMAND($self, -1, $PRESETS_CHANGED_EVENT, sub { + my ($self, $event) = @_; + print "PRESETS_CHANGED_EVENT: ", $event->GetString, "\n"; + }); + Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}, wxTheApp->{app_config}, $VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT); if ($self->{plater}) { $self->{plater}->on_select_preset(sub { diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 2953f6492..9118999ab 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -185,7 +185,7 @@ void add_debug_menu(wxMenuBar *menu) #endif } -void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config) +void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config, int event_value_change, int event_presets_changed) { add_created_tab(new TabPrint (g_wxTabPanel, "Print"), preset_bundle, app_config); add_created_tab(new TabFilament(g_wxTabPanel, "Filament"), preset_bundle, app_config); @@ -196,6 +196,13 @@ void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config) panel->GetName().compare("Filament") == 0) panel->OnActivate(); }), g_wxTabPanel->GetId() ); + for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++ i) { + Tab *tab = dynamic_cast<Tab*>(g_wxTabPanel->GetPage(i)); + if (! tab) + continue; + tab->set_event_value_change(wxEventType(event_value_change)); + tab->set_event_presets_changed(wxEventType(event_presets_changed)); + } } void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, boost::any value) @@ -282,7 +289,7 @@ void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_con panel->m_show_btn_incompatible_presets = app_config->get("show_incompatible_presets").empty(); panel->create_preset_tab(preset_bundle); // Callback to be executed after any of the configuration fields(Perl class Slic3r::GUI::OptionsGroup::Field) change their value. - panel->m_on_value_change = [/*this*/](std::string opt_key, boost::any value){ +// panel->m_on_value_change = [/*this*/](std::string opt_key, boost::any value){ //! plater & loaded - variables of MainFrame // if (plater) { // plater->on_config_change(m_config); //# propagate config change events to the plater @@ -290,11 +297,11 @@ void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_con // } // don't save while loading for the first time // if (loaded && Slic3r::GUI::autosave) m_config->save(Slic3r::GUI::autosave) ; - }; +// }; // Install a callback for the tab to update the platter and print controller presets, when // a preset changes at Slic3r::GUI::Tab. - panel->m_on_presets_changed = [](){ +// panel->m_on_presets_changed = [](){ // if ($self->{plater}) { // # Update preset combo boxes(Print settings, Filament, Printer) from their respective tabs. // $self->{plater}->update_presets($tab_name, @_); @@ -313,7 +320,7 @@ void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_con // } // $self->{plater}->on_config_change($tab->{presets}->get_current_preset->config); // } - }; +// }; // Load the currently selected preset into the GUI, update the preset selection box. panel->load_current_preset(); diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index f1b15f135..3d57b9977 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -35,7 +35,7 @@ void set_tab_panel(wxNotebook *tab_panel); void add_debug_menu(wxMenuBar *menu); // Create a new preset tab (print, filament and printer), -void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config); +void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config, int event_value_change, int event_presets_changed); // add it at the end of the tab panel. void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_config); // Change option value in config diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 3ebcf3405..b575e557c 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -269,14 +269,34 @@ void Tab::load_key_value(std::string opt_key, boost::any value) update(); } +extern wxFrame *g_wxMainFrame; + +void Tab::on_value_change(std::string opt_key, boost::any value) +{ +// if (m_on_value_change != nullptr) +// m_on_value_change(opt_key, value); + if (m_event_value_change > 0) { + wxCommandEvent event(m_event_value_change); + event.SetString(opt_key); + g_wxMainFrame->ProcessWindowEvent(event); + } + update(); +}; + // Call a callback to update the selection of presets on the platter: // To update the content of the selection boxes, // to update the filament colors of the selection boxes, // to update the "dirty" flags of the selection boxes, // to uddate number of "filament" selection boxes when the number of extruders change. -void Tab::on_presets_changed(/*std::vector<std::string> reload_dependent_tabs*/){ - if (m_on_presets_changed != nullptr) - m_on_presets_changed(/*m_presets, reload_dependent_tabs*/); +void Tab::on_presets_changed(/*std::vector<std::string> reload_dependent_tabs*/) +{ +// if (m_on_presets_changed != nullptr) +// m_on_presets_changed(/*m_presets, reload_dependent_tabs*/); + if (m_event_presets_changed > 0) { + wxCommandEvent event(m_event_presets_changed); + //event.SetString(opt_key); + g_wxMainFrame->ProcessWindowEvent(event); + } } void Tab::reload_compatible_printers_widget() diff --git a/xs/src/slic3r/GUI/Tab.h b/xs/src/slic3r/GUI/Tab.h index aa8008b51..14c84af08 100644 --- a/xs/src/slic3r/GUI/Tab.h +++ b/xs/src/slic3r/GUI/Tab.h @@ -98,14 +98,18 @@ protected: std::vector<std::string> m_reload_dependent_tabs = {}; + // The two following two event IDs are generated at Plater.pm by calling Wx::NewEventType. + wxEventType m_event_value_change = 0; + wxEventType m_event_presets_changed = 0; + public: PresetBundle* m_preset_bundle; bool m_no_controller; bool m_show_btn_incompatible_presets; PresetCollection* m_presets; DynamicPrintConfig* m_config; - t_change m_on_value_change{ nullptr }; - std::function<void()> m_on_presets_changed{ nullptr }; +// t_change m_on_value_change{ nullptr }; +// std::function<void()> m_on_presets_changed{ nullptr }; public: Tab() {} @@ -116,13 +120,12 @@ public: wxWindow* parent() const { return m_parent; } wxString title() const { return m_title; } + + // Set the events to the callbacks posted to the main frame window (currently implemented in Perl). + void set_event_value_change(wxEventType evt) { m_event_value_change = evt; } + void set_event_presets_changed(wxEventType evt) { m_event_presets_changed = evt; } void create_preset_tab(PresetBundle *preset_bundle); - void on_value_change(std::string opt_key, boost::any value){ - if (m_on_value_change != nullptr) - m_on_value_change(opt_key, value); - update(); - }; void load_current_preset(); void rebuild_page_tree(); void select_preset(wxString preset_name = ""); @@ -130,7 +133,6 @@ public: wxSizer* compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn); void load_key_value(std::string opt_key, boost::any value); - void on_presets_changed(); void reload_compatible_printers_widget(); void OnTreeSelChange(wxTreeEvent& event); @@ -155,6 +157,11 @@ public: Field* get_field(t_config_option_key opt_key, int opt_index = -1) const; bool set_value(t_config_option_key opt_key, boost::any value); wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText); + + void on_value_change(std::string opt_key, boost::any value); + +protected: + void on_presets_changed(); }; //Slic3r::GUI::Tab::Print; diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp index eae1b73ea..b2f11f06f 100644 --- a/xs/xsp/GUI.xsp +++ b/xs/xsp/GUI.xsp @@ -35,5 +35,5 @@ void set_tab_panel(SV *ui) void add_debug_menu(SV *ui) %code%{ Slic3r::GUI::add_debug_menu((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar")); %}; -void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config) - %code%{ Slic3r::GUI::create_preset_tabs(preset_bundle, app_config); %}; +void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config, int event_value_change, int event_presets_changed) + %code%{ Slic3r::GUI::create_preset_tabs(preset_bundle, app_config, event_value_change, event_presets_changed); %};