diff --git a/resources/icons/settings.svg b/resources/icons/settings.svg index db5bf458d7..d4801ae0bb 100644 --- a/resources/icons/settings.svg +++ b/resources/icons/settings.svg @@ -37,7 +37,7 @@ - - diff --git a/resources/localization/list.txt b/resources/localization/list.txt index 18ef74bf8e..8acf52612d 100644 --- a/resources/localization/list.txt +++ b/resources/localization/list.txt @@ -109,6 +109,8 @@ src/slic3r/GUI/SurfaceDrag.cpp src/slic3r/GUI/SysInfoDialog.cpp src/slic3r/GUI/Tab.cpp src/slic3r/GUI/Tab.hpp +src/slic3r/GUI/TopBar.cpp +src/slic3r/GUI/TopBarMenu.cpp src/slic3r/GUI/UnsavedChangesDialog.cpp src/slic3r/GUI/UpdateDialogs.cpp src/slic3r/GUI/WifiConfigDialog.cpp diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 82900f4ab8..69269ae0ce 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -101,9 +101,6 @@ void AppConfig::set_defaults() if (get("associate_stl").empty()) set("associate_stl", "0"); - if (get("tabs_as_menu").empty()) - set("tabs_as_menu", "0"); - if (get("suppress_round_corners").empty()) set("suppress_round_corners", "1"); #endif // _WIN32 diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 577e170bff..1ae73a1f89 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -258,6 +258,8 @@ set(SLIC3R_GUI_SOURCES GUI/Notebook.hpp GUI/TopBar.cpp GUI/TopBar.hpp + GUI/TopBarMenus.cpp + GUI/TopBarMenus.hpp GUI/ObjectDataViewModel.cpp GUI/ObjectDataViewModel.hpp GUI/InstanceCheck.cpp diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index bdd6111d41..42e743bc88 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5137,7 +5137,7 @@ bool GLCanvas3D::_init_main_toolbar() if (!m_main_toolbar.add_separator()) return false; - +/* item.name = "settings"; item.icon_filename = "settings.svg"; item.tooltip = _u8L("Switch to Settings") + "\n" + "[" + GUI::shortkey_ctrl_prefix() + "2] - " + _u8L("Print Settings Tab") + @@ -5145,12 +5145,11 @@ bool GLCanvas3D::_init_main_toolbar() "\n" + "[" + GUI::shortkey_ctrl_prefix() + "4] - " + _u8L("Printer Settings Tab")) ; item.sprite_id = 10; item.enabling_callback = GLToolbarItem::Default_Enabling_Callback; - item.visibility_callback = []() { return wxGetApp().app_config->get_bool("new_settings_layout_mode") || - wxGetApp().app_config->get_bool("dlg_settings_layout_mode"); }; + item.visibility_callback = []() { return wxGetApp().app_config->get_bool("dlg_settings_layout_mode"); }; item.left.action_callback = []() { wxGetApp().mainframe->select_tab(); }; if (!m_main_toolbar.add_item(item)) return false; - +*/ if (!m_main_toolbar.add_separator()) return false; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index ffa9277976..9d29c73873 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -12,6 +12,7 @@ #include "GUI_ObjectList.hpp" #include "GUI_ObjectManipulation.hpp" #include "GUI_Factories.hpp" +#include "TopBar.hpp" #include "format.hpp" // Localization headers: include libslic3r version first so everything in this file @@ -1111,11 +1112,16 @@ void GUI_App::jump_to_option(const std::string& composite_key) } } +void GUI_App::update_search_lines() +{ + mainframe->update_search_lines(m_searcher->search_string()); +} + void GUI_App::show_search_dialog() { // To avoid endless loop caused by mutual lose focuses from serch_input and search_dialog // invoke killFocus for serch_input by set focus to tab_panel - GUI::wxGetApp().tab_panel()->SetFocus(); + m_searcher->set_focus_to_parent(); check_and_update_searcher(get_mode()); m_searcher->show_dialog(); @@ -1823,11 +1829,6 @@ void GUI_App::set_mode_palette(const std::vector& palette) } } -bool GUI_App::tabs_as_menu() const -{ - return app_config->get_bool("tabs_as_menu"); // || dark_mode(); -} - bool GUI_App::suppress_round_corners() const { return true;// app_config->get("suppress_round_corners") == "1"; @@ -2479,8 +2480,8 @@ void GUI_App::update_mode() { sidebar().update_mode(); - if (!wxGetApp().tabs_as_menu()) - dynamic_cast(mainframe->m_tabpanel)->UpdateMode(); + mainframe->m_tmp_top_bar->UpdateMode(); + mainframe->m_tabpanel->UpdateMode(); for (auto tab : tabs_list) tab->update_mode(); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 50c8c25773..6eb67b47ee 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -203,6 +203,7 @@ public: void jump_to_option(const std::string& opt_key, Preset::Type type, const std::wstring& category); // jump to option which is represented by composite key : "opt_key;tab_name" void jump_to_option(const std::string& composite_key); + void update_search_lines(); void show_search_dialog(); // To be called after the GUI is fully built up. @@ -265,7 +266,6 @@ public: const wxFont& code_font() { return m_code_font; } const wxFont& link_font() { return m_link_font; } int em_unit() const { return m_em_unit; } - bool tabs_as_menu() const; bool suppress_round_corners() const; wxSize get_min_size(wxWindow* display_win) const; int get_max_font_pt_size(); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 1fe3ed6590..99baa4263b 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -57,7 +57,6 @@ #include "GUI_App.hpp" #include "UnsavedChangesDialog.hpp" #include "MsgDialog.hpp" -//#include "Notebook.hpp" #include "TopBar.hpp" #include "GUI_Factories.hpp" #include "GUI_ObjectList.hpp" @@ -278,26 +277,32 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S event.Skip(); }); - -#ifdef _WIN32 Bind(wxEVT_SIZE, [this](wxSizeEvent& event) { event.Skip(); +#ifdef _WIN32 // Update window property to mainframe so other instances can indentify it. wxGetApp().other_instance_message_handler()->update_windows_properties(this); - }); #endif //WIN32 + if (m_layout == ESettingsLayout::Dlg || m_layout == ESettingsLayout::Old) { + if (m_layout == ESettingsLayout::Old) + m_tabpanel->UpdateSearchSizeAndPosition(); + else + m_tmp_top_bar->UpdateSearchSizeAndPosition(); + } + }); + Bind(wxEVT_MOVE, [](wxMoveEvent& event) { // OSX specific issue: // When we move application between Retina and non-Retina displays, The legend on a canvas doesn't redraw // So, redraw explicitly canvas, when application is moved //FIXME maybe this is useful for __WXGTK3__ as well? #if __APPLE__ - Bind(wxEVT_MOVE, [](wxMoveEvent& event) { wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); wxGetApp().plater()->get_current_canvas3D()->request_extra_frame(); +#endif + wxGetApp().searcher().update_dialog_position(); event.Skip(); }); -#endif wxGetApp().persist_window_geometry(this, true); wxGetApp().persist_window_geometry(&m_settings_dialog, true); @@ -317,91 +322,6 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S } } -#ifdef _MSW_DARK_MODE -static wxString pref() { return " [ "; } -static wxString suff() { return " ] "; } -static void append_tab_menu_items_to_menubar(wxMenuBar* bar, PrinterTechnology pt, bool is_mainframe_menu) -{ - if (is_mainframe_menu) - bar->Append(new wxMenu(), pref() + _L("Plater") + suff()); - for (const wxString& title : { is_mainframe_menu ? _L("Print Settings") : pref() + _L("Print Settings") + suff(), - pt == ptSLA ? _L("Material Settings") : _L("Filament Settings"), - _L("Printer Settings") }) - bar->Append(new wxMenu(), title); -} - -// update markers for selected/unselected menu items -static void update_marker_for_tabs_menu(wxMenuBar* bar, const wxString& title, bool is_mainframe_menu) -{ - if (!bar) - return; - size_t items_cnt = bar->GetMenuCount(); - for (size_t id = items_cnt - (is_mainframe_menu ? 4 : 3); id < items_cnt; id++) { - wxString label = bar->GetMenuLabel(id); - if (label.First(pref()) == 0) { - if (label == pref() + title + suff()) - return; - label.Remove(size_t(0), pref().Len()); - label.RemoveLast(suff().Len()); - bar->SetMenuLabel(id, label); - break; - } - } - if (int id = bar->FindMenu(title); id != wxNOT_FOUND) - bar->SetMenuLabel(id, pref() + title + suff()); -} - -static void add_tabs_as_menu(wxMenuBar* bar, MainFrame* main_frame, wxWindow* bar_parent) -{ - PrinterTechnology pt = main_frame->plater() ? main_frame->plater()->printer_technology() : ptFFF; - - bool is_mainframe_menu = bar_parent == main_frame; - if (!is_mainframe_menu) - append_tab_menu_items_to_menubar(bar, pt, is_mainframe_menu); - - bar_parent->Bind(wxEVT_MENU_OPEN, [main_frame, bar, is_mainframe_menu](wxMenuEvent& event) { - wxMenu* const menu = event.GetMenu(); - if (!menu || menu->GetMenuItemCount() > 0) { - // If we are here it means that we open regular menu and not a tab used as a menu - event.Skip(); // event.Skip() is verry important to next processing of the wxEVT_UPDATE_UI by this menu items. - // If wxEVT_MENU_OPEN will not be pocessed in next event queue then MenuItems of this menu will never caught wxEVT_UPDATE_UI - // and, as a result, "check/radio value" will not be updated - return; - } - - // update tab selection - - const wxString& title = menu->GetTitle(); - if (title == _L("Plater")) - main_frame->select_tab(size_t(0)); - else if (title == _L("Print Settings")) - main_frame->select_tab(wxGetApp().get_tab(main_frame->plater()->printer_technology() == ptFFF ? Preset::TYPE_PRINT : Preset::TYPE_SLA_PRINT)); - else if (title == _L("Filament Settings")) - main_frame->select_tab(wxGetApp().get_tab(Preset::TYPE_FILAMENT)); - else if (title == _L("Material Settings")) - main_frame->select_tab(wxGetApp().get_tab(Preset::TYPE_SLA_MATERIAL)); - else if (title == _L("Printer Settings")) - main_frame->select_tab(wxGetApp().get_tab(Preset::TYPE_PRINTER)); - - // update markers for selected/unselected menu items - update_marker_for_tabs_menu(bar, title, is_mainframe_menu); - }); -} - -void MainFrame::show_tabs_menu(bool show) -{ - if (!m_menubar) - return; - if (show) - append_tab_menu_items_to_menubar(m_menubar, plater() ? plater()->printer_technology() : ptFFF, true); - else - while (m_menubar->GetMenuCount() >= 8) { - if (wxMenu* menu = m_menubar->Remove(7)) - delete menu; - } -} -#endif // _MSW_DARK_MODE - void MainFrame::update_layout() { auto restore_to_creation = [this]() { @@ -435,6 +355,7 @@ void MainFrame::update_layout() m_settings_dialog.Close(); m_tabpanel->Hide(); + m_tmp_top_bar->Hide(); m_plater->Hide(); Layout(); @@ -442,7 +363,6 @@ void MainFrame::update_layout() ESettingsLayout layout = wxGetApp().is_gcode_viewer() ? ESettingsLayout::GCodeViewer : (wxGetApp().app_config->get_bool("old_settings_layout_mode") ? ESettingsLayout::Old : - wxGetApp().app_config->get_bool("new_settings_layout_mode") ? ( wxGetApp().tabs_as_menu() ? ESettingsLayout::Old : ESettingsLayout::New) : wxGetApp().app_config->get_bool("dlg_settings_layout_mode") ? ESettingsLayout::Dlg : ESettingsLayout::Old); if (m_layout == layout) @@ -484,54 +404,35 @@ void MainFrame::update_layout() { m_plater->Reparent(m_tabpanel); m_plater->Layout(); -#ifdef _WIN32 - if (wxGetApp().tabs_as_menu()) - m_tabpanel->InsertPage(0, m_plater, _L("Plater")); - else -#endif - dynamic_cast(m_tabpanel)->InsertNewPage(0, m_plater, _L("Plater"), std::string("plater"), true); + m_tabpanel->InsertNewPage(0, m_plater, _L("Plater"), std::string("plater"), true); m_main_sizer->Add(m_tabpanel, 1, wxEXPAND | wxTOP, 1); m_plater->Show(); - m_tabpanel->Show(); + m_tabpanel->ShowFull(); + m_tmp_top_bar->Hide(); + // update Tabs if (old_layout == ESettingsLayout::Dlg) if (int sel = m_tabpanel->GetSelection(); sel != wxNOT_FOUND) m_tabpanel->SetSelection(sel+1);// call SetSelection to correct layout after switching from Dlg to Old mode -#ifdef _MSW_DARK_MODE - if (wxGetApp().tabs_as_menu()) - show_tabs_menu(true); -#endif - break; - } - case ESettingsLayout::New: - { - m_main_sizer->Add(m_plater, 1, wxEXPAND); - m_tabpanel->Hide(); - m_main_sizer->Add(m_tabpanel, 1, wxEXPAND); - m_plater_page = new wxPanel(m_tabpanel); -#ifdef _WIN32 - if (wxGetApp().tabs_as_menu()) - m_tabpanel->InsertPage(0, m_plater_page, _L("Plater")); // empty panel just for Plater tab - else -#endif - dynamic_cast(m_tabpanel)->InsertNewPage(0, m_plater_page, _L("Plater"), std::string("plater"), true); - - m_plater->Show(); break; } case ESettingsLayout::Dlg: { - m_main_sizer->Add(m_plater, 1, wxEXPAND); - m_tabpanel->Reparent(&m_settings_dialog); - m_settings_dialog.GetSizer()->Add(m_tabpanel, 1, wxEXPAND | wxTOP, 2); - m_tabpanel->Show(); + const int sel = m_tabpanel->GetSelection(); + + m_plater->Reparent(this); + m_main_sizer->Add(m_tmp_top_bar, 0, wxEXPAND | wxTOP, 1); + m_main_sizer->Add(m_plater, 1, wxEXPAND | wxTOP, 1); + m_plater->Layout(); + m_tmp_top_bar->ShowFull(); m_plater->Show(); -#ifdef _WIN32 - if (wxGetApp().tabs_as_menu()) - show_tabs_menu(false); -#endif + m_tabpanel->Reparent(&m_settings_dialog); + m_tabpanel->SetSelection(sel > 0 ? (sel - 1) : 0); + m_tabpanel->ShowJustMode(); + m_settings_dialog.GetSizer()->Add(m_tabpanel, 1, wxEXPAND | wxTOP, 2); + m_settings_dialog.Layout(); break; } case ESettingsLayout::GCodeViewer: @@ -574,20 +475,6 @@ void MainFrame::update_layout() } } #endif //__WXMSW__ - -//#ifdef __APPLE__ -// // Using SetMinSize() on Mac messes up the window position in some cases -// // cf. https://groups.google.com/forum/#!topic/wx-users/yUKPBBfXWO0 -// // So, if we haven't possibility to set MinSize() for the MainFrame, -// // set the MinSize() as a half of regular for the m_plater and m_tabpanel, when settings layout is in slNew mode -// // Otherwise, MainFrame will be maximized by height -// if (m_layout == ESettingsLayout::New) { -// wxSize size = wxGetApp().get_min_size(); -// size.SetHeight(int(0.5 * size.GetHeight())); -// m_plater->SetMinSize(size); -// m_tabpanel->SetMinSize(size); -// } -//#endif Layout(); Thaw(); @@ -704,20 +591,27 @@ void MainFrame::update_title() SetTitle(title); } +static wxString GetTooltipForSettingsButton(PrinterTechnology pt) +{ + std::string tooltip = _u8L("Switch to Settings") + "\n" + "[" + shortkey_ctrl_prefix() + "2] - " + _u8L("Print Settings Tab") + + "\n" + "[" + shortkey_ctrl_prefix() + "3] - " + (pt == ptFFF ? _u8L("Filament Settings Tab") : _u8L("Material Settings Tab")) + + "\n" + "[" + shortkey_ctrl_prefix() + "4] - " + _u8L("Printer Settings Tab"); + return from_u8(tooltip); +} + void MainFrame::init_tabpanel() { wxGetApp().update_ui_colours_from_appconfig(); + if (wxGetApp().is_editor()) { + m_tmp_top_bar = new TopBar(this, &m_bar_menus, false); + m_tmp_top_bar->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + m_tmp_top_bar->Hide(); + } + // wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on Windows 10 // with multiple high resolution displays connected. -#ifdef _MSW_DARK_MODE - if (wxGetApp().tabs_as_menu()) { - m_tabpanel = new wxSimplebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME); -// wxGetApp().UpdateDarkUI(m_tabpanel); - } - else -#endif - m_tabpanel = new TopBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME); + m_tabpanel = new TopBar(this, &m_bar_menus); m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font()); m_tabpanel->Hide(); @@ -748,10 +642,6 @@ void MainFrame::init_tabpanel() // before the MainFrame is fully set up. tab->OnActivate(); m_last_selected_tab = m_tabpanel->GetSelection(); -#ifdef _MSW_DARK_MODE - if (wxGetApp().tabs_as_menu()) - tab->SetFocus(); -#endif } else select_tab(size_t(0)); // select Plater @@ -775,6 +665,9 @@ void MainFrame::init_tabpanel() if (full_config.has("nozzle_diameter")) { m_plater->sidebar().set_extruders_count(full_config.option("nozzle_diameter")->values.size()); } + + if (wxGetApp().is_editor()) + m_tmp_top_bar->SetSettingsButtonTooltip(GetTooltipForSettingsButton(m_plater->printer_technology())); } } @@ -854,15 +747,17 @@ void MainFrame::add_connect_webview_tab() { if (m_connect_webview_added) { return; - } // parameters of InsertNewPage (to prevent ambigous overloaded function) - // insert to positon 4, if physical printer is already added, it moves to 5 + } + // parameters of InsertNewPage (to prevent ambigous overloaded function) + // insert "Connect" tab to position next to "Printer" tab // order of tabs: Plater - Print Settings - Filaments - Printers - Prusa Connect - Prusa Link - size_t n = 4; + + int n = m_tabpanel->FindPage(wxGetApp().get_tab(Preset::TYPE_PRINTER)) + 1; wxWindow* page = m_connect_webview; const wxString text(L"Prusa Connect"); const std::string bmp_name = ""; bool bSelect = false; - dynamic_cast(m_tabpanel)->InsertNewPage(n, page, text, bmp_name, bSelect); + m_tabpanel->InsertNewPage(n, page, text, bmp_name, bSelect); m_connect_webview->load_default_url_delayed(); m_connect_webview_added = true; } @@ -871,10 +766,10 @@ void MainFrame::remove_connect_webview_tab() if (!m_connect_webview_added) { return; } - // connect tab should always be at position 4 - if (m_tabpanel->GetSelection() == 4) + int n = m_tabpanel->FindPage(m_connect_webview); + if (m_tabpanel->GetSelection() == n) m_tabpanel->SetSelection(0); - dynamic_cast(m_tabpanel)->RemovePage(4); + m_tabpanel->RemovePage(size_t(n)); m_connect_webview_added = false; m_connect_webview->logout(); } @@ -922,7 +817,7 @@ void MainFrame::add_printer_webview_tab(const wxString& url) } m_printer_webview_added = true; // add as the last (rightmost) panel - dynamic_cast(m_tabpanel)->AddNewPage(m_printer_webview, _L("Physical Printer"), ""); + m_tabpanel->AddNewPage(m_printer_webview, _L("Physical Printer"), ""); m_printer_webview->set_default_url(url); m_printer_webview->load_default_url_delayed(); } @@ -933,7 +828,7 @@ void MainFrame::remove_printer_webview_tab() } m_printer_webview_added = false; m_printer_webview->Hide(); - dynamic_cast(m_tabpanel)->RemovePage(m_tabpanel->FindPage(m_printer_webview)); + m_tabpanel->RemovePage(m_tabpanel->FindPage(m_printer_webview)); } void MainFrame::set_printer_webview_tab_url(const wxString& url) { @@ -963,7 +858,9 @@ void MainFrame::set_printer_webview_credentials(const std::string& usr, const st void Slic3r::GUI::MainFrame::refresh_account_menu(bool avatar/* = false */) { // Update User name in TopBar - dynamic_cast(m_tabpanel)->GetTopBarItemsCtrl()->UpdateAccountMenu(avatar); + m_bar_menus.UpdateAccountMenu(m_plater->get_user_account()); + m_tabpanel->GetTopBarItemsCtrl()->UpdateAccountButton(avatar); + m_tmp_top_bar->GetTopBarItemsCtrl()->UpdateAccountButton(avatar); } void MainFrame::add_created_tab(Tab* panel, const std::string& bmp_name /*= ""*/) @@ -972,14 +869,8 @@ void MainFrame::add_created_tab(Tab* panel, const std::string& bmp_name /*= ""* const auto printer_tech = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology(); - if (panel->supports_printer_technology(printer_tech)) { -#ifdef _WIN32 - if (wxGetApp().tabs_as_menu()) - m_tabpanel->AddPage(panel, panel->title()); - else -#endif - dynamic_cast(m_tabpanel)->AddNewPage(panel, panel->title(), bmp_name); - } + if (panel->supports_printer_technology(printer_tech)) + m_tabpanel->AddNewPage(panel, panel->title(), bmp_name); } bool MainFrame::is_active_and_shown_tab(Tab* tab) @@ -991,9 +882,6 @@ bool MainFrame::is_active_and_shown_tab(Tab* tab) if (m_layout == ESettingsLayout::Dlg) return m_settings_dialog.IsShown(); - - if (m_layout == ESettingsLayout::New) - return m_main_sizer->IsShown(m_tabpanel); return true; } @@ -1122,7 +1010,6 @@ bool MainFrame::can_change_view() const switch (m_layout) { default: { return false; } - case ESettingsLayout::New: { return m_plater->IsShown(); } case ESettingsLayout::Dlg: { return true; } case ESettingsLayout::Old: { int page_id = m_tabpanel->GetSelection(); @@ -1164,8 +1051,7 @@ void MainFrame::on_dpi_changed(const wxRect& suggested_rect) #ifdef _WIN32 // update common mode sizer - if (!wxGetApp().tabs_as_menu()) - dynamic_cast(m_tabpanel)->Rescale(); + m_tabpanel->Rescale(); #endif // update Plater @@ -1210,9 +1096,10 @@ void MainFrame::on_sys_color_changed() wxGetApp().update_ui_colours_from_appconfig(); #ifdef __WXMSW__ wxGetApp().UpdateDarkUI(m_tabpanel); - if (!wxGetApp().tabs_as_menu()) + wxGetApp().UpdateDarkUI(m_tmp_top_bar); #endif - dynamic_cast(m_tabpanel)->OnColorsChanged(); + m_tabpanel->OnColorsChanged(); + m_tmp_top_bar->OnColorsChanged(); // update Plater wxGetApp().plater()->sys_color_changed(); @@ -1236,8 +1123,8 @@ void MainFrame::on_sys_color_changed() void MainFrame::update_mode_markers() { // update markers in common mode sizer - if (!wxGetApp().tabs_as_menu()) - dynamic_cast(m_tabpanel)->UpdateModeMarkers(); + m_tmp_top_bar->UpdateModeMarkers(); + m_tabpanel->UpdateModeMarkers(); // update mode markers in tabs for (auto tab : wxGetApp().tabs_list) @@ -1663,22 +1550,21 @@ void MainFrame::init_menubar_as_editor() #ifndef __APPLE__ // append menus for Menu button from TopBar - TopBar* top_bar = dynamic_cast(m_tabpanel); - top_bar->AppendMenuItem(fileMenu, _L("&File")); + m_bar_menus.AppendMenuItem(fileMenu, _L("&File")); if (editMenu) - top_bar->AppendMenuItem(editMenu, _L("&Edit")); + m_bar_menus.AppendMenuItem(editMenu, _L("&Edit")); - top_bar->AppendMenuSeparaorItem(); + m_bar_menus.AppendMenuSeparaorItem(); - top_bar->AppendMenuItem(windowMenu, _L("&Window")); + m_bar_menus.AppendMenuItem(windowMenu, _L("&Window")); if (viewMenu) - top_bar->AppendMenuItem(viewMenu, _L("&View")); + m_bar_menus.AppendMenuItem(viewMenu, _L("&View")); - top_bar->AppendMenuItem(wxGetApp().get_config_menu(), _L("&Configuration")); + m_bar_menus.AppendMenuItem(wxGetApp().get_config_menu(), _L("&Configuration")); - top_bar->AppendMenuSeparaorItem(); + m_bar_menus.AppendMenuSeparaorItem(); - top_bar->AppendMenuItem(helpMenu, _L("&Help")); + m_bar_menus.AppendMenuItem(helpMenu, _L("&Help")); #else @@ -2071,6 +1957,13 @@ void MainFrame::load_config(const DynamicPrintConfig& config) #endif } +void MainFrame::update_search_lines(const std::string search_line) +{ + wxString search = from_u8(search_line); + m_tabpanel ->UpdateSearch(search); + m_tmp_top_bar->UpdateSearch(search); +} + void MainFrame::select_tab(Tab* tab) { if (!tab) @@ -2095,14 +1988,7 @@ void MainFrame::select_tab(size_t tab/* = size_t(-1)*/) if (m_tabpanel->GetSelection() != (int)new_selection) m_tabpanel->SetSelection(new_selection); -#ifdef _MSW_DARK_MODE - if (wxGetApp().tabs_as_menu()) { - if (Tab* cur_tab = dynamic_cast(m_tabpanel->GetPage(new_selection))) - update_marker_for_tabs_menu((m_layout == ESettingsLayout::Old ? m_menubar : m_settings_dialog.menubar()), cur_tab->title(), m_layout == ESettingsLayout::Old); - else if (tab == 0 && m_layout == ESettingsLayout::Old) - m_plater->get_current_canvas3D()->render(); - } -#endif + if (tab == 0 && m_layout == ESettingsLayout::Old) m_plater->canvas3D()->render(); else if (was_hidden) { @@ -2143,26 +2029,11 @@ void MainFrame::select_tab(size_t tab/* = size_t(-1)*/) if (m_settings_dialog.IsIconized()) m_settings_dialog.Iconize(false); } - else if (m_layout == ESettingsLayout::New) { - m_main_sizer->Show(m_plater, tab == 0); - tabpanel_was_hidden = !m_main_sizer->IsShown(m_tabpanel); - select(tabpanel_was_hidden); - m_main_sizer->Show(m_tabpanel, tab != 0); - - // plater should be focused for correct navigation inside search window - if (tab == 0) - m_plater->SetFocus(); - Layout(); - } else { select(false); -#ifdef _MSW_DARK_MODE - if (wxGetApp().tabs_as_menu() && tab == 0) - m_plater->SetFocus(); -#endif } - // When we run application in ESettingsLayout::New or ESettingsLayout::Dlg mode, tabpanel is hidden from the very beginning + // When we run application in ESettingsLayout::Dlg mode, tabpanel is hidden from the very beginning // and as a result Tab::update_changed_tree_ui() function couldn't update m_is_nonsys_values values, // which are used for update TreeCtrl and "revert_buttons". // So, force the call of this function for Tabs, if tab panel was hidden @@ -2233,10 +2104,12 @@ void MainFrame::add_to_recent_projects(const wxString& filename) void MainFrame::technology_changed() { + PrinterTechnology pt = plater()->printer_technology(); + m_tmp_top_bar->SetSettingsButtonTooltip(GetTooltipForSettingsButton(pt)); + if (!m_menubar) return; // update menu titles - PrinterTechnology pt = plater()->printer_technology(); if (int id = m_menubar->FindMenu(pt == ptFFF ? _L("Material Settings") : _L("Filament Settings")); id != wxNOT_FOUND) m_menubar->SetMenuLabel(id , pt == ptSLA ? _L("Material Settings") : _L("Filament Settings")); @@ -2318,6 +2191,8 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe) default:break; } } + + evt.Skip(); }; if (evt.IsShown()) { @@ -2333,14 +2208,11 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe) //just hide the Frame on closing this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& evt) { this->Hide(); }); -#ifdef _MSW_DARK_MODE - if (wxGetApp().tabs_as_menu()) { - // menubar - m_menubar = new wxMenuBar(); - add_tabs_as_menu(m_menubar, mainframe, this); - this->SetMenuBar(m_menubar); - } -#endif + this->Bind(wxEVT_SIZE, [this](wxSizeEvent& event) { + event.Skip(); + if (m_tabpanel) + m_tabpanel->UpdateSearchSizeAndPosition(); + }); // initialize layout auto sizer = new wxBoxSizer(wxVERTICAL); @@ -2358,6 +2230,11 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe) SetSize(GetMinSize()); #endif Layout(); + + Bind(wxEVT_MOVE, [](wxMoveEvent& event) { + wxGetApp().searcher().update_dialog_position(); + event.Skip(); + }); } void SettingsDialog::on_dpi_changed(const wxRect& suggested_rect) @@ -2369,9 +2246,7 @@ void SettingsDialog::on_dpi_changed(const wxRect& suggested_rect) const wxSize& size = wxSize(85 * em, 50 * em); #ifdef _WIN32 - // update common mode sizer - if (!wxGetApp().tabs_as_menu()) - dynamic_cast(m_tabpanel)->Rescale(); + m_tabpanel->Rescale(); #endif // update Tabs diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index bee3ac38e7..147059d945 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -29,7 +29,9 @@ #include "UnsavedChangesDialog.hpp" #include "Search.hpp" -class wxBookCtrlBase; +#include "TopBarMenus.hpp" + +class TopBar; class wxProgressDialog; namespace Slic3r { @@ -67,13 +69,13 @@ struct PresetTab { class SettingsDialog : public DPIFrame//DPIDialog { - wxBookCtrlBase* m_tabpanel { nullptr }; + TopBar* m_tabpanel { nullptr }; MainFrame* m_main_frame { nullptr }; wxMenuBar* m_menubar{ nullptr }; public: SettingsDialog(MainFrame* mainframe); ~SettingsDialog() = default; - void set_tabpanel(wxBookCtrlBase* tabpanel) { m_tabpanel = tabpanel; } + void set_tabpanel(TopBar* tabpanel) { m_tabpanel = tabpanel; } wxMenuBar* menubar() { return m_menubar; } protected: @@ -88,6 +90,7 @@ class MainFrame : public DPIFrame wxString m_qs_last_output_file = wxEmptyString; wxString m_last_config = wxEmptyString; wxMenuBar* m_menubar{ nullptr }; + TopBarMenus m_bar_menus; #if 0 wxMenuItem* m_menu_item_repeat { nullptr }; // doesn't used now @@ -143,7 +146,6 @@ class MainFrame : public DPIFrame { Unknown, Old, - New, Dlg, GCodeViewer }; @@ -181,9 +183,6 @@ public: void update_menubar(); // Open item in menu by menu and item name (in actual language) void open_menubar_item(const wxString& menu_name,const wxString& item_name); -#ifdef _WIN32 - void show_tabs_menu(bool show); -#endif void update_ui_from_settings(); bool is_loaded() const { return m_loaded; } bool is_last_input_file() const { return !m_qs_last_input_file.IsEmpty(); } @@ -199,6 +198,7 @@ public: void export_configbundle(bool export_physical_printers = false); void load_configbundle(wxString file = wxEmptyString); void load_config(const DynamicPrintConfig& config); + void update_search_lines(const std::string search_line); // Select tab in m_tabpanel // When tab == -1, will be selected last selected tab void select_tab(Tab* tab); @@ -232,7 +232,8 @@ public: PrintHostQueueDialog* printhost_queue_dlg() { return m_printhost_queue_dlg; } Plater* m_plater { nullptr }; - wxBookCtrlBase* m_tabpanel { nullptr }; + TopBar* m_tmp_top_bar { nullptr }; + TopBar* m_tabpanel { nullptr }; SettingsDialog m_settings_dialog; DiffPresetDialog diff_dialog; wxWindow* m_plater_page{ nullptr }; diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 266604c2f0..71bcecdb12 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -1167,7 +1167,7 @@ wxString OptionsGroup::get_url(const std::string& path_end) bool OptionsGroup::launch_browser(const std::string& path_end) { - return wxGetApp().open_browser_with_warning_dialog(OptionsGroup::get_url(path_end), wxGetApp().mainframe->m_tabpanel); + return wxGetApp().open_browser_with_warning_dialog(OptionsGroup::get_url(path_end), wxGetApp().tab_panel()); } // list of options, which doesn't have a related filed diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 8c74c79356..1dbf81bd66 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -502,15 +502,6 @@ void PreferencesDialog::build() wxGetApp().plater()->get_current_canvas3D()->render(); return; } - if (opt_key == "tabs_as_menu") { - bool disable_new_layout = boost::any_cast(value); - m_rb_new_settings_layout_mode->Show(!disable_new_layout); - if (disable_new_layout && m_rb_new_settings_layout_mode->GetValue()) { - m_rb_new_settings_layout_mode->SetValue(false); - m_rb_old_settings_layout_mode->SetValue(true); - } - refresh_og(m_optgroup_gui); - } if (auto it = m_values.find(opt_key); it != m_values.end()) { m_values.erase(it); // we shouldn't change value, if some of those parameters were selected, and then deselected @@ -564,13 +555,6 @@ void PreferencesDialog::build() L("If enabled, related notification will be shown, when sliced object looks like a logo or a sign."), app_config->get_bool("allow_auto_color_change")); -#ifdef _MSW_DARK_MODE - append_bool_option(m_optgroup_gui, "tabs_as_menu", - L("Set settings tabs as menu items"), - L("If enabled, Settings Tabs will be placed as menu items. If disabled, old UI will be used."), - app_config->get_bool("tabs_as_menu")); -#endif - m_optgroup_gui->append_separator(); /* append_bool_option(m_optgroup_gui, "suppress_round_corners", @@ -766,7 +750,7 @@ void PreferencesDialog::accept(wxEvent&) #endif //(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION) } - std::vector options_to_recreate_GUI = { "no_defaults", "tabs_as_menu", "sys_menu_enabled", "font_pt_size", "suppress_round_corners" }; + std::vector options_to_recreate_GUI = { "no_defaults", "sys_menu_enabled", "font_pt_size", "suppress_round_corners" }; for (const std::string& option : options_to_recreate_GUI) { if (m_values.find(option) != m_values.end()) { @@ -797,7 +781,6 @@ void PreferencesDialog::accept(wxEvent&) m_settings_layout_changed = false; for (const std::string& key : { "old_settings_layout_mode", - "new_settings_layout_mode", "dlg_settings_layout_mode" }) { auto it = m_values.find(key); @@ -875,11 +858,6 @@ void PreferencesDialog::revert(wxEvent&) m_settings_layout_changed = false; continue; } - if (key == "new_settings_layout_mode") { - m_rb_new_settings_layout_mode->SetValue(app_config->get_bool(key)); - m_settings_layout_changed = false; - continue; - } if (key == "dlg_settings_layout_mode") { m_rb_dlg_settings_layout_mode->SetValue(app_config->get_bool(key)); m_settings_layout_changed = false; @@ -897,11 +875,6 @@ void PreferencesDialog::revert(wxEvent&) if (opt_group->set_value(key, app_config->get_bool(key))) break; } - if (key == "tabs_as_menu") { - m_rb_new_settings_layout_mode->Show(!app_config->get_bool(key)); - refresh_og(m_optgroup_gui); - continue; - } } clear_cache(); @@ -1026,7 +999,6 @@ void PreferencesDialog::create_settings_mode_widget() auto app_config = get_app_config(); std::vector choices = { _L("Old regular layout with the tab bar"), - _L("New layout, access via settings button in the top menu"), _L("Settings in non-modal window") }; int id = -1; auto add_radio = [this, parent, stb_sizer, choices](wxRadioButton** rb, int id, bool select) { @@ -1035,25 +1007,13 @@ void PreferencesDialog::create_settings_mode_widget() (*rb)->SetValue(select); (*rb)->Bind(wxEVT_RADIOBUTTON, [this, id](wxCommandEvent&) { m_values["old_settings_layout_mode"] = (id == 0) ? "1" : "0"; - m_values["new_settings_layout_mode"] = (id == 1) ? "1" : "0"; - m_values["dlg_settings_layout_mode"] = (id == 2) ? "1" : "0"; + m_values["dlg_settings_layout_mode"] = (id == 1) ? "1" : "0"; }); }; add_radio(&m_rb_old_settings_layout_mode, ++id, app_config->get_bool("old_settings_layout_mode")); - add_radio(&m_rb_new_settings_layout_mode, ++id, app_config->get_bool("new_settings_layout_mode")); add_radio(&m_rb_dlg_settings_layout_mode, ++id, app_config->get_bool("dlg_settings_layout_mode")); -#ifdef _MSW_DARK_MODE - if (app_config->get_bool("tabs_as_menu")) { - m_rb_new_settings_layout_mode->Hide(); - if (m_rb_new_settings_layout_mode->GetValue()) { - m_rb_new_settings_layout_mode->SetValue(false); - m_rb_old_settings_layout_mode->SetValue(true); - } - } -#endif - std::string opt_key = "settings_layout_mode"; m_blinkers[opt_key] = new BlinkingBitmap(parent); diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index f352a7b02f..6f97063bbb 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -57,7 +57,6 @@ class PreferencesDialog : public DPIDialog wxSizer* m_icon_size_sizer {nullptr}; wxSlider* m_icon_size_slider {nullptr}; wxRadioButton* m_rb_old_settings_layout_mode {nullptr}; - wxRadioButton* m_rb_new_settings_layout_mode {nullptr}; wxRadioButton* m_rb_dlg_settings_layout_mode {nullptr}; wxColourPickerCtrl* m_sys_colour {nullptr}; diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index a35388a88a..d92f5cf2eb 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -441,11 +441,25 @@ static bool has_focus(wxWindow* win) void OptionsSearcher::update_dialog_position() { if (search_dialog) { - search_dialog->CenterOnParent(wxHORIZONTAL); - search_dialog->SetPosition({ search_dialog->GetPosition().x, search_input->GetScreenPosition().y + search_input->GetSize().y }); + wxPoint old_pos = search_dialog->GetPosition(); + wxPoint pos = search_input->GetScreenPosition() + wxPoint(-5, search_input->GetSize().y); + if (old_pos != pos) + search_dialog->SetPosition(pos); } } +void OptionsSearcher::check_and_hide_dialog() +{ + if (search_dialog && search_dialog->IsShown() && !has_focus(search_dialog)) + show_dialog(false); +} + +void OptionsSearcher::set_focus_to_parent() +{ + if (search_input) + search_input->GetParent()->SetFocus(); +} + void OptionsSearcher::show_dialog(bool show /*= true*/) { if (search_dialog && !show) { @@ -455,7 +469,6 @@ void OptionsSearcher::show_dialog(bool show /*= true*/) if (!search_dialog) { search_dialog = new SearchDialog(this, search_input); - update_dialog_position(); search_dialog->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) { @@ -463,14 +476,8 @@ void OptionsSearcher::show_dialog(bool show /*= true*/) show_dialog(false); e.Skip(); }); - - search_input->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) - { - e.Skip(); - if (search_dialog->IsShown() && !has_focus(search_dialog)) - show_dialog(false); - }); } + update_dialog_position(); search_string(); search_input->SetSelection(-1,-1); @@ -492,55 +499,33 @@ void OptionsSearcher::dlg_msw_rescale() search_dialog->msw_rescale(); } +void OptionsSearcher::edit_search_input() +{ + if (!search_input) + return; + + if (search_dialog) { + search_dialog->input_text(search_input->GetValue()); + if (!search_dialog->IsShown()) + search_dialog->Popup(); + } + else + GUI::wxGetApp().show_search_dialog(); +} + +void OptionsSearcher::process_key_down_from_input(wxKeyEvent& e) +{ + int key = e.GetKeyCode(); + if (key == WXK_ESCAPE) + search_dialog->EndModal(wxID_CLOSE); + else if (search_dialog && (key == WXK_UP || key == WXK_DOWN || key == WXK_NUMPAD_ENTER || key == WXK_RETURN)) + search_dialog->KeyDown(e); +} + void OptionsSearcher::set_search_input(TextInput* input_ctrl) { search_input = input_ctrl; - - search_input->Bind(wxEVT_TEXT, [this](wxEvent& e) - { - if (search_dialog) { - search_dialog->input_text(search_input->GetValue()); - if (!search_dialog->IsShown()) - search_dialog->Popup(); - } - else - GUI::wxGetApp().show_search_dialog(); - }); - - wxTextCtrl* ctrl = search_input->GetTextCtrl(); - ctrl->SetToolTip(GUI::format_wxstr(_L("Search in settings [%1%]"), "Ctrl+F")); - - ctrl->Bind(wxEVT_KEY_DOWN, [this](wxKeyEvent& e) - { - int key = e.GetKeyCode(); - if (key == WXK_TAB) - search_input->Navigate(e.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); - else if (key == WXK_ESCAPE) - search_dialog->EndModal(wxID_CLOSE); - else if (search_dialog && (key == WXK_UP || key == WXK_DOWN || key == WXK_NUMPAD_ENTER || key == WXK_RETURN)) - search_dialog->KeyDown(e); - e.Skip(); - }); - - ctrl->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent& event) - { - if (search_input->GetValue() == default_string) - search_input->SetValue(""); - event.Skip(); - }); - - ctrl->Bind(wxEVT_LEFT_DOWN, [](wxMouseEvent& event) { - GUI::wxGetApp().show_search_dialog(); - event.Skip(); - }); - - search_input->Bind(wxEVT_MOVE, [this](wxMoveEvent& event) - { - event.Skip(); - update_dialog_position(); - }); - - search_input->SetOnDropDownIcon([](){ GUI::wxGetApp().show_search_dialog(); }); + update_dialog_position(); } void OptionsSearcher::add_key(const std::string& opt_key, Preset::Type type, const wxString& group, const wxString& category) @@ -707,7 +692,7 @@ void SearchDialog::OnKeyDown(wxKeyEvent& event) if (key == WXK_UP || key == WXK_DOWN) { // So, for the next correct navigation, set focus on the search_list - search_list->SetFocus(); + // search_list->SetFocus(); // #ys_delete_after_test -> Looks like no need anymore auto item = search_list->GetSelection(); diff --git a/src/slic3r/GUI/Search.hpp b/src/slic3r/GUI/Search.hpp index 87187247f3..ffa34de2be 100644 --- a/src/slic3r/GUI/Search.hpp +++ b/src/slic3r/GUI/Search.hpp @@ -148,6 +148,10 @@ public: void sort_options_by_label() { sort_options(); } void update_dialog_position(); + void edit_search_input(); + void process_key_down_from_input(wxKeyEvent& e); + void check_and_hide_dialog(); + void set_focus_to_parent(); void show_dialog(bool show = true); void dlg_sys_color_changed(); void dlg_msw_rescale(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 42a1329c58..3ddb44e9ac 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3658,13 +3658,7 @@ void Tab::load_current_preset() } if (tab->supports_printer_technology(printer_technology)) { -#ifdef _WIN32 - if (wxGetApp().tabs_as_menu()) - wxGetApp().tab_panel()->InsertPage(wxGetApp().tab_panel()->FindPage(this), tab, tab->title()); - else -#endif - dynamic_cast(wxGetApp().tab_panel())->InsertNewPage(wxGetApp().tab_panel()->FindPage(this), tab, tab->title(),""); - + dynamic_cast(wxGetApp().tab_panel())->InsertNewPage(wxGetApp().tab_panel()->FindPage(this), tab, tab->title(),""); } else { int page_id = wxGetApp().tab_panel()->FindPage(tab); diff --git a/src/slic3r/GUI/TopBar.cpp b/src/slic3r/GUI/TopBar.cpp index 6b1d00c32a..2268676f85 100644 --- a/src/slic3r/GUI/TopBar.cpp +++ b/src/slic3r/GUI/TopBar.cpp @@ -1,10 +1,11 @@ #include "TopBar.hpp" +#include "TopBarMenus.hpp" #include "GUI_App.hpp" +#include "MainFrame.hpp" #include "Plater.hpp" #include "Search.hpp" #include "UserAccount.hpp" -//#include "wxExtensions.hpp" #include "format.hpp" #include "I18N.hpp" @@ -34,21 +35,18 @@ TopBarItemsCtrl::Button::Button(wxWindow* parent, const wxString& label, const s { int btn_margin = em_unit(this); int x, y; - GetTextExtent(label, &x, &y); + GetTextExtent(label.IsEmpty() ? "a" : label, &x, &y); wxSize size(x + 4 * btn_margin, y + int(1.5 * btn_margin)); if (icon_name.empty()) this->SetMinSize(size); -#ifdef _WIN32 else if (label.IsEmpty()) { - const int btn_side = px_cnt + btn_margin; + const int btn_side = size.y; this->SetMinSize(wxSize(btn_side, btn_side)); } else +#ifdef _WIN32 this->SetMinSize(wxSize(-1, size.y)); #else - else if (label.IsEmpty()) - this->SetMinSize(wxSize(px_cnt, px_cnt)); - else this->SetMinSize(wxSize(size.x + px_cnt, size.y)); #endif @@ -130,9 +128,11 @@ void TopBarItemsCtrl::Button::render() wxPoint pt = { 0, 0 }; + wxString text = GetLabelText(); + if (m_bmp_bundle.IsOk()) { wxSize szIcon = get_preferred_size(m_bmp_bundle, this); - pt.x = em; + pt.x = text.IsEmpty() ? ((rc.width - szIcon.x) / 2) : em; pt.y = (rc.height - szIcon.y) / 2; #ifdef __WXGTK3__ dc.DrawBitmap(m_bmp_bundle.GetBitmap(szIcon), pt); @@ -144,7 +144,6 @@ void TopBarItemsCtrl::Button::render() // Draw text - wxString text = GetLabelText(); if (!text.IsEmpty()) { wxSize labelSize = dc.GetTextExtent(text); if (labelSize.x > rc.width) @@ -185,18 +184,35 @@ void TopBarItemsCtrl::ButtonWithPopup::SetLabel(const wxString& label) wxString text = label; int btn_height = GetMinSize().GetHeight(); + if (label.IsEmpty()) { + ScalableButton::SetLabel(label); + SetMinSize(wxSize(btn_height, btn_height)); + return; + } + + const int label_width = GetTextExtent(text).GetWidth(); bool resize_and_layout{ false }; if (m_fixed_width != wxDefaultCoord) { const int text_width = m_fixed_width - 2 * btn_height; - const int label_width = GetTextExtent(text).GetWidth(); - if (label_width > text_width) { + if (label_width > text_width || GetMinSize().GetWidth() <= btn_height) { wxWindowDC wdc(this); text = wxControl::Ellipsize(text, wdc, wxELLIPSIZE_END, text_width); resize_and_layout = true; } } + else if (GetMinSize().GetWidth() <= btn_height) +#ifdef _WIN32 + this->SetMinSize(wxSize(-1, btn_height)); +#elif __APPLE__ + this->SetMinSize(wxSize(label_width + 3 * btn_height, btn_height)); +#else + this->SetMinSize(wxSize(label_width + 2 * btn_height, btn_height)); +#endif - wxString full_label = " " + text + " " + down_arrow; + wxString full_label = " " + text + " "; +#ifndef __linux__ + full_label += down_arrow; +#endif ScalableButton::SetLabel(full_label); if (resize_and_layout) { SetMinSize(wxSize(m_fixed_width, btn_height)); @@ -204,81 +220,11 @@ void TopBarItemsCtrl::ButtonWithPopup::SetLabel(const wxString& label) } } -static wxString get_workspace_name(Slic3r::ConfigOptionMode mode) -{ - return mode == Slic3r::ConfigOptionMode::comSimple ? _L("Beginner mode") : - mode == Slic3r::ConfigOptionMode::comAdvanced ? _L("Normal mode") : _L("Expert mode"); -} - -void TopBarItemsCtrl::ApplyWorkspacesMenu() -{ - wxMenuItemList& items = m_workspaces_menu.GetMenuItems(); - if (!items.IsEmpty()) { - for (int id = int(m_workspaces_menu.GetMenuItemCount()) - 1; id >= 0; id--) - m_workspaces_menu.Destroy(items[id]); - } - - for (const Slic3r::ConfigOptionMode& mode : { Slic3r::ConfigOptionMode::comSimple, - Slic3r::ConfigOptionMode::comAdvanced, - Slic3r::ConfigOptionMode::comExpert }) { - const wxString label = get_workspace_name(mode); - append_menu_item(&m_workspaces_menu, wxID_ANY, label, label, - [mode](wxCommandEvent&) { - if (wxGetApp().get_mode() != mode) - wxGetApp().save_mode(mode); - }, get_bmp_bundle("mode", 16, -1, wxGetApp().get_mode_btn_color(mode))); - - if (mode < Slic3r::ConfigOptionMode::comExpert) - m_workspaces_menu.AppendSeparator(); - } -} - -void TopBarItemsCtrl::CreateAccountMenu() -{ - m_user_menu_item = append_menu_item(&m_account_menu, wxID_ANY, "", "", - [this](wxCommandEvent& e) { - m_account_btn->set_selected(true); - wxGetApp().plater()->PopupMenu(&m_account_menu, m_account_btn->GetPosition()); - }, get_bmp_bundle("user", 16)); - - m_account_menu.AppendSeparator(); - -#if 0 - m_connect_dummy_menu_item = append_menu_item(&m_account_menu, wxID_ANY, _L("PrusaConnect Printers"), "", - [](wxCommandEvent&) { wxGetApp().plater()->get_user_account()->enqueue_connect_printers_action(); }, - "", nullptr, []() { return wxGetApp().plater()->get_user_account()->is_logged(); }, this->GetParent()); - - wxMenuItem* remember_me_menu_item = append_menu_check_item(&m_account_menu, wxID_ANY, _L("Remember me"), "" - , [](wxCommandEvent&) { wxGetApp().plater()->get_user_account()->toggle_remember_session(); } - , &m_account_menu - , []() { return wxGetApp().plater()->get_user_account() ? wxGetApp().plater()->get_user_account()->is_logged() : false; } - , []() { return wxGetApp().plater()->get_user_account() ? wxGetApp().plater()->get_user_account()->get_remember_session() : false; } - , this->GetParent()); -#endif // 0 - - m_login_menu_item = append_menu_item(&m_account_menu, wxID_ANY, "", "", - [](wxCommandEvent&) { - auto user_account = wxGetApp().plater()->get_user_account(); - if (user_account->is_logged()) - user_account->do_logout(); - else - user_account->do_login(); - }, get_bmp_bundle("login", 16)); -} - -void TopBarItemsCtrl::UpdateAccountMenu(bool avatar/* = false*/) +void TopBarItemsCtrl::UpdateAccountButton(bool avatar/* = false*/) { auto user_account = wxGetApp().plater()->get_user_account(); - if (m_login_menu_item) { - m_login_menu_item->SetItemLabel(user_account->is_logged() ? _L("Prusa Account Log out") : _L("Prusa Account Log in")); - m_login_menu_item->SetBitmap(user_account->is_logged() ? *get_bmp_bundle("logout", 16) : *get_bmp_bundle("login", 16)); - } - - const wxString user_name = user_account->is_logged() ? from_u8(user_account->get_username()) : _L("Anonymous"); - if (m_user_menu_item) - m_user_menu_item->SetItemLabel(user_name); - - m_account_btn->SetLabel(user_name); + const wxString user_name = user_account->is_logged() ? from_u8(user_account->get_username()) : _L("Anonymous"); + m_account_btn->SetLabel(m_collapsed_btns ? "" : user_name); #ifdef __linux__ if (avatar) { if (user_account->is_logged()) { @@ -311,6 +257,14 @@ void TopBarItemsCtrl::UpdateAccountMenu(bool avatar/* = false*/) m_account_btn->Refresh(); } +void TopBarItemsCtrl::UnselectPopupButtons() +{ + if (m_menu_btn) + m_menu_btn ->set_selected(false); + m_workspace_btn ->set_selected(false); + m_account_btn ->set_selected(false); +} + void TopBarItemsCtrl::CreateSearch() { // Linux specific: If wxDefaultSize is used in constructor and than set just maxSize, @@ -319,7 +273,105 @@ void TopBarItemsCtrl::CreateSearch() m_search = new ::TextInput(this, wxGetApp().searcher().default_string, "", "search", wxDefaultPosition, wxSize(2 * em_unit(this), -1), wxTE_PROCESS_ENTER); m_search->SetMaxSize(wxSize(42*em_unit(this), -1)); wxGetApp().UpdateDarkUI(m_search); - wxGetApp().searcher().set_search_input(m_search); + + m_search->Bind(wxEVT_TEXT, [](wxEvent& e) + { + wxGetApp().searcher().edit_search_input(); + wxGetApp().update_search_lines(); + }); + + m_search->Bind(wxEVT_MOVE, [](wxMoveEvent& event) + { + event.Skip(); + wxGetApp().searcher().update_dialog_position(); + }); + + m_search->SetOnDropDownIcon([this]() + { + wxGetApp().searcher().set_search_input(m_search); + wxGetApp().show_search_dialog(); + }); + + m_search->Bind(wxEVT_KILL_FOCUS, [](wxFocusEvent& e) + { + e.Skip(); + wxGetApp().searcher().check_and_hide_dialog(); + }); + + wxTextCtrl* ctrl = m_search->GetTextCtrl(); + ctrl->SetToolTip(format_wxstr(_L("Search in settings [%1%]"), "Ctrl+F")); + + ctrl->Bind(wxEVT_KEY_DOWN, [this](wxKeyEvent& e) + { + wxGetApp().searcher().set_search_input(m_search); + if (e.GetKeyCode() == WXK_TAB) + m_search->Navigate(e.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); + else + wxGetApp().searcher().process_key_down_from_input(e); + e.Skip(); + }); + + ctrl->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& event) + { + wxGetApp().searcher().set_search_input(m_search); + wxGetApp().show_search_dialog(); + event.Skip(); + }); + + ctrl->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent& event) + { + if (m_search->GetValue() == wxGetApp().searcher().default_string) + m_search->SetValue(""); + event.Skip(); + }); +} + +void TopBarItemsCtrl::UpdateSearchSizeAndPosition() +{ + if (!m_workspace_btn || !m_account_btn) + return; + + int em = em_unit(this); + + int btns_width = 2 * m_btn_margin; + if (m_menu_btn) + btns_width += m_menu_btn->GetSize().GetWidth(); + else + btns_width += 4 * em; + + if (m_settings_btn) + btns_width += m_settings_btn->GetSize().GetWidth() + m_btn_margin; + else { + for (const Button* btn : m_pageButtons) + btns_width += btn->GetSize().GetWidth() + m_btn_margin; + } + + wxWindow* parent_win = GetParent()->GetParent(); + int top_win_without_sidebar = parent_win->GetSize().GetWidth() - 42 * em; + + bool update_bnts{ false }; + if (top_win_without_sidebar - btns_width < 15 * em) { + if (!m_collapsed_btns) { + m_sizer->SetItemMinSize(1, wxSize(20, -1)); + m_collapsed_btns = update_bnts = true; + } + } + else if (m_collapsed_btns) { + m_sizer->SetItemMinSize(1, wxSize(42 * em, -1)); + m_collapsed_btns = false; + update_bnts = true; + } + + if (update_bnts) { + UpdateMode(); + UpdateAccountButton(); + } +} + +void TopBarItemsCtrl::UpdateSearch(const wxString& search) +{ + if (search != m_search->GetValue()) + m_search->SetValue(search); } void TopBarItemsCtrl::update_margins() @@ -332,12 +384,13 @@ void TopBarItemsCtrl::update_margins() wxPoint TopBarItemsCtrl::ButtonWithPopup::get_popup_pos() { wxPoint pos = this->GetPosition(); - pos.y = -pos.y + int(0.2 * wxGetApp().em_unit()); + pos.y += this->GetSize().GetHeight() + int(0.2 * wxGetApp().em_unit()); return pos; } -TopBarItemsCtrl::TopBarItemsCtrl(wxWindow *parent) : +TopBarItemsCtrl::TopBarItemsCtrl(wxWindow *parent, TopBarMenus* menus/* = nullptr*/, bool is_main/* = true*/) : wxControl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE | wxTAB_TRAVERSAL) + ,m_menus(menus) { #ifdef __WINDOWS__ SetDoubleBuffered(true); @@ -360,57 +413,61 @@ TopBarItemsCtrl::TopBarItemsCtrl(wxWindow *parent) : m_menu_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) { m_menu_btn->set_selected(true); - // !!! To popup main menu use native wxPanel::PopupMenu() function - // Don't use wrap function Plater::PopupMenu(), because it's no need in this case - wxGetApp().plater()->wxPanel::PopupMenu(&m_main_menu, m_menu_btn->get_popup_pos()); + m_menus->Popup(this, &m_menus->main, m_menu_btn->get_popup_pos()); }); - m_main_menu.Bind(wxEVT_MENU_CLOSE, [this](wxMenuEvent&) { m_menu_btn->set_selected(false); }); #endif + if (!is_main) { + m_settings_btn = new Button(this, _L("Settings"/*, "settings"*/)); + m_settings_btn->Bind(wxEVT_BUTTON, [](wxCommandEvent& event) { + wxGetApp().mainframe->select_tab(); + }); + left_sizer->Add(m_settings_btn, 0, wxALIGN_CENTER_VERTICAL); + } + m_buttons_sizer = new wxFlexGridSizer(1, m_btn_margin, m_btn_margin); - left_sizer->Add(m_buttons_sizer, 0, wxALIGN_CENTER_VERTICAL/* | wxLEFT*/ | wxRIGHT, 2 * m_btn_margin); + left_sizer->Add(m_buttons_sizer, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, m_btn_margin); CreateSearch(); + if (!is_main) + wxGetApp().searcher().set_search_input(m_search); wxBoxSizer* search_sizer = new wxBoxSizer(wxVERTICAL); search_sizer->Add(m_search, 1, wxEXPAND | wxALIGN_RIGHT); - left_sizer->Add(search_sizer, 1, wxALIGN_CENTER_VERTICAL); + left_sizer->Add(search_sizer, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, m_btn_margin); m_sizer->Add(left_sizer, 1, wxEXPAND); wxBoxSizer* right_sizer = new wxBoxSizer(wxHORIZONTAL); - // create modes menu - ApplyWorkspacesMenu(); - m_workspace_btn = new ButtonWithPopup(this, _L("Workspace"), "mode_simple"); right_sizer->AddStretchSpacer(20); - right_sizer->Add(m_workspace_btn, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT); + right_sizer->Add(m_workspace_btn, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, m_btn_margin); m_workspace_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) { m_workspace_btn->set_selected(true); - wxGetApp().plater()->wxPanel::PopupMenu(&m_workspaces_menu, m_workspace_btn->get_popup_pos()); + m_menus->Popup(this, &m_menus->workspaces, m_workspace_btn->get_popup_pos()); }); - m_workspaces_menu.Bind(wxEVT_MENU_CLOSE, [this](wxMenuEvent&) { m_workspace_btn->set_selected(false); }); - - // create Account menu - CreateAccountMenu(); m_account_btn = new ButtonWithPopup(this, _L("Anonymous"), "user", wxSize(18 * em_unit(this), -1)); - right_sizer->Add(m_account_btn, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxRIGHT | wxLEFT, m_btn_margin); + right_sizer->Add(m_account_btn, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxRIGHT, m_btn_margin); m_account_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) { - UpdateAccountMenu(); m_account_btn->set_selected(true); - wxGetApp().plater()->wxPanel::PopupMenu(&m_account_menu, m_account_btn->get_popup_pos()); - }); - m_account_menu.Bind(wxEVT_MENU_CLOSE, [this](wxMenuEvent&) { m_account_btn->set_selected(false); }); + m_menus->Popup(this, &m_menus->account, m_account_btn->get_popup_pos()); + }); m_sizer->Add(right_sizer, 0, wxALIGN_CENTER_VERTICAL); m_sizer->SetItemMinSize(1, wxSize(42 * wxGetApp().em_unit(), -1)); this->Bind(wxEVT_PAINT, &TopBarItemsCtrl::OnPaint, this); + + this->Bind(wxEVT_UPDATE_UI, [](wxUpdateUIEvent& evt) { + auto user_account = wxGetApp().plater()->get_user_account(); + evt.Enable(user_account ? user_account->is_logged() : false); + evt.Check (user_account ? user_account->get_remember_session() : false); + }, m_menus->remember_me_item_id); } void TopBarItemsCtrl::OnPaint(wxPaintEvent&) @@ -432,7 +489,7 @@ void TopBarItemsCtrl::UpdateMode() m_workspace_btn->SetBitmapBundle(bmp); #endif - m_workspace_btn->SetLabel(get_workspace_name(mode)); + m_workspace_btn->SetLabel(m_collapsed_btns ? "" : m_menus->get_workspace_name(mode)); this->Layout(); } @@ -450,6 +507,7 @@ void TopBarItemsCtrl::Rescale() m_buttons_sizer->SetVGap(m_btn_margin); m_buttons_sizer->SetHGap(m_btn_margin); + UpdateSearchSizeAndPosition(); m_sizer->Layout(); } @@ -458,6 +516,8 @@ void TopBarItemsCtrl::OnColorsChanged() wxGetApp().UpdateDarkUI(this); if (m_menu_btn) m_menu_btn->sys_color_changed(); + if (m_settings_btn) + m_settings_btn->sys_color_changed(); m_workspace_btn->sys_color_changed(); m_account_btn->sys_color_changed(); @@ -472,7 +532,7 @@ void TopBarItemsCtrl::OnColorsChanged() void TopBarItemsCtrl::UpdateModeMarkers() { UpdateMode(); - ApplyWorkspacesMenu(); + m_menus->ApplyWorkspacesMenu(); } void TopBarItemsCtrl::UpdateSelection() @@ -486,9 +546,9 @@ void TopBarItemsCtrl::UpdateSelection() Refresh(); } -void TopBarItemsCtrl::SetSelection(int sel) +void TopBarItemsCtrl::SetSelection(int sel, bool force /*= false*/) { - if (m_selection == sel) + if (m_selection == sel && !force) return; m_selection = sel; UpdateSelection(); @@ -510,6 +570,8 @@ bool TopBarItemsCtrl::InsertPage(size_t n, const wxString& text, bool bSelect/* m_pageButtons.insert(m_pageButtons.begin() + n, btn); m_buttons_sizer->Insert(n, new wxSizerItem(btn, 0, wxALIGN_CENTER_VERTICAL)); m_buttons_sizer->SetCols(m_buttons_sizer->GetCols() + 1); + + UpdateSearchSizeAndPosition(); m_sizer->Layout(); return true; } @@ -523,6 +585,8 @@ void TopBarItemsCtrl::RemovePage(size_t n) // Under OSX call of btn->Reparent(nullptr) causes a crash, so as a workaround use RemoveChild() instead this->RemoveChild(btn); btn->Destroy(); + + UpdateSearchSizeAndPosition(); m_sizer->Layout(); } @@ -530,6 +594,7 @@ void TopBarItemsCtrl::SetPageText(size_t n, const wxString& strText) { ScalableButton* btn = m_pageButtons[n]; btn->SetLabel(strText); + UpdateSearchSizeAndPosition(); } wxString TopBarItemsCtrl::GetPageText(size_t n) const @@ -538,12 +603,35 @@ wxString TopBarItemsCtrl::GetPageText(size_t n) const return btn->GetLabel(); } -void TopBarItemsCtrl::AppendMenuItem(wxMenu* menu, const wxString& title) +void TopBarItemsCtrl::ShowFull() { - append_submenu(&m_main_menu, menu, wxID_ANY, title, "cog"); + if (m_menu_btn) + m_menu_btn->Show(); + if (m_settings_btn) + m_settings_btn->Show(); + m_account_btn->Show(); + m_menus->set_cb_on_user_item([this]() { + m_account_btn->set_selected(true); + m_menus->Popup(this, &m_menus->account, m_account_btn->get_popup_pos()); + }); + + UpdateSearchSizeAndPosition(); } -void TopBarItemsCtrl::AppendMenuSeparaorItem() +void TopBarItemsCtrl::ShowJustMode() { - m_main_menu.AppendSeparator(); + if (m_menu_btn) + m_menu_btn->Hide(); + if (m_settings_btn) + m_settings_btn->Hide(); + m_account_btn->Hide(); + m_menus->set_cb_on_user_item(nullptr); + + UpdateSearchSizeAndPosition(); +} + +void TopBarItemsCtrl::SetSettingsButtonTooltip(const wxString& tooltip) +{ + if (m_settings_btn) + m_settings_btn->SetToolTip(tooltip); } diff --git a/src/slic3r/GUI/TopBar.hpp b/src/slic3r/GUI/TopBar.hpp index 3e858525f6..bb79cf542e 100644 --- a/src/slic3r/GUI/TopBar.hpp +++ b/src/slic3r/GUI/TopBar.hpp @@ -1,14 +1,11 @@ #ifndef slic3r_TopBar_hpp_ #define slic3r_TopBar_hpp_ -//#ifdef _WIN32 - #include #include "wxExtensions.hpp" #include "Widgets/TextInput.hpp" -class ModeSizer; -//class ScalableButton; +class TopBarMenus; // custom message the TopBarItemsCtrl sends to its parent (TopBar) to notify a selection change: wxDECLARE_EVENT(wxCUSTOMEVT_TOPBAR_SEL_CHANGED, wxCommandEvent); @@ -60,24 +57,20 @@ class TopBarItemsCtrl : public wxControl wxPoint get_popup_pos(); }; - wxMenu m_main_menu; - wxMenu m_workspaces_menu; - wxMenu m_account_menu; - // Prusa Account menu items - wxMenuItem* m_user_menu_item{ nullptr }; - wxMenuItem* m_login_menu_item{ nullptr }; -#if 0 - wxMenuItem* m_connect_dummy_menu_item{ nullptr }; -#endif // 0 + TopBarMenus* m_menus{ nullptr }; ::TextInput* m_search{ nullptr }; + bool m_collapsed_btns{ false }; + public: - TopBarItemsCtrl(wxWindow* parent); + TopBarItemsCtrl(wxWindow* parent, + TopBarMenus* menus = nullptr, + bool is_main = true); ~TopBarItemsCtrl() {} void OnPaint(wxPaintEvent&); - void SetSelection(int sel); + void SetSelection(int sel, bool force = false); void UpdateMode(); void Rescale(); void OnColorsChanged(); @@ -88,21 +81,25 @@ public: void SetPageText(size_t n, const wxString& strText); wxString GetPageText(size_t n) const; - void AppendMenuItem(wxMenu* menu, const wxString& title); - void AppendMenuSeparaorItem(); - void ApplyWorkspacesMenu(); - void CreateAccountMenu(); - void UpdateAccountMenu(bool avatar = false); + void UpdateAccountButton(bool avatar = false); + void UnselectPopupButtons(); + void CreateSearch(); + void ShowFull(); + void ShowJustMode(); + void SetSettingsButtonTooltip(const wxString& tooltip); + void UpdateSearchSizeAndPosition(); + void UpdateSearch(const wxString& search); wxWindow* GetSearchCtrl() { return m_search->GetTextCtrl(); } private: wxFlexGridSizer* m_buttons_sizer; wxFlexGridSizer* m_sizer; - ButtonWithPopup* m_menu_btn {nullptr}; + ButtonWithPopup* m_menu_btn {nullptr}; ButtonWithPopup* m_workspace_btn {nullptr}; - ButtonWithPopup* m_account_btn {nullptr}; + ButtonWithPopup* m_account_btn {nullptr}; + Button* m_settings_btn {nullptr}; std::vector m_pageButtons; int m_selection {-1}; int m_btn_margin; @@ -124,16 +121,28 @@ public: Create(parent, winid, pos, size, style); } + TopBar( wxWindow * parent, + TopBarMenus* menus, + bool is_main = true) + { + Init(); + // wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on Windows 10 + // with multiple high resolution displays connected. + Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME, menus, is_main); + } + bool Create(wxWindow * parent, wxWindowID winid = wxID_ANY, const wxPoint & pos = wxDefaultPosition, const wxSize & size = wxDefaultSize, - long style = 0) + long style = 0, + TopBarMenus* menus = nullptr, + bool is_main = true) { if (!wxBookCtrlBase::Create(parent, winid, pos, size, style | wxBK_TOP)) return false; - m_bookctrl = new TopBarItemsCtrl(this); + m_bookctrl = new TopBarItemsCtrl(this, menus, is_main); wxSizer* mainSizer = new wxBoxSizer(IsVertical() ? wxVERTICAL : wxHORIZONTAL); @@ -250,7 +259,7 @@ public: virtual int SetSelection(size_t n) override { - GetTopBarItemsCtrl()->SetSelection(n); + GetTopBarItemsCtrl()->SetSelection(n, true); int ret = DoSetSelection(n, SetSelection_SendEvent); // check that only the selected page is visible and others are hidden: @@ -258,6 +267,9 @@ public: if (page != n) m_pages[page]->Hide(); + if (!m_pages[n]->IsShown()) + m_pages[n]->Show(); + return ret; } @@ -418,12 +430,26 @@ public: // Methods for extensions of this class - void AppendMenuItem(wxMenu* menu, const wxString& title) { - GetTopBarItemsCtrl()->AppendMenuItem(menu, title); + void ShowFull() { + Show(); + GetTopBarItemsCtrl()->ShowFull(); } - void AppendMenuSeparaorItem() { - GetTopBarItemsCtrl()->AppendMenuSeparaorItem(); + void ShowJustMode() { + Show(); + GetTopBarItemsCtrl()->ShowJustMode(); + } + + void SetSettingsButtonTooltip(const wxString& tooltip) { + GetTopBarItemsCtrl()->SetSettingsButtonTooltip(tooltip); + } + + void UpdateSearchSizeAndPosition() { + GetTopBarItemsCtrl()->UpdateSearchSizeAndPosition(); + } + + void UpdateSearch(const wxString& search) { + GetTopBarItemsCtrl()->UpdateSearch(search); } protected: diff --git a/src/slic3r/GUI/TopBarMenus.cpp b/src/slic3r/GUI/TopBarMenus.cpp new file mode 100644 index 0000000000..b84da244c7 --- /dev/null +++ b/src/slic3r/GUI/TopBarMenus.cpp @@ -0,0 +1,111 @@ +#include "TopBarMenus.hpp" +#include "TopBar.hpp" + +#include "GUI_App.hpp" +#include "Plater.hpp" +#include "UserAccount.hpp" + +#include "I18N.hpp" + +using namespace Slic3r::GUI; + +TopBarMenus::TopBarMenus() +{ + CreateAccountMenu(); + ApplyWorkspacesMenu(); + UpdateAccountMenu(); + + BindEvtClose(); +} + +void TopBarMenus::AppendMenuItem(wxMenu* menu, const wxString& title) +{ + append_submenu(&main, menu, wxID_ANY, title, "cog"); +} + +void TopBarMenus::AppendMenuSeparaorItem() +{ + main.AppendSeparator(); +} + +wxString TopBarMenus::get_workspace_name(const int mode) +{ + return mode == Slic3r::ConfigOptionMode::comSimple ? _L("Beginner mode") : + mode == Slic3r::ConfigOptionMode::comAdvanced ? _L("Normal mode") : _L("Expert mode"); +} + +void TopBarMenus::ApplyWorkspacesMenu() +{ + wxMenuItemList& items = workspaces.GetMenuItems(); + if (!items.IsEmpty()) { + for (int id = int(workspaces.GetMenuItemCount()) - 1; id >= 0; id--) + workspaces.Destroy(items[id]); + } + + for (const Slic3r::ConfigOptionMode& mode : { Slic3r::ConfigOptionMode::comSimple, + Slic3r::ConfigOptionMode::comAdvanced, + Slic3r::ConfigOptionMode::comExpert }) { + const wxString label = get_workspace_name(mode); + append_menu_item(&workspaces, wxID_ANY, label, label, + [mode](wxCommandEvent&) { + if (wxGetApp().get_mode() != mode) + wxGetApp().save_mode(mode); + }, get_bmp_bundle("mode", 16, -1, wxGetApp().get_mode_btn_color(mode))); + + if (mode < Slic3r::ConfigOptionMode::comExpert) + workspaces.AppendSeparator(); + } +} + +void TopBarMenus::CreateAccountMenu() +{ + m_user_item = append_menu_item(&account, wxID_ANY, "", "", + [this](wxCommandEvent& e) { if (m_cb_on_user_item) m_cb_on_user_item(); }, get_bmp_bundle("user", 16)); + + account.AppendSeparator(); + + remember_me_item_id = wxWindow::NewControlId(); + append_menu_check_item(&account, remember_me_item_id, _L("Remember me"), "" , + [](wxCommandEvent&) { wxGetApp().plater()->get_user_account()->toggle_remember_session(); } , nullptr); + + m_login_item = append_menu_item(&account, wxID_ANY, "", "", + [](wxCommandEvent&) { + auto user_account = wxGetApp().plater()->get_user_account(); + if (user_account->is_logged()) + user_account->do_logout(); + else + user_account->do_login(); + }, get_bmp_bundle("login", 16)); +} + +void TopBarMenus::UpdateAccountMenu(Slic3r::GUI::UserAccount* user_account) +{ + bool is_logged = user_account && user_account->is_logged(); + if (m_login_item) { + m_login_item->SetItemLabel(is_logged ? _L("Prusa Account Log out") : _L("Prusa Account Log in")); + m_login_item->SetBitmap(is_logged ? *get_bmp_bundle("logout", 16) : *get_bmp_bundle("login", 16)); + } + + const wxString user_name = is_logged ? from_u8(user_account->get_username()) : _L("Anonymous"); + if (m_user_item) + m_user_item->SetItemLabel(user_name); +} + +void TopBarMenus::Popup(TopBarItemsCtrl* popup_ctrl, wxMenu* menu, wxPoint pos) +{ + m_popup_ctrl = popup_ctrl; + m_popup_ctrl->PopupMenu(menu, pos); +} + +void TopBarMenus::BindEvtClose() +{ + auto close_fn = [this]() { + if (m_popup_ctrl) + m_popup_ctrl->UnselectPopupButtons(); + m_popup_ctrl = nullptr; + }; + + main. Bind(wxEVT_MENU_CLOSE, [close_fn](wxMenuEvent&) { close_fn(); }); + workspaces. Bind(wxEVT_MENU_CLOSE, [close_fn](wxMenuEvent&) { close_fn(); }); + account. Bind(wxEVT_MENU_CLOSE, [close_fn](wxMenuEvent&) { close_fn(); }); +} \ No newline at end of file diff --git a/src/slic3r/GUI/TopBarMenus.hpp b/src/slic3r/GUI/TopBarMenus.hpp new file mode 100644 index 0000000000..0a0017b245 --- /dev/null +++ b/src/slic3r/GUI/TopBarMenus.hpp @@ -0,0 +1,48 @@ +#ifndef slic3r_TopBarMenus_hpp_ +#define slic3r_TopBarMenus_hpp_ + +#include + +class TopBarItemsCtrl; +class wxString; + +namespace Slic3r { +namespace GUI { +class UserAccount; +} +} + +class TopBarMenus +{ + // Prusa Account menu items + wxMenuItem* m_user_item { nullptr }; + wxMenuItem* m_login_item { nullptr }; + + TopBarItemsCtrl* m_popup_ctrl { nullptr }; + + std::function m_cb_on_user_item { nullptr }; + +public: + wxMenu main; + wxMenu workspaces; + wxMenu account; + wxWindowID remember_me_item_id { wxID_ANY }; + + TopBarMenus(); + ~TopBarMenus() = default; + + void AppendMenuItem(wxMenu* menu, const wxString& title); + void AppendMenuSeparaorItem(); + void ApplyWorkspacesMenu(); + void CreateAccountMenu(); + void UpdateAccountMenu(Slic3r::GUI::UserAccount* user_account = nullptr); + + void Popup(TopBarItemsCtrl* popup_ctrl, wxMenu* menu, wxPoint pos); + void BindEvtClose(); + + wxString get_workspace_name(const /*ConfigOptionMode*/int mode); + void set_cb_on_user_item (std::function cb) { m_cb_on_user_item = cb; } + +}; + +#endif // slic3r_TopBarMenus_hpp_