diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 1be2495ca..4c4b4b4c2 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1033,6 +1033,12 @@ void GUI_App::update_label_colours_from_appconfig() } } +void GUI_App::update_label_colours() +{ + for (Tab* tab : tabs_list) + tab->update_label_colours(); +} + void GUI_App::init_fonts() { m_small_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); @@ -1066,7 +1072,10 @@ void GUI_App::update_fonts(const MainFrame *main_frame) m_code_font.SetPointSize(m_normal_font.GetPointSize()); } -void GUI_App::set_label_clr_modified(const wxColour& clr) { +void GUI_App::set_label_clr_modified(const wxColour& clr) +{ + if (m_color_label_modified == clr) + return; m_color_label_modified = clr; auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue()); std::string str = clr_str.ToStdString(); @@ -1074,7 +1083,10 @@ void GUI_App::set_label_clr_modified(const wxColour& clr) { app_config->save(); } -void GUI_App::set_label_clr_sys(const wxColour& clr) { +void GUI_App::set_label_clr_sys(const wxColour& clr) +{ + if (m_color_label_sys == clr) + return; m_color_label_sys = clr; auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue()); std::string str = clr_str.ToStdString(); @@ -1229,6 +1241,7 @@ void fatal_error(wxWindow* parent) // Update the UI based on the current preferences. void GUI_App::update_ui_from_settings(bool apply_free_camera_correction) { + update_label_colours(); mainframe->update_ui_from_settings(apply_free_camera_correction); } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 8aceb7a69..132776dcb 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -167,6 +167,7 @@ public: static bool dark_mode(); void init_label_colours(); void update_label_colours_from_appconfig(); + void update_label_colours(); void init_fonts(); void update_fonts(const MainFrame *main_frame = nullptr); void set_label_clr_modified(const wxColour& clr); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 3d08b26f1..a1249c696 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -260,13 +260,27 @@ ObjectList::~ObjectList() void ObjectList::set_min_height() { - /* Temporary workaround for the correct behavior of the Scrolled sidebar panel: - * change min hight of object list to the normal min value (20 * wxGetApp().em_unit()) - * after first whole Mainframe updating/layouting - */ - const int list_min_height = 20 * wxGetApp().em_unit(); - if (this->GetMinSize().GetY() > list_min_height) - this->SetMinSize(wxSize(-1, list_min_height)); + if (m_items_count == size_t(-1)) + m_items_count = 7; + int list_min_height = lround(2.25 * (m_items_count + 1) * wxGetApp().em_unit()); // +1 is for height of control header + this->SetMinSize(wxSize(1, list_min_height)); +} + +void ObjectList::update_min_height() +{ + wxDataViewItemArray all_items; + m_objects_model->GetAllChildren(wxDataViewItem(nullptr), all_items); + size_t items_cnt = all_items.Count(); + if (items_cnt < 7) + items_cnt = 7; + else if (items_cnt >= 15) + items_cnt = 15; + + if (m_items_count == items_cnt) + return; + + m_items_count = items_cnt; + set_min_height(); } @@ -274,7 +288,7 @@ void ObjectList::create_objects_ctrl() { /* Temporary workaround for the correct behavior of the Scrolled sidebar panel: * 1. set a height of the list to some big value - * 2. change it to the normal min value (20 * wxGetApp().em_unit()) after first whole Mainframe updating/layouting + * 2. change it to the normal(meaningful) min value after first whole Mainframe updating/layouting */ SetMinSize(wxSize(-1, 3000)); @@ -2993,6 +3007,8 @@ void ObjectList::part_selection_changed() else if (update_and_show_layers) wxGetApp().obj_layers()->get_og()->set_name(" " + og_name + " "); + update_min_height(); + Sidebar& panel = wxGetApp().sidebar(); panel.Freeze(); @@ -3659,16 +3675,28 @@ void ObjectList::update_selections() return; sels.Add(m_objects_model->GetItemById(selection.get_object_idx())); } - if (selection.is_single_volume() || selection.is_any_modifier()) { + else if (selection.is_single_volume() || selection.is_any_modifier()) { const auto gl_vol = selection.get_volume(*selection.get_volume_idxs().begin()); if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx()) return; } - // but if there is selected only one of several instances by context menu, // then select this instance in ObjectList - if (selection.is_single_full_instance()) + else if (selection.is_single_full_instance()) sels.Add(m_objects_model->GetItemByInstanceId(selection.get_object_idx(), selection.get_instance_idx())); + // Can be the case, when we have selected itSettings | itLayerRoot | itLayer in the ObjectList and selected object/instance in the Scene + // and then select some object/instance in 3DScene using Ctrt+left click + // see https://github.com/prusa3d/PrusaSlicer/issues/5517 + else { + // Unselect all items in ObjectList + m_last_selected_item = wxDataViewItem(nullptr); + m_prevent_list_events = true; + UnselectAll(); + m_prevent_list_events = false; + // call this function again to update selection from the canvas + update_selections(); + return; + } } else if (selection.is_single_full_object() || selection.is_multiple_full_object()) { @@ -4467,9 +4495,9 @@ void ObjectList::update_item_error_icon(const int obj_idx, const int vol_idx) co void ObjectList::msw_rescale() { + set_min_height(); + const int em = wxGetApp().em_unit(); - // update min size !!! A width of control shouldn't be a wxDefaultCoord - SetMinSize(wxSize(1, 15 * em)); GetColumn(colName )->SetWidth(20 * em); GetColumn(colPrint )->SetWidth( 3 * em); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 52aefe0e6..15d5ecb08 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -197,6 +197,8 @@ private: SettingsBundle m_freq_settings_sla; #endif + size_t m_items_count { size_t(-1) }; + inline void ensure_current_item_visible() { if (const auto &item = this->GetCurrentItem()) @@ -208,6 +210,7 @@ public: ~ObjectList(); void set_min_height(); + void update_min_height(); std::map CATEGORY_ICON; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 7824dcfdf..80826eab9 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -633,7 +633,11 @@ Sidebar::Sidebar(Plater *parent) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(42 * wxGetApp().em_unit(), -1)), p(new priv(parent)) { p->scrolled = new wxScrolledWindow(this); - p->scrolled->SetScrollbars(0, 100, 1, 2); +// p->scrolled->SetScrollbars(0, 100, 1, 2); // ys_DELETE_after_testing. pixelsPerUnitY = 100 from https://github.com/prusa3d/PrusaSlicer/commit/8f019e5fa992eac2c9a1e84311c990a943f80b01, + // but this cause the bad layout of the sidebar, when all infoboxes appear. + // As a result we can see the empty block at the bottom of the sidebar + // But if we set this value to 5, layout will be better + p->scrolled->SetScrollRate(0, 5); SetFont(wxGetApp().normal_font()); #ifndef __APPLE__ @@ -2380,6 +2384,10 @@ std::vector Plater::priv::load_files(const std::vector& input_ CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, &wxGetApp().preset_bundle->project_config); // For exporting from the amf/3mf we shouldn't check printer_presets for the containing information about "Print Host upload" wxGetApp().load_current_presets(false); + // Update filament colors for the MM-printer profile in the full config + // to avoid black (default) colors for Extruders in the ObjectList, + // when for extruder colors are used filament colors + q->update_filament_colors_in_full_config(); is_project_file = true; } wxGetApp().app_config->update_config_dir(path.parent_path().string()); @@ -5788,6 +5796,26 @@ void Plater::on_extruders_change(size_t num_extruders) sidebar().scrolled_panel()->Refresh(); } +bool Plater::update_filament_colors_in_full_config() +{ + // There is a case, when we use filament_color instead of extruder_color (when extruder_color == ""). + // Thus plater config option "filament_colour" should be filled with filament_presets values. + // Otherwise, on 3dScene will be used last edited filament color for all volumes with extruder_color == "". + const std::vector filament_presets = wxGetApp().preset_bundle->filament_presets; + if (filament_presets.size() == 1 || !p->config->has("filament_colour")) + return false; + + const PresetCollection& filaments = wxGetApp().preset_bundle->filaments; + std::vector filament_colors; + filament_colors.reserve(filament_presets.size()); + + for (const std::string& filament_preset : filament_presets) + filament_colors.push_back(filaments.find_preset(filament_preset, true)->config.opt_string("filament_colour", (unsigned)0)); + + p->config->option("filament_colour")->values = filament_colors; + return true; +} + void Plater::on_config_change(const DynamicPrintConfig &config) { bool update_scheduled = false; @@ -5797,22 +5825,7 @@ void Plater::on_config_change(const DynamicPrintConfig &config) { update_scheduled = true; // update should be scheduled (for update 3DScene) #2738 - /* There is a case, when we use filament_color instead of extruder_color (when extruder_color == ""). - * Thus plater config option "filament_colour" should be filled with filament_presets values. - * Otherwise, on 3dScene will be used last edited filament color for all volumes with extruder_color == "". - */ - const std::vector filament_presets = wxGetApp().preset_bundle->filament_presets; - if (filament_presets.size() > 1 && - p->config->option(opt_key)->values.size() != config.option(opt_key)->values.size()) - { - const PresetCollection& filaments = wxGetApp().preset_bundle->filaments; - std::vector filament_colors; - filament_colors.reserve(filament_presets.size()); - - for (const std::string& filament_preset : filament_presets) - filament_colors.push_back(filaments.find_preset(filament_preset, true)->config.opt_string("filament_colour", (unsigned)0)); - - p->config->option(opt_key)->values = filament_colors; + if (update_filament_colors_in_full_config()) { p->sidebar->obj_list()->update_extruder_colors(); continue; } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 5c7c6d7c9..5407a6e85 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -233,6 +233,7 @@ public: void leave_gizmos_stack(); void on_extruders_change(size_t extruders_count); + bool update_filament_colors_in_full_config(); void on_config_change(const DynamicPrintConfig &config); void force_filament_colors_update(); void force_print_bed_update(); diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 9c9ea8c4b..0a8a6c886 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -312,6 +312,7 @@ void PreferencesDialog::build() m_icon_size_sizer->ShowItems(app_config->get("use_custom_toolbar_size") == "1"); create_settings_mode_widget(); + create_settings_text_color_widget(); } #if ENABLE_ENVIRONMENT_MAP @@ -379,6 +380,10 @@ void PreferencesDialog::accept() app_config->set(it->first, it->second); app_config->save(); + + wxGetApp().set_label_clr_sys(m_sys_colour->GetColour()); + wxGetApp().set_label_clr_modified(m_mod_colour->GetColour()); + EndModal(wxID_OK); if (m_settings_layout_changed) @@ -498,6 +503,42 @@ void PreferencesDialog::create_settings_mode_widget() m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND); } +void PreferencesDialog::create_settings_text_color_widget() +{ + wxWindow* parent = m_optgroup_gui->parent(); + + wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _L("Text color Settings")); + if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); + + wxSizer* sizer = new wxStaticBoxSizer(stb, wxVERTICAL); + wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(2, 10, 20); + sizer->Add(grid_sizer, 0, wxEXPAND); + + auto sys_label = new wxStaticText(parent, wxID_ANY, _L("Value is the same as the system value")); + sys_label->SetForegroundColour(wxGetApp().get_label_clr_sys()); + m_sys_colour = new wxColourPickerCtrl(parent, wxID_ANY, wxGetApp().get_label_clr_sys()); + m_sys_colour->Bind(wxEVT_COLOURPICKER_CHANGED, [this, sys_label](wxCommandEvent&) { + sys_label->SetForegroundColour(m_sys_colour->GetColour()); + sys_label->Refresh(); + }); + + grid_sizer->Add(m_sys_colour, -1, wxALIGN_CENTRE_VERTICAL); + grid_sizer->Add(sys_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND); + + auto mod_label = new wxStaticText(parent, wxID_ANY, _L("Value was changed and is not equal to the system value or the last saved preset")); + mod_label->SetForegroundColour(wxGetApp().get_label_clr_modified()); + m_mod_colour = new wxColourPickerCtrl(parent, wxID_ANY, wxGetApp().get_label_clr_modified()); + m_mod_colour->Bind(wxEVT_COLOURPICKER_CHANGED, [this, mod_label](wxCommandEvent&) { + mod_label->SetForegroundColour(m_mod_colour->GetColour()); + mod_label->Refresh(); + }); + + grid_sizer->Add(m_mod_colour, -1, wxALIGN_CENTRE_VERTICAL); + grid_sizer->Add(mod_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND); + + m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit()); +} + } // GUI } // Slic3r diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index 68574fbcc..0da044736 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -8,6 +8,7 @@ #include class wxRadioBox; +class wxColourPickerCtrl; namespace Slic3r { namespace GUI { @@ -25,6 +26,8 @@ class PreferencesDialog : public DPIDialog #endif // ENABLE_ENVIRONMENT_MAP wxSizer* m_icon_size_sizer; wxRadioBox* m_layout_mode_box; + wxColourPickerCtrl* m_sys_colour {nullptr}; + wxColourPickerCtrl* m_mod_colour {nullptr}; bool isOSX {false}; bool m_settings_layout_changed {false}; bool m_seq_top_layer_only_changed{ false }; @@ -43,6 +46,7 @@ protected: void layout(); void create_icon_size_slider(); void create_settings_mode_widget(); + void create_settings_text_color_widget(); }; } // GUI diff --git a/src/slic3r/GUI/SavePresetDialog.cpp b/src/slic3r/GUI/SavePresetDialog.cpp index 65bd3acb9..e659f8e02 100644 --- a/src/slic3r/GUI/SavePresetDialog.cpp +++ b/src/slic3r/GUI/SavePresetDialog.cpp @@ -153,6 +153,11 @@ void SavePresetDialog::Item::update() m_valid_type = NoValid; } + if (m_valid_type == Valid && m_presets->get_preset_name_by_alias(m_preset_name) != m_preset_name) { + info_line = _L("The name cannot be the same as a preset alias name."); + m_valid_type = NoValid; + } + m_valid_label->SetLabel(info_line); m_valid_label->Show(!info_line.IsEmpty()); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index ccb82b011..aec2f8754 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -235,18 +235,11 @@ void Tab::create_preset_tab() m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_roll_back_value(); })); m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_roll_back_value(true); })); - m_question_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) - { + m_question_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent) { ButtonsDescription dlg(this, m_icon_descriptions); - if (dlg.ShowModal() == wxID_OK) { - // Colors for ui "decoration" - for (Tab *tab : wxGetApp().tabs_list) { - tab->m_sys_label_clr = wxGetApp().get_label_clr_sys(); - tab->m_modified_label_clr = wxGetApp().get_label_clr_modified(); - tab->update_labels_colour(); - } - } - })); + if (dlg.ShowModal() == wxID_OK) + wxGetApp().update_label_colours(); + }); m_search_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent) { wxGetApp().plater()->search(false); }); // Colors for ui "decoration" @@ -489,8 +482,13 @@ void Tab::OnActivate() Refresh(); } -void Tab::update_labels_colour() +void Tab::update_label_colours() { + if (m_sys_label_clr == wxGetApp().get_label_clr_sys() && m_modified_label_clr == wxGetApp().get_label_clr_modified()) + return; + m_sys_label_clr = wxGetApp().get_label_clr_sys(); + m_modified_label_clr = wxGetApp().get_label_clr_modified(); + //update options "decoration" for (const auto opt : m_options_list) { @@ -536,6 +534,8 @@ void Tab::update_labels_colour() } cur_item = m_treectrl->GetNextVisible(cur_item); } + + decorate(); } void Tab::decorate() @@ -999,9 +999,7 @@ void Tab::sys_color_changed() m_treectrl->AssignImageList(m_icons); // Colors for ui "decoration" - m_sys_label_clr = wxGetApp().get_label_clr_sys(); - m_modified_label_clr = wxGetApp().get_label_clr_modified(); - update_labels_colour(); + update_label_colours(); // update options_groups if (m_active_page) diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 927787933..29588ba20 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -295,7 +295,7 @@ public: void toggle_show_hide_incompatible(); void update_show_hide_incompatible_button(); void update_ui_from_settings(); - void update_labels_colour(); + void update_label_colours(); void decorate(); void update_changed_ui(); void get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page);