diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 5d6d8e4a6..e585a6967 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -67,6 +67,10 @@ our $medium_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); $medium_font->SetPointSize(12); our $grey = Wx::Colour->new(200,200,200); +# Events to be sent from a C++ menu implementation: +# 1) To inform about a change of the application language. +our $LANGUAGE_CHANGE_EVENT = Wx::NewEventType; + sub OnInit { my ($self) = @_; @@ -80,6 +84,7 @@ sub OnInit { # Mac: "~/Library/Application Support/Slic3r" Slic3r::set_data_dir($datadir || Wx::StandardPaths::Get->GetUserDataDir); Slic3r::GUI::set_wxapp($self); + Slic3r::GUI::load_language(); $self->{notifier} = Slic3r::GUI::Notifier->new; $self->{app_config} = Slic3r::GUI::AppConfig->new; @@ -114,10 +119,12 @@ sub OnInit { # If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden. no_controller => $self->{app_config}->get('no_controller'), no_plater => $no_plater, + lang_ch_event => $LANGUAGE_CHANGE_EVENT, ); $self->SetTopWindow($frame); - EVT_IDLE($frame, sub { + #EVT_IDLE($frame, sub { + EVT_IDLE($self->{mainframe}, sub { while (my $cb = shift @cb) { $cb->(); } @@ -132,10 +139,43 @@ sub OnInit { $self->{mainframe}->config_wizard(1); }); } + + # The following event is emited by the C++ menu implementation of application language change. + EVT_COMMAND($self, -1, $LANGUAGE_CHANGE_EVENT, sub{ + $self->recreate_GUI; + }); return 1; } +sub recreate_GUI{ + my ($self) = @_; + print "Inside recreate_GUI \n"; + my $topwindow = $self->GetTopWindow(); + $self->{mainframe} = my $frame = Slic3r::GUI::MainFrame->new( + # If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden. + no_controller => $self->{app_config}->get('no_controller'), + no_plater => $no_plater, + lang_ch_event => $LANGUAGE_CHANGE_EVENT, + ); + + if($topwindow) + { + $self->SetTopWindow($frame); + $topwindow->Destroy; + } + + my $run_wizard = 1 if $self->{preset_bundle}->has_defauls_only; + if ($run_wizard) { + # On OSX the UI was not initialized correctly if the wizard was called + # before the UI was up and running. + $self->CallAfter(sub { + # Run the config wizard, don't offer the "reset user profile" checkbox. + $self->{mainframe}->config_wizard(1); + }); + } +} + sub about { my ($self) = @_; my $about = Slic3r::GUI::AboutDialog->new(undef); diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 9f47b8d3e..4ca456338 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -47,6 +47,7 @@ sub new { $self->{no_controller} = $params{no_controller}; $self->{no_plater} = $params{no_plater}; $self->{loaded} = 0; + $self->{lang_ch_event} = $params{lang_ch_event}; # initialize tabpanel and menubar $self->_init_tabpanel; @@ -146,21 +147,23 @@ sub _init_tabpanel { if ($self->{plater}) { # Update preset combo boxes (Print settings, Filament, Printer) from their respective tabs. my $presets = $tab->get_presets; - my $reload_dependent_tabs = $tab->get_dependent_tabs; - $self->{plater}->update_presets($tab_name, $reload_dependent_tabs, $presets); - if ($tab_name eq 'printer') { - # Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. - for my $tab_name_other (qw(print filament)) { - # If the printer tells us that the print or filament preset has been switched or invalidated, - # refresh the print or filament tab page. Otherwise just refresh the combo box. - my $update_action = ($reload_dependent_tabs && (first { $_ eq $tab_name_other } (@{$reload_dependent_tabs}))) - ? 'load_current_preset' : 'update_tab_ui'; - $self->{options_tabs}{$tab_name_other}->$update_action; + if (defined $presets){ + my $reload_dependent_tabs = $tab->get_dependent_tabs; + $self->{plater}->update_presets($tab_name, $reload_dependent_tabs, $presets); + if ($tab_name eq 'printer') { + # Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. + for my $tab_name_other (qw(print filament)) { + # If the printer tells us that the print or filament preset has been switched or invalidated, + # refresh the print or filament tab page. Otherwise just refresh the combo box. + my $update_action = ($reload_dependent_tabs && (first { $_ eq $tab_name_other } (@{$reload_dependent_tabs}))) + ? 'load_current_preset' : 'update_tab_ui'; + $self->{options_tabs}{$tab_name_other}->$update_action; + } + # Update the controller printers. + $self->{controller}->update_presets($presets) if $self->{controller}; } - # Update the controller printers. - $self->{controller}->update_presets($presets) if $self->{controller}; + $self->{plater}->on_config_change($tab->get_config); } - $self->{plater}->on_config_change($tab->get_config); } }); # The following event is emited by the C++ Tab implementation , @@ -413,7 +416,7 @@ sub _init_menubar { # Add an optional debug menu # (Select application language from the list of installed languages) # In production code, the add_debug_menu() call should do nothing. - Slic3r::GUI::add_debug_menu($menubar); + Slic3r::GUI::add_debug_menu($menubar, $self->{lang_ch_event}); $menubar->Append($helpMenu, "&Help"); $self->SetMenuBar($menubar); } diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 8063c98fd..3b825ad92 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -166,6 +166,8 @@ wxApp *g_wxApp = nullptr; wxFrame *g_wxMainFrame = nullptr; wxNotebook *g_wxTabPanel = nullptr; +std::vector g_tabs_list; + wxLocale* m_Locale; std::string m_local_dir; @@ -184,6 +186,26 @@ void set_tab_panel(wxNotebook *tab_panel) g_wxTabPanel = tab_panel; } +std::vector& get_tabs_list() +{ + return g_tabs_list; +} + +bool checked_tab(Tab* tab) +{ + bool ret = true; + if (find(g_tabs_list.begin(), g_tabs_list.end(), tab) == g_tabs_list.end()) + ret = false; + return ret; +} + +void delete_tab_from_list(Tab* tab) +{ + std::vector::iterator itr = find(g_tabs_list.begin(), g_tabs_list.end(), tab); + if (itr != g_tabs_list.end()) + g_tabs_list.erase(itr); +} + bool select_language(wxArrayString & names, wxArrayLong & identifiers) { @@ -214,10 +236,10 @@ bool load_language() long language; // if (!config.Read(wxT("wxTranslation_Language"), // &language, wxLANGUAGE_UNKNOWN)) -// { - language = wxLANGUAGE_UKRAINIAN;// wxLANGUAGE_UNKNOWN; -// } -// if (language == wxLANGUAGE_UNKNOWN) return false; + { + language = wxLANGUAGE_ENGLISH_US;// wxLANGUAGE_UKRAINIAN;// wxLANGUAGE_UNKNOWN; + } + if (language == wxLANGUAGE_UNKNOWN) return false; wxArrayString names; wxArrayLong identifiers; get_installed_languages(names, identifiers); @@ -287,16 +309,22 @@ void get_installed_languages(wxArrayString & names, } } -void add_debug_menu(wxMenuBar *menu) +void add_debug_menu(wxMenuBar *menu, int event_language_change) { //#if 0 auto local_menu = new wxMenu(); local_menu->Append(wxWindow::NewControlId(1), _L("Change Application Language")); - local_menu->Bind(wxEVT_MENU, [](wxEvent&){ + local_menu->Bind(wxEVT_MENU, [event_language_change](wxEvent&){ wxArrayString names; wxArrayLong identifiers; get_installed_languages(names, identifiers); - select_language(names, identifiers); + if (select_language(names, identifiers)){ + show_info(g_wxTabPanel, "Application will be restarted", "Attention!"); + if (event_language_change > 0) { + wxCommandEvent event(event_language_change); + g_wxApp->ProcessEvent(event); + } + } }); menu->Append(local_menu, _T("&Localization")); //#endif diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index c8f156846..d3db707fa 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -58,7 +58,7 @@ void set_wxapp(wxApp *app); void set_main_frame(wxFrame *main_frame); void set_tab_panel(wxNotebook *tab_panel); -void add_debug_menu(wxMenuBar *menu); +void add_debug_menu(wxMenuBar *menu, int event_language_change); // Create a new preset tab (print, filament and printer), void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config, bool no_controller, bool is_disabled_button_browse, bool is_user_agent, @@ -83,6 +83,10 @@ void get_installed_languages(wxArrayString & names, wxArrayLong & identifiers); // select language from the list of installed languages bool select_language(wxArrayString & names, wxArrayLong & identifiers); +std::vector& get_tabs_list(); +bool checked_tab(Tab* tab); +void delete_tab_from_list(Tab* tab); + } } #endif diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 77c441005..904842a5e 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -1238,7 +1238,7 @@ void TabPrinter::build_extruder_pages(){ // # rebuild page list PageShp page_note = m_pages.back(); m_pages.pop_back(); - while (m_pages.back()->title().find("Extruder") != std::string::npos) + while (m_pages.back()->title().find(_L("Extruder")) != std::string::npos) m_pages.pop_back(); for (auto page_extruder : m_extruder_pages) m_pages.push_back(page_extruder); @@ -1361,6 +1361,9 @@ void Tab::load_current_preset() // preset dirty again // (not sure this is true anymore now that update_dirty is idempotent) wxTheApp->CallAfter([this]{ + // checking out if this Tab exists till this moment + if (!checked_tab(this)) + return; update_tab_ui(); on_presets_changed(); }); diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp index 2b030f4da..4f3a15736 100644 --- a/xs/src/slic3r/GUI/Tab.hpp +++ b/xs/src/slic3r/GUI/Tab.hpp @@ -112,11 +112,12 @@ public: public: Tab() {} - Tab(wxNotebook* parent, const char *title, const char* name, bool no_controller) : + Tab(wxNotebook* parent, wxString title, const char* name, bool no_controller) : m_parent(parent), m_title(title), m_name(name), m_no_controller(no_controller) { Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); + get_tabs_list().push_back(this); } - ~Tab(){} + ~Tab() { delete_tab_from_list(this); } wxWindow* parent() const { return m_parent; } wxString title() const { return m_title; } @@ -160,7 +161,10 @@ public: wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText); bool current_preset_is_dirty(); DynamicPrintConfig* get_config() { return m_config; } - PresetCollection* get_presets() { return m_presets; } + PresetCollection* get_presets() + { + return m_presets; + } std::vector get_dependent_tabs() { return m_reload_dependent_tabs; } void on_value_change(std::string opt_key, boost::any value); diff --git a/xs/src/slic3r/GUI/TabIface.cpp b/xs/src/slic3r/GUI/TabIface.cpp index 2b897a7b9..2f3adea3c 100644 --- a/xs/src/slic3r/GUI/TabIface.cpp +++ b/xs/src/slic3r/GUI/TabIface.cpp @@ -13,7 +13,7 @@ bool TabIface::current_preset_is_dirty() { return m_tab->current_preset_is_d void TabIface::OnActivate() { return m_tab->OnActivate();} std::string TabIface::title() { return m_tab->title().ToStdString();} DynamicPrintConfig* TabIface::get_config() { return m_tab->get_config(); } -PresetCollection* TabIface::get_presets() { return m_tab->get_presets(); } +PresetCollection* TabIface::get_presets() { return m_tab!=nullptr ? m_tab->get_presets() : nullptr; } std::vector TabIface::get_dependent_tabs() { return m_tab->get_dependent_tabs(); } }; // namespace Slic3r diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp index c273013db..8f6b6ee68 100644 --- a/xs/xsp/GUI.xsp +++ b/xs/xsp/GUI.xsp @@ -32,8 +32,8 @@ void set_main_frame(SV *ui) void set_tab_panel(SV *ui) %code%{ Slic3r::GUI::set_tab_panel((wxNotebook*)wxPli_sv_2_object(aTHX_ ui, "Wx::Notebook")); %}; -void add_debug_menu(SV *ui) - %code%{ Slic3r::GUI::add_debug_menu((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar")); %}; +void add_debug_menu(SV *ui, int event_language_change) + %code%{ Slic3r::GUI::add_debug_menu((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar"), event_language_change); %}; void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config, bool no_controller, bool is_disabled_button_browse, bool is_user_agent, @@ -46,3 +46,6 @@ void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config, Ref get_preset_tab(char *name) %code%{ RETVAL=Slic3r::GUI::get_preset_tab_iface(name); %}; + +bool load_language() + %code%{ RETVAL=Slic3r::GUI::load_language(); %};