From cd5d30d3b1d9c65de120490a85e716ecdef3ac88 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 17 Apr 2024 14:05:38 +0200 Subject: [PATCH] Menus related to the TopBar's buttons are extracted to the separate class. + Updated top bar layout in respect to the mode + Linux specific: Don`t show down arrow for buttons with PopupMenu + MainFrame: Use TopBar instead wxBookCtrlBase --- resources/localization/list.txt | 2 + src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/GUI_App.cpp | 4 +- src/slic3r/GUI/MainFrame.cpp | 73 +++++++++------ src/slic3r/GUI/MainFrame.hpp | 12 ++- src/slic3r/GUI/OptionsGroup.cpp | 2 +- src/slic3r/GUI/TopBar.cpp | 152 ++++++++++---------------------- src/slic3r/GUI/TopBar.hpp | 61 +++++++------ src/slic3r/GUI/TopBarMenus.cpp | 111 +++++++++++++++++++++++ src/slic3r/GUI/TopBarMenus.hpp | 48 ++++++++++ 10 files changed, 303 insertions(+), 164 deletions(-) create mode 100644 src/slic3r/GUI/TopBarMenus.cpp create mode 100644 src/slic3r/GUI/TopBarMenus.hpp 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/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/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index d7c2d2f4cc..d53b4ba503 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 @@ -2474,7 +2475,8 @@ void GUI_App::update_mode() { sidebar().update_mode(); - 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/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 00b92559ff..5bdaa4751b 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" @@ -350,6 +349,7 @@ void MainFrame::update_layout() m_settings_dialog.Close(); m_tabpanel->Hide(); + m_tmp_top_bar->Hide(); m_plater->Hide(); Layout(); @@ -398,11 +398,13 @@ void MainFrame::update_layout() { m_plater->Reparent(m_tabpanel); m_plater->Layout(); - 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) @@ -411,11 +413,20 @@ void MainFrame::update_layout() } 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(); + + 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: @@ -578,9 +589,15 @@ void MainFrame::init_tabpanel() { wxGetApp().update_ui_colours_from_appconfig(); + if (wxGetApp().is_editor()) { + m_tmp_top_bar = new TopBar(this, &m_bar_menus); + 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. - 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(); @@ -721,7 +738,7 @@ void MainFrame::add_connect_webview_tab() 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; } @@ -733,7 +750,7 @@ void MainFrame::remove_connect_webview_tab() // connect tab should always be at position 4 if (m_tabpanel->GetSelection() == 4) m_tabpanel->SetSelection(0); - dynamic_cast(m_tabpanel)->RemovePage(4); + m_tabpanel->RemovePage(4); m_connect_webview_added = false; m_connect_webview->logout(); } @@ -781,7 +798,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(); } @@ -792,7 +809,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) { @@ -822,7 +839,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 /*= ""*/) @@ -832,7 +851,7 @@ 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)) - dynamic_cast(m_tabpanel)->AddNewPage(panel, panel->title(), bmp_name); + m_tabpanel->AddNewPage(panel, panel->title(), bmp_name); } bool MainFrame::is_active_and_shown_tab(Tab* tab) @@ -1013,7 +1032,7 @@ void MainFrame::on_dpi_changed(const wxRect& suggested_rect) #ifdef _WIN32 // update common mode sizer - dynamic_cast(m_tabpanel)->Rescale(); + m_tabpanel->Rescale(); #endif // update Plater @@ -1059,7 +1078,7 @@ void MainFrame::on_sys_color_changed() #ifdef __WXMSW__ wxGetApp().UpdateDarkUI(m_tabpanel); #endif - dynamic_cast(m_tabpanel)->OnColorsChanged(); + m_tabpanel->OnColorsChanged(); // update Plater wxGetApp().plater()->sys_color_changed(); @@ -1083,7 +1102,8 @@ void MainFrame::on_sys_color_changed() void MainFrame::update_mode_markers() { // update markers in common mode sizer - dynamic_cast(m_tabpanel)->UpdateModeMarkers(); + m_tmp_top_bar->UpdateModeMarkers(); + m_tabpanel->UpdateModeMarkers(); // update mode markers in tabs for (auto tab : wxGetApp().tabs_list) @@ -1509,22 +1529,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 @@ -2184,7 +2203,7 @@ void SettingsDialog::on_dpi_changed(const wxRect& suggested_rect) const wxSize& size = wxSize(85 * em, 50 * em); #ifdef _WIN32 - 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 85c08f5b57..de389061f4 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 @@ -228,7 +231,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/TopBar.cpp b/src/slic3r/GUI/TopBar.cpp index 6b1d00c32a..2cd629672f 100644 --- a/src/slic3r/GUI/TopBar.cpp +++ b/src/slic3r/GUI/TopBar.cpp @@ -1,10 +1,10 @@ #include "TopBar.hpp" +#include "TopBarMenus.hpp" #include "GUI_App.hpp" #include "Plater.hpp" #include "Search.hpp" #include "UserAccount.hpp" -//#include "wxExtensions.hpp" #include "format.hpp" #include "I18N.hpp" @@ -196,7 +196,10 @@ void TopBarItemsCtrl::ButtonWithPopup::SetLabel(const wxString& label) } } - 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,80 +207,10 @@ 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); - + const wxString user_name = user_account->is_logged() ? from_u8(user_account->get_username()) : _L("Anonymous"); m_account_btn->SetLabel(user_name); #ifdef __linux__ if (avatar) { @@ -311,6 +244,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, @@ -332,12 +273,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*/) : wxControl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE | wxTAB_TRAVERSAL) + ,m_menus(menus) { #ifdef __WINDOWS__ SetDoubleBuffered(true); @@ -360,57 +302,51 @@ 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 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(); 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); 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 +368,7 @@ void TopBarItemsCtrl::UpdateMode() m_workspace_btn->SetBitmapBundle(bmp); #endif - m_workspace_btn->SetLabel(get_workspace_name(mode)); + m_workspace_btn->SetLabel(m_menus->get_workspace_name(mode)); this->Layout(); } @@ -472,7 +408,7 @@ void TopBarItemsCtrl::OnColorsChanged() void TopBarItemsCtrl::UpdateModeMarkers() { UpdateMode(); - ApplyWorkspacesMenu(); + m_menus->ApplyWorkspacesMenu(); } void TopBarItemsCtrl::UpdateSelection() @@ -486,9 +422,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(); @@ -538,12 +474,22 @@ 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(); + m_account_btn->Show(); + UpdateAccountButton(); + 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()); + }); } -void TopBarItemsCtrl::AppendMenuSeparaorItem() +void TopBarItemsCtrl::ShowJustMode() { - m_main_menu.AppendSeparator(); + if (m_menu_btn) + m_menu_btn->Hide(); + m_account_btn->Hide(); + m_menus->set_cb_on_user_item(nullptr); } diff --git a/src/slic3r/GUI/TopBar.hpp b/src/slic3r/GUI/TopBar.hpp index 3e858525f6..ee0fabf6e5 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,17 @@ 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 }; public: - TopBarItemsCtrl(wxWindow* parent); + TopBarItemsCtrl(wxWindow* parent, + TopBarMenus* menus = nullptr); ~TopBarItemsCtrl() {} void OnPaint(wxPaintEvent&); - void SetSelection(int sel); + void SetSelection(int sel, bool force = false); void UpdateMode(); void Rescale(); void OnColorsChanged(); @@ -88,12 +78,12 @@ 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(); wxWindow* GetSearchCtrl() { return m_search->GetTextCtrl(); } @@ -124,16 +114,26 @@ public: Create(parent, winid, pos, size, style); } + TopBar( wxWindow * parent, + TopBarMenus* menus) + { + 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); + } + 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) { if (!wxBookCtrlBase::Create(parent, winid, pos, size, style | wxBK_TOP)) return false; - m_bookctrl = new TopBarItemsCtrl(this); + m_bookctrl = new TopBarItemsCtrl(this, menus); wxSizer* mainSizer = new wxBoxSizer(IsVertical() ? wxVERTICAL : wxHORIZONTAL); @@ -250,7 +250,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 +258,9 @@ public: if (page != n) m_pages[page]->Hide(); + if (!m_pages[n]->IsShown()) + m_pages[n]->Show(); + return ret; } @@ -418,13 +421,15 @@ 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(); + }; protected: virtual void UpdateSelectedPage(size_t WXUNUSED(newsel)) override 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_