diff --git a/resources/icons/check_off.svg b/resources/icons/check_off.svg new file mode 100644 index 0000000000..f28cba5ea4 --- /dev/null +++ b/resources/icons/check_off.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/check_off_disabled.svg b/resources/icons/check_off_disabled.svg new file mode 100644 index 0000000000..492a88ea83 --- /dev/null +++ b/resources/icons/check_off_disabled.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/check_off_focused.svg b/resources/icons/check_off_focused.svg new file mode 100644 index 0000000000..3fb1ab9bc2 --- /dev/null +++ b/resources/icons/check_off_focused.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/check_on.svg b/resources/icons/check_on.svg new file mode 100644 index 0000000000..62c23441a9 --- /dev/null +++ b/resources/icons/check_on.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/check_on_disabled.svg b/resources/icons/check_on_disabled.svg new file mode 100644 index 0000000000..2c00ecfa59 --- /dev/null +++ b/resources/icons/check_on_disabled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/check_on_focused.svg b/resources/icons/check_on_focused.svg new file mode 100644 index 0000000000..6b4e7935e1 --- /dev/null +++ b/resources/icons/check_on_focused.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/checked.svg b/resources/icons/checked.svg new file mode 100644 index 0000000000..88747cb95d --- /dev/null +++ b/resources/icons/checked.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/drop_down.svg b/resources/icons/drop_down.svg new file mode 100644 index 0000000000..3354ddc295 --- /dev/null +++ b/resources/icons/drop_down.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/spin_dec.svg b/resources/icons/spin_dec.svg new file mode 100644 index 0000000000..889ad9ce23 --- /dev/null +++ b/resources/icons/spin_dec.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/spin_dec_act.svg b/resources/icons/spin_dec_act.svg new file mode 100644 index 0000000000..a9924d8235 --- /dev/null +++ b/resources/icons/spin_dec_act.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/spin_inc.svg b/resources/icons/spin_inc.svg new file mode 100644 index 0000000000..cf6b3a6998 --- /dev/null +++ b/resources/icons/spin_inc.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/spin_inc_act.svg b/resources/icons/spin_inc_act.svg new file mode 100644 index 0000000000..e052bb7644 --- /dev/null +++ b/resources/icons/spin_inc_act.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/toggle_off.svg b/resources/icons/toggle_off.svg new file mode 100644 index 0000000000..4a7925a155 --- /dev/null +++ b/resources/icons/toggle_off.svg @@ -0,0 +1,5 @@ + + + rect x="1" y="1.00293" width="22" height="12" rx="6" fill="#BBG"/--> + + diff --git a/resources/icons/toggle_on.svg b/resources/icons/toggle_on.svg new file mode 100644 index 0000000000..caae9478be --- /dev/null +++ b/resources/icons/toggle_on.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 426cc53309..4bf4b4a2cd 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -104,6 +104,9 @@ void AppConfig::set_defaults() if (get("tabs_as_menu").empty()) set("tabs_as_menu", "0"); + + if (get("suppress_round_corners").empty()) + set("suppress_round_corners", "1"); #endif // _WIN32 // remove old 'use_legacy_opengl' parameter from this config, if present diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 8f9900bbf2..5eee8dd7e4 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -256,6 +256,29 @@ set(SLIC3R_GUI_SOURCES GUI/DesktopIntegrationDialog.hpp GUI/HintNotification.cpp GUI/HintNotification.hpp + GUI/Widgets/BitmapToggleButton.cpp + GUI/Widgets/BitmapToggleButton.hpp + GUI/Widgets/Button.cpp + GUI/Widgets/Button.hpp + GUI/Widgets/CheckBox.cpp + GUI/Widgets/CheckBox.hpp + GUI/Widgets/ComboBox.cpp + GUI/Widgets/ComboBox.hpp + GUI/Widgets/DropDown.cpp + GUI/Widgets/DropDown.hpp + GUI/Widgets/StateColor.cpp + GUI/Widgets/StateColor.hpp + GUI/Widgets/StateHandler.cpp + GUI/Widgets/StateHandler.hpp + GUI/Widgets/StaticBox.cpp + GUI/Widgets/StaticBox.hpp + GUI/Widgets/SpinInput.cpp + GUI/Widgets/SpinInput.hpp + GUI/Widgets/SwitchButton.cpp + GUI/Widgets/SwitchButton.hpp + GUI/Widgets/TextInput.cpp + GUI/Widgets/TextInput.hpp + GUI/Widgets/UIColors.hpp GUI/FileArchiveDialog.cpp GUI/FileArchiveDialog.hpp GUI/Downloader.cpp diff --git a/src/slic3r/GUI/BitmapCache.cpp b/src/slic3r/GUI/BitmapCache.cpp index 10f7277309..98b2889aa1 100644 --- a/src/slic3r/GUI/BitmapCache.cpp +++ b/src/slic3r/GUI/BitmapCache.cpp @@ -414,6 +414,8 @@ wxBitmapBundle* BitmapCache::from_svg(const std::string& bitmap_name, unsigned t if (!new_color.empty()) replaces["\"#ED6B21\""] = "\"" + new_color + "\""; + replaces["\"#ButtonBG\""] = dark_mode ? "\"#4E4E4E\"" : "\"#828282\""; + std::string str; nsvgGetDataFromFileWithReplace(Slic3r::var(bitmap_name + ".svg").c_str(), str, replaces); if (str.empty()) diff --git a/src/slic3r/GUI/BitmapComboBox.cpp b/src/slic3r/GUI/BitmapComboBox.cpp index 465eb4822b..2c50ab8cf7 100644 --- a/src/slic3r/GUI/BitmapComboBox.cpp +++ b/src/slic3r/GUI/BitmapComboBox.cpp @@ -66,10 +66,11 @@ BitmapComboBox::BitmapComboBox(wxWindow* parent, int n/* = 0*/, const wxString choices[]/* = NULL*/, long style/* = 0*/) : - wxBitmapComboBox(parent, id, value, pos, size, n, choices, style) +// wxBitmapComboBox(parent, id, value, pos, size, n, choices, style) + ::ComboBox(parent, id, value, pos, size, n, choices, style | DD_NO_CHECK_ICON) { SetFont(Slic3r::GUI::wxGetApp().normal_font()); -#ifdef _WIN32 +#if 0 //#ifdef _WIN32 // Workaround for ignoring CBN_EDITCHANGE events, which are processed after the content of the combo box changes, so that // the index of the item inside CBN_EDITCHANGE may no more be valid. EnableTextChangedEvents(false); @@ -79,11 +80,12 @@ BitmapComboBox::BitmapComboBox(wxWindow* parent, #endif /* _WIN32 */ } +#if 0 BitmapComboBox::~BitmapComboBox() { } -#ifdef _WIN32 +//#ifdef _WIN32 int BitmapComboBox::Append(const wxString& item) { diff --git a/src/slic3r/GUI/BitmapComboBox.hpp b/src/slic3r/GUI/BitmapComboBox.hpp index 07031f6bf2..e1398ec041 100644 --- a/src/slic3r/GUI/BitmapComboBox.hpp +++ b/src/slic3r/GUI/BitmapComboBox.hpp @@ -8,6 +8,8 @@ #include #include +#include "Widgets/ComboBox.hpp" + #include "GUI_Utils.hpp" // --------------------------------- @@ -17,7 +19,8 @@ namespace Slic3r { namespace GUI { // BitmapComboBox used to presets list on Sidebar and Tabs -class BitmapComboBox : public wxBitmapComboBox +//class BitmapComboBox : public wxBitmapComboBox +class BitmapComboBox : public ::ComboBox { public: BitmapComboBox(wxWindow* parent, @@ -28,6 +31,7 @@ BitmapComboBox(wxWindow* parent, int n = 0, const wxString choices[] = NULL, long style = 0); +#if 0 ~BitmapComboBox(); #ifdef _WIN32 @@ -40,7 +44,7 @@ BitmapComboBox(wxWindow* parent, protected: -#ifdef _WIN32 +//#ifdef _WIN32 bool MSWOnDraw(WXDRAWITEMSTRUCT* item) override; void DrawBackground_(wxDC& dc, const wxRect& rect, int WXUNUSED(item), int flags) const; public: diff --git a/src/slic3r/GUI/ButtonsDescription.cpp b/src/slic3r/GUI/ButtonsDescription.cpp index 105dbe777d..08d1cb76c8 100644 --- a/src/slic3r/GUI/ButtonsDescription.cpp +++ b/src/slic3r/GUI/ButtonsDescription.cpp @@ -78,7 +78,7 @@ wxBitmapBundle * ModePaletteComboBox::get_bmp(const std::vector &pa // Create the bitmap with color bars. std::vector bmps; for (const auto& color : palette) { - bmps.emplace_back(get_bmp_bundle("mode", icon_height, color)); + bmps.emplace_back(get_bmp_bundle("mode", icon_height, icon_height, color)); bmps.emplace_back(get_empty_bmp_bundle(wxOSX ? 5 : 6, icon_height)); } bmp_bndl = bitmap_cache().insert_bndl(bitmap_key, bmps); diff --git a/src/slic3r/GUI/ExtruderSequenceDialog.cpp b/src/slic3r/GUI/ExtruderSequenceDialog.cpp index ca2fee15e6..1268b3595f 100644 --- a/src/slic3r/GUI/ExtruderSequenceDialog.cpp +++ b/src/slic3r/GUI/ExtruderSequenceDialog.cpp @@ -22,6 +22,7 @@ #include "MainFrame.hpp" #include "BitmapComboBox.hpp" +#include "Widgets/CheckBox.hpp" namespace Slic3r { namespace GUI { @@ -165,7 +166,7 @@ ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequ intervals_box_sizer->Add(m_intervals_grid_sizer, 0, wxLEFT, em); option_sizer->Add(intervals_box_sizer, 0, wxEXPAND); - m_random_sequence = new wxCheckBox(this, wxID_ANY, _L("Random sequence")); + m_random_sequence = new ::CheckBox(this, _L("Random sequence")); m_random_sequence->SetValue(m_sequence.random_sequence); m_random_sequence->SetToolTip(_L("If enabled, random sequence of the selected extruders will be used.")); m_random_sequence->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& e) { @@ -173,7 +174,7 @@ ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequ m_color_repetition->Enable(m_sequence.random_sequence); }); - m_color_repetition = new wxCheckBox(this, wxID_ANY, _L("Allow next color repetition")); + m_color_repetition = new ::CheckBox(this, _L("Allow next color repetition")); m_color_repetition->SetValue(m_sequence.color_repetition); m_color_repetition->SetToolTip(_L("If enabled, a repetition of the next random color will be allowed.")); m_color_repetition->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& e) {m_sequence.color_repetition = e.IsChecked(); }); diff --git a/src/slic3r/GUI/ExtruderSequenceDialog.hpp b/src/slic3r/GUI/ExtruderSequenceDialog.hpp index 1c986682c9..61cd057425 100644 --- a/src/slic3r/GUI/ExtruderSequenceDialog.hpp +++ b/src/slic3r/GUI/ExtruderSequenceDialog.hpp @@ -10,7 +10,7 @@ class wxTextCtrl; class wxFlexGridSizer; -class wxCheckBox; +class CheckBox; namespace Slic3r { namespace GUI { @@ -27,8 +27,8 @@ class ExtruderSequenceDialog: public DPIDialog wxTextCtrl* m_interval_by_layers {nullptr}; wxTextCtrl* m_interval_by_mm {nullptr}; - wxCheckBox* m_random_sequence {nullptr}; - wxCheckBox* m_color_repetition{nullptr}; + CheckBox* m_random_sequence {nullptr}; + CheckBox* m_color_repetition{nullptr}; wxFlexGridSizer* m_intervals_grid_sizer {nullptr}; wxFlexGridSizer* m_extruders_grid_sizer {nullptr}; diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index c93a831927..9a8c0287c3 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -28,6 +28,8 @@ #include "MsgDialog.hpp" #include "BitmapComboBox.hpp" +#include "Widgets/ComboBox.hpp" + #ifdef __WXOSX__ #define wxOSX true #else @@ -102,8 +104,6 @@ Field::~Field() void Field::PostInitialize() { - auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - switch (m_opt.type) { case coPercents: @@ -488,10 +488,7 @@ void TextCtrl::BUILD() { } long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER; -#ifdef _WIN32 - style |= wxBORDER_SIMPLE; -#endif - auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, style); + auto temp = new text_ctrl(m_parent, text_value, "", "", wxDefaultPosition, size, style); if (parent_is_custom_ctrl && m_opt.height < 0) opt_height = (double)temp->GetSize().GetHeight()/m_em_unit; temp->SetFont(m_opt.is_code ? @@ -503,9 +500,6 @@ void TextCtrl::BUILD() { // Only disable background refresh for single line input fields, as they are completely painted over by the edit control. // This does not apply to the multi-line edit field, where the last line and a narrow frame around the text is not cleared. temp->SetBackgroundStyle(wxBG_STYLE_PAINT); -#ifdef __WXOSX__ - temp->OSXDisableAllSmartSubstitutions(); -#endif // __WXOSX__ temp->SetToolTip(get_tooltip_text(text_value)); @@ -562,7 +556,7 @@ bool TextCtrl::value_was_changed() return true; boost::any val = m_value; - wxString ret_str = static_cast(window)->GetValue(); + wxString ret_str = static_cast(window)->GetValue(); // update m_value! // ret_str might be changed inside get_value_by_opt_type get_value_by_opt_type(ret_str); @@ -593,11 +587,11 @@ bool TextCtrl::value_was_changed() void TextCtrl::propagate_value() { - wxString val = dynamic_cast(window)->GetValue(); + wxString val = dynamic_cast(window)->GetValue(); if (m_opt.nullable && val != na_value()) m_last_meaningful_value = val; - if (!is_defined_input_value(window, m_opt.type) ) + if (!is_defined_input_value(window, m_opt.type) ) // on_kill_focus() cause a call of OptionsGroup::reload_config(), // Thus, do it only when it's really needed (when undefined value was input) on_kill_focus(); @@ -611,14 +605,14 @@ void TextCtrl::set_value(const boost::any& value, bool change_event/* = false*/) const bool m_is_na_val = boost::any_cast(value) == na_value(); if (!m_is_na_val) m_last_meaningful_value = value; - dynamic_cast(window)->SetValue(m_is_na_val ? na_value() : boost::any_cast(value)); + dynamic_cast(window)->SetValue(m_is_na_val ? na_value() : boost::any_cast(value)); } else - dynamic_cast(window)->SetValue(boost::any_cast(value)); + dynamic_cast(window)->SetValue(boost::any_cast(value)); m_disable_change_event = false; if (!change_event) { - wxString ret_str = static_cast(window)->GetValue(); + wxString ret_str = static_cast(window)->GetValue(); /* Update m_value to correct work of next value_was_changed(). * But after checking of entered value, don't fix the "incorrect" value and don't show a warning message, * just clear m_value in this case. @@ -629,19 +623,19 @@ void TextCtrl::set_value(const boost::any& value, bool change_event/* = false*/) void TextCtrl::set_last_meaningful_value() { - dynamic_cast(window)->SetValue(boost::any_cast(m_last_meaningful_value)); + dynamic_cast(window)->SetValue(boost::any_cast(m_last_meaningful_value)); propagate_value(); } void TextCtrl::set_na_value() { - dynamic_cast(window)->SetValue(na_value()); + dynamic_cast(window)->SetValue(na_value()); propagate_value(); } boost::any& TextCtrl::get_value() { - wxString ret_str = static_cast(window)->GetValue(); + wxString ret_str = static_cast(window)->GetValue(); // update m_value get_value_by_opt_type(ret_str); @@ -659,8 +653,11 @@ void TextCtrl::msw_rescale() size.SetHeight(lround(opt_height*m_em_unit)); if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); - if (size != wxDefaultSize) - { + if (size != wxDefaultSize) { + if (::TextInput* text_input = dynamic_cast<::TextInput*>(window)) { + text_input->SetCtrlSize(size); + return; + } wxTextCtrl* field = dynamic_cast(window); if (parent_is_custom_ctrl) field->SetSize(size); @@ -670,8 +667,8 @@ void TextCtrl::msw_rescale() } -void TextCtrl::enable() { dynamic_cast(window)->Enable(); dynamic_cast(window)->SetEditable(true); } -void TextCtrl::disable() { dynamic_cast(window)->Disable(); dynamic_cast(window)->SetEditable(false); } +void TextCtrl::enable() { dynamic_cast(window)->Enable(); } +void TextCtrl::disable() { dynamic_cast(window)->Disable();} #ifdef __WXGTK__ void TextCtrl::change_field_value(wxEvent& event) @@ -682,10 +679,71 @@ void TextCtrl::change_field_value(wxEvent& event) }; #endif //__WXGTK__ + +wxWindow* CheckBox::GetNewWin(wxWindow* parent, const wxString& label /*= wxEmptyString*/) +{ + if (wxGetApp().suppress_round_corners()) + return new ::CheckBox(parent, label); + + return new ::SwitchButton(parent, label); +} + +void CheckBox::SetValue(wxWindow* win, bool value) +{ + if (wxGetApp().suppress_round_corners()) { + if (::CheckBox* ch_b = dynamic_cast<::CheckBox*>(win)) + ch_b->SetValue(value); + } + else { + if (::SwitchButton* ch_b = dynamic_cast<::SwitchButton*>(win)) + ch_b->SetValue(value); + } +} + +bool CheckBox::GetValue(wxWindow* win) +{ + if (wxGetApp().suppress_round_corners()) + return dynamic_cast<::CheckBox*>(win)->GetValue(); + + return dynamic_cast<::SwitchButton*>(win)->GetValue(); +} + +void CheckBox::Rescale(wxWindow* win) +{ + if (wxGetApp().suppress_round_corners()) + dynamic_cast<::CheckBox*>(win)->Rescale(); + else + dynamic_cast<::SwitchButton*>(win)->Rescale(); +} + +void CheckBox::SysColorChanged(wxWindow* win) +{ + if (!wxGetApp().suppress_round_corners()) + dynamic_cast<::SwitchButton*>(win)->SysColorChange(); +} + +void CheckBox::SetValue(bool value) +{ + if (wxGetApp().suppress_round_corners()) + dynamic_cast<::CheckBox*>(window)->SetValue(value); + else + dynamic_cast<::SwitchButton*>(window)->SetValue(value); +} + +bool CheckBox::GetValue() +{ + if (wxGetApp().suppress_round_corners()) + return dynamic_cast<::CheckBox*>(window)->GetValue(); + + return dynamic_cast<::SwitchButton*>(window)->GetValue(); +} + void CheckBox::BUILD() { auto size = wxSize(wxDefaultSize); - if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); - if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); + if (m_opt.height >= 0) + size.SetHeight(m_opt.height*m_em_unit); + if (m_opt.width >= 0) + size.SetWidth(m_opt.width*m_em_unit); bool check_value = m_opt.type == coBool ? m_opt.default_value->getBool() : m_opt.type == coBools ? @@ -695,21 +753,29 @@ void CheckBox::BUILD() { m_last_meaningful_value = static_cast(check_value); // Set Label as a string of at least one space simbol to correct system scaling of a CheckBox - auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(" "), wxDefaultPosition, size); - temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT); - temp->SetValue(check_value); - if (m_opt.readonly) temp->Disable(); + window = GetNewWin(m_parent); + wxGetApp().UpdateDarkUI(window); + window->SetFont(wxGetApp().normal_font()); + if (!wxOSX) + window->SetBackgroundStyle(wxBG_STYLE_PAINT); + if (m_opt.readonly) + window->Disable(); - temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { + SetValue(check_value); + + window->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent e) { m_is_na_val = false; on_change_field(); - }), temp->GetId()); + }); - temp->SetToolTip(get_tooltip_text(check_value ? "true" : "false")); + window->SetToolTip(get_tooltip_text(check_value ? "true" : "false")); +} - // recast as a wxWindow to fit the calling convention - window = dynamic_cast(temp); +void CheckBox::set_value(const bool value, bool change_event/* = false*/) +{ + m_disable_change_event = !change_event; + SetValue(value); + m_disable_change_event = false; } void CheckBox::set_value(const boost::any& value, bool change_event) @@ -719,10 +785,10 @@ void CheckBox::set_value(const boost::any& value, bool change_event) m_is_na_val = boost::any_cast(value) == ConfigOptionBoolsNullable::nil_value(); if (!m_is_na_val) m_last_meaningful_value = value; - dynamic_cast(window)->SetValue(m_is_na_val ? false : boost::any_cast(value) != 0); + SetValue(m_is_na_val ? false : boost::any_cast(value) != 0); } else - dynamic_cast(window)->SetValue(boost::any_cast(value)); + SetValue(boost::any_cast(value)); m_disable_change_event = false; } @@ -730,7 +796,7 @@ void CheckBox::set_last_meaningful_value() { if (m_opt.nullable) { m_is_na_val = false; - dynamic_cast(window)->SetValue(boost::any_cast(m_last_meaningful_value) != 0); + SetValue(boost::any_cast(m_last_meaningful_value) != 0); on_change_field(); } } @@ -739,15 +805,13 @@ void CheckBox::set_na_value() { if (m_opt.nullable) { m_is_na_val = true; - dynamic_cast(window)->SetValue(false); on_change_field(); } } boost::any& CheckBox::get_value() { -// boost::any m_value; - bool value = dynamic_cast(window)->GetValue(); + bool value = GetValue(); if (m_opt.type == coBool) m_value = static_cast(value); else @@ -761,6 +825,23 @@ void CheckBox::msw_rescale() window->SetInitialSize(window->GetBestSize()); } +void CheckBox::sys_color_changed() +{ + Field::sys_color_changed(); + if (auto switch_btn = dynamic_cast<::SwitchButton*>(window)) + switch_btn->SysColorChange(); +} + +void CheckBox::enable() +{ + window->Enable(); +} + +void CheckBox::disable() +{ + window->Disable(); +} + void SpinCtrl::BUILD() { auto size = wxSize(def_width() * m_em_unit, wxDefaultCoord); @@ -804,11 +885,9 @@ void SpinCtrl::BUILD() { ? (int)0 : (int)m_opt.min; const int max_val = m_opt.max < FLT_MAX ? (int)m_opt.max : INT_MAX; - auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, + auto temp = new ::SpinInput(m_parent, text_value, "", wxDefaultPosition, size, wxTE_PROCESS_ENTER | wxSP_ARROW_KEYS -#ifdef _WIN32 - | wxBORDER_SIMPLE -#endif + , min_val, max_val, default_value); #ifdef __WXGTK3__ @@ -823,14 +902,7 @@ void SpinCtrl::BUILD() { if (m_opt.height < 0 && parent_is_custom_ctrl) opt_height = (double)temp->GetSize().GetHeight() / m_em_unit; -// XXX: On OS X the wxSpinCtrl widget is made up of two subwidgets, unfortunatelly -// the kill focus event is not propagated to the encompassing widget, -// so we need to bind it on the inner text widget instead. (Ugh.) -#ifdef __WXOSX__ - temp->GetText()->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) -#else temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) -#endif { e.Skip(); if (bEnterPressed) { @@ -849,29 +921,16 @@ void SpinCtrl::BUILD() { propagate_value(); bEnterPressed = true; }), temp->GetId()); + temp->SetToolTip(get_tooltip_text(text_value)); - temp->Bind(wxEVT_TEXT, ([this, temp](wxCommandEvent e) - { -// # On OSX / Cocoa, wxSpinCtrl::GetValue() doesn't return the new value -// # when it was changed from the text control, so the on_change callback -// # gets the old one, and on_kill_focus resets the control to the old value. -// # As a workaround, we get the new value from $event->GetString and store -// # here temporarily so that we can return it from get_value() - - long value; - const bool parsed = e.GetString().ToLong(&value); - if (!parsed || value < INT_MIN || value > INT_MAX) + temp->Bind(wxEVT_TEXT, [this, temp](wxCommandEvent e) { + long value; + if (!e.GetString().ToLong(&value)) + return; + if (value < INT_MIN || value > INT_MAX) tmp_value = UNDEF_VALUE; else { tmp_value = std::min(std::max((int)value, temp->GetMin()), temp->GetMax()); -#ifdef __WXOSX__ - // Forcibly set the input value for SpinControl, since the value - // inserted from the keyboard or clipboard is not updated under OSX - temp->SetValue(tmp_value); - // But in SetValue() is executed m_text_ctrl->SelectAll(), so - // discard this selection and set insertion point to the end of string - temp->GetText()->SetInsertionPointEnd(); -#else // update value for the control only if it was changed in respect to the Min/max values if (tmp_value != (int)value) { temp->SetValue(tmp_value); @@ -880,11 +939,8 @@ void SpinCtrl::BUILD() { int pos = std::to_string(tmp_value).length(); temp->SetSelection(pos, pos); } -#endif } - }), temp->GetId()); - - temp->SetToolTip(get_tooltip_text(text_value)); + }, temp->GetId()); // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); @@ -898,35 +954,35 @@ void SpinCtrl::set_value(const boost::any& value, bool change_event/* = false*/) if (m_opt.nullable) { const bool m_is_na_val = tmp_value == ConfigOptionIntsNullable::nil_value(); if (m_is_na_val) - dynamic_cast(window)->SetValue(na_value(true)); + dynamic_cast<::SpinInput*>(window)->SetValue(na_value(true)); else { m_last_meaningful_value = value; - dynamic_cast(window)->SetValue(tmp_value); + dynamic_cast<::SpinInput*>(window)->SetValue(tmp_value); } } else - dynamic_cast(window)->SetValue(tmp_value); + dynamic_cast<::SpinInput*>(window)->SetValue(tmp_value); m_disable_change_event = false; } void SpinCtrl::set_last_meaningful_value() { const int val = boost::any_cast(m_last_meaningful_value); - dynamic_cast(window)->SetValue(val); + dynamic_cast<::SpinInput*>(window)->SetValue(val); tmp_value = val; propagate_value(); } void SpinCtrl::set_na_value() { - dynamic_cast(window)->SetValue(na_value(true)); + dynamic_cast<::SpinInput*>(window)->SetValue(na_value(true)); m_value = ConfigOptionIntsNullable::nil_value(); propagate_value(); } boost::any& SpinCtrl::get_value() { - wxSpinCtrl* spin = static_cast(window); + ::SpinInput* spin = static_cast<::SpinInput*>(window); if (spin->GetTextValue() == na_value(true)) return m_value; @@ -949,7 +1005,7 @@ void SpinCtrl::propagate_value() #ifdef __WXOSX__ // check input value for minimum if (m_opt.min > 0 && tmp_value < m_opt.min) { - wxSpinCtrl* spin = static_cast(window); + ::SpinInput* spin = static_cast<::SpinInput*>(window); spin->SetValue(m_opt.min); spin->GetText()->SetInsertionPointEnd(); } @@ -962,13 +1018,16 @@ void SpinCtrl::msw_rescale() { Field::msw_rescale(); - wxSpinCtrl* field = dynamic_cast(window); + auto field = dynamic_cast<::SpinInput*>(window); if (parent_is_custom_ctrl) field->SetSize(wxSize(def_width() * m_em_unit, lround(opt_height * m_em_unit))); else field->SetMinSize(wxSize(def_width() * m_em_unit, int(1.9f*field->GetFont().GetPixelSize().y))); } +#if 1 +using choice_ctrl = ::ComboBox; +#else #ifdef __WXOSX__ static_assert(wxMAJOR_VERSION >= 3, "Use of wxBitmapComboBox on Settings Tabs requires wxWidgets 3.0 and newer"); using choice_ctrl = wxBitmapComboBox; @@ -979,6 +1038,7 @@ using choice_ctrl = BitmapComboBox; using choice_ctrl = wxComboBox; #endif #endif // __WXOSX__ +#endif void Choice::BUILD() { wxSize size(def_width_wider() * m_em_unit, wxDefaultCoord); @@ -989,10 +1049,10 @@ void Choice::BUILD() { if (m_opt.gui_type != ConfigOptionDef::GUIType::undefined && m_opt.gui_type != ConfigOptionDef::GUIType::select_close) { m_is_editable = true; - temp = new choice_ctrl(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxTE_PROCESS_ENTER); + temp = new choice_ctrl(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxTE_PROCESS_ENTER | DD_NO_CHECK_ICON); } else { -#ifdef __WXOSX__ +#if 0 //#ifdef __WXOSX__ /* wxBitmapComboBox with wxCB_READONLY style return NULL for GetTextCtrl(), * so ToolTip doesn't shown. * Next workaround helps to solve this problem @@ -1001,7 +1061,7 @@ void Choice::BUILD() { temp->SetTextCtrlStyle(wxTE_READONLY); temp->Create(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr); #else - temp = new choice_ctrl(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxCB_READONLY); + temp = new choice_ctrl(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxCB_READONLY | DD_NO_CHECK_ICON); #endif //__WXOSX__ } @@ -1458,18 +1518,15 @@ void PointCtrl::BUILD() wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None); long style = wxTE_PROCESS_ENTER; -#ifdef _WIN32 - style |= wxBORDER_SIMPLE; -#endif - x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size, style); - y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size, style); + x_textctrl = new text_ctrl(m_parent, X, "", "", wxDefaultPosition, field_size, style); + y_textctrl = new text_ctrl(m_parent, Y, "", "", wxDefaultPosition, field_size, style); if (parent_is_custom_ctrl && m_opt.height < 0) opt_height = (double)x_textctrl->GetSize().GetHeight() / m_em_unit; x_textctrl->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - x_textctrl->SetBackgroundStyle(wxBG_STYLE_PAINT); + if (!wxOSX) x_textctrl->SetBackgroundStyle(wxBG_STYLE_PAINT); y_textctrl->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - y_textctrl->SetBackgroundStyle(wxBG_STYLE_PAINT); + if (!wxOSX) y_textctrl->SetBackgroundStyle(wxBG_STYLE_PAINT); auto static_text_x = new wxStaticText(m_parent, wxID_ANY, "x : "); auto static_text_y = new wxStaticText(m_parent, wxID_ANY, " y : "); @@ -1527,7 +1584,7 @@ void PointCtrl::sys_color_changed() #endif } -bool PointCtrl::value_was_changed(wxTextCtrl* win) +bool PointCtrl::value_was_changed(text_ctrl* win) { if (m_value.empty()) return true; @@ -1539,7 +1596,7 @@ bool PointCtrl::value_was_changed(wxTextCtrl* win) return boost::any_cast(m_value) != boost::any_cast(val); } -void PointCtrl::propagate_value(wxTextCtrl* win) +void PointCtrl::propagate_value(text_ctrl* win) { if (win->GetValue().empty()) on_kill_focus(); diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index bdc8199136..2d9625e499 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -25,6 +25,10 @@ #include "GUI.hpp" #include "wxExtensions.hpp" +#include "Widgets/CheckBox.hpp" +#include "Widgets/SwitchButton.hpp" +#include "Widgets/SpinInput.hpp" +#include "Widgets/TextInput.hpp" #ifdef __WXMSW__ #define wxMSW true @@ -294,6 +298,8 @@ inline bool is_window_field(const t_field& obj) { return !is_bad_field(obj) && o /// Covenience function to determine whether this field is a valid sizer field. inline bool is_sizer_field(const t_field& obj) { return !is_bad_field(obj) && obj->getSizer() != nullptr; } +using text_ctrl = ::TextInput; //wxTextCtrl + class TextCtrl : public Field { using Field::Field; #ifdef __WXGTK__ @@ -314,7 +320,7 @@ public: void set_value(const std::string& value, bool change_event = false) { m_disable_change_event = !change_event; - dynamic_cast(window)->SetValue(wxString(value)); + dynamic_cast(window)->SetValue(wxString(value)); m_disable_change_event = false; } void set_value(const boost::any& value, bool change_event = false) override; @@ -338,24 +344,31 @@ public: CheckBox(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} ~CheckBox() {} + static wxWindow* GetNewWin(wxWindow* parent, const wxString& label = wxEmptyString); + static void SetValue(wxWindow* win, bool value); + static bool GetValue(wxWindow* win); + static void Rescale(wxWindow* win); + static void SysColorChanged(wxWindow* win); + wxWindow* window{ nullptr }; void BUILD() override; - void set_value(const bool value, bool change_event = false) { - m_disable_change_event = !change_event; - dynamic_cast(window)->SetValue(value); - m_disable_change_event = false; - } + void set_value(const bool value, bool change_event = false); void set_value(const boost::any& value, bool change_event = false) override; void set_last_meaningful_value() override; void set_na_value() override; boost::any& get_value() override; void msw_rescale() override; + void sys_color_changed() override; - void enable() override { dynamic_cast(window)->Enable(); } - void disable() override { dynamic_cast(window)->Disable(); } + void enable() override; + void disable() override; wxWindow* getWindow() override { return window; } + +private: + void SetValue(bool value); + bool GetValue(); }; class SpinCtrl : public Field { @@ -377,20 +390,32 @@ public: /* void set_value(const std::string& value, bool change_event = false) { m_disable_change_event = !change_event; - dynamic_cast(window)->SetValue(value); + dynamic_cast<::SpinInput*>(window)->SetValue(value); m_disable_change_event = false; } + void set_value(const boost::any& value, bool change_event = false) override { + m_disable_change_event = !change_event; + tmp_value = boost::any_cast(value); + m_value = value; + dynamic_cast<::SpinInput*>(window)->SetValue(tmp_value); + m_disable_change_event = false; + } */ void set_value(const boost::any& value, bool change_event = false) override; void set_last_meaningful_value() override; void set_na_value() override; boost::any& get_value() override; - +/* + boost::any& get_value() override { + int value = static_cast<::SpinInput*>(window)->GetValue(); + return m_value = value; + } +*/ void msw_rescale() override; - void enable() override { dynamic_cast(window)->Enable(); } - void disable() override { dynamic_cast(window)->Disable(); } + void enable() override { dynamic_cast<::SpinInput*>(window)->Enable(); } + void disable() override { dynamic_cast<::SpinInput*>(window)->Disable(); } wxWindow* getWindow() override { return window; } }; @@ -466,13 +491,13 @@ public: ~PointCtrl(); wxSizer* sizer{ nullptr }; - wxTextCtrl* x_textctrl{ nullptr }; - wxTextCtrl* y_textctrl{ nullptr }; + text_ctrl* x_textctrl{ nullptr }; + text_ctrl* y_textctrl{ nullptr }; void BUILD() override; - bool value_was_changed(wxTextCtrl* win); + bool value_was_changed(text_ctrl* win); // Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER - void propagate_value(wxTextCtrl* win); + void propagate_value(text_ctrl* win); void set_value(const Vec2d& value, bool change_event = false); void set_value(const boost::any& value, bool change_event = false) override; boost::any& get_value() override; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 41745e843c..04c2c5c506 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1756,6 +1756,11 @@ 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 app_config->get("suppress_round_corners") == "1"; +} + wxSize GUI_App::get_min_size() const { return wxSize(76*m_em_unit, 49 * m_em_unit); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 039818e012..fb4e1d87ab 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -248,6 +248,7 @@ public: 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() const; float toolbar_icon_scale(const bool is_limited = false) const; void set_auto_toolbar_icon_scale(float scale) const; diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 0b7534b1d6..19b8b3e108 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -25,6 +25,8 @@ #include #include "slic3r/Utils/FixModelByWin10.hpp" +#include "Widgets/CheckBox.hpp" + // For special mirroring in manipulation gizmo #include "Gizmos/GLGizmosManager.hpp" #include "Gizmos/GLGizmoEmboss.hpp" @@ -77,7 +79,7 @@ static choice_ctrl* create_word_local_combo(wxWindow *parent) wxSize size(15 * wxGetApp().em_unit(), -1); choice_ctrl* temp = nullptr; -#ifdef __WXOSX__ +#if 0//def __WXOSX__ /* wxBitmapComboBox with wxCB_READONLY style return NULL for GetTextCtrl(), * so ToolTip doesn't shown. * Next workaround helps to solve this problem @@ -86,7 +88,7 @@ static choice_ctrl* create_word_local_combo(wxWindow *parent) temp->SetTextCtrlStyle(wxTE_READONLY); temp->Create(parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr); #else - temp = new choice_ctrl(parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxCB_READONLY | wxBORDER_SIMPLE); + temp = new choice_ctrl(parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxCB_READONLY/* | wxBORDER_SIMPLE*/); #endif //__WXOSX__ temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -137,7 +139,7 @@ void msw_rescale_word_local_combo(choice_ctrl* combo) static void set_font_and_background_style(wxWindow* win, const wxFont& font) { win->SetFont(font); - win->SetBackgroundStyle(wxBG_STYLE_PAINT); + if (!wxOSX) win->SetBackgroundStyle(wxBG_STYLE_PAINT); } static const wxString axes_color_text[] = { "#990000", "#009900", "#000099" }; @@ -495,16 +497,16 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : }); m_main_grid_sizer->Add(m_reset_skew_button); - m_check_inch = new wxCheckBox(parent, wxID_ANY, _L("Inches")); + m_check_inch = CheckBox::GetNewWin(parent, _L("Inches")); m_check_inch->SetFont(wxGetApp().normal_font()); - m_check_inch->SetValue(m_imperial_units); + CheckBox::SetValue(m_check_inch, m_imperial_units); m_check_inch->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { - wxGetApp().app_config->set("use_inches", m_check_inch->GetValue() ? "1" : "0"); + wxGetApp().app_config->set("use_inches", CheckBox::GetValue(m_check_inch) ? "1" : "0"); wxGetApp().sidebar().update_ui_from_settings(); }); - m_main_grid_sizer->Add(m_check_inch, 1, wxEXPAND); + m_main_grid_sizer->Add(m_check_inch); m_og->activate(); m_og->sizer->Clear(true); @@ -533,7 +535,7 @@ void ObjectManipulation::Show(const bool show) const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); bool show_world_local_combo = wxGetApp().get_mode() != comSimple && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()); if (selection.is_single_volume_or_modifier() && m_word_local_combo->GetCount() < 3) { -#ifdef __linux__ +#if 0//def __linux__ m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Local), 2); #else m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Local), wxNullBitmap, 2); @@ -615,7 +617,7 @@ void ObjectManipulation::update_ui_from_settings() update(3/*meSize*/, m_new_size); } } - m_check_inch->SetValue(m_imperial_units); + CheckBox::SetValue(m_check_inch, m_imperial_units); if (m_use_colors != wxGetApp().app_config->get_bool("color_mapinulation_panel")) { m_use_colors = wxGetApp().app_config->get_bool("color_mapinulation_panel"); @@ -1199,6 +1201,8 @@ void ObjectManipulation::sys_color_changed() wxGetApp().UpdateDarkUI(m_word_local_combo); wxGetApp().UpdateDarkUI(m_check_inch); #endif + + CheckBox::SysColorChanged(m_check_inch); for (ManipulationEditor* editor : m_editors) editor->sys_color_changed(this); @@ -1227,19 +1231,12 @@ static const char axes[] = { 'x', 'y', 'z' }; ManipulationEditor::ManipulationEditor(ObjectManipulation* parent, const std::string& opt_key, int axis) : - wxTextCtrl(parent->parent(), wxID_ANY, wxEmptyString, wxDefaultPosition, - wxSize((wxOSX ? 5 : 6)*int(wxGetApp().em_unit()), wxDefaultCoord), wxTE_PROCESS_ENTER -#ifdef _WIN32 - | wxBORDER_SIMPLE -#endif - ), + ::TextInput(parent->parent(), "", "", "", wxDefaultPosition, + wxSize(int(5.8 * wxGetApp().em_unit()), wxDefaultCoord), wxTE_PROCESS_ENTER), m_opt_key(opt_key), m_axis(axis) { set_font_and_background_style(this, wxGetApp().normal_font()); -#ifdef __WXOSX__ - this->OSXDisableAllSmartSubstitutions(); -#endif // __WXOSX__ if (parent->use_colors()) { this->SetBackgroundColour(wxColour(axes_color_back[axis])); this->SetForegroundColour(*wxBLACK); @@ -1295,8 +1292,7 @@ ManipulationEditor::ManipulationEditor(ObjectManipulation* parent, void ManipulationEditor::msw_rescale() { - const int em = wxGetApp().em_unit(); - SetMinSize(wxSize(5 * em, wxDefaultCoord)); + SetCtrlSize(wxSize(int(5.8 * wxGetApp().em_unit()), wxDefaultCoord)); } void ManipulationEditor::sys_color_changed(ObjectManipulation* parent) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 8952f7248d..96e006a6ba 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -13,6 +13,9 @@ #include "libslic3r/Point.hpp" #include +#include "Widgets/ComboBox.hpp" +#include "Widgets/TextInput.hpp" + #ifdef __WXOSX__ class wxBitmapComboBox; #else @@ -21,15 +24,17 @@ class wxComboBox; class wxStaticText; class LockButton; class wxStaticBitmap; -class wxCheckBox; namespace Slic3r { -namespace GUI { + namespace GUI { #ifdef _WIN32 -class BitmapComboBox; + class BitmapComboBox; #endif +#if 1 + using choice_ctrl = ::ComboBox; +#else #ifdef __WXOSX__ static_assert(wxMAJOR_VERSION >= 3, "Use of wxBitmapComboBox on Manipulation panel requires wxWidgets 3.0 and newer"); using choice_ctrl = wxBitmapComboBox; @@ -40,11 +45,12 @@ class BitmapComboBox; using choice_ctrl = wxComboBox; #endif #endif // __WXOSX__ +#endif class Selection; class ObjectManipulation; -class ManipulationEditor : public wxTextCtrl +class ManipulationEditor : public ::TextInput { std::string m_opt_key; int m_axis; @@ -128,7 +134,7 @@ private: ScalableButton* m_reset_skew_button{ nullptr }; ScalableButton* m_drop_to_bed_button{ nullptr }; - wxCheckBox* m_check_inch {nullptr}; + wxWindow* m_check_inch {nullptr}; std::array m_mirror_buttons; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 1ee12c1fb5..c6bb44851c 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -732,7 +732,7 @@ void MainFrame::init_tabpanel() #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); +// wxGetApp().UpdateDarkUI(m_tabpanel); } else m_tabpanel = new Notebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME, true); @@ -740,6 +740,8 @@ void MainFrame::init_tabpanel() m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME); #endif + wxGetApp().UpdateDarkUI(m_tabpanel); + #ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font()); #endif @@ -1107,7 +1109,6 @@ void MainFrame::on_sys_color_changed() wxGetApp().update_ui_colours_from_appconfig(); #ifdef __WXMSW__ wxGetApp().UpdateDarkUI(m_tabpanel); - // m_statusbar->update_dark_ui(); #ifdef _MSW_DARK_MODE // update common mode sizer if (!wxGetApp().tabs_as_menu()) @@ -2311,7 +2312,7 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe) this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); #else this->SetFont(wxGetApp().normal_font()); - this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +// this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); #endif // __WXMSW__ // Load the icon either from the exe, or from the ico file. diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index bf919a6f8f..b8c4151ad0 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -27,6 +27,8 @@ #include "slic3r/GUI/MainFrame.hpp" #include "GUI_App.hpp" +#include "Widgets/CheckBox.hpp" + namespace Slic3r { namespace GUI { @@ -268,7 +270,7 @@ RichMessageDialog::RichMessageDialog(wxWindow* parent, { add_msg_content(this, content_sizer, get_wraped_wxString(message)); - m_checkBox = new wxCheckBox(this, wxID_ANY, m_checkBoxText); + m_checkBox = new ::CheckBox(this, m_checkBoxText); wxGetApp().UpdateDarkUI(m_checkBox); m_checkBox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { m_checkBoxValue = m_checkBox->GetValue(); }); diff --git a/src/slic3r/GUI/MsgDialog.hpp b/src/slic3r/GUI/MsgDialog.hpp index cde5928425..96c7703755 100644 --- a/src/slic3r/GUI/MsgDialog.hpp +++ b/src/slic3r/GUI/MsgDialog.hpp @@ -17,7 +17,7 @@ #include class wxBoxSizer; -class wxCheckBox; +class CheckBox; class wxStaticBitmap; namespace Slic3r { @@ -132,7 +132,7 @@ public: // Generic rich message dialog, used intead of wxRichMessageDialog class RichMessageDialog : public MsgDialog { - wxCheckBox* m_checkBox{ nullptr }; + CheckBox* m_checkBox{ nullptr }; wxString m_checkBoxText; bool m_checkBoxValue{ false }; diff --git a/src/slic3r/GUI/OG_CustomCtrl.cpp b/src/slic3r/GUI/OG_CustomCtrl.cpp index ad38d68435..fb1cfc2138 100644 --- a/src/slic3r/GUI/OG_CustomCtrl.cpp +++ b/src/slic3r/GUI/OG_CustomCtrl.cpp @@ -686,7 +686,8 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_mode_bmp(wxDC& dc, wxCoord v_pos) return ctrl->m_h_gap; ConfigOptionMode mode = og_line.get_options()[0].opt.mode; - wxBitmapBundle* bmp = get_bmp_bundle("mode", wxOSX ? 10 : 12, wxGetApp().get_mode_btn_color(mode)); + int pix_cnt = wxOSX ? 10 : 12; + wxBitmapBundle* bmp = get_bmp_bundle("mode", pix_cnt, pix_cnt, wxGetApp().get_mode_btn_color(mode)); wxCoord y_draw = v_pos + lround((height - get_bitmap_size(bmp, ctrl).GetHeight()) / 2); if (og_line.get_options().front().opt.gui_type != ConfigOptionDef::GUIType::legend) diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 0fa39cd106..bf6c8571a3 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -288,6 +288,7 @@ void OptionsGroup::activate_line(Line& line) if (!custom_ctrl && m_use_custom_ctrl) { custom_ctrl = new OG_CustomCtrl(is_legend_line || !staticbox ? this->parent() : static_cast(this->stb), this); + wxGetApp().UpdateDarkUI(custom_ctrl); if (is_legend_line) sizer->Add(custom_ctrl, 0, wxEXPAND | wxLEFT, wxOSX ? 0 : 10); else diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 0bd5f21312..ddbe95a156 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -141,6 +141,8 @@ #include "libslic3r/CustomGCode.hpp" #include "libslic3r/Platform.hpp" +#include "Widgets/CheckBox.hpp" + using boost::optional; namespace fs = boost::filesystem; using Slic3r::_3DScene; @@ -800,7 +802,7 @@ Sidebar::Sidebar(Plater *parent) wxGetApp().UpdateDarkUI(this); wxGetApp().UpdateDarkUI(p->scrolled); #else - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +// SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); #endif #endif @@ -6112,7 +6114,7 @@ ProjectDropDialog::ProjectDropDialog(const std::string& filename) main_sizer->Add(stb_sizer, 1, wxEXPAND | wxRIGHT | wxLEFT, 10); wxBoxSizer* bottom_sizer = new wxBoxSizer(wxHORIZONTAL); - wxCheckBox* check = new wxCheckBox(this, wxID_ANY, _L("Don't show again")); + ::CheckBox* check = new ::CheckBox(this, _L("Don't show again")); check->Bind(wxEVT_CHECKBOX, [](wxCommandEvent& evt) { wxGetApp().app_config->set("show_drop_project_dialog", evt.IsChecked() ? "0" : "1"); }); diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 6fb2f23258..1e884e3fc0 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -212,7 +212,7 @@ void PreferencesDialog::build() #ifdef _WIN32 wxGetApp().UpdateDarkUI(this); #else - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + //SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); #endif const wxFont& font = wxGetApp().normal_font(); SetFont(font); @@ -223,7 +223,7 @@ void PreferencesDialog::build() tabs = new Notebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME | wxNB_DEFAULT); #else tabs = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL |wxNB_NOPAGETHEME | wxNB_DEFAULT ); - tabs->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +// tabs->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); #endif // Add "General" tab @@ -527,6 +527,13 @@ void PreferencesDialog::build() m_optgroup_gui->append_separator(); + append_bool_option(m_optgroup_gui, "suppress_round_corners", + L("Suppress round corners for controls (experimental)"), + L("If enabled, Settings Tabs will be placed as menu items. If disabled, old UI will be used."), + app_config->get("suppress_round_corners") == "1"); + + m_optgroup_gui->append_separator(); + append_bool_option(m_optgroup_gui, "show_hints", L("Show \"Tip of the day\" notification after start"), L("If enabled, useful hints are displayed at startup."), @@ -706,7 +713,7 @@ void PreferencesDialog::accept(wxEvent&) #endif // __linux__ } - std::vector options_to_recreate_GUI = { "no_defaults", "tabs_as_menu", "sys_menu_enabled", "font_size" }; + std::vector options_to_recreate_GUI = { "no_defaults", "tabs_as_menu", "sys_menu_enabled", "font_size", "suppress_round_corners" }; for (const std::string& option : options_to_recreate_GUI) { if (m_values.find(option) != m_values.end()) { diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index e31e47647b..224752bdff 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -45,6 +45,8 @@ #include "PhysicalPrinterDialog.hpp" #include "MsgDialog.hpp" +#include "Widgets/ComboBox.hpp" + // A workaround for a set of issues related to text fitting into gtk widgets: // See e.g.: https://github.com/prusa3d/PrusaSlicer/issues/4584 #if defined(__WXGTK20__) || defined(__WXGTK3__) @@ -437,6 +439,7 @@ void PresetComboBox::update_from_bundle() void PresetComboBox::msw_rescale() { m_em_unit = em_unit(this); + ::ComboBox::Rescale(); } void PresetComboBox::sys_color_changed() diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index 951e01b691..79b7ed70d4 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -525,9 +525,9 @@ SearchDialog::SearchDialog(OptionsSearcher* searcher) wxBoxSizer* check_sizer = new wxBoxSizer(wxHORIZONTAL); - check_category = new wxCheckBox(this, wxID_ANY, _L("Category")); + check_category = new ::CheckBox(this, _L("Category")); if (GUI::wxGetApp().is_localized()) - check_english = new wxCheckBox(this, wxID_ANY, _L("Search in English")); + check_english = new ::CheckBox(this, _L("Search in English")); wxStdDialogButtonSizer* cancel_btn = this->CreateStdDialogButtonSizer(wxCANCEL); GUI::wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CANCEL, this))); diff --git a/src/slic3r/GUI/Search.hpp b/src/slic3r/GUI/Search.hpp index 99c3b319e7..571448d492 100644 --- a/src/slic3r/GUI/Search.hpp +++ b/src/slic3r/GUI/Search.hpp @@ -24,6 +24,9 @@ #include "OptionsGroup.hpp" #include "libslic3r/Preset.hpp" +#include "Widgets/CheckBox.hpp" + +class CheckBox; namespace Slic3r { @@ -162,8 +165,8 @@ class SearchDialog : public GUI::DPIDialog wxTextCtrl* search_line { nullptr }; wxDataViewCtrl* search_list { nullptr }; SearchListModel* search_list_model { nullptr }; - wxCheckBox* check_category { nullptr }; - wxCheckBox* check_english { nullptr }; + CheckBox* check_category { nullptr }; + CheckBox* check_english { nullptr }; OptionsSearcher* searcher { nullptr }; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 4d279ebbeb..5199e45220 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -69,6 +69,8 @@ #include "MsgDialog.hpp" #include "Notebook.hpp" +#include "Widgets/CheckBox.hpp" + #ifdef WIN32 #include #endif // WIN32 @@ -82,7 +84,11 @@ Tab::Tab(wxBookCtrlBase* parent, const wxString& title, Preset::Type type) : Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL/*, name*/); this->SetFont(Slic3r::GUI::wxGetApp().normal_font()); +#ifdef __WXMSW__ wxGetApp().UpdateDarkUI(this); +#else + SetBackgroundColour(parent->GetBackgroundColour()); +#endif m_compatible_printers.type = Preset::TYPE_PRINTER; m_compatible_printers.key_list = "compatible_printers"; @@ -167,8 +173,6 @@ void Tab::create_preset_tab() } }); - auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - //buttons m_scaled_buttons.reserve(6); m_scaled_buttons.reserve(2); @@ -422,10 +426,6 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str } // Initialize the page. PageShp page(new Page(m_page_view, title, icon_idx)); -// page->SetBackgroundStyle(wxBG_STYLE_SYSTEM); -#ifdef __WINDOWS__ -// page->SetDoubleBuffered(true); -#endif //__WINDOWS__ if (!is_extruder_pages) m_pages.push_back(page); @@ -961,6 +961,11 @@ void Tab::msw_rescale() m_presets_choice->msw_rescale(); m_treectrl->SetMinSize(wxSize(20 * m_em_unit, -1)); + if (m_compatible_printers.checkbox) + CheckBox::Rescale(m_compatible_printers.checkbox); + if (m_compatible_prints.checkbox) + CheckBox::Rescale(m_compatible_prints.checkbox); + // rescale options_groups if (m_active_page) m_active_page->msw_rescale(); @@ -1939,21 +1944,23 @@ void TabFilament::create_line_with_near_label_widget(ConfigOptionsGroupShp optgr else line = optgroup->create_single_option_line(optgroup->get_option(opt_key)); - line.near_label_widget = [this, optgroup_wk = ConfigOptionsGroupWkp(optgroup), opt_key, opt_index](wxWindow* parent) { - wxCheckBox* check_box = new wxCheckBox(parent, wxID_ANY, ""); - check_box->Bind(wxEVT_CHECKBOX, [optgroup_wk, opt_key, opt_index](wxCommandEvent& evt) { - const bool is_checked = evt.IsChecked(); - if (auto optgroup_sh = optgroup_wk.lock(); optgroup_sh) { - if (Field *field = optgroup_sh->get_fieldc(opt_key, opt_index); field != nullptr) { - field->toggle(is_checked); - if (is_checked) - field->set_last_meaningful_value(); - else - field->set_na_value(); + line.near_label_widget = [this, optgroup_wk = ConfigOptionsGroupWkp(optgroup), opt_key, opt_index](wxWindow* parent) { + wxWindow* check_box = CheckBox::GetNewWin(parent); + wxGetApp().UpdateDarkUI(check_box); + + check_box->Bind(wxEVT_CHECKBOX, [optgroup_wk, opt_key, opt_index](wxCommandEvent& evt) { + const bool is_checked = evt.IsChecked(); + if (auto optgroup_sh = optgroup_wk.lock(); optgroup_sh) { + if (Field *field = optgroup_sh->get_fieldc(opt_key, opt_index); field != nullptr) { + field->toggle(is_checked); + if (is_checked) + field->set_last_meaningful_value(); + else + field->set_na_value(); + } } - } - }, check_box->GetId()); + }); m_overrides_options[opt_key] = check_box; return check_box; @@ -1969,7 +1976,7 @@ void TabFilament::update_line_with_near_label_widget(ConfigOptionsGroupShp optgr m_overrides_options[opt_key]->Enable(is_checked); is_checked &= !m_config->option(opt_key)->is_nil(); - m_overrides_options[opt_key]->SetValue(is_checked); + CheckBox::SetValue(m_overrides_options[opt_key], is_checked); Field* field = optgroup->get_fieldc(opt_key, opt_index); if (field != nullptr) @@ -2038,6 +2045,16 @@ void TabFilament::update_filament_overrides_page() { bool is_checked = opt_key=="filament_retract_length" ? true : have_retract_length; update_line_with_near_label_widget(optgroup, opt_key, extruder_idx, is_checked); +/* + m_overrides_options[opt_key]->Enable(is_checked); + + is_checked &= !m_config->option(opt_key)->is_nil(); + CheckBox::SetValue(m_overrides_options[opt_key], is_checked); + + Field* field = optgroup->get_fieldc(opt_key, extruder_idx); + if (field != nullptr) + field->toggle(is_checked); +*/ } og_it = std::find_if(page->m_optgroups.begin(), page->m_optgroups.end(), [](const ConfigOptionsGroupShp og) { return og->title == "Retraction when tool is disabled"; }); @@ -2399,6 +2416,9 @@ void TabFilament::clear_pages() m_volumetric_speed_description_line = nullptr; m_cooling_description_line = nullptr; + + for (auto& over_opt : m_overrides_options) + over_opt.second = nullptr; } void TabFilament::msw_rescale() @@ -2406,7 +2426,6 @@ void TabFilament::msw_rescale() for (const auto& over_opt : m_overrides_options) if (wxWindow* win = over_opt.second) win->SetInitialSize(win->GetBestSize()); - Tab::msw_rescale(); } @@ -2416,8 +2435,16 @@ void TabFilament::sys_color_changed() update_extruder_combobox(); Tab::sys_color_changed(); + + for (const auto& over_opt : m_overrides_options) + if (wxWindow* check_box = over_opt.second) { + wxGetApp().UpdateDarkUI(check_box); + CheckBox::SysColorChanged(check_box); + } } + + void TabFilament::load_current_preset() { const std::string& selected_filament_name = m_presets->get_selected_preset_name(); @@ -4463,9 +4490,9 @@ void Tab::create_line_with_widget(ConfigOptionsGroup* optgroup, const std::strin // Return a callback to create a Tab widget to mark the preferences as compatible / incompatible to the current printer. wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &deps) { - deps.checkbox = new wxCheckBox(parent, wxID_ANY, _(L("All"))); + deps.checkbox = CheckBox::GetNewWin(parent, _L("All")); deps.checkbox->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - wxGetApp().UpdateDarkUI(deps.checkbox, false, true); + wxGetApp().UpdateDarkUI(deps.checkbox); deps.btn = new ScalableButton(parent, wxID_ANY, "printer", format_wxstr(" %s %s", _L("Set"), dots), wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT); deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -4477,11 +4504,12 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep deps.checkbox->Bind(wxEVT_CHECKBOX, ([this, &deps](wxCommandEvent e) { - deps.btn->Enable(! deps.checkbox->GetValue()); + const bool is_checked = CheckBox::GetValue(deps.checkbox); + deps.btn->Enable(!is_checked); // All printers have been made compatible with this preset. - if (deps.checkbox->GetValue()) + if (is_checked) this->load_key_value(deps.key_list, std::vector {}); - this->get_field(deps.key_condition)->toggle(deps.checkbox->GetValue()); + this->get_field(deps.key_condition)->toggle(is_checked); this->update_changed_ui(); }) ); @@ -4524,7 +4552,7 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep for (auto idx : selections) value.push_back(presets[idx].ToUTF8().data()); if (value.empty()) { - deps.checkbox->SetValue(1); + CheckBox::SetValue(deps.checkbox, true); deps.btn->Disable(); } // All depending_presets have been made compatible with this preset. @@ -4646,11 +4674,7 @@ void SubstitutionManager::add_substitution( int substitution_id, auto top_sizer = new wxBoxSizer(wxHORIZONTAL); auto add_text_editor = [substitution_id, top_sizer, this](const wxString& value, int opt_pos, int proportion) { - auto editor = new wxTextCtrl(m_parent, wxID_ANY, value, wxDefaultPosition, wxSize(15 * m_em, wxDefaultCoord), wxTE_PROCESS_ENTER -#ifdef _WIN32 - | wxBORDER_SIMPLE -#endif - ); + auto editor = new ::TextInput(m_parent, value, "", "", wxDefaultPosition, wxSize(15 * m_em, wxDefaultCoord), wxTE_PROCESS_ENTER); editor->SetFont(wxGetApp().normal_font()); wxGetApp().UpdateDarkUI(editor); @@ -4679,39 +4703,39 @@ void SubstitutionManager::add_substitution( int substitution_id, bool whole_word = strchr(params.c_str(), 'w') != nullptr || strchr(params.c_str(), 'W') != nullptr; bool match_single_line = strchr(params.c_str(), 's') != nullptr || strchr(params.c_str(), 'S') != nullptr; - auto chb_regexp = new wxCheckBox(m_parent, wxID_ANY, _L("Regular expression")); - chb_regexp->SetValue(regexp); + auto chb_regexp = CheckBox::GetNewWin(m_parent, _L("Regular expression")); + CheckBox::SetValue(chb_regexp, regexp); params_sizer->Add(chb_regexp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, m_em); - auto chb_case_insensitive = new wxCheckBox(m_parent, wxID_ANY, _L("Case insensitive")); - chb_case_insensitive->SetValue(case_insensitive); + auto chb_case_insensitive = CheckBox::GetNewWin(m_parent, _L("Case insensitive")); + CheckBox::SetValue(chb_case_insensitive, case_insensitive); params_sizer->Add(chb_case_insensitive, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, m_em); - auto chb_whole_word = new wxCheckBox(m_parent, wxID_ANY, _L("Whole word")); - chb_whole_word->SetValue(whole_word); + auto chb_whole_word = CheckBox::GetNewWin(m_parent, _L("Whole word")); + CheckBox::SetValue(chb_whole_word, whole_word); params_sizer->Add(chb_whole_word, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, m_em); - auto chb_match_single_line = new wxCheckBox(m_parent, wxID_ANY, _L("Match single line")); - chb_match_single_line->SetValue(match_single_line); + auto chb_match_single_line = CheckBox::GetNewWin(m_parent, _L("Match single line")); + CheckBox::SetValue(chb_match_single_line, match_single_line); chb_match_single_line->Show(regexp); m_chb_match_single_lines.emplace_back(chb_match_single_line); params_sizer->Add(chb_match_single_line, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, m_em); - for (wxCheckBox* chb : std::initializer_list{ chb_regexp, chb_case_insensitive, chb_whole_word, chb_match_single_line }) { + for (wxWindow* chb : std::initializer_list{ chb_regexp, chb_case_insensitive, chb_whole_word, chb_match_single_line }) { chb->SetFont(wxGetApp().normal_font()); chb->Bind(wxEVT_CHECKBOX, [this, substitution_id, chb_regexp, chb_case_insensitive, chb_whole_word, chb_match_single_line](wxCommandEvent e) { std::string value = std::string(); - if (chb_regexp->GetValue()) + if (CheckBox::GetValue(chb_regexp)) value += "r"; - if (chb_case_insensitive->GetValue()) + if (CheckBox::GetValue(chb_case_insensitive)) value += "i"; - if (chb_whole_word->GetValue()) + if (CheckBox::GetValue(chb_whole_word)) value += "w"; - if (chb_match_single_line->GetValue()) + if (CheckBox::GetValue(chb_match_single_line)) value += "s"; - chb_match_single_line->Show(chb_regexp->GetValue()); + chb_match_single_line->Show(CheckBox::GetValue(chb_regexp)); m_grid_sizer->Layout(); edit_substitution(substitution_id, 2, value); @@ -4978,7 +5002,7 @@ void Tab::compatible_widget_reload(PresetDependencies &deps) bool has_any = ! m_config->option(deps.key_list)->values.empty(); has_any ? deps.btn->Enable() : deps.btn->Disable(); - deps.checkbox->SetValue(! has_any); + CheckBox::SetValue(deps.checkbox, !has_any); field->toggle(! has_any); } diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 1b8dc99bc5..69ac11f95c 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -51,6 +51,8 @@ #include "OptionsGroup.hpp" #include "libslic3r/Preset.hpp" +class CheckBox; + namespace Slic3r { namespace GUI { @@ -202,7 +204,7 @@ protected: struct PresetDependencies { Preset::Type type = Preset::TYPE_INVALID; - wxCheckBox *checkbox = nullptr; + wxWindow *checkbox = nullptr; ScalableButton *btn = nullptr; std::string key_list; // "compatible_printers" std::string key_condition; @@ -473,7 +475,7 @@ class TabFilament : public Tab void create_extruder_combobox(); void update_volumetric_flow_preset_hints(); - std::map m_overrides_options; + std::map m_overrides_options; public: TabFilament(wxBookCtrlBase* parent) : Tab(parent, _(L("Filament Settings")), Slic3r::Preset::TYPE_FILAMENT) {} diff --git a/src/slic3r/GUI/Widgets/BitmapToggleButton.cpp b/src/slic3r/GUI/Widgets/BitmapToggleButton.cpp new file mode 100644 index 0000000000..4531446665 --- /dev/null +++ b/src/slic3r/GUI/Widgets/BitmapToggleButton.cpp @@ -0,0 +1,47 @@ +#include "BitmapToggleButton.hpp" + +#include + +BitmapToggleButton::BitmapToggleButton(wxWindow* parent, const wxString& label, wxWindowID id) +{ +#ifdef __linux__ + long style = wxBORDER_NONE | wxBU_EXACTFIT; + if (label.IsEmpty()) + style = style | wxBU_NOTEXT; + // Call Create() from wxToggleButton instead of wxBitmapToggleButton to allow add Label text under Linux + wxToggleButton::Create(parent, id, label, wxDefaultPosition, wxDefaultSize, style); +#else + wxBitmapToggleButton::Create(parent, id, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE | wxBU_EXACTFIT); + if (!label.IsEmpty()) + SetLabel(label); +#endif + +#ifdef __WXMSW__ + if (parent) { + SetBackgroundColour(parent->GetBackgroundColour()); + SetForegroundColour(parent->GetForegroundColour()); + } +#elif __linux__ + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif + + Bind(wxEVT_TOGGLEBUTTON, [this](auto& e) { + update(); + + wxCommandEvent evt(wxEVT_CHECKBOX); + evt.SetInt(int(GetValue())); + wxPostEvent(this, evt); + + e.Skip(); + }); +} + +void BitmapToggleButton::update_size() +{ +#ifdef __linux__ + if (GetLabel().IsEmpty()) + SetSize(GetBitmap().GetSize()); + else +#endif + SetSize(GetBestSize()); +} diff --git a/src/slic3r/GUI/Widgets/BitmapToggleButton.hpp b/src/slic3r/GUI/Widgets/BitmapToggleButton.hpp new file mode 100644 index 0000000000..db653e03fb --- /dev/null +++ b/src/slic3r/GUI/Widgets/BitmapToggleButton.hpp @@ -0,0 +1,17 @@ +#ifndef slic3r_GUI_BitmapToggleButton_hpp_ +#define slic3r_GUI_BitmapToggleButton_hpp_ + +#include + +class BitmapToggleButton : public wxBitmapToggleButton +{ + virtual void update() = 0; + +public: + BitmapToggleButton(wxWindow * parent = NULL, const wxString& label = wxEmptyString, wxWindowID id = wxID_ANY); + +protected: + void update_size(); +}; + +#endif // !slic3r_GUI_BitmapToggleButton_hpp_ diff --git a/src/slic3r/GUI/Widgets/Button.cpp b/src/slic3r/GUI/Widgets/Button.cpp index fa1dc15ee2..10e2819b05 100644 --- a/src/slic3r/GUI/Widgets/Button.cpp +++ b/src/slic3r/GUI/Widgets/Button.cpp @@ -1,7 +1,8 @@ #include "Button.hpp" -#include "Label.hpp" #include +#include +#include BEGIN_EVENT_TABLE(Button, StaticBox) @@ -36,23 +37,20 @@ Button::Button() std::make_pair(*wxBLACK, (int) StateColor::Normal)); } -Button::Button(wxWindow* parent, wxString text, wxString icon, long style, int iconSize) +Button::Button(wxWindow* parent, wxString text, wxString icon, long style, wxSize iconSize/* = wxSize(16, 16)*/) : Button() { Create(parent, text, icon, style, iconSize); } -bool Button::Create(wxWindow* parent, wxString text, wxString icon, long style, int iconSize) +bool Button::Create(wxWindow* parent, wxString text, wxString icon, long style, wxSize iconSize/* = wxSize(16, 16)*/) { StaticBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style); state_handler.attach({&text_color}); state_handler.update_binds(); - //BBS set default font - SetFont(Label::Body_14); wxWindow::SetLabel(text); if (!icon.IsEmpty()) { - //BBS set button icon default size to 20 - this->active_icon = ScalableBitmap(this, icon.ToStdString(), iconSize > 0 ? iconSize : 20); + this->active_icon = ScalableBitmap(this, icon.ToStdString(), iconSize); } messureSize(); return true; @@ -68,8 +66,7 @@ void Button::SetLabel(const wxString& label) void Button::SetIcon(const wxString& icon) { if (!icon.IsEmpty()) { - //BBS set button icon default size to 20 - this->active_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_cnt()); + this->active_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_size()); } else { @@ -81,8 +78,7 @@ void Button::SetIcon(const wxString& icon) void Button::SetInactiveIcon(const wxString &icon) { if (!icon.IsEmpty()) { - // BBS set button icon default size to 20 - this->inactive_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_cnt()); + this->inactive_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_size()); } else { this->inactive_icon = ScalableBitmap(); } @@ -129,12 +125,12 @@ void Button::SetCanFocus(bool canFocus) { this->canFocus = canFocus; } void Button::Rescale() { - if (this->active_icon.bmp().IsOk()) +/* if (this->active_icon.bmp().IsOk()) this->active_icon.msw_rescale(); if (this->inactive_icon.bmp().IsOk()) this->inactive_icon.msw_rescale(); - +*/ messureSize(); } @@ -162,6 +158,7 @@ void Button::render(wxDC& dc) ScalableBitmap icon; if (m_selected || ((states & (int)StateColor::State::Hovered) != 0)) +// if (m_selected || (states & (int)StateColor::State::Hovered)) icon = active_icon; else icon = inactive_icon; @@ -171,7 +168,7 @@ void Button::render(wxDC& dc) //BBS norrow size between text and icon szContent.x += padding; } - szIcon = icon.GetBmpSize(); + szIcon = icon.GetSize(); szContent.x += szIcon.x; if (szIcon.y > szContent.y) szContent.y = szIcon.y; @@ -190,7 +187,7 @@ void Button::render(wxDC& dc) wxPoint pt = rcContent.GetLeftTop(); if (icon.bmp().IsOk()) { pt.y += (rcContent.height - szIcon.y) / 2; - dc.DrawBitmap(icon.bmp(), pt); + dc.DrawBitmap(icon.get_bitmap(), pt); //BBS norrow size between text and icon pt.x += szIcon.x + padding; pt.y = rcContent.y; @@ -220,7 +217,7 @@ void Button::messureSize() //BBS norrow size between text and icon szContent.x += 5; } - wxSize szIcon = this->active_icon.GetBmpSize(); + wxSize szIcon = this->active_icon.GetSize(); szContent.x += szIcon.x; if (szIcon.y > szContent.y) szContent.y = szIcon.y; diff --git a/src/slic3r/GUI/Widgets/Button.hpp b/src/slic3r/GUI/Widgets/Button.hpp index 43aac6b9fb..249989ddff 100644 --- a/src/slic3r/GUI/Widgets/Button.hpp +++ b/src/slic3r/GUI/Widgets/Button.hpp @@ -24,9 +24,9 @@ class Button : public StaticBox public: Button(); - Button(wxWindow* parent, wxString text, wxString icon = "", long style = 0, int iconSize = 0); + Button(wxWindow* parent, wxString text, wxString icon = "", long style = 0, wxSize iconSize = wxSize(16, 16)); - bool Create(wxWindow* parent, wxString text, wxString icon = "", long style = 0, int iconSize = 0); + bool Create(wxWindow* parent, wxString text, wxString icon = "", long style = 0, wxSize iconSize = wxSize(16, 16)); void SetLabel(const wxString& label) override; diff --git a/src/slic3r/GUI/Widgets/CheckBox.cpp b/src/slic3r/GUI/Widgets/CheckBox.cpp index 4ca1ca5ba0..627f1d0971 100644 --- a/src/slic3r/GUI/Widgets/CheckBox.cpp +++ b/src/slic3r/GUI/Widgets/CheckBox.cpp @@ -1,31 +1,25 @@ #include "CheckBox.hpp" -#include "../wxExtensions.hpp" +//#include "../wxExtensions.hpp" -CheckBox::CheckBox(wxWindow* parent) - : wxBitmapToggleButton(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE) - , m_on(this, "check_on", 18) - , m_half(this, "check_half", 18) - , m_off(this, "check_off", 18) - , m_on_disabled(this, "check_on_disabled", 18) - , m_half_disabled(this, "check_half_disabled", 18) - , m_off_disabled(this, "check_off_disabled", 18) - , m_on_focused(this, "check_on_focused", 18) - , m_half_focused(this, "check_half_focused", 18) - , m_off_focused(this, "check_off_focused", 18) +const int px_cnt = 16; + +CheckBox::CheckBox(wxWindow* parent, const wxString& name) + : BitmapToggleButton(parent, name, wxID_ANY) + , m_on(this, "check_on", px_cnt) + , m_off(this, "check_off", px_cnt) + , m_on_disabled(this, "check_on_disabled", px_cnt) + , m_off_disabled(this, "check_off_disabled", px_cnt) + , m_on_focused(this, "check_on_focused", px_cnt) + , m_off_focused(this, "check_off_focused", px_cnt) { - //SetBackgroundStyle(wxBG_STYLE_TRANSPARENT); - if (parent) - SetBackgroundColour(parent->GetBackgroundColour()); - Bind(wxEVT_TOGGLEBUTTON, [this](auto& e) { m_half_checked = false; update(); e.Skip(); }); #ifdef __WXOSX__ // State not fully implement on MacOS Bind(wxEVT_SET_FOCUS, &CheckBox::updateBitmap, this); Bind(wxEVT_KILL_FOCUS, &CheckBox::updateBitmap, this); Bind(wxEVT_ENTER_WINDOW, &CheckBox::updateBitmap, this); Bind(wxEVT_LEAVE_WINDOW, &CheckBox::updateBitmap, this); #endif - SetSize(m_on.GetBmpSize()); - SetMinSize(m_on.GetBmpSize()); + update(); } @@ -35,61 +29,59 @@ void CheckBox::SetValue(bool value) update(); } -void CheckBox::SetHalfChecked(bool value) +void CheckBox::Update() { - m_half_checked = value; - update(); + update(); } void CheckBox::Rescale() { - m_on.msw_rescale(); - m_half.msw_rescale(); - m_off.msw_rescale(); - m_on_disabled.msw_rescale(); - m_half_disabled.msw_rescale(); - m_off_disabled.msw_rescale(); - m_on_focused.msw_rescale(); - m_half_focused.msw_rescale(); - m_off_focused.msw_rescale(); - SetSize(m_on.GetBmpSize()); update(); } void CheckBox::update() { - SetBitmapLabel((m_half_checked ? m_half : GetValue() ? m_on : m_off).bmp()); - SetBitmapDisabled((m_half_checked ? m_half_disabled : GetValue() ? m_on_disabled : m_off_disabled).bmp()); + const bool val = GetValue(); + const wxBitmapBundle& bmp = (val ? m_on : m_off).bmp(); + SetBitmap(bmp); + SetBitmapCurrent(bmp); + SetBitmapDisabled((val ? m_on_disabled : m_off_disabled).bmp()); #ifdef __WXMSW__ - SetBitmapFocus((m_half_checked ? m_half_focused : GetValue() ? m_on_focused : m_off_focused).bmp()); + SetBitmapFocus((val ? m_on_focused : m_off_focused).bmp()); #endif - SetBitmapCurrent((m_half_checked ? m_half_focused : GetValue() ? m_on_focused : m_off_focused).bmp()); #ifdef __WXOSX__ wxCommandEvent e(wxEVT_UPDATE_UI); updateBitmap(e); #endif + + update_size(); } #ifdef __WXMSW__ -CheckBox::State CheckBox::GetNormalState() const { return State_Normal; } +CheckBox::State CheckBox::GetNormalState() const +{ + return State_Normal; +} #endif - -#ifdef __WXOSX__ - bool CheckBox::Enable(bool enable) { bool result = wxBitmapToggleButton::Enable(enable); + +#ifdef __WXOSX__ if (result) { m_disable = !enable; wxCommandEvent e(wxEVT_ACTIVATE); updateBitmap(e); } +#endif return result; } +#ifdef __WXOSX__ + wxBitmap CheckBox::DoGetBitmap(State which) const { if (m_disable) { diff --git a/src/slic3r/GUI/Widgets/CheckBox.hpp b/src/slic3r/GUI/Widgets/CheckBox.hpp index 53c41b6470..727bbce9b5 100644 --- a/src/slic3r/GUI/Widgets/CheckBox.hpp +++ b/src/slic3r/GUI/Widgets/CheckBox.hpp @@ -2,25 +2,20 @@ #define slic3r_GUI_CheckBox_hpp_ #include "../wxExtensions.hpp" +#include "BitmapToggleButton.hpp" -#include - -class CheckBox : public wxBitmapToggleButton +class CheckBox : public BitmapToggleButton { public: - CheckBox(wxWindow * parent = NULL); + CheckBox(wxWindow* parent = NULL, const wxString& name = wxEmptyString); public: void SetValue(bool value) override; - - void SetHalfChecked(bool value = true); + void Update() override; + bool Enable(bool enable = true) override; void Rescale(); -#ifdef __WXOSX__ - virtual bool Enable(bool enable = true) wxOVERRIDE; -#endif - protected: #ifdef __WXMSW__ virtual State GetNormalState() const wxOVERRIDE; @@ -37,19 +32,14 @@ protected: #endif private: - void update(); + void update() override; -private: - ScalableBitmap m_on; - ScalableBitmap m_half; - ScalableBitmap m_off; - ScalableBitmap m_on_disabled; - ScalableBitmap m_half_disabled; - ScalableBitmap m_off_disabled; - ScalableBitmap m_on_focused; - ScalableBitmap m_half_focused; - ScalableBitmap m_off_focused; - bool m_half_checked = false; + ScalableBitmap m_on; + ScalableBitmap m_off; + ScalableBitmap m_on_disabled; + ScalableBitmap m_off_disabled; + ScalableBitmap m_on_focused; + ScalableBitmap m_off_focused; }; #endif // !slic3r_GUI_CheckBox_hpp_ diff --git a/src/slic3r/GUI/Widgets/ComboBox.cpp b/src/slic3r/GUI/Widgets/ComboBox.cpp index 01d7d9614c..68fc6ee8c5 100644 --- a/src/slic3r/GUI/Widgets/ComboBox.cpp +++ b/src/slic3r/GUI/Widgets/ComboBox.cpp @@ -1,11 +1,13 @@ #include "ComboBox.hpp" -#include "Label.hpp" +#include "UIColors.hpp" #include +#include "../GUI_App.hpp" + BEGIN_EVENT_TABLE(ComboBox, TextInput) -EVT_LEFT_DOWN(ComboBox::mouseDown) + EVT_LEFT_DOWN(ComboBox::mouseDown) //EVT_MOUSEWHEEL(ComboBox::mouseWheelMoved) EVT_KEY_DOWN(ComboBox::keyDown) @@ -28,27 +30,23 @@ ComboBox::ComboBox(wxWindow * parent, long style) : drop(texts, icons) { - if (style & wxCB_READONLY) - style |= wxRIGHT; text_off = style & CB_NO_TEXT; TextInput::Create(parent, "", value, (style & CB_NO_DROP_ICON) ? "" : "drop_down", pos, size, style | wxTE_PROCESS_ENTER); - drop.Create(this, style & DD_STYLE_MASK); + drop.Create(this, style); - if (style & wxCB_READONLY) { + SetFont(Slic3r::GUI::wxGetApp().normal_font()); + if (style & wxCB_READONLY) GetTextCtrl()->Hide(); - TextInput::SetFont(Label::Body_14); - TextInput::SetBorderColor(StateColor(std::make_pair(0xDBDBDB, (int) StateColor::Disabled), - std::make_pair(0x00AE42, (int) StateColor::Hovered), - std::make_pair(0xDBDBDB, (int) StateColor::Normal))); - TextInput::SetBackgroundColor(StateColor(std::make_pair(0xF0F0F0, (int) StateColor::Disabled), - std::make_pair(0xEDFAF2, (int) StateColor::Focused), - std::make_pair(*wxWHITE, (int) StateColor::Normal))); - TextInput::SetLabelColor(StateColor(std::make_pair(0x909090, (int) StateColor::Disabled), - std::make_pair(0x262E30, (int) StateColor::Normal))); - } else { + else GetTextCtrl()->Bind(wxEVT_KEY_DOWN, &ComboBox::keyDown, this); + + SetBorderColor(TextInput::GetBorderColor()); + if (parent) { + SetBackgroundColour(parent->GetBackgroundColour()); + SetForegroundColour(parent->GetForegroundColour()); } + drop.Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &e) { SetSelection(e.GetInt()); e.SetEventObject(this); @@ -75,6 +73,8 @@ void ComboBox::SetSelection(int n) void ComboBox::Rescale() { + SetFont(Slic3r::GUI::wxGetApp().normal_font()); + TextInput::Rescale(); drop.Rescale(); } @@ -120,27 +120,74 @@ wxString ComboBox::GetTextLabel() const bool ComboBox::SetFont(wxFont const& font) { + const bool set_drop_font = drop.SetFont(font); if (GetTextCtrl() && GetTextCtrl()->IsShown()) - return GetTextCtrl()->SetFont(font); - else - return TextInput::SetFont(font); + return GetTextCtrl()->SetFont(font) && set_drop_font; + return TextInput::SetFont(font) && set_drop_font; } -int ComboBox::Append(const wxString &item, const wxBitmap &bitmap) +bool ComboBox::SetBackgroundColour(const wxColour& colour) +{ + TextInput::SetBackgroundColour(colour); + + drop.SetBackgroundColour(colour); + drop.SetSelectorBackgroundColor(background_color); + + return true; +} + +bool ComboBox::SetForegroundColour(const wxColour& colour) +{ + TextInput::SetForegroundColour(colour); + + drop.SetTextColor(TextInput::GetTextColor()); + + return true; +} + +void ComboBox::SetBorderColor(StateColor const& color) +{ + TextInput::SetBorderColor(color); + drop.SetBorderColor(color); + drop.SetSelectorBorderColor(color); +} + +int ComboBox::Append(const wxString &item, const wxBitmapBundle &bitmap) { return Append(item, bitmap, nullptr); } -int ComboBox::Append(const wxString &item, - const wxBitmap &bitmap, - void * clientData) +int ComboBox::Append(const wxString &item, + const wxBitmapBundle &bitmap, + void * clientData) { texts.push_back(item); icons.push_back(bitmap); datas.push_back(clientData); types.push_back(wxClientData_None); drop.Invalidate(); - return texts.size() - 1; + return int(texts.size()) - 1; +} + +int ComboBox::Insert(const wxString& item, + const wxBitmapBundle& bitmap, + unsigned int pos) +{ + return Insert(item, bitmap, pos, nullptr); +} + +int ComboBox::Insert(const wxString& item, const wxBitmapBundle& bitmap, + unsigned int pos, void* clientData) +{ + const int n = wxItemContainer::Insert(item, pos); + if (n != wxNOT_FOUND) { + texts.insert(texts.begin() + n, item); + icons.insert(icons.begin() + n, bitmap); + datas.insert(datas.begin() + n, clientData); + types.insert(types.begin() + n, wxClientData_None); + drop.Invalidate(); + } + return n; } void ComboBox::DoClear() @@ -174,10 +221,13 @@ void ComboBox::SetString(unsigned int n, wxString const &value) if (n >= texts.size()) return; texts[n] = value; drop.Invalidate(); - if (n == drop.GetSelection()) SetLabel(value); + if (int(n) == drop.GetSelection()) SetLabel(value); } -wxBitmap ComboBox::GetItemBitmap(unsigned int n) { return icons[n]; } +wxBitmap ComboBox::GetItemBitmap(unsigned int n) +{ + return icons[n].GetBitmapFor(m_parent); +} int ComboBox::DoInsertItems(const wxArrayStringsAdapter &items, unsigned int pos, @@ -185,7 +235,7 @@ int ComboBox::DoInsertItems(const wxArrayStringsAdapter &items, wxClientDataType type) { if (pos > texts.size()) return -1; - for (int i = 0; i < items.GetCount(); ++i) { + for (size_t i = 0; i < items.GetCount(); ++i) { texts.insert(texts.begin() + pos, items[i]); icons.insert(icons.begin() + pos, wxNullBitmap); datas.insert(datas.begin() + pos, clientData ? clientData[i] : NULL); @@ -193,7 +243,7 @@ int ComboBox::DoInsertItems(const wxArrayStringsAdapter &items, ++pos; } drop.Invalidate(true); - return pos - 1; + return int(pos) - 1; } void *ComboBox::DoGetItemClientData(unsigned int n) const { return n < texts.size() ? datas[n] : NULL; } @@ -232,8 +282,11 @@ void ComboBox::mouseWheelMoved(wxMouseEvent &event) void ComboBox::keyDown(wxKeyEvent& event) { - switch (event.GetKeyCode()) { + int key_code = event.GetKeyCode(); + switch (key_code) { +#ifndef __WXOSX__ case WXK_RETURN: +#endif case WXK_SPACE: if (drop_down) { drop.DismissAndNotify(); @@ -251,7 +304,7 @@ void ComboBox::keyDown(wxKeyEvent& event) case WXK_RIGHT: if ((event.GetKeyCode() == WXK_UP || event.GetKeyCode() == WXK_LEFT) && GetSelection() > 0) { SetSelection(GetSelection() - 1); - } else if ((event.GetKeyCode() == WXK_DOWN || event.GetKeyCode() == WXK_RIGHT) && GetSelection() + 1 < texts.size()) { + } else if ((event.GetKeyCode() == WXK_DOWN || event.GetKeyCode() == WXK_RIGHT) && GetSelection() + 1 < int(texts.size())) { SetSelection(GetSelection() + 1); } else { break; diff --git a/src/slic3r/GUI/Widgets/ComboBox.hpp b/src/slic3r/GUI/Widgets/ComboBox.hpp index 0a8e018dce..7ba9911228 100644 --- a/src/slic3r/GUI/Widgets/ComboBox.hpp +++ b/src/slic3r/GUI/Widgets/ComboBox.hpp @@ -4,13 +4,13 @@ #include "TextInput.hpp" #include "DropDown.hpp" -#define CB_NO_DROP_ICON DD_NO_CHECK_ICON +#define CB_NO_DROP_ICON DD_NO_DROP_ICON #define CB_NO_TEXT DD_NO_TEXT class ComboBox : public wxWindowWithItems { std::vector texts; - std::vector icons; + std::vector icons; std::vector datas; std::vector types; @@ -32,10 +32,18 @@ public: virtual bool SetFont(wxFont const & font) override; -public: - int Append(const wxString &item, const wxBitmap &bitmap = wxNullBitmap); + bool SetBackgroundColour(const wxColour& colour) override; + bool SetForegroundColour(const wxColour& colour) override; - int Append(const wxString &item, const wxBitmap &bitmap, void *clientData); + void SetBorderColor(StateColor const& color); + + int Append(const wxString &item, const wxBitmapBundle &bitmap = wxNullBitmap); + + int Append(const wxString &item, const wxBitmapBundle &bitmap, void *clientData); + + int Insert(const wxString& item, const wxBitmapBundle& bitmap, unsigned int pos); + int Insert(const wxString& item, const wxBitmapBundle& bitmap, + unsigned int pos, void* clientData); unsigned int GetCount() const override; diff --git a/src/slic3r/GUI/Widgets/DropDown.cpp b/src/slic3r/GUI/Widgets/DropDown.cpp index c0074b531d..873a734e80 100644 --- a/src/slic3r/GUI/Widgets/DropDown.cpp +++ b/src/slic3r/GUI/Widgets/DropDown.cpp @@ -1,7 +1,15 @@ #include "DropDown.hpp" -#include "Label.hpp" +#include "../GUI_App.hpp" +#include "../OptionsGroup.hpp" #include +#include +#include +#include +#include +#include + +#include wxDEFINE_EVENT(EVT_DISMISS, wxCommandEvent); @@ -25,12 +33,13 @@ END_EVENT_TABLE() */ DropDown::DropDown(std::vector &texts, - std::vector &icons) + std::vector &icons) : texts(texts) , icons(icons) + , radius(Slic3r::GUI::wxGetApp().suppress_round_corners() ? 0 : 5) , state_handler(this) - , border_color(0xDBDBDB) , text_color(0x363636) + , border_color(0xDBDBDB) , selector_border_color(std::make_pair(0x00AE42, (int) StateColor::Hovered), std::make_pair(*wxWHITE, (int) StateColor::Normal)) , selector_background_color(std::make_pair(0xEDFAF2, (int) StateColor::Checked), @@ -40,7 +49,7 @@ DropDown::DropDown(std::vector &texts, DropDown::DropDown(wxWindow * parent, std::vector &texts, - std::vector &icons, + std::vector &icons, long style) : DropDown(texts, icons) { @@ -51,16 +60,14 @@ void DropDown::Create(wxWindow * parent, long style) { wxPopupTransientWindow::Create(parent); - SetBackgroundStyle(wxBG_STYLE_PAINT); - SetBackgroundColour(*wxWHITE); + if (!wxOSX) SetBackgroundStyle(wxBG_STYLE_PAINT); state_handler.attach({&border_color, &text_color, &selector_border_color, &selector_background_color}); state_handler.update_binds(); - if ((style & DD_NO_CHECK_ICON) == 0) + if (!(style & DD_NO_CHECK_ICON)) check_bitmap = ScalableBitmap(this, "checked", 16); text_off = style & DD_NO_TEXT; - // BBS set default font - SetFont(Label::Body_14); + SetFont(parent->GetFont()); #ifdef __WXOSX__ // wxPopupTransientWindow releases mouse on idle, which may cause various problems, // such as losting mouse move, and dismissing soon on first LEFT_DOWN event. @@ -99,9 +106,9 @@ void DropDown::SetValue(const wxString &value) selection = i == texts.end() ? -1 : std::distance(texts.begin(), i); } -void DropDown::SetCornerRadius(double radius) +void DropDown::SetCornerRadius(double radius_in) { - this->radius = radius; + radius = radius_in; paintNow(); } @@ -179,6 +186,28 @@ void DropDown::paintNow() Refresh(); } +void DropDown::SetTransparentBG(wxDC& dc, wxWindow* win) +{ + const wxSize size = win->GetSize(); + const wxPoint screen_pos = win->GetScreenPosition(); + wxScreenDC screen_dc; + +#ifdef __WXMSW__ + // Draw screen_dc to dc for transparent background + dc.Blit(0, 0, size.x, size.y, &screen_dc, screen_pos.x, screen_pos.y); +#else + // See https://forums.wxwidgets.org/viewtopic.php?f=1&t=49318 + wxClientDC client_dc(win); + client_dc.Blit(0, 0, size.x, size.y, &screen_dc, screen_pos.x, screen_pos.y); + + wxBitmap bmp(size.x, size.y); + wxMemoryDC mem_dc(bmp); + mem_dc.Blit(0, 0, size.x, size.y, &client_dc, 0, 0); + mem_dc.SelectObject(wxNullBitmap); + dc.DrawBitmap(bmp, 0, 0); +#endif //__WXMSW__ +} + /* * Here we do the actual rendering. I put it in a separate * method so that it can work no matter what type of DC @@ -188,17 +217,26 @@ void DropDown::render(wxDC &dc) { if (texts.size() == 0) return; int states = state_handler.states(); + + const wxSize size = GetSize(); + if (radius > 0. && !wxOSX) + SetTransparentBG(dc, this); + dc.SetPen(wxPen(border_color.colorForStates(states))); dc.SetBrush(wxBrush(GetBackgroundColour())); // if (GetWindowStyle() & wxBORDER_NONE) // dc.SetPen(wxNullPen); + wxRect rc(0, 0, size.x, size.y); + if (wxOSX && dc.GetContentScaleFactor() > 1.0) + // On Retina displays all controls are cut on 1px + rc.x = rc.y = 1; + // draw background - wxSize size = GetSize(); - if (radius == 0) - dc.DrawRectangle(0, 0, size.x, size.y); + if (radius == 0.0 || wxOSX) + dc.DrawRectangle(rc); else - dc.DrawRoundedRectangle(0, 0, size.x, size.y, radius); + dc.DrawRoundedRectangle(rc, radius); // draw hover rectangle wxRect rcContent = {{0, offset.y}, rowSize}; @@ -233,8 +271,9 @@ void DropDown::render(wxDC &dc) } // draw position bar - if (rowSize.y * texts.size() > size.y) { - int height = rowSize.y * texts.size(); + const int text_size = int(texts.size()); + if (rowSize.y * text_size > size.y) { + int height = rowSize.y * text_size; wxRect rect = {size.x - 6, -offset.y * size.y / height, 4, size.y * size.y / height}; dc.SetPen(wxPen(border_color.defaultColor())); @@ -247,13 +286,13 @@ void DropDown::render(wxDC &dc) rcContent.x += 5; rcContent.width -= 5; if (check_bitmap.bmp().IsOk()) { - auto szBmp = check_bitmap.GetBmpSize(); + auto szBmp = check_bitmap.GetSize(); if (selection >= 0) { wxPoint pt = rcContent.GetLeftTop(); pt.y += (rcContent.height - szBmp.y) / 2; pt.y += rowSize.y * selection; if (pt.y + szBmp.y > 0 && pt.y < size.y) - dc.DrawBitmap(check_bitmap.bmp(), pt); + dc.DrawBitmap(check_bitmap.get_bitmap(), pt); } rcContent.x += szBmp.x + 5; rcContent.width -= szBmp.x + 5; @@ -268,17 +307,26 @@ void DropDown::render(wxDC &dc) if (rcContent.y > size.y) break; wxPoint pt = rcContent.GetLeftTop(); auto & icon = icons[i]; + const wxSize pref_icon_sz = get_preferred_size(icon, m_parent); if (iconSize.x > 0) { if (icon.IsOk()) { - pt.y += (rcContent.height - icon.GetSize().y) / 2; - dc.DrawBitmap(icon, pt); + pt.y += (rcContent.height - pref_icon_sz.y) / 2; +#ifdef __WXGTK3__ + dc.DrawBitmap(icon.GetBitmap(pref_icon_sz), pt); +#else + dc.DrawBitmap(icon.GetBitmapFor(m_parent), pt); +#endif } pt.x += iconSize.x + 5; pt.y = rcContent.y; } else if (icon.IsOk()) { - pt.y += (rcContent.height - icon.GetSize().y) / 2; - dc.DrawBitmap(icon, pt); - pt.x += icon.GetWidth() + 5; + pt.y += (rcContent.height - pref_icon_sz.y) / 2; +#ifdef __WXGTK3__ + dc.DrawBitmap(icon.GetBitmap(pref_icon_sz), pt); +#else + dc.DrawBitmap(icon.GetBitmapFor(m_parent), pt); +#endif + pt.x += pref_icon_sz.GetWidth() + 5; pt.y = rcContent.y; } auto text = texts[i]; @@ -305,7 +353,7 @@ void DropDown::messureSize() for (size_t i = 0; i < texts.size(); ++i) { wxSize size1 = text_off ? wxSize() : dc.GetMultiLineTextExtent(texts[i]); if (icons[i].IsOk()) { - wxSize size2 = icons[i].GetSize(); + wxSize size2 = get_preferred_size(icons[i], m_parent); if (size2.x > iconSize.x) iconSize = size2; if (!align_icon) { size1.x += size2.x + (text_off ? 0 : 5); @@ -317,7 +365,7 @@ void DropDown::messureSize() wxSize szContent = textSize; szContent.x += 10; if (check_bitmap.bmp().IsOk()) { - auto szBmp = check_bitmap.bmp().GetSize(); + auto szBmp = check_bitmap.GetSize(); szContent.x += szBmp.x + 5; } if (iconSize.x > 0) szContent.x += iconSize.x + (text_off ? 0 : 5); diff --git a/src/slic3r/GUI/Widgets/DropDown.hpp b/src/slic3r/GUI/Widgets/DropDown.hpp index b2b7eaa73e..87eccd0238 100644 --- a/src/slic3r/GUI/Widgets/DropDown.hpp +++ b/src/slic3r/GUI/Widgets/DropDown.hpp @@ -2,24 +2,29 @@ #define slic3r_GUI_DropDown_hpp_ #include +#include + +#include + #include "../wxExtensions.hpp" #include "StateHandler.hpp" #define DD_NO_CHECK_ICON 0x0001 -#define DD_NO_TEXT 0x0002 -#define DD_STYLE_MASK 0x0003 +#define DD_NO_DROP_ICON 0x0002 +#define DD_NO_TEXT 0x0004 +#define DD_STYLE_MASK 0x0008 wxDECLARE_EVENT(EVT_DISMISS, wxCommandEvent); class DropDown : public wxPopupTransientWindow { std::vector & texts; - std::vector & icons; + std::vector & icons; bool need_sync = false; int selection = -1; int hover_item = -1; - double radius = 0; + double radius; bool use_content_width = false; bool align_icon = false; bool text_off = false; @@ -42,17 +47,16 @@ class DropDown : public wxPopupTransientWindow public: DropDown(std::vector &texts, - std::vector &icons); + std::vector &icons); DropDown(wxWindow * parent, std::vector &texts, - std::vector &icons, + std::vector &icons, long style = 0); void Create(wxWindow * parent, long style = 0); -public: void Invalidate(bool clear = false); int GetSelection() const { return selection; } @@ -62,7 +66,6 @@ public: wxString GetValue() const; void SetValue(const wxString &value); -public: void SetCornerRadius(double radius); void SetBorderColor(StateColor const & color); @@ -77,10 +80,11 @@ public: void SetAlignIcon(bool align); -public: void Rescale(); bool HasDismissLongTime(); + + static void SetTransparentBG(wxDC& dc, wxWindow* win); protected: void OnDismiss() override; diff --git a/src/slic3r/GUI/Widgets/Label.cpp b/src/slic3r/GUI/Widgets/Label.cpp index 4a541f3478..c0bc2278fc 100644 --- a/src/slic3r/GUI/Widgets/Label.cpp +++ b/src/slic3r/GUI/Widgets/Label.cpp @@ -1,6 +1,8 @@ #include "Label.hpp" #include "StaticBox.hpp" +#include + wxFont Label::sysFont(int size, bool bold) { //#ifdef __linux__ diff --git a/src/slic3r/GUI/Widgets/Label.hpp b/src/slic3r/GUI/Widgets/Label.hpp index 1d3d387fb7..90ce81a338 100644 --- a/src/slic3r/GUI/Widgets/Label.hpp +++ b/src/slic3r/GUI/Widgets/Label.hpp @@ -2,6 +2,7 @@ #define slic3r_GUI_Label_hpp_ #include +#include #define LB_HYPERLINK 0x0001 diff --git a/src/slic3r/GUI/Widgets/SpinInput.cpp b/src/slic3r/GUI/Widgets/SpinInput.cpp index 9bea97dcdc..1dce77bb8a 100644 --- a/src/slic3r/GUI/Widgets/SpinInput.cpp +++ b/src/slic3r/GUI/Widgets/SpinInput.cpp @@ -1,8 +1,14 @@ #include "SpinInput.hpp" -#include "Label.hpp" #include "Button.hpp" +#include "UIColors.hpp" + +#include "../GUI_App.hpp" + #include +#include +#include +#include BEGIN_EVENT_TABLE(SpinInput, wxPanel) @@ -23,11 +29,9 @@ SpinInput::SpinInput() : label_color(std::make_pair(0x909090, (int) StateColor::Disabled), std::make_pair(0x6B6B6B, (int) StateColor::Normal)) , text_color(std::make_pair(0x909090, (int) StateColor::Disabled), std::make_pair(0x262E30, (int) StateColor::Normal)) { - radius = 0; + if (Slic3r::GUI::wxGetApp().suppress_round_corners()) + radius = 0; border_width = 1; - border_color = StateColor(std::make_pair(0xDBDBDB, (int) StateColor::Disabled), std::make_pair(0x00AE42, (int) StateColor::Hovered), - std::make_pair(0xDBDBDB, (int) StateColor::Normal)); - background_color = StateColor(std::make_pair(0xF0F0F0, (int) StateColor::Disabled), std::make_pair(*wxWHITE, (int) StateColor::Normal)); } @@ -52,17 +56,20 @@ void SpinInput::Create(wxWindow *parent, int min, int max, int initial) { StaticBox::Create(parent, wxID_ANY, pos, size); - SetFont(Label::Body_12); wxWindow::SetLabel(label); + state_handler.attach({&label_color, &text_color}); state_handler.update_binds(); + text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {20, 4}, wxDefaultSize, style | wxBORDER_NONE | wxTE_PROCESS_ENTER, wxTextValidator(wxFILTER_DIGITS)); - text_ctrl->SetFont(Label::Body_14); - text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states())); - text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states())); +#ifdef __WXOSX__ + text_ctrl->OSXDisableAllSmartSubstitutions(); +#endif // __WXOSX__ text_ctrl->SetInitialSize(text_ctrl->GetBestSize()); state_handler.attach_child(text_ctrl); + text_ctrl->Bind(wxEVT_KILL_FOCUS, &SpinInput::onTextLostFocus, this); + text_ctrl->Bind(wxEVT_TEXT, &SpinInput::onText, this); text_ctrl->Bind(wxEVT_TEXT_ENTER, &SpinInput::onTextEnter, this); text_ctrl->Bind(wxEVT_KEY_DOWN, &SpinInput::keyPressed, this); text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu @@ -71,6 +78,12 @@ void SpinInput::Create(wxWindow *parent, delta = 0; timer.Bind(wxEVT_TIMER, &SpinInput::onTimer, this); + SetFont(Slic3r::GUI::wxGetApp().normal_font()); + if (parent) { + SetBackgroundColour(parent->GetBackgroundColour()); + SetForegroundColour(parent->GetForegroundColour()); + } + long initialFromText; if (text.ToLong(&initialFromText)) initial = initialFromText; SetRange(min, max); @@ -114,6 +127,8 @@ void SpinInput::SetValue(const wxString &text) long value; if ( text.ToLong(&value) ) SetValue(value); + else + text_ctrl->SetValue(text); } void SpinInput::SetValue(int value) @@ -129,12 +144,76 @@ int SpinInput::GetValue()const return val; } +wxString SpinInput::GetTextValue() const +{ + return text_ctrl->GetValue(); +} + void SpinInput::SetRange(int min, int max) { this->min = min; this->max = max; } +void SpinInput::SetSelection(long from, long to) +{ + if (text_ctrl) + text_ctrl->SetSelection(from, to); +} + +bool SpinInput::SetFont(wxFont const& font) +{ + if (text_ctrl) + return text_ctrl->SetFont(font); + return StaticBox::SetFont(font); +} + +bool SpinInput::SetBackgroundColour(const wxColour& colour) +{ + const int clr_background_disabled = Slic3r::GUI::wxGetApp().dark_mode() ? clr_background_disabled_dark : clr_background_disabled_light; + StateColor clr_state(std::make_pair(clr_background_disabled, (int)StateColor::Disabled), + std::make_pair(clr_background_focused, (int)StateColor::Checked), + std::make_pair(colour, (int)StateColor::Focused), + std::make_pair(colour, (int)StateColor::Normal)); + + StaticBox::SetBackgroundColor(clr_state); + if (text_ctrl) + text_ctrl->SetBackgroundColour(colour); + if (button_inc) + button_inc->SetBackgroundColor(clr_state); + if (button_dec) + button_dec->SetBackgroundColor(clr_state); + + return true; +} + +bool SpinInput::SetForegroundColour(const wxColour& colour) +{ + StateColor clr_state(std::make_pair(clr_foreground_disabled, (int)StateColor::Disabled), + std::make_pair(colour, (int)StateColor::Normal)); + + SetLabelColor(clr_state); + SetTextColor(clr_state); + + if (text_ctrl) + text_ctrl->SetForegroundColour(colour); + if (button_inc) + button_inc->SetTextColor(clr_state); + if (button_dec) + button_dec->SetTextColor(clr_state); + + return true; +} + +void SpinInput::SetBorderColor(StateColor const &color) +{ + StaticBox::SetBorderColor(color); + if (button_inc) + button_inc->SetBorderColor(color); + if (button_dec) + button_dec->SetBorderColor(color); +} + void SpinInput::DoSetToolTipText(wxString const &tip) { wxWindow::DoSetToolTipText(tip); @@ -143,6 +222,9 @@ void SpinInput::DoSetToolTipText(wxString const &tip) void SpinInput::Rescale() { + SetFont(Slic3r::GUI::wxGetApp().normal_font()); + text_ctrl->SetInitialSize(text_ctrl->GetBestSize()); + button_inc->Rescale(); button_dec->Rescale(); messureSize(); @@ -183,8 +265,11 @@ void SpinInput::render(wxDC& dc) // draw seperator of buttons wxPoint pt = button_inc->GetPosition(); pt.y = size.y / 2; + pt.x += 1; dc.SetPen(wxPen(border_color.defaultColor())); - dc.DrawLine(pt, pt + wxSize{button_inc->GetSize().x - 2, 0}); + + const double scale = dc.GetContentScaleFactor(); + dc.DrawLine(pt, pt + wxSize{button_inc->GetSize().x - int(3. * scale), 0}); // draw label auto label = GetLabel(); if (!label.IsEmpty()) { @@ -201,31 +286,36 @@ void SpinInput::messureSize() wxSize size = GetSize(); wxSize textSize = text_ctrl->GetSize(); int h = textSize.y + 8; - if (size.y < h) { + if (size.y != h) { size.y = h; SetSize(size); SetMinSize(size); - } else { - textSize.y = size.y * 14 / 24; } + wxSize btnSize = {14, (size.y - 4) / 2}; btnSize.x = btnSize.x * btnSize.y / 10; + + const double scale = this->GetContentScaleFactor(); + wxClientDC dc(this); labelSize = dc.GetMultiLineTextExtent(GetLabel()); textSize.x = size.x - labelSize.x - btnSize.x - 16; text_ctrl->SetSize(textSize); - text_ctrl->SetPosition({6 + btnSize.x, (size.y - textSize.y) / 2}); + text_ctrl->SetPosition({int(3. * scale), (size.y - textSize.y) / 2}); button_inc->SetSize(btnSize); button_dec->SetSize(btnSize); - button_inc->SetPosition({3, size.y / 2 - btnSize.y - 1}); - button_dec->SetPosition({3, size.y / 2 + 1}); + button_inc->SetPosition({size.x - btnSize.x - int(3. * scale), size.y / 2 - btnSize.y/* - 1*/}); + button_dec->SetPosition({size.x - btnSize.x - int(3. * scale), size.y / 2 + 1}); } Button *SpinInput::createButton(bool inc) { - auto btn = new Button(this, "", inc ? "spin_inc" : "spin_dec", wxBORDER_NONE, 6); + auto btn = new Button(this, "", inc ? "spin_inc_act" : "spin_dec_act", wxBORDER_NONE, wxSize(12, 7)); btn->SetCornerRadius(0); + btn->SetInactiveIcon(inc ? "spin_inc" : "spin_dec"); btn->DisableFocusFromKeyboard(); + btn->SetSelected(false); + btn->Bind(wxEVT_LEFT_DOWN, [=](auto &e) { delta = inc ? 1 : -1; SetValue(val + delta); @@ -286,6 +376,13 @@ void SpinInput::onTextEnter(wxCommandEvent &event) ProcessEventLocally(event); } +void SpinInput::onText(wxCommandEvent &event) +{ + sendSpinEvent(); + event.SetId(GetId()); + ProcessEventLocally(event); +} + void SpinInput::mouseWheelMoved(wxMouseEvent &event) { auto delta = (event.GetWheelRotation() < 0 == event.IsWheelInverted()) ? 1 : -1; diff --git a/src/slic3r/GUI/Widgets/SpinInput.hpp b/src/slic3r/GUI/Widgets/SpinInput.hpp index 5b0868880c..932958e138 100644 --- a/src/slic3r/GUI/Widgets/SpinInput.hpp +++ b/src/slic3r/GUI/Widgets/SpinInput.hpp @@ -11,9 +11,9 @@ class SpinInput : public wxNavigationEnabled wxSize labelSize; StateColor label_color; StateColor text_color; - wxTextCtrl * text_ctrl; - Button * button_inc; - Button * button_dec; + wxTextCtrl * text_ctrl{nullptr}; + Button * button_inc {nullptr}; + Button * button_dec {nullptr}; wxTimer timer; int val; @@ -59,16 +59,27 @@ public: virtual bool Enable(bool enable = true) wxOVERRIDE; - wxTextCtrl * GetTextCtrl() { return text_ctrl; } + wxTextCtrl * GetText() { return text_ctrl; } void SetValue(const wxString &text); void SetValue (int value); int GetValue () const; + wxString GetTextValue() const; void SetRange(int min, int max); + bool SetFont(wxFont const& font) override; + + bool SetBackgroundColour(const wxColour& colour) override; + bool SetForegroundColour(const wxColour& colour) override; + void SetBorderColor(StateColor const& color); + + int GetMin() const { return this->min; } + int GetMax() const { return this->max; } + void SetSelection(long from, long to); + protected: void DoSetToolTipText(wxString const &tip) override; @@ -86,6 +97,7 @@ private: void keyPressed(wxKeyEvent& event); void onTimer(wxTimerEvent &evnet); void onTextLostFocus(wxEvent &event); + void onText(wxCommandEvent &event); void onTextEnter(wxCommandEvent &event); void sendSpinEvent(); diff --git a/src/slic3r/GUI/Widgets/StateHandler.cpp b/src/slic3r/GUI/Widgets/StateHandler.cpp index 72616ed8fd..87d14674cc 100644 --- a/src/slic3r/GUI/Widgets/StateHandler.cpp +++ b/src/slic3r/GUI/Widgets/StateHandler.cpp @@ -1,5 +1,7 @@ #include "StateHandler.hpp" +#include + wxDEFINE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent); StateHandler::StateHandler(wxWindow * owner) diff --git a/src/slic3r/GUI/Widgets/StateHandler.hpp b/src/slic3r/GUI/Widgets/StateHandler.hpp index 9ef155c7db..d7d6faeb40 100644 --- a/src/slic3r/GUI/Widgets/StateHandler.hpp +++ b/src/slic3r/GUI/Widgets/StateHandler.hpp @@ -2,6 +2,7 @@ #define slic3r_GUI_StateHandler_hpp_ #include +#include #include "StateColor.hpp" diff --git a/src/slic3r/GUI/Widgets/StaticBox.cpp b/src/slic3r/GUI/Widgets/StaticBox.cpp index 1a806e0007..29d5ff69e3 100644 --- a/src/slic3r/GUI/Widgets/StaticBox.cpp +++ b/src/slic3r/GUI/Widgets/StaticBox.cpp @@ -1,11 +1,13 @@ #include "StaticBox.hpp" #include "../GUI.hpp" #include +#include + +#include "DropDown.hpp" +#include "UIColors.hpp" BEGIN_EVENT_TABLE(StaticBox, wxWindow) -// catch paint events -//EVT_ERASE_BACKGROUND(StaticBox::eraseEvent) EVT_PAINT(StaticBox::paintEvent) END_EVENT_TABLE() @@ -20,9 +22,9 @@ StaticBox::StaticBox() : state_handler(this) , radius(8) { - border_color = StateColor( - std::make_pair(*wxLIGHT_GREY, (int) StateColor::Disabled), - std::make_pair(0x303A3C, (int) StateColor::Normal)); + border_color = StateColor(std::make_pair(clr_border_disabled, (int) StateColor::Disabled), + std::make_pair(clr_border_hovered, (int) StateColor::Hovered), + std::make_pair(clr_border_nornal, (int) StateColor::Normal)); } StaticBox::StaticBox(wxWindow* parent, @@ -41,7 +43,8 @@ bool StaticBox::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, cons wxWindow::Create(parent, id, pos, size, style); state_handler.attach({&border_color, &background_color, &background_color2}); state_handler.update_binds(); - SetBackgroundColour(GetParentBackgroundColor(parent)); +// SetBackgroundColour(GetParentBackgroundColor(parent)); +// SetForegroundColour(parent->GetParent()->GetForegroundColour()); return true; } @@ -109,21 +112,10 @@ wxColor StaticBox::GetParentBackgroundColor(wxWindow* parent) return *wxWHITE; } -void StaticBox::eraseEvent(wxEraseEvent& evt) -{ - // for transparent background, but not work -#ifdef __WXMSW__ - wxDC *dc = evt.GetDC(); - wxSize size = GetSize(); - wxClientDC dc2(GetParent()); - dc->Blit({0, 0}, size, &dc2, GetPosition()); -#endif -} - void StaticBox::paintEvent(wxPaintEvent& evt) { // depending on your system you may need to look at double-buffered dcs - wxPaintDC dc(this); + wxBufferedPaintDC dc(this);//wxPaintDC dc(this); render(dc); } @@ -134,29 +126,7 @@ void StaticBox::paintEvent(wxPaintEvent& evt) */ void StaticBox::render(wxDC& dc) { -#ifdef __WXMSW__ - if (radius == 0) { - doRender(dc); - return; - } - - wxSize size = GetSize(); - wxMemoryDC memdc; - wxBitmap bmp(size.x, size.y); - memdc.SelectObject(bmp); - //memdc.Blit({0, 0}, size, &dc, {0, 0}); - memdc.SetBackground(wxBrush(GetBackgroundColour())); - memdc.Clear(); - { - wxGCDC dc2(memdc); - doRender(dc2); - } - - memdc.SelectObject(wxNullBitmap); - dc.DrawBitmap(bmp, 0, 0); -#else doRender(dc); -#endif } void StaticBox::doRender(wxDC& dc) @@ -166,35 +136,53 @@ void StaticBox::doRender(wxDC& dc) if (background_color2.count() == 0) { if ((border_width && border_color.count() > 0) || background_color.count() > 0) { wxRect rc(0, 0, size.x, size.y); - if (border_width && border_color.count() > 0) { - if (dc.GetContentScaleFactor() == 1.0) { - int d = floor(border_width / 2.0); - int d2 = floor(border_width - 1); - rc.x += d; - rc.width -= d2; - rc.y += d; - rc.height -= d2; - } else { - int d = 1; - rc.x += d; - rc.width -= d; - rc.y += d; - rc.height -= d; - } - dc.SetPen(wxPen(border_color.colorForStates(states), border_width)); - } else { - dc.SetPen(wxPen(background_color.colorForStates(states))); +#ifdef __WXOSX__ + // On Retina displays all controls are cut on 1px + if (dc.GetContentScaleFactor() > 1.) + rc.Deflate(1, 1); +#endif //__WXOSX__ + + if (radius > 0.) { +#if 0 + DropDown::SetTransparentBG(dc, this); +#else +#ifdef __WXMSW__ + wxColour bg_clr = GetParentBackgroundColor(m_parent); + dc.SetBrush(wxBrush(bg_clr)); + dc.SetPen(wxPen(bg_clr)); + dc.DrawRectangle(rc); +#endif +#endif } + if (background_color.count() > 0) dc.SetBrush(wxBrush(background_color.colorForStates(states))); else dc.SetBrush(wxBrush(GetBackgroundColour())); - if (radius == 0) { + + if (border_width && border_color.count() > 0) { +#ifdef __WXOSX__ + const double bw = (double)border_width; +#else + const double bw = dc.GetContentScaleFactor() * (double)border_width; +#endif //__WXOSX__ + { + int d = floor(bw / 2.0); + int d2 = floor(bw - 1); + rc.x += d; + rc.width -= d2; + rc.y += d; + rc.height -= d2; + } + dc.SetPen(wxPen(border_color.colorForStates(states), bw)); + } else { + dc.SetPen(wxPen(background_color.colorForStates(states))); + } + + if (radius == 0.) dc.DrawRectangle(rc); - } - else { + else dc.DrawRoundedRectangle(rc, radius - border_width); - } } } else { diff --git a/src/slic3r/GUI/Widgets/StaticBox.hpp b/src/slic3r/GUI/Widgets/StaticBox.hpp index 871c5651d9..9cfddaef24 100644 --- a/src/slic3r/GUI/Widgets/StaticBox.hpp +++ b/src/slic3r/GUI/Widgets/StaticBox.hpp @@ -31,7 +31,7 @@ public: void SetBorderColorNormal(wxColor const &color); - void SetBackgroundColor(StateColor const &color); + virtual void SetBackgroundColor(StateColor const &color); void SetBackgroundColorNormal(wxColor const &color); @@ -40,15 +40,12 @@ public: static wxColor GetParentBackgroundColor(wxWindow * parent); protected: - void eraseEvent(wxEraseEvent& evt); - void paintEvent(wxPaintEvent& evt); void render(wxDC& dc); virtual void doRender(wxDC& dc); -protected: double radius; int border_width = 1; StateHandler state_handler; diff --git a/src/slic3r/GUI/Widgets/SwitchButton.cpp b/src/slic3r/GUI/Widgets/SwitchButton.cpp index 8ae1165dcb..c87d302037 100644 --- a/src/slic3r/GUI/Widgets/SwitchButton.cpp +++ b/src/slic3r/GUI/Widgets/SwitchButton.cpp @@ -1,23 +1,20 @@ #include "SwitchButton.hpp" -#include "Label.hpp" -#include "StaticBox.hpp" #include "../wxExtensions.hpp" -#include "../Utils/MacDarkMode.hpp" +#include "../../Utils/MacDarkMode.hpp" #include +#include +#include -SwitchButton::SwitchButton(wxWindow* parent, wxWindowID id) - : wxBitmapToggleButton(parent, id, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE | wxBU_EXACTFIT) - , m_on(this, "toggle_on", 16) - , m_off(this, "toggle_off", 16) +SwitchButton::SwitchButton(wxWindow* parent, const wxString& name, wxWindowID id) + : BitmapToggleButton(parent, name, id) + , m_on(this, "toggle_on", 28, 16) + , m_off(this, "toggle_off", 28, 16) , text_color(std::pair{*wxWHITE, (int) StateColor::Checked}, std::pair{0x6B6B6B, (int) StateColor::Normal}) , track_color(0xD9D9D9) , thumb_color(std::pair{0x00AE42, (int) StateColor::Checked}, std::pair{0xD9D9D9, (int) StateColor::Normal}) { - SetBackgroundColour(StaticBox::GetParentBackgroundColor(parent)); - Bind(wxEVT_TOGGLEBUTTON, [this](auto& e) { update(); e.Skip(); }); - SetFont(Label::Body_12); Rescale(); } @@ -52,11 +49,7 @@ void SwitchButton::SetValue(bool value) void SwitchButton::Rescale() { - if (labels[0].IsEmpty()) { - m_on.msw_rescale(); - m_off.msw_rescale(); - } - else { + if (!labels[0].IsEmpty()) { #ifdef __WXOSX__ auto scale = Slic3r::GUI::mac_max_scaling_factor(); int BS = (int) scale; @@ -121,14 +114,23 @@ void SwitchButton::Rescale() #ifdef __WXOSX__ bmp = wxBitmap(bmp.ConvertToImage(), -1, scale); #endif - (i == 0 ? m_off : m_on).bmp() = bmp; + (i == 0 ? m_off : m_on).SetBitmap(bmp); } } - SetSize(m_on.GetBmpSize()); + + update(); +} + +void SwitchButton::SysColorChange() +{ + m_on.sys_color_changed(); + m_off.sys_color_changed(); + update(); } void SwitchButton::update() { SetBitmap((GetValue() ? m_on : m_off).bmp()); + update_size(); } diff --git a/src/slic3r/GUI/Widgets/SwitchButton.hpp b/src/slic3r/GUI/Widgets/SwitchButton.hpp index 25581f3762..5c1859e9c2 100644 --- a/src/slic3r/GUI/Widgets/SwitchButton.hpp +++ b/src/slic3r/GUI/Widgets/SwitchButton.hpp @@ -4,12 +4,12 @@ #include "../wxExtensions.hpp" #include "StateColor.hpp" -#include +#include "BitmapToggleButton.hpp" -class SwitchButton : public wxBitmapToggleButton +class SwitchButton : public BitmapToggleButton { public: - SwitchButton(wxWindow * parent = NULL, wxWindowID id = wxID_ANY); + SwitchButton(wxWindow * parent = NULL, const wxString& name = wxEmptyString, wxWindowID id = wxID_ANY); public: void SetLabels(wxString const & lbl_on, wxString const & lbl_off); @@ -24,8 +24,10 @@ public: void Rescale(); + void SysColorChange(); + private: - void update(); + void update() override; private: ScalableBitmap m_on; diff --git a/src/slic3r/GUI/Widgets/TextInput.cpp b/src/slic3r/GUI/Widgets/TextInput.cpp index 823dd5512d..4b7dd44ddc 100644 --- a/src/slic3r/GUI/Widgets/TextInput.cpp +++ b/src/slic3r/GUI/Widgets/TextInput.cpp @@ -1,7 +1,10 @@ #include "TextInput.hpp" -#include "Label.hpp" +#include "UIColors.hpp" #include +#include + +#include "slic3r/GUI/GUI_App.hpp" BEGIN_EVENT_TABLE(TextInput, wxPanel) @@ -21,12 +24,9 @@ TextInput::TextInput() , text_color(std::make_pair(0x909090, (int) StateColor::Disabled), std::make_pair(0x262E30, (int) StateColor::Normal)) { - radius = 0; + if (Slic3r::GUI::wxGetApp().suppress_round_corners()) + radius = 0; border_width = 1; - border_color = StateColor(std::make_pair(0xDBDBDB, (int) StateColor::Disabled), std::make_pair(0x00AE42, (int) StateColor::Hovered), - std::make_pair(0xDBDBDB, (int) StateColor::Normal)); - background_color = StateColor(std::make_pair(0xF0F0F0, (int) StateColor::Disabled), std::make_pair(*wxWHITE, (int) StateColor::Normal)); - SetFont(Label::Body_12); } TextInput::TextInput(wxWindow * parent, @@ -52,15 +52,21 @@ void TextInput::Create(wxWindow * parent, text_ctrl = nullptr; StaticBox::Create(parent, wxID_ANY, pos, size, style); wxWindow::SetLabel(label); - style &= ~wxRIGHT; - state_handler.attach({&label_color, & text_color}); + + state_handler.attach({&label_color, &text_color}); state_handler.update_binds(); - text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {4, 4}, wxDefaultSize, style | wxBORDER_NONE | wxTE_PROCESS_ENTER); - text_ctrl->SetFont(Label::Body_14); + + text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {4, 4}, wxDefaultSize, style | wxBORDER_NONE); +#ifdef __WXOSX__ + text_ctrl->OSXDisableAllSmartSubstitutions(); +#endif // __WXOSX__ text_ctrl->SetInitialSize(text_ctrl->GetBestSize()); - text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states())); - text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states())); + if (parent) { + SetBackgroundColour(parent->GetBackgroundColour()); + SetForegroundColour(parent->GetForegroundColour()); + } state_handler.attach_child(text_ctrl); + text_ctrl->Bind(wxEVT_KILL_FOCUS, [this](auto &e) { OnEdit(); e.SetId(GetId()); @@ -73,8 +79,9 @@ void TextInput::Create(wxWindow * parent, ProcessEventLocally(e); }); text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu + if (!icon.IsEmpty()) { - this->icon = ScalableBitmap(this, icon.ToStdString(), 16); + this->drop_down_icon = ScalableBitmap(this, icon.ToStdString(), 16); } messureSize(); } @@ -92,10 +99,54 @@ void TextInput::SetLabel(const wxString& label) Refresh(); } -void TextInput::SetIcon(const wxBitmap &icon) +bool TextInput::SetBackgroundColour(const wxColour& colour) { - this->icon.bmp() = icon; - Rescale(); + const int clr_background_disabled = Slic3r::GUI::wxGetApp().dark_mode() ? clr_background_disabled_dark : clr_background_disabled_light; + const StateColor clr_state( std::make_pair(clr_background_disabled, (int)StateColor::Disabled), + std::make_pair(clr_background_focused, (int)StateColor::Checked), + std::make_pair(colour, (int)StateColor::Focused), + std::make_pair(colour, (int)StateColor::Normal)); + + SetBackgroundColor(clr_state); + if (text_ctrl) + text_ctrl->SetBackgroundColour(colour); + + return true; +} + +bool TextInput::SetForegroundColour(const wxColour& colour) +{ + const StateColor clr_state( std::make_pair(clr_foreground_disabled, (int)StateColor::Disabled), + std::make_pair(colour, (int)StateColor::Normal)); + + SetLabelColor(clr_state); + SetTextColor (clr_state); + + return true; +} + +void TextInput::SetValue(const wxString& value) +{ + if (text_ctrl) + text_ctrl->SetValue(value); +} + +wxString TextInput::GetValue() +{ + if (text_ctrl) + return text_ctrl->GetValue(); + return wxEmptyString; +} + +void TextInput::SetSelection(long from, long to) +{ + if (text_ctrl) + text_ctrl->SetSelection(from, to); +} + +void TextInput::SetIcon(const wxBitmapBundle& icon_in) +{ + icon = icon_in; } void TextInput::SetLabelColor(StateColor const &color) @@ -106,18 +157,41 @@ void TextInput::SetLabelColor(StateColor const &color) void TextInput::SetTextColor(StateColor const& color) { - text_color= color; + text_color = color; state_handler.update_binds(); + if (text_ctrl) + text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states())); +} + +void TextInput::SetBGColor(StateColor const& color) +{ + background_color = color; + state_handler.update_binds(); +} + +void TextInput::SetCtrlSize(wxSize const& size) +{ + StaticBox::SetInitialSize(size); + Rescale(); } void TextInput::Rescale() { - if (!this->icon.name().empty()) - this->icon.msw_rescale(); + if (text_ctrl) + text_ctrl->SetInitialSize(text_ctrl->GetBestSize()); + messureSize(); Refresh(); } +bool TextInput::SetFont(const wxFont& font) +{ + bool ret = StaticBox::SetFont(font); + if (text_ctrl) + return ret && text_ctrl->SetFont(font); + return ret; +} + bool TextInput::Enable(bool enable) { bool result = text_ctrl->Enable(enable) && wxWindow::Enable(enable); @@ -149,16 +223,22 @@ void TextInput::DoSetSize(int x, int y, int width, int height, int sizeFlags) if (sizeFlags & wxSIZE_USE_EXISTING) return; wxSize size = GetSize(); wxPoint textPos = {5, 0}; - if (this->icon.bmp().IsOk()) { - wxSize szIcon = this->icon.GetBmpSize(); + if (this->icon.IsOk()) { + wxSize szIcon = get_preferred_size(icon, m_parent); textPos.x += szIcon.x; } + wxSize dd_icon_size = wxSize(0,0); + if (this->drop_down_icon.bmp().IsOk()) + dd_icon_size = this->drop_down_icon.GetSize(); + bool align_right = GetWindowStyle() & wxRIGHT; if (align_right) textPos.x += labelSize.x; if (text_ctrl) { wxSize textSize = text_ctrl->GetSize(); - textSize.x = size.x - textPos.x - labelSize.x - 10; + wxClientDC dc(this); + const int r_shift = int((dd_icon_size.x == 0 ? 3. : 2.) * dc.GetContentScaleFactor()); + textSize.x = size.x - textPos.x - labelSize.x - dd_icon_size.x - r_shift; text_ctrl->SetSize(textSize); text_ctrl->SetPosition({textPos.x, (size.y - textSize.y) / 2}); } @@ -190,22 +270,36 @@ void TextInput::render(wxDC& dc) bool align_right = GetWindowStyle() & wxRIGHT; // start draw wxPoint pt = {5, 0}; - if (icon.bmp().IsOk()) { - wxSize szIcon = icon.GetBmpSize(); + if (icon.IsOk()) { + wxSize szIcon = get_preferred_size(icon, m_parent); pt.y = (size.y - szIcon.y) / 2; - dc.DrawBitmap(icon.bmp(), pt); - pt.x += szIcon.x + 0; +#ifdef __WXGTK3__ + dc.DrawBitmap(icon.GetBitmap(szIcon), pt); +#else + dc.DrawBitmap(icon.GetBitmapFor(m_parent), pt); +#endif + pt.x += szIcon.x + 5; } + + // drop_down_icon draw + wxPoint pt_r = {size.x, 0}; + if (drop_down_icon.bmp().IsOk()) { + wxSize szIcon = drop_down_icon.GetSize(); + pt_r.x -= szIcon.x + 2; + pt_r.y = (size.y - szIcon.y) / 2; + dc.DrawBitmap(drop_down_icon.get_bitmap(), pt_r); + } + auto text = wxWindow::GetLabel(); if (!text.IsEmpty()) { wxSize textSize = text_ctrl->GetSize(); if (align_right) { - if (pt.x + labelSize.x > size.x) - text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, size.x - pt.x); - pt.y = (size.y - labelSize.y) / 2; - } else { pt.x += textSize.x; pt.y = (size.y + textSize.y) / 2 - labelSize.y; + } else { + if (pt.x + labelSize.x > pt_r.x) + text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, pt_r.x - pt.x); + pt.y = (size.y - labelSize.y) / 2; } dc.SetTextForeground(label_color.colorForStates(states)); dc.SetFont(GetFont()); @@ -218,11 +312,11 @@ void TextInput::messureSize() wxSize size = GetSize(); wxClientDC dc(this); labelSize = dc.GetTextExtent(wxWindow::GetLabel()); - wxSize textSize = text_ctrl->GetSize(); - int h = textSize.y + 8; - if (size.y < h) { - size.y = h; - } + + const wxSize textSize = text_ctrl->GetSize(); + const wxSize iconSize = drop_down_icon.bmp().IsOk() ? drop_down_icon.GetSize() : wxSize(0, 0); + size.y = ((textSize.y > iconSize.y) ? textSize.y : iconSize.y) + 8; + wxSize minSize = size; minSize.x = GetMinWidth(); SetMinSize(minSize); diff --git a/src/slic3r/GUI/Widgets/TextInput.hpp b/src/slic3r/GUI/Widgets/TextInput.hpp index 152fb88f3d..84bdf7126b 100644 --- a/src/slic3r/GUI/Widgets/TextInput.hpp +++ b/src/slic3r/GUI/Widgets/TextInput.hpp @@ -8,10 +8,11 @@ class TextInput : public wxNavigationEnabled { wxSize labelSize; - ScalableBitmap icon; + wxBitmapBundle icon; + ScalableBitmap drop_down_icon; StateColor label_color; StateColor text_color; - wxTextCtrl * text_ctrl; + wxTextCtrl* text_ctrl{nullptr}; static const int TextInputWidth = 200; static const int TextInputHeight = 50; @@ -40,22 +41,38 @@ public: void SetLabel(const wxString& label); - void SetIcon(const wxBitmap & icon); + void SetIcon(const wxBitmapBundle& icon); void SetLabelColor(StateColor const &color); + void SetBGColor(StateColor const &color); + void SetTextColor(StateColor const &color); + void SetCtrlSize(wxSize const& size); + virtual void Rescale(); + bool SetFont(const wxFont &font) override; + virtual bool Enable(bool enable = true) override; virtual void SetMinSize(const wxSize& size) override; + bool SetBackgroundColour(const wxColour &colour) override; + + bool SetForegroundColour(const wxColour &colour) override; + wxTextCtrl *GetTextCtrl() { return text_ctrl; } wxTextCtrl const *GetTextCtrl() const { return text_ctrl; } + void SetValue(const wxString& value); + + wxString GetValue(); + + void SetSelection(long from, long to); + protected: virtual void OnEdit() {} @@ -64,6 +81,9 @@ protected: void DoSetToolTipText(wxString const &tip) override; + StateColor GetTextColor() const { return text_color; } + StateColor GetBorderColor() const { return border_color; } + private: void paintEvent(wxPaintEvent& evt); diff --git a/src/slic3r/GUI/Widgets/UIColors.hpp b/src/slic3r/GUI/Widgets/UIColors.hpp new file mode 100644 index 0000000000..fefa6efd71 --- /dev/null +++ b/src/slic3r/GUI/Widgets/UIColors.hpp @@ -0,0 +1,18 @@ +#ifndef slic3r_UI_Colors_hpp_ +#define slic3r_UI_Colors_hpp_ + +static const int clr_border_nornal = 0x646464;//0xDBDBDB; +static const int clr_border_hovered = 0xED6B21;//0x00AE42; +static const int clr_border_disabled = 0x646464;//0xDBDBDB; + +static const int clr_background_nornal_light = 0xFFFFFF; +static const int clr_background_nornal_dark = 0x2B2B2B;//0x434343; +static const int clr_background_focused = 0xED6B21;//0xEDFAF2; +static const int clr_background_disabled_dark = 0x404040;//0xF0F0F0; +static const int clr_background_disabled_light = 0xD9D9D9;//0xF0F0F0; + +static const int clr_foreground_nornal = 0x262E30; +static const int clr_foreground_focused = 0x00AE42; +static const int clr_foreground_disabled = 0x909090; + +#endif // !slic3r_UI_Colors_hpp_ \ No newline at end of file diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 87f6a0ac02..0984c82c57 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -422,10 +422,12 @@ static int scale() } #endif // __WXGTK2__ -wxBitmapBundle* get_bmp_bundle(const std::string& bmp_name_in, int px_cnt/* = 16*/, const std::string& new_color/* = std::string()*/) +wxBitmapBundle* get_bmp_bundle(const std::string& bmp_name_in, int width/* = 16*/, int height/* = -1*/, const std::string& new_color/* = std::string()*/) { #ifdef __WXGTK2__ - px_cnt *= scale(); + width *= scale(); + if (height > 0) + height *= scale(); #endif // __WXGTK2__ static Slic3r::GUI::BitmapCache cache; @@ -433,10 +435,13 @@ wxBitmapBundle* get_bmp_bundle(const std::string& bmp_name_in, int px_cnt/* = 16 std::string bmp_name = bmp_name_in; boost::replace_last(bmp_name, ".png", ""); + if (height < 0) + height = width; + // Try loading an SVG first, then PNG if SVG is not found: - wxBitmapBundle* bmp = cache.from_svg(bmp_name, px_cnt, px_cnt, Slic3r::GUI::wxGetApp().dark_mode(), new_color); + wxBitmapBundle* bmp = cache.from_svg(bmp_name, width, height, Slic3r::GUI::wxGetApp().dark_mode(), new_color); if (bmp == nullptr) { - bmp = cache.from_png(bmp_name, px_cnt, px_cnt); + bmp = cache.from_png(bmp_name, width, height); if (!bmp) // Neither SVG nor PNG has been found, raise error throw Slic3r::RuntimeError("Could not load bitmap: " + bmp_name); @@ -658,7 +663,7 @@ void ModeButton::SetState(const bool state) void ModeButton::update_bitmap() { - m_bmp = *get_bmp_bundle("mode", m_px_cnt, Slic3r::GUI::wxGetApp().get_mode_btn_color(m_mode_id)); + m_bmp = *get_bmp_bundle("mode", m_bmp_width, m_bmp_height, Slic3r::GUI::wxGetApp().get_mode_btn_color(m_mode_id)); SetBitmap(m_bmp); SetBitmapCurrent(m_bmp); @@ -785,19 +790,28 @@ void MenuWithSeparators::SetSecondSeparator() // PrusaBitmap // ---------------------------------------------------------------------------- ScalableBitmap::ScalableBitmap( wxWindow *parent, - const std::string& icon_name/* = ""*/, - const int px_cnt/* = 16*/, + const std::string& icon_name, + const int width/* = 16*/, + const int height/* = -1*/, const bool grayscale/* = false*/): m_parent(parent), m_icon_name(icon_name), - m_px_cnt(px_cnt) + m_bmp_width(width), m_bmp_height(height) { - m_bmp = *get_bmp_bundle(icon_name, px_cnt); + m_bmp = *get_bmp_bundle(icon_name, width, height); m_bitmap = m_bmp.GetBitmapFor(m_parent); } +ScalableBitmap::ScalableBitmap( wxWindow* parent, + const std::string& icon_name, + const wxSize icon_size, + const bool grayscale/* = false*/) : +ScalableBitmap(parent, icon_name, icon_size.x, icon_size.y, grayscale) +{ +} + void ScalableBitmap::sys_color_changed() { - m_bmp = *get_bmp_bundle(m_icon_name, m_px_cnt); + m_bmp = *get_bmp_bundle(m_icon_name, m_bmp_width, m_bmp_height); } // ---------------------------------------------------------------------------- @@ -811,17 +825,19 @@ ScalableButton::ScalableButton( wxWindow * parent, const wxSize& size /* = wxDefaultSize*/, const wxPoint& pos /* = wxDefaultPosition*/, long style /*= wxBU_EXACTFIT | wxNO_BORDER*/, - int bmp_px_cnt/* = 16*/) : + int width/* = 16*/, + int height/* = -1*/) : m_parent(parent), m_current_icon_name(icon_name), - m_px_cnt(bmp_px_cnt), + m_bmp_width(width), + m_bmp_height(height), m_has_border(!(style & wxNO_BORDER)) { Create(parent, id, label, pos, size, style); Slic3r::GUI::wxGetApp().UpdateDarkUI(this); if (!icon_name.empty()) { - SetBitmap(*get_bmp_bundle(icon_name, m_px_cnt)); + SetBitmap(*get_bmp_bundle(icon_name, width, height)); if (!label.empty()) SetBitmapMargins(int(0.5* em_unit(parent)), 0); } @@ -842,7 +858,8 @@ ScalableButton::ScalableButton( wxWindow * parent, long style /*= wxBU_EXACTFIT | wxNO_BORDER*/) : m_parent(parent), m_current_icon_name(bitmap.name()), - m_px_cnt(bitmap.px_cnt()), + m_bmp_width(bitmap.px_size().x), + m_bmp_height(bitmap.px_size().y), m_has_border(!(style& wxNO_BORDER)) { Create(parent, id, label, wxDefaultPosition, wxDefaultSize, style); @@ -863,7 +880,7 @@ bool ScalableButton::SetBitmap_(const std::string& bmp_name) if (m_current_icon_name.empty()) return false; - wxBitmapBundle bmp = *get_bmp_bundle(m_current_icon_name, m_px_cnt); + wxBitmapBundle bmp = *get_bmp_bundle(m_current_icon_name, m_bmp_width, m_bmp_height); SetBitmap(bmp); SetBitmapCurrent(bmp); SetBitmapPressed(bmp); @@ -891,13 +908,13 @@ void ScalableButton::sys_color_changed() { Slic3r::GUI::wxGetApp().UpdateDarkUI(this, m_has_border); - wxBitmapBundle bmp = *get_bmp_bundle(m_current_icon_name, m_px_cnt); + wxBitmapBundle bmp = *get_bmp_bundle(m_current_icon_name, m_bmp_width, m_bmp_height); SetBitmap(bmp); SetBitmapCurrent(bmp); SetBitmapPressed(bmp); SetBitmapFocus(bmp); if (!m_disabled_icon_name.empty()) - SetBitmapDisabled(*get_bmp_bundle(m_disabled_icon_name, m_px_cnt)); + SetBitmapDisabled(*get_bmp_bundle(m_disabled_icon_name, m_bmp_width, m_bmp_height)); if (!GetLabelText().IsEmpty()) SetBitmapMargins(int(0.5 * em_unit(m_parent)), 0); } diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 8b33d902f5..a0ed1bbd4c 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -54,7 +54,7 @@ void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector< int em_unit(wxWindow* win); int mode_icon_px_size(); -wxBitmapBundle* get_bmp_bundle(const std::string& bmp_name, int px_cnt = 16, const std::string& new_color_rgb = std::string()); +wxBitmapBundle* get_bmp_bundle(const std::string& bmp_name, int width = 16, int height = -1, const std::string& new_color_rgb = std::string()); wxBitmapBundle* get_empty_bmp_bundle(int width, int height); wxBitmapBundle* get_solid_bmp_bundle(int width, int height, const std::string& color); @@ -131,6 +131,17 @@ public: void SetItemsCnt(int cnt) { m_cnt_open_items = cnt; } }; +inline wxSize get_preferred_size(const wxBitmapBundle& bmp, wxWindow* parent) +{ + if (!bmp.IsOk()) + return wxSize(0,0); +#ifdef __WIN32__ + return bmp.GetPreferredBitmapSizeFor(parent); +#else + return bmp.GetDefaultSize(); +#endif +} + // ---------------------------------------------------------------------------- // ScalableBitmap @@ -141,8 +152,14 @@ class ScalableBitmap public: ScalableBitmap() {}; ScalableBitmap( wxWindow *parent, - const std::string& icon_name = "", - const int px_cnt = 16, + const std::string& icon_name, + const int width = 16, + const int height = -1 , + const bool grayscale = false); + + ScalableBitmap( wxWindow *parent, + const std::string& icon_name, + const wxSize icon_size, const bool grayscale = false); ~ScalableBitmap() {} @@ -153,15 +170,10 @@ public: wxBitmap get_bitmap() { return m_bmp.GetBitmapFor(m_parent); } wxWindow* parent() const { return m_parent;} const std::string& name() const { return m_icon_name; } - int px_cnt() const { return m_px_cnt;} + wxSize px_size() const { return wxSize(m_bmp_width, m_bmp_height);} - wxSize GetSize() const { -#ifdef __WIN32__ - return m_bmp.GetPreferredBitmapSizeFor(m_parent); -#else - return m_bmp.GetDefaultSize(); -#endif - } + void SetBitmap(const wxBitmapBundle& bmp) { m_bmp = bmp; } + wxSize GetSize() const { return get_preferred_size(m_bmp, m_parent); } int GetWidth() const { return GetSize().GetWidth(); } int GetHeight() const { return GetSize().GetHeight(); } @@ -170,7 +182,8 @@ private: wxBitmapBundle m_bmp = wxBitmapBundle(); wxBitmap m_bitmap = wxBitmap(); std::string m_icon_name = ""; - int m_px_cnt {16}; + int m_bmp_width{ 16 }; + int m_bmp_height{ -1 }; }; @@ -229,7 +242,8 @@ public: const wxSize& size = wxDefaultSize, const wxPoint& pos = wxDefaultPosition, long style = wxBU_EXACTFIT | wxNO_BORDER, - int bmp_px_cnt = 16); + int width = 16, + int height = -1); ScalableButton( wxWindow * parent, @@ -256,7 +270,8 @@ private: protected: // bitmap dimensions - int m_px_cnt{ 16 }; + int m_bmp_width{ 16 }; + int m_bmp_height{ -1 }; bool m_has_border {false}; };