diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index dd300f985e..3d7109799d 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -1733,6 +1733,37 @@ PageVendors::PageVendors(ConfigWizard *parent) auto *cbox = new wxCheckBox(this, wxID_ANY, vendor->name); cbox->Bind(wxEVT_CHECKBOX, [=](wxCommandEvent &event) { + if (cbox->IsChecked()) { + wxString user_presets_list{ wxString() }; + int user_presets_cnt { 0 }; + + // Check if some of preset doesn't exist as a user_preset + // to avoid rewrite those user_presets by new installed system presets + const PresetCollection& presets = wizard_p()->bundles.at(vendor->id).preset_bundle.get()->printers; + for (const Preset& preset : presets) + if (!preset.is_default && boost::filesystem::exists(preset.file)) { + user_presets_list += " * " + from_u8(preset.name) + "\n"; + user_presets_cnt++; + } + + if (!user_presets_list.IsEmpty()) { + wxString message = format_wxstr(_L_PLURAL("Following user preset has a same name as one of added system presets from '%1%' vendor:\n" + "%2%Please note that this user preset will be rewrite by system preset.\n\n" + "Do you still wish to add presets from '%1%'?", + "Following user presets have same names as some of added system presets from '%1%' vendor:\n" + "%2%Please note that these user presets will be rewrite by system presets.\n\n" + "Do you still wish to add presets from '%1%'?", + user_presets_cnt), vendor->name, user_presets_list); + + MessageDialog msg(this->GetParent(), message, _L("Notice"), wxYES_NO); + if (msg.ShowModal() == wxID_NO) { + // uncheck checked ckeckbox + cbox->SetValue(false); + return; + } + } + } + wizard_p()->on_3rdparty_install(vendor, cbox->IsChecked()); }); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 96c9c69f18..ffa9277976 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3707,34 +3707,8 @@ void GUI_App::handle_connect_request_printer_pick(std::string msg) void GUI_App::show_printer_webview_tab() { - //bool show, const DynamicPrintConfig& dpc - - if (DynamicPrintConfig* dpc = preset_bundle->physical_printers.get_selected_printer_config(); dpc == nullptr) { - this->mainframe->select_tab(size_t(0)); - mainframe->remove_printer_webview_tab(); - } else { - std::string url = dpc->opt_string("print_host"); - - if (url.find("http://") != 0 && url.find("https://") != 0) { - url = "http://" + url; - } - - // set password / api key - if (dynamic_cast*>(dpc->option("printhost_authorization_type"))->value == AuthorizationType::atKeyPassword) { - mainframe->set_printer_webview_api_key(dpc->opt_string("printhost_apikey")); - } -#if 0 // The user password authentication is not working in prusa link as of now. - else { - mainframe->set_printer_webview_credentials(dpc->opt_string("printhost_user"), dpc->opt_string("printhost_password")); - } -#endif // 0 - // add printer or change url - if (mainframe->get_printer_webview_tab_added()) { - mainframe->set_printer_webview_tab_url(from_u8(url)); - } else { - mainframe->add_printer_webview_tab(from_u8(url)); - } - } + mainframe->show_printer_webview_tab(preset_bundle->physical_printers.get_selected_printer_config()); } + } // GUI } //Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 9070ecf7f6..68bfc2d9d4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -2639,13 +2639,20 @@ void GLGizmoCut3D::render_snap_specific_input(const std::string& label, const wx } } +static std::string get_string_from_wchar(const wchar_t& icon) +{ + std::wstring tmp; + tmp += icon; + return boost::nowide::narrow(tmp); +} + void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors) { // if (m_mode == size_t(CutMode::cutPlanar)) { CutMode mode = CutMode(m_mode); if (mode == CutMode::cutPlanar || mode == CutMode::cutTongueAndGroove) { ImGui::AlignTextToFramePadding(); - ImGuiPureWrap::text(std::wstring(&ImGui::InfoMarkerSmall)); + ImGuiPureWrap::text(get_string_from_wchar(ImGui::InfoMarkerSmall)); ImGui::SameLine(); ImGuiPureWrap::text_colored(ImGuiPureWrap::COL_ORANGE_LIGHT, into_u8(get_wraped_wxString(_L("Hold SHIFT key to draw a cut line"), 40))); @@ -2901,7 +2908,7 @@ void GLGizmoCut3D::init_input_window_data(CutConnectors &connectors) void GLGizmoCut3D::render_input_window_warning() const { - const std::string warning_marker = boost::nowide::narrow(std::wstring(&ImGui::WarningMarkerSmall)); + const std::string warning_marker = get_string_from_wchar(ImGui::WarningMarkerSmall); if (! m_invalid_connectors_idxs.empty()) { std::string out = warning_marker + _u8L("Invalid connectors detected") + ":"; diff --git a/src/slic3r/GUI/InstanceCheck.cpp b/src/slic3r/GUI/InstanceCheck.cpp index 595b71fd1a..ce96c1c42f 100644 --- a/src/slic3r/GUI/InstanceCheck.cpp +++ b/src/slic3r/GUI/InstanceCheck.cpp @@ -119,11 +119,14 @@ namespace instance_check_internal other_instance_hash_major = PtrToUint(handle); other_instance_hash_major = other_instance_hash_major << 32; other_instance_hash += other_instance_hash_major; + handle = GetProp(hwnd, L"Instance_Is_Maximized"); + const bool maximized = PtrToUint(handle) == 1; + if(my_instance_hash == other_instance_hash) { BOOST_LOG_TRIVIAL(debug) << "win enum - found correct instance"; l_prusa_slicer_hwnd = hwnd; - ShowWindow(hwnd, SW_SHOWMAXIMIZED); + ShowWindow(hwnd, maximized ? SW_SHOWMAXIMIZED : SW_SHOW); SetForegroundWindow(hwnd); return false; } @@ -411,6 +414,7 @@ void OtherInstanceMessageHandler::shutdown(MainFrame* main_frame) HWND hwnd = main_frame->GetHandle(); RemoveProp(hwnd, L"Instance_Hash_Minor"); RemoveProp(hwnd, L"Instance_Hash_Major"); + RemoveProp(hwnd, L"Instance_Is_Maximized"); #endif //_WIN32 #if __APPLE__ //delete macos implementation @@ -440,14 +444,30 @@ void OtherInstanceMessageHandler::init_windows_properties(MainFrame* main_frame, { size_t minor_hash = instance_hash & 0xFFFFFFFF; size_t major_hash = (instance_hash & 0xFFFFFFFF00000000) >> 32; + size_t is_maximized = main_frame->IsMaximized() ? 1 : 0; HWND hwnd = main_frame->GetHandle(); HANDLE handle_minor = UIntToPtr(minor_hash); HANDLE handle_major = UIntToPtr(major_hash); + HANDLE handle_is_maximized = UIntToPtr(is_maximized); SetProp(hwnd, L"Instance_Hash_Minor", handle_minor); SetProp(hwnd, L"Instance_Hash_Major", handle_major); + SetProp(hwnd, L"Instance_Is_Maximized", handle_is_maximized); //BOOST_LOG_TRIVIAL(debug) << "window properties initialized " << instance_hash << " (" << minor_hash << " & "<< major_hash; } +void OtherInstanceMessageHandler::update_windows_properties(MainFrame* main_frame) +{ + if (m_initialized) { + // dlete old value of "Instance_Is_Maximized" property + HWND hwnd = main_frame->GetHandle(); + RemoveProp(hwnd, L"Instance_Is_Maximized"); + // set new value for "Instance_Is_Maximized" property + size_t is_maximized = main_frame->IsMaximized() ? 1 : 0; + HANDLE handle_is_maximized = UIntToPtr(is_maximized); + SetProp(hwnd, L"Instance_Is_Maximized", handle_is_maximized); + } +} + #if 0 void OtherInstanceMessageHandler::print_window_info(HWND hwnd) diff --git a/src/slic3r/GUI/InstanceCheck.hpp b/src/slic3r/GUI/InstanceCheck.hpp index d70f4a90a5..26cf6bd14b 100644 --- a/src/slic3r/GUI/InstanceCheck.hpp +++ b/src/slic3r/GUI/InstanceCheck.hpp @@ -81,6 +81,7 @@ public: #endif //__APPLE__ #ifdef _WIN32 static void init_windows_properties(MainFrame* main_frame, size_t instance_hash); + void update_windows_properties(MainFrame* main_frame); #endif //WIN32 private: bool m_initialized { false }; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index a4435d37ef..1fe3ed6590 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -278,6 +278,15 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S event.Skip(); }); + +#ifdef _WIN32 + Bind(wxEVT_SIZE, [this](wxSizeEvent& event) { + event.Skip(); + // Update window property to mainframe so other instances can indentify it. + wxGetApp().other_instance_message_handler()->update_windows_properties(this); + }); +#endif //WIN32 + // 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 @@ -476,13 +485,12 @@ void MainFrame::update_layout() m_plater->Reparent(m_tabpanel); m_plater->Layout(); #ifdef _WIN32 - if (!wxGetApp().tabs_as_menu()) -#endif - dynamic_cast(m_tabpanel)->InsertPage(0, m_plater, _L("Plater"), std::string("plater"), true); -#ifdef _WIN32 + if (wxGetApp().tabs_as_menu()) + m_tabpanel->InsertPage(0, m_plater, _L("Plater")); else - m_tabpanel->InsertPage(0, m_plater, _L("Plater")); #endif + dynamic_cast(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(); @@ -503,13 +511,12 @@ void MainFrame::update_layout() m_main_sizer->Add(m_tabpanel, 1, wxEXPAND); m_plater_page = new wxPanel(m_tabpanel); #ifdef _WIN32 - if (!wxGetApp().tabs_as_menu()) -#endif - dynamic_cast(m_tabpanel)->InsertPage(0, m_plater_page, _L("Plater"), std::string("plater"), true); -#ifdef _WIN32 + if (wxGetApp().tabs_as_menu()) + m_tabpanel->InsertPage(0, m_plater_page, _L("Plater")); // empty panel just for Plater tab else - m_tabpanel->InsertPage(0, m_plater_page, _L("Plater")); // empty panel just for Plater tab */ #endif + dynamic_cast(m_tabpanel)->InsertNewPage(0, m_plater_page, _L("Plater"), std::string("plater"), true); + m_plater->Show(); break; } @@ -847,7 +854,7 @@ void MainFrame::add_connect_webview_tab() { if (m_connect_webview_added) { return; - } // parameters of InsertPage (to prevent ambigous overloaded function) + } // parameters of InsertNewPage (to prevent ambigous overloaded function) // insert to positon 4, if physical printer is already added, it moves to 5 // order of tabs: Plater - Print Settings - Filaments - Printers - Prusa Connect - Prusa Link size_t n = 4; @@ -855,7 +862,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)->InsertPage(n, page, text, bmp_name, bSelect); + dynamic_cast(m_tabpanel)->InsertNewPage(n, page, text, bmp_name, bSelect); m_connect_webview->load_default_url_delayed(); m_connect_webview_added = true; } @@ -872,6 +879,41 @@ void MainFrame::remove_connect_webview_tab() m_connect_webview->logout(); } +void MainFrame::show_printer_webview_tab(DynamicPrintConfig* dpc) +{ + // if physical printer is selected + if (dpc) { + std::string url = dpc->opt_string("print_host"); + + if (url.find("http://") != 0 && url.find("https://") != 0) { + url = "http://" + url; + } + + // set password / api key + if (dynamic_cast*>(dpc->option("printhost_authorization_type"))->value == AuthorizationType::atKeyPassword) { + set_printer_webview_api_key(dpc->opt_string("printhost_apikey")); + } +#if 0 // The user password authentication is not working in prusa link as of now. + else { + mset_printer_webview_credentials(dpc->opt_string("printhost_user"), dpc->opt_string("printhost_password")); + } +#endif // 0 + // add printer or change url + if (get_printer_webview_tab_added()) { + set_printer_webview_tab_url(from_u8(url)); + } + else { + add_printer_webview_tab(from_u8(url)); + } + } + // if physical printer isn't selected, so delete page from TopBar + else { + if (m_tabpanel->GetPageText(m_tabpanel->GetSelection()) == _L("Physical Printer")) + select_tab(size_t(0)); + remove_printer_webview_tab(); + } +} + void MainFrame::add_printer_webview_tab(const wxString& url) { if (m_printer_webview_added) { @@ -891,8 +933,7 @@ void MainFrame::remove_printer_webview_tab() } m_printer_webview_added = false; m_printer_webview->Hide(); - // always remove the last tab - dynamic_cast(m_tabpanel)->RemovePage(m_tabpanel->GetPageCount() - 1); + dynamic_cast(m_tabpanel)->RemovePage(m_tabpanel->FindPage(m_printer_webview)); } void MainFrame::set_printer_webview_tab_url(const wxString& url) { @@ -902,7 +943,8 @@ void MainFrame::set_printer_webview_tab_url(const wxString& url) } m_printer_webview->clear(); m_printer_webview->set_default_url(url); - if (m_tabpanel->GetSelection() == int(m_tabpanel->GetPageCount() - 1)) { + + if (m_tabpanel->GetSelection() == m_tabpanel->FindPage(m_printer_webview)) { m_printer_webview->load_url(url); } else { m_printer_webview->load_default_url_delayed(); diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 4206c4496e..bee3ac38e7 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -218,6 +218,8 @@ public: void add_connect_webview_tab(); void remove_connect_webview_tab(); + void show_printer_webview_tab(DynamicPrintConfig* dpc); + void add_printer_webview_tab(const wxString& url); void remove_printer_webview_tab(); void set_printer_webview_tab_url(const wxString& url); diff --git a/src/slic3r/GUI/SavePresetDialog.cpp b/src/slic3r/GUI/SavePresetDialog.cpp index 89cca4bba6..c915c5c170 100644 --- a/src/slic3r/GUI/SavePresetDialog.cpp +++ b/src/slic3r/GUI/SavePresetDialog.cpp @@ -52,6 +52,18 @@ std::string SavePresetDialog::Item::get_init_preset_name(const std::string &suff return preset_name; } +void SavePresetDialog::Item::init_casei_preset_names() +{ + m_casei_preset_names.clear(); + m_casei_preset_names.reserve(m_presets->size()); + + for (const Preset& preset : *m_presets) + if (!preset.is_default) + m_casei_preset_names.emplace_back(PresetName({ boost::to_lower_copy(preset.name), preset.name })); + + std::sort(m_casei_preset_names.begin(), m_casei_preset_names.end()); +} + void SavePresetDialog::Item::init_input_name_ctrl(wxBoxSizer *input_name_sizer, const std::string preset_name) { if (m_use_text_ctrl) { @@ -114,6 +126,8 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBox input_name_sizer->Add(m_valid_bmp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W); init_input_name_ctrl(input_name_sizer, get_init_preset_name(suffix)); + init_casei_preset_names(); + if (label_top) sizer->Add(label_top, 0, wxEXPAND | wxTOP| wxBOTTOM, BORDER_W); sizer->Add(input_name_sizer,0, wxEXPAND | (label_top ? 0 : wxTOP) | wxBOTTOM, BORDER_W); @@ -144,14 +158,44 @@ SavePresetDialog::Item::Item(wxWindow* parent, wxBoxSizer* sizer, const std::str update(); } +static std::string get_conflict_name(const std::vector& casei_names, const std::string& preset_name) +{ + if (!casei_names.empty()) { + const std::string lower_name = boost::to_lower_copy(preset_name); + auto it = Slic3r::lower_bound_by_predicate(casei_names.begin(), casei_names.end(), + [lower_name](const auto& l) { return l.casei_name < lower_name; }); + if (it != casei_names.end() && it->casei_name == lower_name) + return it->name; + } + return std::string(); +} + +std::string SavePresetDialog::Item::preset_name() const +{ + if (m_use_text_ctrl) + return m_preset_name; + + const std::string existed_preset_name = get_conflict_name(m_casei_preset_names, m_preset_name); + if (existed_preset_name.empty()) + return m_preset_name; + + return existed_preset_name; +} + const Preset* SavePresetDialog::Item::get_existing_preset() const { + std::string existed_preset_name = get_conflict_name(m_casei_preset_names, m_preset_name); + if (existed_preset_name.empty()) { + // Preset has not been not found in the sorted list of non-default presets. Try the defaults. + return nullptr; + } + if (m_presets) - return m_presets->find_preset(m_preset_name, false); + return m_presets->find_preset(existed_preset_name, false); for (const Preset::Type& type : PresetBundle::types_list(m_printer_technology)) { const PresetCollection& presets = wxGetApp().preset_bundle->get_presets(type); - if (const Preset* preset = presets.find_preset(m_preset_name, false)) + if (const Preset* preset = presets.find_preset(existed_preset_name, false)) return preset; } @@ -191,6 +235,7 @@ void SavePresetDialog::Item::update() if (m_valid_type == ValidationType::Valid && existing && (existing->is_default || existing->is_system)) { info_line = m_use_text_ctrl ? _L("This name is used for a system profile name, use another.") : _L("Cannot overwrite a system profile."); + info_line += "\n" + GUI::format_wxstr("(%1%)", existing->name); m_valid_type = ValidationType::NoValid; } @@ -211,10 +256,11 @@ void SavePresetDialog::Item::update() } else { if (existing->is_compatible) - info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists.")) % m_preset_name).str()); + info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists.")) % existing->name).str()); else - info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists and is incompatible with selected printer.")) % m_preset_name).str()); - info_line += "\n" + _L("Note: This preset will be replaced after saving"); + info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists and is incompatible with selected printer.")) % existing->name).str()); + info_line += "\n" + (m_use_text_ctrl ? _L("Note: This preset will be replaced after renaming") : + _L("Note: Preset modifications will be saved exactly into this preset")); m_valid_type = ValidationType::Warning; } } @@ -273,8 +319,6 @@ void SavePresetDialog::Item::update_valid_bmp() void SavePresetDialog::Item::accept() { - if (m_valid_type == ValidationType::Warning) - m_presets->delete_preset(m_preset_name); } void SavePresetDialog::Item::Enable(bool enable /*= true*/) diff --git a/src/slic3r/GUI/SavePresetDialog.hpp b/src/slic3r/GUI/SavePresetDialog.hpp index 04ba731702..6922dcfa9b 100644 --- a/src/slic3r/GUI/SavePresetDialog.hpp +++ b/src/slic3r/GUI/SavePresetDialog.hpp @@ -49,7 +49,14 @@ public: bool is_valid() const { return m_valid_type != ValidationType::NoValid; } Preset::Type type() const { return m_type; } - std::string preset_name() const { return m_preset_name; } + std::string preset_name() const; + + struct PresetName { + std::string casei_name; + std::string name; + + bool operator<(const PresetName& other) const { return other.casei_name > this->casei_name; } + }; private: Preset::Type m_type {Preset::TYPE_INVALID}; @@ -66,8 +73,11 @@ public: PresetCollection* m_presets {nullptr}; + std::vector m_casei_preset_names; + std::string get_init_preset_name(const std::string &suffix); void init_input_name_ctrl(wxBoxSizer *input_name_sizer, std::string preset_name); + void init_casei_preset_names(); const Preset* get_existing_preset() const ; void update(); diff --git a/src/slic3r/GUI/Sidebar.cpp b/src/slic3r/GUI/Sidebar.cpp index 9bcb672c2c..846f666432 100644 --- a/src/slic3r/GUI/Sidebar.cpp +++ b/src/slic3r/GUI/Sidebar.cpp @@ -502,7 +502,7 @@ Sidebar::Sidebar(Plater *parent) auto* complect_btns_sizer = new wxBoxSizer(wxHORIZONTAL); complect_btns_sizer->Add(m_btn_export_gcode, 1, wxEXPAND); - complect_btns_sizer->Add(m_btn_connect_gcode, 1, wxLEFT, margin_5); + complect_btns_sizer->Add(m_btn_connect_gcode, 1, wxEXPAND | wxLEFT, margin_5); complect_btns_sizer->Add(m_btn_send_gcode, 0, wxLEFT, margin_5); complect_btns_sizer->Add(m_btn_export_gcode_removable, 0, wxLEFT, margin_5); @@ -511,7 +511,7 @@ Sidebar::Sidebar(Plater *parent) auto *sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(m_scrolled_panel, 1, wxEXPAND); - sizer->Add(btns_sizer, 0, wxEXPAND | wxLEFT, margin_5); + sizer->Add(btns_sizer, 0, wxEXPAND | wxLEFT | wxBOTTOM, margin_5); SetSizer(sizer); // Events @@ -717,8 +717,6 @@ void Sidebar::on_select_preset(wxCommandEvent& evt) * and for SLA presets they should be deleted */ m_object_list->update_object_list_by_printer_technology(); - - wxGetApp().show_printer_webview_tab(); } #ifdef __WXMSW__ diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 70de17c645..643cd52f2b 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3619,6 +3619,8 @@ void Tab::load_current_preset() on_preset_loaded(); else wxGetApp().sidebar().update_objects_list_extruder_column(1); + // Check and show "Physical printer" page if needed + wxGetApp().show_printer_webview_tab(); } // Reload preset pages with the new configuration values. reload_config(); @@ -3646,27 +3648,19 @@ void Tab::load_current_preset() Page* tmp_page = m_active_page; m_active_page = nullptr; for (auto tab : wxGetApp().tabs_list) { - if (tab->type() == Preset::TYPE_PRINTER) { // Printer tab is shown every time - int cur_selection = wxGetApp().tab_panel()->GetSelection(); - if (cur_selection != 0) - wxGetApp().tab_panel()->SetSelection(wxGetApp().tab_panel()->GetPageCount() - 1); + if (tab->type() == Preset::TYPE_PRINTER) { + // Printer tab is shown every time continue; } if (tab->supports_printer_technology(printer_technology)) { #ifdef _WIN32 - if (!wxGetApp().tabs_as_menu()) { -#endif - dynamic_cast(wxGetApp().tab_panel())->InsertPage(wxGetApp().tab_panel()->FindPage(this), tab, tab->title(),""); -#ifdef _WIN32 - } - else + if (wxGetApp().tabs_as_menu()) wxGetApp().tab_panel()->InsertPage(wxGetApp().tab_panel()->FindPage(this), tab, tab->title()); + else #endif - #ifdef __linux__ // the tabs apparently need to be explicitly shown on Linux (pull request #1563) - int page_id = wxGetApp().tab_panel()->FindPage(tab); - wxGetApp().tab_panel()->GetPage(page_id)->Show(true); - #endif // __linux__ + dynamic_cast(wxGetApp().tab_panel())->InsertNewPage(wxGetApp().tab_panel()->FindPage(this), tab, tab->title(),""); + } else { int page_id = wxGetApp().tab_panel()->FindPage(tab); @@ -4376,8 +4370,11 @@ void Tab::delete_preset() { PhysicalPrinter& printer = physical_printers.get_selected_printer(); if (printer.preset_names.size() == 1) { - if (m_presets_choice->del_physical_printer(_L("It's a last preset for this physical printer."))) + if (m_presets_choice->del_physical_printer(_L("It's a last preset for this physical printer."))) { + // Hide "Physical printer" page + wxGetApp().show_printer_webview_tab(); Layout(); + } return; } diff --git a/src/slic3r/GUI/TopBar.cpp b/src/slic3r/GUI/TopBar.cpp index 19c2ede4b2..6b1d00c32a 100644 --- a/src/slic3r/GUI/TopBar.cpp +++ b/src/slic3r/GUI/TopBar.cpp @@ -22,8 +22,8 @@ using namespace Slic3r::GUI; #endif -TopBarItemsCtrl::Button::Button(wxWindow* parent, const wxString& label, const std::string& icon_name, const int px_cnt) -:ScalableButton(parent, wxID_ANY, icon_name, label, wxDefaultSize, wxDefaultPosition, wxNO_BORDER, px_cnt) +TopBarItemsCtrl::Button::Button(wxWindow* parent, const wxString& label, const std::string& icon_name, const int px_cnt, wxSize size_def) +:ScalableButton(parent, wxID_ANY, icon_name, label, size_def, wxDefaultPosition, wxNO_BORDER, px_cnt) #ifdef _WIN32 ,m_background_color(wxGetApp().get_window_default_clr()) #else @@ -167,9 +167,11 @@ void TopBarItemsCtrl::Button::sys_color_changed() m_foreground_color = wxGetApp().get_label_clr_default(); } -TopBarItemsCtrl::ButtonWithPopup::ButtonWithPopup(wxWindow* parent, const wxString& label, const std::string& icon_name) - :TopBarItemsCtrl::Button(parent, label, icon_name, 24) +TopBarItemsCtrl::ButtonWithPopup::ButtonWithPopup(wxWindow* parent, const wxString& label, const std::string& icon_name, wxSize size) + :TopBarItemsCtrl::Button(parent, label, icon_name, 24, size) { + if (size != wxDefaultSize) + m_fixed_width = size.x; this->SetLabel(label); } @@ -180,8 +182,26 @@ TopBarItemsCtrl::ButtonWithPopup::ButtonWithPopup(wxWindow* parent, const std::s void TopBarItemsCtrl::ButtonWithPopup::SetLabel(const wxString& label) { - wxString full_label = " " + label + " " + down_arrow; + wxString text = label; + int btn_height = GetMinSize().GetHeight(); + + 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) { + wxWindowDC wdc(this); + text = wxControl::Ellipsize(text, wdc, wxELLIPSIZE_END, text_width); + resize_and_layout = true; + } + } + + wxString full_label = " " + text + " " + down_arrow; ScalableButton::SetLabel(full_label); + if (resize_and_layout) { + SetMinSize(wxSize(m_fixed_width, btn_height)); + GetParent()->Layout(); + } } static wxString get_workspace_name(Slic3r::ConfigOptionMode mode) @@ -281,10 +301,10 @@ void TopBarItemsCtrl::UpdateAccountMenu(bool avatar/* = false*/) if (new_logo.IsOk()) m_account_btn->SetBitmapBundle(new_logo.bmp()); else - m_account_btn->SetBitmapBundle(*get_bmp_bundle("user")); + m_account_btn->SetBitmapBundle(*get_bmp_bundle("user", 24)); } else { - m_account_btn->SetBitmapBundle(*get_bmp_bundle("user")); + m_account_btn->SetBitmapBundle(*get_bmp_bundle("user", 24)); } } #endif @@ -293,7 +313,10 @@ void TopBarItemsCtrl::UpdateAccountMenu(bool avatar/* = false*/) void TopBarItemsCtrl::CreateSearch() { - m_search = new ::TextInput(this, wxGetApp().searcher().default_string, "", "search", wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); + // Linux specific: If wxDefaultSize is used in constructor and than set just maxSize, + // than this max size will be used as a default control size and can't be resized. + // So, set initial size for some minimum value + 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); @@ -350,7 +373,7 @@ TopBarItemsCtrl::TopBarItemsCtrl(wxWindow *parent) : CreateSearch(); wxBoxSizer* search_sizer = new wxBoxSizer(wxVERTICAL); - search_sizer->Add(m_search, 0, wxEXPAND | wxALIGN_RIGHT); + search_sizer->Add(m_search, 1, wxEXPAND | wxALIGN_RIGHT); left_sizer->Add(search_sizer, 1, wxALIGN_CENTER_VERTICAL); m_sizer->Add(left_sizer, 1, wxEXPAND); @@ -373,7 +396,7 @@ TopBarItemsCtrl::TopBarItemsCtrl(wxWindow *parent) : // create Account menu CreateAccountMenu(); - m_account_btn = new ButtonWithPopup(this, _L("Anonymous"), "user"); + 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) { diff --git a/src/slic3r/GUI/TopBar.hpp b/src/slic3r/GUI/TopBar.hpp index 5b5173c61c..3e858525f6 100644 --- a/src/slic3r/GUI/TopBar.hpp +++ b/src/slic3r/GUI/TopBar.hpp @@ -27,7 +27,8 @@ class TopBarItemsCtrl : public wxControl Button( wxWindow* parent, const wxString& label, const std::string& icon_name = "", - const int px_cnt = 16); + const int px_cnt = 16, + wxSize size = wxDefaultSize); ~Button() {} @@ -41,11 +42,13 @@ class TopBarItemsCtrl : public wxControl class ButtonWithPopup : public Button { + int m_fixed_width { wxDefaultCoord }; public: ButtonWithPopup() {}; ButtonWithPopup(wxWindow* parent, const wxString& label, - const std::string& icon_name = ""); + const std::string& icon_name = "", + wxSize size = wxDefaultSize); ButtonWithPopup(wxWindow* parent, const std::string& icon_name, int icon_width = 20, @@ -204,37 +207,10 @@ public: bool bSelect = false) { DoInvalidateBestSize(); - return InsertPage(GetPageCount(), page, text, bmp_name, bSelect); + return InsertNewPage(GetPageCount(), page, text, bmp_name, bSelect); } - // override AddPage with using of AddNewPage - bool AddPage( wxWindow* page, - const wxString& text, - bool bSelect = false, - int imageId = NO_IMAGE) override - { - return AddNewPage(page, text, "", bSelect); - } - - // Page management - virtual bool InsertPage(size_t n, - wxWindow * page, - const wxString & text, - bool bSelect = false, - int imageId = NO_IMAGE) override - { - if (!wxBookCtrlBase::InsertPage(n, page, text, bSelect, imageId)) - return false; - - GetTopBarItemsCtrl()->InsertPage(n, text, bSelect); - - if (!DoSetSelectionAfterInsertion(n, bSelect)) - page->Hide(); - - return true; - } - - bool InsertPage(size_t n, + bool InsertNewPage(size_t n, wxWindow * page, const wxString & text, const std::string& bmp_name = "", @@ -247,10 +223,31 @@ public: if (bSelect) SetSelection(n); + else + page->Hide(); return true; } + // override AddPage with using of AddNewPage + bool AddPage( wxWindow* page, + const wxString& text, + bool bSelect = false, + int imageId = NO_IMAGE) override + { + return AddNewPage(page, text, "", bSelect); + } + + // Page management + bool InsertPage(size_t n, + wxWindow * page, + const wxString & text, + bool bSelect = false, + int imageId = NO_IMAGE) override + { + return InsertNewPage(n, page, text, "", bSelect); + } + virtual int SetSelection(size_t n) override { GetTopBarItemsCtrl()->SetSelection(n); @@ -453,7 +450,8 @@ protected: if (win) { GetTopBarItemsCtrl()->RemovePage(page); - DoSetSelectionAfterRemoval(page); + // Don't setect any page after deletion some of them + // DoSetSelectionAfterRemoval(page); } return win; diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 3cb671fb02..ef70cdf9ae 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -96,8 +96,27 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const #ifndef __APPLE__ if (wxAcceleratorEntry* entry = wxAcceleratorEntry::Create(string)) { - entry->SetMenuItem(item); - accelerator_entries_cache().push_back(entry); + + static const std::set special_keys = { + WXK_PAGEUP, + WXK_PAGEDOWN, + WXK_NUMPAD_PAGEDOWN, + WXK_END, + WXK_HOME, + WXK_LEFT, + WXK_UP, + WXK_RIGHT, + WXK_DOWN, + WXK_INSERT, + WXK_DELETE, + }; + + // Check for special keys not included in the table + // see wxMSWKeyboard::WXWORD WXToVK(int wxk, bool *isExtended) + if (std::find(special_keys.begin(), special_keys.end(), entry->GetKeyCode()) == special_keys.end()) { + entry->SetMenuItem(item); + accelerator_entries_cache().push_back(entry); + } } #endif @@ -841,6 +860,11 @@ ScalableBitmap::ScalableBitmap(wxWindow* parent, boost::filesystem::path& icon_p wxBitmap::Rescale(bitmap, icon_size); m_bmp = wxBitmapBundle(bitmap); } + else if (ext == ".jpg") { + bitmap.LoadFile(path, wxBITMAP_TYPE_JPEG); + wxBitmap::Rescale(bitmap, icon_size); + m_bmp = wxBitmapBundle(bitmap); + } else if (ext == ".svg") { m_bmp = wxBitmapBundle::FromSVGFile(path, icon_size); }