Skinned UI: WIP

* Non-MSW specific: Next improvements for BG of the controls
  + Create wrap class BitmapToggleButton to correct create under all platforms
  + TabFilament: Fixes crash on recreating of the app

* Next improvements for background under nonMSW systems
 + Fixed Field::SpinCtrl::propagate_value

* DropDown: Implemented transparent background for rounded corners.
  + Tab: use TextInput and SwitchButton for substitutions
  + nonMSW specific: Don't set BackgroundColors for panels

* ObjectManipulation: Use TextInput instead wxTextCtrl

* Process rectangle/rounded controls
  + Preferences: Added "Suppress round corners" parameter

* Skinned UI: SwitchButton. Use it for CheckBox Field

* Skinned UI: SpinInput
  + ScalableBitmap/ScalableButton respects to different width and height of bitmap.

* Skinned UI: ComboBox

* Skinned UI: CheckBox
This commit is contained in:
YuSanka 2023-07-19 15:41:14 +02:00 committed by Lukas Matena
parent aff3864200
commit c0aef5ff0a
65 changed files with 1181 additions and 537 deletions

View File

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1.5" y="1.5" width="15" height="15" rx="0.5" stroke="#646464"/>
</svg>

After

Width:  |  Height:  |  Size: 176 B

View File

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1.5" y="1.5" width="15" height="15" rx="0.5" fill="#C8C8C8" stroke="#646464"/>
</svg>

After

Width:  |  Height:  |  Size: 191 B

View File

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1.5" y="1.5" width="15" height="15" rx="0.5" stroke="#ED6B21"/>
</svg>

After

Width:  |  Height:  |  Size: 176 B

View File

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="16" height="16" rx="1" fill="#ED6B21"/>
<path d="M4.35537 8.5374L8.30284 11.9361C8.71855 12.294 9.34501 12.2502 9.70687 11.838L14.8175 6.01521" stroke="white" stroke-width="1.2" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 331 B

View File

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="16" height="16" rx="1" fill="#C8C8C8wx"/>
<path d="M4.35537 8.5374L8.30284 11.9361C8.71855 12.294 9.34501 12.2502 9.70687 11.838L14.8175 6.01521" stroke="white" stroke-width="1.2" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 333 B

View File

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="16" height="16" rx="1" fill="#ED8D21"/>
<path d="M4.35537 8.5374L8.30284 11.9361C8.71855 12.294 9.34501 12.2502 9.70687 11.838L14.8175 6.01521" stroke="white" stroke-width="1.2" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 331 B

View File

@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 8.9375L6.45062 11.6772C6.67263 11.8535 6.99663 11.8101 7.16447 11.5817L12 5" stroke="white" stroke-linecap="round"/>
<path d="M3 8.9375L6.45062 11.6772C6.67263 11.8535 6.99663 11.8101 7.16447 11.5817L12 5" stroke="white" stroke-opacity="0.2" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 382 B

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.75 6.25L7.75 9.75L2.75 6.25" stroke="#646464" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 187 B

View File

@ -0,0 +1,3 @@
<svg width="8" height="5" viewBox="0 0 8 5" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 1L4 4L7 1" stroke="#646464" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 164 B

View File

@ -0,0 +1,3 @@
<svg width="8" height="5" viewBox="0 0 8 5" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 1L4 4L7 1" stroke="#ED6B21" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 164 B

View File

@ -0,0 +1,3 @@
<svg width="8" height="5" viewBox="0 0 8 5" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 4L4 1L1 4" stroke="#646464" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 164 B

View File

@ -0,0 +1,3 @@
<svg width="8" height="5" viewBox="0 0 8 5" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 4L4 1L1 4" stroke="#ED6B21" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 164 B

View File

@ -0,0 +1,5 @@
<svg width="24" height="14" viewBox="0 0 24 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="24" height="14" rx="7" fill="#ButtonBG"/>
<!-->rect x="1" y="1.00293" width="22" height="12" rx="6" fill="#BBG"/-->
<rect x="1" y="1.00293" width="12.0384" height="12" rx="6" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 308 B

View File

@ -0,0 +1,4 @@
<svg width="24" height="14" viewBox="0 0 24 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="24" height="14" rx="7" fill="#ED6B21"/>
<rect x="11" y="1.00293" width="12.0384" height="12" rx="6" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 231 B

View File

@ -104,6 +104,9 @@ void AppConfig::set_defaults()
if (get("tabs_as_menu").empty()) if (get("tabs_as_menu").empty())
set("tabs_as_menu", "0"); set("tabs_as_menu", "0");
if (get("suppress_round_corners").empty())
set("suppress_round_corners", "1");
#endif // _WIN32 #endif // _WIN32
// remove old 'use_legacy_opengl' parameter from this config, if present // remove old 'use_legacy_opengl' parameter from this config, if present

View File

@ -256,6 +256,29 @@ set(SLIC3R_GUI_SOURCES
GUI/DesktopIntegrationDialog.hpp GUI/DesktopIntegrationDialog.hpp
GUI/HintNotification.cpp GUI/HintNotification.cpp
GUI/HintNotification.hpp 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.cpp
GUI/FileArchiveDialog.hpp GUI/FileArchiveDialog.hpp
GUI/Downloader.cpp GUI/Downloader.cpp

View File

@ -414,6 +414,8 @@ wxBitmapBundle* BitmapCache::from_svg(const std::string& bitmap_name, unsigned t
if (!new_color.empty()) if (!new_color.empty())
replaces["\"#ED6B21\""] = "\"" + new_color + "\""; replaces["\"#ED6B21\""] = "\"" + new_color + "\"";
replaces["\"#ButtonBG\""] = dark_mode ? "\"#4E4E4E\"" : "\"#828282\"";
std::string str; std::string str;
nsvgGetDataFromFileWithReplace(Slic3r::var(bitmap_name + ".svg").c_str(), str, replaces); nsvgGetDataFromFileWithReplace(Slic3r::var(bitmap_name + ".svg").c_str(), str, replaces);
if (str.empty()) if (str.empty())

View File

@ -66,10 +66,11 @@ BitmapComboBox::BitmapComboBox(wxWindow* parent,
int n/* = 0*/, int n/* = 0*/,
const wxString choices[]/* = NULL*/, const wxString choices[]/* = NULL*/,
long style/* = 0*/) : 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()); 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 // 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. // the index of the item inside CBN_EDITCHANGE may no more be valid.
EnableTextChangedEvents(false); EnableTextChangedEvents(false);
@ -79,11 +80,12 @@ BitmapComboBox::BitmapComboBox(wxWindow* parent,
#endif /* _WIN32 */ #endif /* _WIN32 */
} }
#if 0
BitmapComboBox::~BitmapComboBox() BitmapComboBox::~BitmapComboBox()
{ {
} }
#ifdef _WIN32 //#ifdef _WIN32
int BitmapComboBox::Append(const wxString& item) int BitmapComboBox::Append(const wxString& item)
{ {

View File

@ -8,6 +8,8 @@
#include <wx/bmpcbox.h> #include <wx/bmpcbox.h>
#include <wx/gdicmn.h> #include <wx/gdicmn.h>
#include "Widgets/ComboBox.hpp"
#include "GUI_Utils.hpp" #include "GUI_Utils.hpp"
// --------------------------------- // ---------------------------------
@ -17,7 +19,8 @@ namespace Slic3r {
namespace GUI { namespace GUI {
// BitmapComboBox used to presets list on Sidebar and Tabs // BitmapComboBox used to presets list on Sidebar and Tabs
class BitmapComboBox : public wxBitmapComboBox //class BitmapComboBox : public wxBitmapComboBox
class BitmapComboBox : public ::ComboBox
{ {
public: public:
BitmapComboBox(wxWindow* parent, BitmapComboBox(wxWindow* parent,
@ -28,6 +31,7 @@ BitmapComboBox(wxWindow* parent,
int n = 0, int n = 0,
const wxString choices[] = NULL, const wxString choices[] = NULL,
long style = 0); long style = 0);
#if 0
~BitmapComboBox(); ~BitmapComboBox();
#ifdef _WIN32 #ifdef _WIN32
@ -40,7 +44,7 @@ BitmapComboBox(wxWindow* parent,
protected: protected:
#ifdef _WIN32 //#ifdef _WIN32
bool MSWOnDraw(WXDRAWITEMSTRUCT* item) override; bool MSWOnDraw(WXDRAWITEMSTRUCT* item) override;
void DrawBackground_(wxDC& dc, const wxRect& rect, int WXUNUSED(item), int flags) const; void DrawBackground_(wxDC& dc, const wxRect& rect, int WXUNUSED(item), int flags) const;
public: public:

View File

@ -78,7 +78,7 @@ wxBitmapBundle * ModePaletteComboBox::get_bmp(const std::vector<std::string> &pa
// Create the bitmap with color bars. // Create the bitmap with color bars.
std::vector<wxBitmapBundle*> bmps; std::vector<wxBitmapBundle*> bmps;
for (const auto& color : palette) { 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)); bmps.emplace_back(get_empty_bmp_bundle(wxOSX ? 5 : 6, icon_height));
} }
bmp_bndl = bitmap_cache().insert_bndl(bitmap_key, bmps); bmp_bndl = bitmap_cache().insert_bndl(bitmap_key, bmps);

View File

@ -22,6 +22,7 @@
#include "MainFrame.hpp" #include "MainFrame.hpp"
#include "BitmapComboBox.hpp" #include "BitmapComboBox.hpp"
#include "Widgets/CheckBox.hpp"
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
@ -165,7 +166,7 @@ ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequ
intervals_box_sizer->Add(m_intervals_grid_sizer, 0, wxLEFT, em); intervals_box_sizer->Add(m_intervals_grid_sizer, 0, wxLEFT, em);
option_sizer->Add(intervals_box_sizer, 0, wxEXPAND); 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->SetValue(m_sequence.random_sequence);
m_random_sequence->SetToolTip(_L("If enabled, random sequence of the selected extruders will be used.")); 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) { 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->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->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->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(); }); m_color_repetition->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& e) {m_sequence.color_repetition = e.IsChecked(); });

View File

@ -10,7 +10,7 @@
class wxTextCtrl; class wxTextCtrl;
class wxFlexGridSizer; class wxFlexGridSizer;
class wxCheckBox; class CheckBox;
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
@ -27,8 +27,8 @@ class ExtruderSequenceDialog: public DPIDialog
wxTextCtrl* m_interval_by_layers {nullptr}; wxTextCtrl* m_interval_by_layers {nullptr};
wxTextCtrl* m_interval_by_mm {nullptr}; wxTextCtrl* m_interval_by_mm {nullptr};
wxCheckBox* m_random_sequence {nullptr}; CheckBox* m_random_sequence {nullptr};
wxCheckBox* m_color_repetition{nullptr}; CheckBox* m_color_repetition{nullptr};
wxFlexGridSizer* m_intervals_grid_sizer {nullptr}; wxFlexGridSizer* m_intervals_grid_sizer {nullptr};
wxFlexGridSizer* m_extruders_grid_sizer {nullptr}; wxFlexGridSizer* m_extruders_grid_sizer {nullptr};

View File

@ -28,6 +28,8 @@
#include "MsgDialog.hpp" #include "MsgDialog.hpp"
#include "BitmapComboBox.hpp" #include "BitmapComboBox.hpp"
#include "Widgets/ComboBox.hpp"
#ifdef __WXOSX__ #ifdef __WXOSX__
#define wxOSX true #define wxOSX true
#else #else
@ -102,8 +104,6 @@ Field::~Field()
void Field::PostInitialize() void Field::PostInitialize()
{ {
auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
switch (m_opt.type) switch (m_opt.type)
{ {
case coPercents: case coPercents:
@ -488,10 +488,7 @@ void TextCtrl::BUILD() {
} }
long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER; long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER;
#ifdef _WIN32 auto temp = new text_ctrl(m_parent, text_value, "", "", wxDefaultPosition, size, style);
style |= wxBORDER_SIMPLE;
#endif
auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, style);
if (parent_is_custom_ctrl && m_opt.height < 0) if (parent_is_custom_ctrl && m_opt.height < 0)
opt_height = (double)temp->GetSize().GetHeight()/m_em_unit; opt_height = (double)temp->GetSize().GetHeight()/m_em_unit;
temp->SetFont(m_opt.is_code ? 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. // 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. // 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); temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
#ifdef __WXOSX__
temp->OSXDisableAllSmartSubstitutions();
#endif // __WXOSX__
temp->SetToolTip(get_tooltip_text(text_value)); temp->SetToolTip(get_tooltip_text(text_value));
@ -562,7 +556,7 @@ bool TextCtrl::value_was_changed()
return true; return true;
boost::any val = m_value; boost::any val = m_value;
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue(); wxString ret_str = static_cast<text_ctrl*>(window)->GetValue();
// update m_value! // update m_value!
// ret_str might be changed inside get_value_by_opt_type // ret_str might be changed inside get_value_by_opt_type
get_value_by_opt_type(ret_str); get_value_by_opt_type(ret_str);
@ -593,11 +587,11 @@ bool TextCtrl::value_was_changed()
void TextCtrl::propagate_value() void TextCtrl::propagate_value()
{ {
wxString val = dynamic_cast<wxTextCtrl*>(window)->GetValue(); wxString val = dynamic_cast<text_ctrl*>(window)->GetValue();
if (m_opt.nullable && val != na_value()) if (m_opt.nullable && val != na_value())
m_last_meaningful_value = val; m_last_meaningful_value = val;
if (!is_defined_input_value<wxTextCtrl>(window, m_opt.type) ) if (!is_defined_input_value<text_ctrl>(window, m_opt.type) )
// on_kill_focus() cause a call of OptionsGroup::reload_config(), // on_kill_focus() cause a call of OptionsGroup::reload_config(),
// Thus, do it only when it's really needed (when undefined value was input) // Thus, do it only when it's really needed (when undefined value was input)
on_kill_focus(); 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<wxString>(value) == na_value(); const bool m_is_na_val = boost::any_cast<wxString>(value) == na_value();
if (!m_is_na_val) if (!m_is_na_val)
m_last_meaningful_value = value; m_last_meaningful_value = value;
dynamic_cast<wxTextCtrl*>(window)->SetValue(m_is_na_val ? na_value() : boost::any_cast<wxString>(value)); dynamic_cast<text_ctrl*>(window)->SetValue(m_is_na_val ? na_value() : boost::any_cast<wxString>(value));
} }
else else
dynamic_cast<wxTextCtrl*>(window)->SetValue(boost::any_cast<wxString>(value)); dynamic_cast<text_ctrl*>(window)->SetValue(boost::any_cast<wxString>(value));
m_disable_change_event = false; m_disable_change_event = false;
if (!change_event) { if (!change_event) {
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue(); wxString ret_str = static_cast<text_ctrl*>(window)->GetValue();
/* Update m_value to correct work of next value_was_changed(). /* 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, * 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. * 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() void TextCtrl::set_last_meaningful_value()
{ {
dynamic_cast<wxTextCtrl*>(window)->SetValue(boost::any_cast<wxString>(m_last_meaningful_value)); dynamic_cast<text_ctrl*>(window)->SetValue(boost::any_cast<wxString>(m_last_meaningful_value));
propagate_value(); propagate_value();
} }
void TextCtrl::set_na_value() void TextCtrl::set_na_value()
{ {
dynamic_cast<wxTextCtrl*>(window)->SetValue(na_value()); dynamic_cast<text_ctrl*>(window)->SetValue(na_value());
propagate_value(); propagate_value();
} }
boost::any& TextCtrl::get_value() boost::any& TextCtrl::get_value()
{ {
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue(); wxString ret_str = static_cast<text_ctrl*>(window)->GetValue();
// update m_value // update m_value
get_value_by_opt_type(ret_str); get_value_by_opt_type(ret_str);
@ -659,8 +653,11 @@ void TextCtrl::msw_rescale()
size.SetHeight(lround(opt_height*m_em_unit)); size.SetHeight(lround(opt_height*m_em_unit));
if (m_opt.width >= 0) size.SetWidth(m_opt.width*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<wxTextCtrl*>(window); wxTextCtrl* field = dynamic_cast<wxTextCtrl*>(window);
if (parent_is_custom_ctrl) if (parent_is_custom_ctrl)
field->SetSize(size); field->SetSize(size);
@ -670,8 +667,8 @@ void TextCtrl::msw_rescale()
} }
void TextCtrl::enable() { dynamic_cast<wxTextCtrl*>(window)->Enable(); dynamic_cast<wxTextCtrl*>(window)->SetEditable(true); } void TextCtrl::enable() { dynamic_cast<text_ctrl*>(window)->Enable(); }
void TextCtrl::disable() { dynamic_cast<wxTextCtrl*>(window)->Disable(); dynamic_cast<wxTextCtrl*>(window)->SetEditable(false); } void TextCtrl::disable() { dynamic_cast<text_ctrl*>(window)->Disable();}
#ifdef __WXGTK__ #ifdef __WXGTK__
void TextCtrl::change_field_value(wxEvent& event) void TextCtrl::change_field_value(wxEvent& event)
@ -682,10 +679,71 @@ void TextCtrl::change_field_value(wxEvent& event)
}; };
#endif //__WXGTK__ #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() { void CheckBox::BUILD() {
auto size = wxSize(wxDefaultSize); auto size = wxSize(wxDefaultSize);
if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); if (m_opt.height >= 0)
if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); 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 ? bool check_value = m_opt.type == coBool ?
m_opt.default_value->getBool() : m_opt.type == coBools ? m_opt.default_value->getBool() : m_opt.type == coBools ?
@ -695,21 +753,29 @@ void CheckBox::BUILD() {
m_last_meaningful_value = static_cast<unsigned char>(check_value); m_last_meaningful_value = static_cast<unsigned char>(check_value);
// Set Label as a string of at least one space simbol to correct system scaling of a CheckBox // 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); window = GetNewWin(m_parent);
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); wxGetApp().UpdateDarkUI(window);
if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT); window->SetFont(wxGetApp().normal_font());
temp->SetValue(check_value); if (!wxOSX)
if (m_opt.readonly) temp->Disable(); 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; m_is_na_val = false;
on_change_field(); 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 void CheckBox::set_value(const bool value, bool change_event/* = false*/)
window = dynamic_cast<wxWindow*>(temp); {
m_disable_change_event = !change_event;
SetValue(value);
m_disable_change_event = false;
} }
void CheckBox::set_value(const boost::any& value, bool change_event) 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<unsigned char>(value) == ConfigOptionBoolsNullable::nil_value(); m_is_na_val = boost::any_cast<unsigned char>(value) == ConfigOptionBoolsNullable::nil_value();
if (!m_is_na_val) if (!m_is_na_val)
m_last_meaningful_value = value; m_last_meaningful_value = value;
dynamic_cast<wxCheckBox*>(window)->SetValue(m_is_na_val ? false : boost::any_cast<unsigned char>(value) != 0); SetValue(m_is_na_val ? false : boost::any_cast<unsigned char>(value) != 0);
} }
else else
dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<bool>(value)); SetValue(boost::any_cast<bool>(value));
m_disable_change_event = false; m_disable_change_event = false;
} }
@ -730,7 +796,7 @@ void CheckBox::set_last_meaningful_value()
{ {
if (m_opt.nullable) { if (m_opt.nullable) {
m_is_na_val = false; m_is_na_val = false;
dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<unsigned char>(m_last_meaningful_value) != 0); SetValue(boost::any_cast<unsigned char>(m_last_meaningful_value) != 0);
on_change_field(); on_change_field();
} }
} }
@ -739,15 +805,13 @@ void CheckBox::set_na_value()
{ {
if (m_opt.nullable) { if (m_opt.nullable) {
m_is_na_val = true; m_is_na_val = true;
dynamic_cast<wxCheckBox*>(window)->SetValue(false);
on_change_field(); on_change_field();
} }
} }
boost::any& CheckBox::get_value() boost::any& CheckBox::get_value()
{ {
// boost::any m_value; bool value = GetValue();
bool value = dynamic_cast<wxCheckBox*>(window)->GetValue();
if (m_opt.type == coBool) if (m_opt.type == coBool)
m_value = static_cast<bool>(value); m_value = static_cast<bool>(value);
else else
@ -761,6 +825,23 @@ void CheckBox::msw_rescale()
window->SetInitialSize(window->GetBestSize()); 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() { void SpinCtrl::BUILD() {
auto size = wxSize(def_width() * m_em_unit, wxDefaultCoord); auto size = wxSize(def_width() * m_em_unit, wxDefaultCoord);
@ -804,11 +885,9 @@ void SpinCtrl::BUILD() {
? (int)0 : (int)m_opt.min; ? (int)0 : (int)m_opt.min;
const int max_val = m_opt.max < FLT_MAX ? (int)m_opt.max : INT_MAX; 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 wxTE_PROCESS_ENTER | wxSP_ARROW_KEYS
#ifdef _WIN32
| wxBORDER_SIMPLE
#endif
, min_val, max_val, default_value); , min_val, max_val, default_value);
#ifdef __WXGTK3__ #ifdef __WXGTK3__
@ -823,14 +902,7 @@ void SpinCtrl::BUILD() {
if (m_opt.height < 0 && parent_is_custom_ctrl) if (m_opt.height < 0 && parent_is_custom_ctrl)
opt_height = (double)temp->GetSize().GetHeight() / m_em_unit; 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) temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e)
#endif
{ {
e.Skip(); e.Skip();
if (bEnterPressed) { if (bEnterPressed) {
@ -849,29 +921,16 @@ void SpinCtrl::BUILD() {
propagate_value(); propagate_value();
bEnterPressed = true; bEnterPressed = true;
}), temp->GetId()); }), temp->GetId());
temp->SetToolTip(get_tooltip_text(text_value));
temp->Bind(wxEVT_TEXT, ([this, temp](wxCommandEvent e) temp->Bind(wxEVT_TEXT, [this, temp](wxCommandEvent e) {
{ long value;
// # On OSX / Cocoa, wxSpinCtrl::GetValue() doesn't return the new value if (!e.GetString().ToLong(&value))
// # when it was changed from the text control, so the on_change callback return;
// # gets the old one, and on_kill_focus resets the control to the old value. if (value < INT_MIN || value > INT_MAX)
// # 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)
tmp_value = UNDEF_VALUE; tmp_value = UNDEF_VALUE;
else { else {
tmp_value = std::min(std::max((int)value, temp->GetMin()), temp->GetMax()); 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 // update value for the control only if it was changed in respect to the Min/max values
if (tmp_value != (int)value) { if (tmp_value != (int)value) {
temp->SetValue(tmp_value); temp->SetValue(tmp_value);
@ -880,11 +939,8 @@ void SpinCtrl::BUILD() {
int pos = std::to_string(tmp_value).length(); int pos = std::to_string(tmp_value).length();
temp->SetSelection(pos, pos); temp->SetSelection(pos, pos);
} }
#endif
} }
}), temp->GetId()); }, temp->GetId());
temp->SetToolTip(get_tooltip_text(text_value));
// recast as a wxWindow to fit the calling convention // recast as a wxWindow to fit the calling convention
window = dynamic_cast<wxWindow*>(temp); window = dynamic_cast<wxWindow*>(temp);
@ -898,35 +954,35 @@ void SpinCtrl::set_value(const boost::any& value, bool change_event/* = false*/)
if (m_opt.nullable) { if (m_opt.nullable) {
const bool m_is_na_val = tmp_value == ConfigOptionIntsNullable::nil_value(); const bool m_is_na_val = tmp_value == ConfigOptionIntsNullable::nil_value();
if (m_is_na_val) if (m_is_na_val)
dynamic_cast<wxSpinCtrl*>(window)->SetValue(na_value(true)); dynamic_cast<::SpinInput*>(window)->SetValue(na_value(true));
else { else {
m_last_meaningful_value = value; m_last_meaningful_value = value;
dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value); dynamic_cast<::SpinInput*>(window)->SetValue(tmp_value);
} }
} }
else else
dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value); dynamic_cast<::SpinInput*>(window)->SetValue(tmp_value);
m_disable_change_event = false; m_disable_change_event = false;
} }
void SpinCtrl::set_last_meaningful_value() void SpinCtrl::set_last_meaningful_value()
{ {
const int val = boost::any_cast<int>(m_last_meaningful_value); const int val = boost::any_cast<int>(m_last_meaningful_value);
dynamic_cast<wxSpinCtrl*>(window)->SetValue(val); dynamic_cast<::SpinInput*>(window)->SetValue(val);
tmp_value = val; tmp_value = val;
propagate_value(); propagate_value();
} }
void SpinCtrl::set_na_value() void SpinCtrl::set_na_value()
{ {
dynamic_cast<wxSpinCtrl*>(window)->SetValue(na_value(true)); dynamic_cast<::SpinInput*>(window)->SetValue(na_value(true));
m_value = ConfigOptionIntsNullable::nil_value(); m_value = ConfigOptionIntsNullable::nil_value();
propagate_value(); propagate_value();
} }
boost::any& SpinCtrl::get_value() boost::any& SpinCtrl::get_value()
{ {
wxSpinCtrl* spin = static_cast<wxSpinCtrl*>(window); ::SpinInput* spin = static_cast<::SpinInput*>(window);
if (spin->GetTextValue() == na_value(true)) if (spin->GetTextValue() == na_value(true))
return m_value; return m_value;
@ -949,7 +1005,7 @@ void SpinCtrl::propagate_value()
#ifdef __WXOSX__ #ifdef __WXOSX__
// check input value for minimum // check input value for minimum
if (m_opt.min > 0 && tmp_value < m_opt.min) { if (m_opt.min > 0 && tmp_value < m_opt.min) {
wxSpinCtrl* spin = static_cast<wxSpinCtrl*>(window); ::SpinInput* spin = static_cast<::SpinInput*>(window);
spin->SetValue(m_opt.min); spin->SetValue(m_opt.min);
spin->GetText()->SetInsertionPointEnd(); spin->GetText()->SetInsertionPointEnd();
} }
@ -962,13 +1018,16 @@ void SpinCtrl::msw_rescale()
{ {
Field::msw_rescale(); Field::msw_rescale();
wxSpinCtrl* field = dynamic_cast<wxSpinCtrl*>(window); auto field = dynamic_cast<::SpinInput*>(window);
if (parent_is_custom_ctrl) if (parent_is_custom_ctrl)
field->SetSize(wxSize(def_width() * m_em_unit, lround(opt_height * m_em_unit))); field->SetSize(wxSize(def_width() * m_em_unit, lround(opt_height * m_em_unit)));
else else
field->SetMinSize(wxSize(def_width() * m_em_unit, int(1.9f*field->GetFont().GetPixelSize().y))); field->SetMinSize(wxSize(def_width() * m_em_unit, int(1.9f*field->GetFont().GetPixelSize().y)));
} }
#if 1
using choice_ctrl = ::ComboBox;
#else
#ifdef __WXOSX__ #ifdef __WXOSX__
static_assert(wxMAJOR_VERSION >= 3, "Use of wxBitmapComboBox on Settings Tabs requires wxWidgets 3.0 and newer"); static_assert(wxMAJOR_VERSION >= 3, "Use of wxBitmapComboBox on Settings Tabs requires wxWidgets 3.0 and newer");
using choice_ctrl = wxBitmapComboBox; using choice_ctrl = wxBitmapComboBox;
@ -979,6 +1038,7 @@ using choice_ctrl = BitmapComboBox;
using choice_ctrl = wxComboBox; using choice_ctrl = wxComboBox;
#endif #endif
#endif // __WXOSX__ #endif // __WXOSX__
#endif
void Choice::BUILD() { void Choice::BUILD() {
wxSize size(def_width_wider() * m_em_unit, wxDefaultCoord); wxSize size(def_width_wider() * m_em_unit, wxDefaultCoord);
@ -989,10 +1049,10 @@ void Choice::BUILD() {
if (m_opt.gui_type != ConfigOptionDef::GUIType::undefined if (m_opt.gui_type != ConfigOptionDef::GUIType::undefined
&& m_opt.gui_type != ConfigOptionDef::GUIType::select_close) { && m_opt.gui_type != ConfigOptionDef::GUIType::select_close) {
m_is_editable = true; 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 { else {
#ifdef __WXOSX__ #if 0 //#ifdef __WXOSX__
/* wxBitmapComboBox with wxCB_READONLY style return NULL for GetTextCtrl(), /* wxBitmapComboBox with wxCB_READONLY style return NULL for GetTextCtrl(),
* so ToolTip doesn't shown. * so ToolTip doesn't shown.
* Next workaround helps to solve this problem * Next workaround helps to solve this problem
@ -1001,7 +1061,7 @@ void Choice::BUILD() {
temp->SetTextCtrlStyle(wxTE_READONLY); temp->SetTextCtrlStyle(wxTE_READONLY);
temp->Create(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr); temp->Create(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr);
#else #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__ #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); wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None);
long style = wxTE_PROCESS_ENTER; long style = wxTE_PROCESS_ENTER;
#ifdef _WIN32 x_textctrl = new text_ctrl(m_parent, X, "", "", wxDefaultPosition, field_size, style);
style |= wxBORDER_SIMPLE; y_textctrl = new text_ctrl(m_parent, Y, "", "", wxDefaultPosition, field_size, style);
#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);
if (parent_is_custom_ctrl && m_opt.height < 0) if (parent_is_custom_ctrl && m_opt.height < 0)
opt_height = (double)x_textctrl->GetSize().GetHeight() / m_em_unit; opt_height = (double)x_textctrl->GetSize().GetHeight() / m_em_unit;
x_textctrl->SetFont(Slic3r::GUI::wxGetApp().normal_font()); 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->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_x = new wxStaticText(m_parent, wxID_ANY, "x : ");
auto static_text_y = new wxStaticText(m_parent, wxID_ANY, " y : "); auto static_text_y = new wxStaticText(m_parent, wxID_ANY, " y : ");
@ -1527,7 +1584,7 @@ void PointCtrl::sys_color_changed()
#endif #endif
} }
bool PointCtrl::value_was_changed(wxTextCtrl* win) bool PointCtrl::value_was_changed(text_ctrl* win)
{ {
if (m_value.empty()) if (m_value.empty())
return true; return true;
@ -1539,7 +1596,7 @@ bool PointCtrl::value_was_changed(wxTextCtrl* win)
return boost::any_cast<Vec2d>(m_value) != boost::any_cast<Vec2d>(val); return boost::any_cast<Vec2d>(m_value) != boost::any_cast<Vec2d>(val);
} }
void PointCtrl::propagate_value(wxTextCtrl* win) void PointCtrl::propagate_value(text_ctrl* win)
{ {
if (win->GetValue().empty()) if (win->GetValue().empty())
on_kill_focus(); on_kill_focus();

View File

@ -25,6 +25,10 @@
#include "GUI.hpp" #include "GUI.hpp"
#include "wxExtensions.hpp" #include "wxExtensions.hpp"
#include "Widgets/CheckBox.hpp"
#include "Widgets/SwitchButton.hpp"
#include "Widgets/SpinInput.hpp"
#include "Widgets/TextInput.hpp"
#ifdef __WXMSW__ #ifdef __WXMSW__
#define wxMSW true #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. /// 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; } 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 { class TextCtrl : public Field {
using Field::Field; using Field::Field;
#ifdef __WXGTK__ #ifdef __WXGTK__
@ -314,7 +320,7 @@ public:
void set_value(const std::string& value, bool change_event = false) { void set_value(const std::string& value, bool change_event = false) {
m_disable_change_event = !change_event; m_disable_change_event = !change_event;
dynamic_cast<wxTextCtrl*>(window)->SetValue(wxString(value)); dynamic_cast<text_ctrl*>(window)->SetValue(wxString(value));
m_disable_change_event = false; m_disable_change_event = false;
} }
void set_value(const boost::any& value, bool change_event = false) override; 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(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
~CheckBox() {} ~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 }; wxWindow* window{ nullptr };
void BUILD() override; void BUILD() override;
void set_value(const bool value, bool change_event = false) { void set_value(const bool value, bool change_event = false);
m_disable_change_event = !change_event;
dynamic_cast<wxCheckBox*>(window)->SetValue(value);
m_disable_change_event = false;
}
void set_value(const boost::any& value, bool change_event = false) override; void set_value(const boost::any& value, bool change_event = false) override;
void set_last_meaningful_value() override; void set_last_meaningful_value() override;
void set_na_value() override; void set_na_value() override;
boost::any& get_value() override; boost::any& get_value() override;
void msw_rescale() override; void msw_rescale() override;
void sys_color_changed() override;
void enable() override { dynamic_cast<wxCheckBox*>(window)->Enable(); } void enable() override;
void disable() override { dynamic_cast<wxCheckBox*>(window)->Disable(); } void disable() override;
wxWindow* getWindow() override { return window; } wxWindow* getWindow() override { return window; }
private:
void SetValue(bool value);
bool GetValue();
}; };
class SpinCtrl : public Field { class SpinCtrl : public Field {
@ -377,20 +390,32 @@ public:
/* /*
void set_value(const std::string& value, bool change_event = false) { void set_value(const std::string& value, bool change_event = false) {
m_disable_change_event = !change_event; m_disable_change_event = !change_event;
dynamic_cast<wxSpinCtrl*>(window)->SetValue(value); dynamic_cast<::SpinInput*>(window)->SetValue(value);
m_disable_change_event = false; 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<int>(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_value(const boost::any& value, bool change_event = false) override;
void set_last_meaningful_value() override; void set_last_meaningful_value() override;
void set_na_value() override; void set_na_value() override;
boost::any& get_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 msw_rescale() override;
void enable() override { dynamic_cast<wxSpinCtrl*>(window)->Enable(); } void enable() override { dynamic_cast<::SpinInput*>(window)->Enable(); }
void disable() override { dynamic_cast<wxSpinCtrl*>(window)->Disable(); } void disable() override { dynamic_cast<::SpinInput*>(window)->Disable(); }
wxWindow* getWindow() override { return window; } wxWindow* getWindow() override { return window; }
}; };
@ -466,13 +491,13 @@ public:
~PointCtrl(); ~PointCtrl();
wxSizer* sizer{ nullptr }; wxSizer* sizer{ nullptr };
wxTextCtrl* x_textctrl{ nullptr }; text_ctrl* x_textctrl{ nullptr };
wxTextCtrl* y_textctrl{ nullptr }; text_ctrl* y_textctrl{ nullptr };
void BUILD() override; 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 // 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 Vec2d& value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false) override; void set_value(const boost::any& value, bool change_event = false) override;
boost::any& get_value() override; boost::any& get_value() override;

View File

@ -1756,6 +1756,11 @@ bool GUI_App::tabs_as_menu() const
return app_config->get_bool("tabs_as_menu"); // || dark_mode(); 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 wxSize GUI_App::get_min_size() const
{ {
return wxSize(76*m_em_unit, 49 * m_em_unit); return wxSize(76*m_em_unit, 49 * m_em_unit);

View File

@ -248,6 +248,7 @@ public:
const wxFont& link_font() { return m_link_font; } const wxFont& link_font() { return m_link_font; }
int em_unit() const { return m_em_unit; } int em_unit() const { return m_em_unit; }
bool tabs_as_menu() const; bool tabs_as_menu() const;
bool suppress_round_corners() const;
wxSize get_min_size() const; wxSize get_min_size() const;
float toolbar_icon_scale(const bool is_limited = false) const; float toolbar_icon_scale(const bool is_limited = false) const;
void set_auto_toolbar_icon_scale(float scale) const; void set_auto_toolbar_icon_scale(float scale) const;

View File

@ -25,6 +25,8 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include "slic3r/Utils/FixModelByWin10.hpp" #include "slic3r/Utils/FixModelByWin10.hpp"
#include "Widgets/CheckBox.hpp"
// For special mirroring in manipulation gizmo // For special mirroring in manipulation gizmo
#include "Gizmos/GLGizmosManager.hpp" #include "Gizmos/GLGizmosManager.hpp"
#include "Gizmos/GLGizmoEmboss.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); wxSize size(15 * wxGetApp().em_unit(), -1);
choice_ctrl* temp = nullptr; choice_ctrl* temp = nullptr;
#ifdef __WXOSX__ #if 0//def __WXOSX__
/* wxBitmapComboBox with wxCB_READONLY style return NULL for GetTextCtrl(), /* wxBitmapComboBox with wxCB_READONLY style return NULL for GetTextCtrl(),
* so ToolTip doesn't shown. * so ToolTip doesn't shown.
* Next workaround helps to solve this problem * 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->SetTextCtrlStyle(wxTE_READONLY);
temp->Create(parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr); temp->Create(parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr);
#else #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__ #endif //__WXOSX__
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); 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) static void set_font_and_background_style(wxWindow* win, const wxFont& font)
{ {
win->SetFont(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" }; 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_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->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&) { 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(); 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->activate();
m_og->sizer->Clear(true); m_og->sizer->Clear(true);
@ -533,7 +535,7 @@ void ObjectManipulation::Show(const bool show)
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); 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()); 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) { 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); m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Local), 2);
#else #else
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Local), wxNullBitmap, 2); 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); 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")) { if (m_use_colors != wxGetApp().app_config->get_bool("color_mapinulation_panel")) {
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_word_local_combo);
wxGetApp().UpdateDarkUI(m_check_inch); wxGetApp().UpdateDarkUI(m_check_inch);
#endif #endif
CheckBox::SysColorChanged(m_check_inch);
for (ManipulationEditor* editor : m_editors) for (ManipulationEditor* editor : m_editors)
editor->sys_color_changed(this); editor->sys_color_changed(this);
@ -1227,19 +1231,12 @@ static const char axes[] = { 'x', 'y', 'z' };
ManipulationEditor::ManipulationEditor(ObjectManipulation* parent, ManipulationEditor::ManipulationEditor(ObjectManipulation* parent,
const std::string& opt_key, const std::string& opt_key,
int axis) : int axis) :
wxTextCtrl(parent->parent(), wxID_ANY, wxEmptyString, wxDefaultPosition, ::TextInput(parent->parent(), "", "", "", wxDefaultPosition,
wxSize((wxOSX ? 5 : 6)*int(wxGetApp().em_unit()), wxDefaultCoord), wxTE_PROCESS_ENTER wxSize(int(5.8 * wxGetApp().em_unit()), wxDefaultCoord), wxTE_PROCESS_ENTER),
#ifdef _WIN32
| wxBORDER_SIMPLE
#endif
),
m_opt_key(opt_key), m_opt_key(opt_key),
m_axis(axis) m_axis(axis)
{ {
set_font_and_background_style(this, wxGetApp().normal_font()); set_font_and_background_style(this, wxGetApp().normal_font());
#ifdef __WXOSX__
this->OSXDisableAllSmartSubstitutions();
#endif // __WXOSX__
if (parent->use_colors()) { if (parent->use_colors()) {
this->SetBackgroundColour(wxColour(axes_color_back[axis])); this->SetBackgroundColour(wxColour(axes_color_back[axis]));
this->SetForegroundColour(*wxBLACK); this->SetForegroundColour(*wxBLACK);
@ -1295,8 +1292,7 @@ ManipulationEditor::ManipulationEditor(ObjectManipulation* parent,
void ManipulationEditor::msw_rescale() void ManipulationEditor::msw_rescale()
{ {
const int em = wxGetApp().em_unit(); SetCtrlSize(wxSize(int(5.8 * wxGetApp().em_unit()), wxDefaultCoord));
SetMinSize(wxSize(5 * em, wxDefaultCoord));
} }
void ManipulationEditor::sys_color_changed(ObjectManipulation* parent) void ManipulationEditor::sys_color_changed(ObjectManipulation* parent)

View File

@ -13,6 +13,9 @@
#include "libslic3r/Point.hpp" #include "libslic3r/Point.hpp"
#include <float.h> #include <float.h>
#include "Widgets/ComboBox.hpp"
#include "Widgets/TextInput.hpp"
#ifdef __WXOSX__ #ifdef __WXOSX__
class wxBitmapComboBox; class wxBitmapComboBox;
#else #else
@ -21,15 +24,17 @@ class wxComboBox;
class wxStaticText; class wxStaticText;
class LockButton; class LockButton;
class wxStaticBitmap; class wxStaticBitmap;
class wxCheckBox;
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
#ifdef _WIN32 #ifdef _WIN32
class BitmapComboBox; class BitmapComboBox;
#endif #endif
#if 1
using choice_ctrl = ::ComboBox;
#else
#ifdef __WXOSX__ #ifdef __WXOSX__
static_assert(wxMAJOR_VERSION >= 3, "Use of wxBitmapComboBox on Manipulation panel requires wxWidgets 3.0 and newer"); static_assert(wxMAJOR_VERSION >= 3, "Use of wxBitmapComboBox on Manipulation panel requires wxWidgets 3.0 and newer");
using choice_ctrl = wxBitmapComboBox; using choice_ctrl = wxBitmapComboBox;
@ -40,11 +45,12 @@ class BitmapComboBox;
using choice_ctrl = wxComboBox; using choice_ctrl = wxComboBox;
#endif #endif
#endif // __WXOSX__ #endif // __WXOSX__
#endif
class Selection; class Selection;
class ObjectManipulation; class ObjectManipulation;
class ManipulationEditor : public wxTextCtrl class ManipulationEditor : public ::TextInput
{ {
std::string m_opt_key; std::string m_opt_key;
int m_axis; int m_axis;
@ -128,7 +134,7 @@ private:
ScalableButton* m_reset_skew_button{ nullptr }; ScalableButton* m_reset_skew_button{ nullptr };
ScalableButton* m_drop_to_bed_button{ nullptr }; ScalableButton* m_drop_to_bed_button{ nullptr };
wxCheckBox* m_check_inch {nullptr}; wxWindow* m_check_inch {nullptr};
std::array<ScalableButton*, 3> m_mirror_buttons; std::array<ScalableButton*, 3> m_mirror_buttons;

View File

@ -732,7 +732,7 @@ void MainFrame::init_tabpanel()
#ifdef _MSW_DARK_MODE #ifdef _MSW_DARK_MODE
if (wxGetApp().tabs_as_menu()) { if (wxGetApp().tabs_as_menu()) {
m_tabpanel = new wxSimplebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME); m_tabpanel = new wxSimplebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME);
wxGetApp().UpdateDarkUI(m_tabpanel); // wxGetApp().UpdateDarkUI(m_tabpanel);
} }
else else
m_tabpanel = new Notebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME, true); 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); m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME);
#endif #endif
wxGetApp().UpdateDarkUI(m_tabpanel);
#ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList #ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font()); m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font());
#endif #endif
@ -1107,7 +1109,6 @@ void MainFrame::on_sys_color_changed()
wxGetApp().update_ui_colours_from_appconfig(); wxGetApp().update_ui_colours_from_appconfig();
#ifdef __WXMSW__ #ifdef __WXMSW__
wxGetApp().UpdateDarkUI(m_tabpanel); wxGetApp().UpdateDarkUI(m_tabpanel);
// m_statusbar->update_dark_ui();
#ifdef _MSW_DARK_MODE #ifdef _MSW_DARK_MODE
// update common mode sizer // update common mode sizer
if (!wxGetApp().tabs_as_menu()) if (!wxGetApp().tabs_as_menu())
@ -2311,7 +2312,7 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe)
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
#else #else
this->SetFont(wxGetApp().normal_font()); this->SetFont(wxGetApp().normal_font());
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); // this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif // __WXMSW__ #endif // __WXMSW__
// Load the icon either from the exe, or from the ico file. // Load the icon either from the exe, or from the ico file.

View File

@ -27,6 +27,8 @@
#include "slic3r/GUI/MainFrame.hpp" #include "slic3r/GUI/MainFrame.hpp"
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "Widgets/CheckBox.hpp"
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
@ -268,7 +270,7 @@ RichMessageDialog::RichMessageDialog(wxWindow* parent,
{ {
add_msg_content(this, content_sizer, get_wraped_wxString(message)); 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); wxGetApp().UpdateDarkUI(m_checkBox);
m_checkBox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { m_checkBoxValue = m_checkBox->GetValue(); }); m_checkBox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { m_checkBoxValue = m_checkBox->GetValue(); });

View File

@ -17,7 +17,7 @@
#include <wx/statline.h> #include <wx/statline.h>
class wxBoxSizer; class wxBoxSizer;
class wxCheckBox; class CheckBox;
class wxStaticBitmap; class wxStaticBitmap;
namespace Slic3r { namespace Slic3r {
@ -132,7 +132,7 @@ public:
// Generic rich message dialog, used intead of wxRichMessageDialog // Generic rich message dialog, used intead of wxRichMessageDialog
class RichMessageDialog : public MsgDialog class RichMessageDialog : public MsgDialog
{ {
wxCheckBox* m_checkBox{ nullptr }; CheckBox* m_checkBox{ nullptr };
wxString m_checkBoxText; wxString m_checkBoxText;
bool m_checkBoxValue{ false }; bool m_checkBoxValue{ false };

View File

@ -686,7 +686,8 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_mode_bmp(wxDC& dc, wxCoord v_pos)
return ctrl->m_h_gap; return ctrl->m_h_gap;
ConfigOptionMode mode = og_line.get_options()[0].opt.mode; 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); 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) if (og_line.get_options().front().opt.gui_type != ConfigOptionDef::GUIType::legend)

View File

@ -288,6 +288,7 @@ void OptionsGroup::activate_line(Line& line)
if (!custom_ctrl && m_use_custom_ctrl) { if (!custom_ctrl && m_use_custom_ctrl) {
custom_ctrl = new OG_CustomCtrl(is_legend_line || !staticbox ? this->parent() : static_cast<wxWindow*>(this->stb), this); custom_ctrl = new OG_CustomCtrl(is_legend_line || !staticbox ? this->parent() : static_cast<wxWindow*>(this->stb), this);
wxGetApp().UpdateDarkUI(custom_ctrl);
if (is_legend_line) if (is_legend_line)
sizer->Add(custom_ctrl, 0, wxEXPAND | wxLEFT, wxOSX ? 0 : 10); sizer->Add(custom_ctrl, 0, wxEXPAND | wxLEFT, wxOSX ? 0 : 10);
else else

View File

@ -141,6 +141,8 @@
#include "libslic3r/CustomGCode.hpp" #include "libslic3r/CustomGCode.hpp"
#include "libslic3r/Platform.hpp" #include "libslic3r/Platform.hpp"
#include "Widgets/CheckBox.hpp"
using boost::optional; using boost::optional;
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
using Slic3r::_3DScene; using Slic3r::_3DScene;
@ -800,7 +802,7 @@ Sidebar::Sidebar(Plater *parent)
wxGetApp().UpdateDarkUI(this); wxGetApp().UpdateDarkUI(this);
wxGetApp().UpdateDarkUI(p->scrolled); wxGetApp().UpdateDarkUI(p->scrolled);
#else #else
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); // SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif #endif
#endif #endif
@ -6112,7 +6114,7 @@ ProjectDropDialog::ProjectDropDialog(const std::string& filename)
main_sizer->Add(stb_sizer, 1, wxEXPAND | wxRIGHT | wxLEFT, 10); main_sizer->Add(stb_sizer, 1, wxEXPAND | wxRIGHT | wxLEFT, 10);
wxBoxSizer* bottom_sizer = new wxBoxSizer(wxHORIZONTAL); 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) { check->Bind(wxEVT_CHECKBOX, [](wxCommandEvent& evt) {
wxGetApp().app_config->set("show_drop_project_dialog", evt.IsChecked() ? "0" : "1"); wxGetApp().app_config->set("show_drop_project_dialog", evt.IsChecked() ? "0" : "1");
}); });

View File

@ -212,7 +212,7 @@ void PreferencesDialog::build()
#ifdef _WIN32 #ifdef _WIN32
wxGetApp().UpdateDarkUI(this); wxGetApp().UpdateDarkUI(this);
#else #else
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); //SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif #endif
const wxFont& font = wxGetApp().normal_font(); const wxFont& font = wxGetApp().normal_font();
SetFont(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); tabs = new Notebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME | wxNB_DEFAULT);
#else #else
tabs = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL |wxNB_NOPAGETHEME | wxNB_DEFAULT ); 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 #endif
// Add "General" tab // Add "General" tab
@ -527,6 +527,13 @@ void PreferencesDialog::build()
m_optgroup_gui->append_separator(); 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", append_bool_option(m_optgroup_gui, "show_hints",
L("Show \"Tip of the day\" notification after start"), L("Show \"Tip of the day\" notification after start"),
L("If enabled, useful hints are displayed at startup."), L("If enabled, useful hints are displayed at startup."),
@ -706,7 +713,7 @@ void PreferencesDialog::accept(wxEvent&)
#endif // __linux__ #endif // __linux__
} }
std::vector<std::string> options_to_recreate_GUI = { "no_defaults", "tabs_as_menu", "sys_menu_enabled", "font_size" }; std::vector<std::string> 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) { for (const std::string& option : options_to_recreate_GUI) {
if (m_values.find(option) != m_values.end()) { if (m_values.find(option) != m_values.end()) {

View File

@ -45,6 +45,8 @@
#include "PhysicalPrinterDialog.hpp" #include "PhysicalPrinterDialog.hpp"
#include "MsgDialog.hpp" #include "MsgDialog.hpp"
#include "Widgets/ComboBox.hpp"
// A workaround for a set of issues related to text fitting into gtk widgets: // A workaround for a set of issues related to text fitting into gtk widgets:
// See e.g.: https://github.com/prusa3d/PrusaSlicer/issues/4584 // See e.g.: https://github.com/prusa3d/PrusaSlicer/issues/4584
#if defined(__WXGTK20__) || defined(__WXGTK3__) #if defined(__WXGTK20__) || defined(__WXGTK3__)
@ -437,6 +439,7 @@ void PresetComboBox::update_from_bundle()
void PresetComboBox::msw_rescale() void PresetComboBox::msw_rescale()
{ {
m_em_unit = em_unit(this); m_em_unit = em_unit(this);
::ComboBox::Rescale();
} }
void PresetComboBox::sys_color_changed() void PresetComboBox::sys_color_changed()

View File

@ -525,9 +525,9 @@ SearchDialog::SearchDialog(OptionsSearcher* searcher)
wxBoxSizer* check_sizer = new wxBoxSizer(wxHORIZONTAL); 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()) 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); wxStdDialogButtonSizer* cancel_btn = this->CreateStdDialogButtonSizer(wxCANCEL);
GUI::wxGetApp().UpdateDarkUI(static_cast<wxButton*>(this->FindWindowById(wxID_CANCEL, this))); GUI::wxGetApp().UpdateDarkUI(static_cast<wxButton*>(this->FindWindowById(wxID_CANCEL, this)));

View File

@ -24,6 +24,9 @@
#include "OptionsGroup.hpp" #include "OptionsGroup.hpp"
#include "libslic3r/Preset.hpp" #include "libslic3r/Preset.hpp"
#include "Widgets/CheckBox.hpp"
class CheckBox;
namespace Slic3r { namespace Slic3r {
@ -162,8 +165,8 @@ class SearchDialog : public GUI::DPIDialog
wxTextCtrl* search_line { nullptr }; wxTextCtrl* search_line { nullptr };
wxDataViewCtrl* search_list { nullptr }; wxDataViewCtrl* search_list { nullptr };
SearchListModel* search_list_model { nullptr }; SearchListModel* search_list_model { nullptr };
wxCheckBox* check_category { nullptr }; CheckBox* check_category { nullptr };
wxCheckBox* check_english { nullptr }; CheckBox* check_english { nullptr };
OptionsSearcher* searcher { nullptr }; OptionsSearcher* searcher { nullptr };

View File

@ -69,6 +69,8 @@
#include "MsgDialog.hpp" #include "MsgDialog.hpp"
#include "Notebook.hpp" #include "Notebook.hpp"
#include "Widgets/CheckBox.hpp"
#ifdef WIN32 #ifdef WIN32
#include <CommCtrl.h> #include <CommCtrl.h>
#endif // WIN32 #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*/); Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL/*, name*/);
this->SetFont(Slic3r::GUI::wxGetApp().normal_font()); this->SetFont(Slic3r::GUI::wxGetApp().normal_font());
#ifdef __WXMSW__
wxGetApp().UpdateDarkUI(this); wxGetApp().UpdateDarkUI(this);
#else
SetBackgroundColour(parent->GetBackgroundColour());
#endif
m_compatible_printers.type = Preset::TYPE_PRINTER; m_compatible_printers.type = Preset::TYPE_PRINTER;
m_compatible_printers.key_list = "compatible_printers"; m_compatible_printers.key_list = "compatible_printers";
@ -167,8 +173,6 @@ void Tab::create_preset_tab()
} }
}); });
auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
//buttons //buttons
m_scaled_buttons.reserve(6); m_scaled_buttons.reserve(6);
m_scaled_buttons.reserve(2); 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. // Initialize the page.
PageShp page(new Page(m_page_view, title, icon_idx)); 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) if (!is_extruder_pages)
m_pages.push_back(page); m_pages.push_back(page);
@ -961,6 +961,11 @@ void Tab::msw_rescale()
m_presets_choice->msw_rescale(); m_presets_choice->msw_rescale();
m_treectrl->SetMinSize(wxSize(20 * m_em_unit, -1)); 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 // rescale options_groups
if (m_active_page) if (m_active_page)
m_active_page->msw_rescale(); m_active_page->msw_rescale();
@ -1939,21 +1944,23 @@ void TabFilament::create_line_with_near_label_widget(ConfigOptionsGroupShp optgr
else else
line = optgroup->create_single_option_line(optgroup->get_option(opt_key)); 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) { line.near_label_widget = [this, optgroup_wk = ConfigOptionsGroupWkp(optgroup), opt_key, opt_index](wxWindow* parent) {
const bool is_checked = evt.IsChecked(); wxWindow* check_box = CheckBox::GetNewWin(parent);
if (auto optgroup_sh = optgroup_wk.lock(); optgroup_sh) { wxGetApp().UpdateDarkUI(check_box);
if (Field *field = optgroup_sh->get_fieldc(opt_key, opt_index); field != nullptr) {
field->toggle(is_checked); check_box->Bind(wxEVT_CHECKBOX, [optgroup_wk, opt_key, opt_index](wxCommandEvent& evt) {
if (is_checked) const bool is_checked = evt.IsChecked();
field->set_last_meaningful_value(); if (auto optgroup_sh = optgroup_wk.lock(); optgroup_sh) {
else if (Field *field = optgroup_sh->get_fieldc(opt_key, opt_index); field != nullptr) {
field->set_na_value(); 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; m_overrides_options[opt_key] = check_box;
return 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); m_overrides_options[opt_key]->Enable(is_checked);
is_checked &= !m_config->option(opt_key)->is_nil(); 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); Field* field = optgroup->get_fieldc(opt_key, opt_index);
if (field != nullptr) 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; 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); 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"; }); 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_volumetric_speed_description_line = nullptr;
m_cooling_description_line = nullptr; m_cooling_description_line = nullptr;
for (auto& over_opt : m_overrides_options)
over_opt.second = nullptr;
} }
void TabFilament::msw_rescale() void TabFilament::msw_rescale()
@ -2406,7 +2426,6 @@ void TabFilament::msw_rescale()
for (const auto& over_opt : m_overrides_options) for (const auto& over_opt : m_overrides_options)
if (wxWindow* win = over_opt.second) if (wxWindow* win = over_opt.second)
win->SetInitialSize(win->GetBestSize()); win->SetInitialSize(win->GetBestSize());
Tab::msw_rescale(); Tab::msw_rescale();
} }
@ -2416,8 +2435,16 @@ void TabFilament::sys_color_changed()
update_extruder_combobox(); update_extruder_combobox();
Tab::sys_color_changed(); 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() void TabFilament::load_current_preset()
{ {
const std::string& selected_filament_name = m_presets->get_selected_preset_name(); 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. // 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) 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()); 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), deps.btn = new ScalableButton(parent, wxID_ANY, "printer", format_wxstr(" %s %s", _L("Set"), dots),
wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT); wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT);
deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); 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.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. // 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<std::string> {}); this->load_key_value(deps.key_list, std::vector<std::string> {});
this->get_field(deps.key_condition)->toggle(deps.checkbox->GetValue()); this->get_field(deps.key_condition)->toggle(is_checked);
this->update_changed_ui(); this->update_changed_ui();
}) ); }) );
@ -4524,7 +4552,7 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep
for (auto idx : selections) for (auto idx : selections)
value.push_back(presets[idx].ToUTF8().data()); value.push_back(presets[idx].ToUTF8().data());
if (value.empty()) { if (value.empty()) {
deps.checkbox->SetValue(1); CheckBox::SetValue(deps.checkbox, true);
deps.btn->Disable(); deps.btn->Disable();
} }
// All depending_presets have been made compatible with this preset. // 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 top_sizer = new wxBoxSizer(wxHORIZONTAL);
auto add_text_editor = [substitution_id, top_sizer, this](const wxString& value, int opt_pos, int proportion) { 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 auto editor = new ::TextInput(m_parent, value, "", "", wxDefaultPosition, wxSize(15 * m_em, wxDefaultCoord), wxTE_PROCESS_ENTER);
#ifdef _WIN32
| wxBORDER_SIMPLE
#endif
);
editor->SetFont(wxGetApp().normal_font()); editor->SetFont(wxGetApp().normal_font());
wxGetApp().UpdateDarkUI(editor); 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 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; 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")); auto chb_regexp = CheckBox::GetNewWin(m_parent, _L("Regular expression"));
chb_regexp->SetValue(regexp); CheckBox::SetValue(chb_regexp, regexp);
params_sizer->Add(chb_regexp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, m_em); 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")); auto chb_case_insensitive = CheckBox::GetNewWin(m_parent, _L("Case insensitive"));
chb_case_insensitive->SetValue(case_insensitive); CheckBox::SetValue(chb_case_insensitive, case_insensitive);
params_sizer->Add(chb_case_insensitive, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, m_em); 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")); auto chb_whole_word = CheckBox::GetNewWin(m_parent, _L("Whole word"));
chb_whole_word->SetValue(whole_word); CheckBox::SetValue(chb_whole_word, whole_word);
params_sizer->Add(chb_whole_word, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, m_em); 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")); auto chb_match_single_line = CheckBox::GetNewWin(m_parent, _L("Match single line"));
chb_match_single_line->SetValue(match_single_line); CheckBox::SetValue(chb_match_single_line, match_single_line);
chb_match_single_line->Show(regexp); chb_match_single_line->Show(regexp);
m_chb_match_single_lines.emplace_back(chb_match_single_line); 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); params_sizer->Add(chb_match_single_line, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, m_em);
for (wxCheckBox* chb : std::initializer_list<wxCheckBox*>{ chb_regexp, chb_case_insensitive, chb_whole_word, chb_match_single_line }) { for (wxWindow* chb : std::initializer_list<wxWindow*>{ chb_regexp, chb_case_insensitive, chb_whole_word, chb_match_single_line }) {
chb->SetFont(wxGetApp().normal_font()); 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) { 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(); std::string value = std::string();
if (chb_regexp->GetValue()) if (CheckBox::GetValue(chb_regexp))
value += "r"; value += "r";
if (chb_case_insensitive->GetValue()) if (CheckBox::GetValue(chb_case_insensitive))
value += "i"; value += "i";
if (chb_whole_word->GetValue()) if (CheckBox::GetValue(chb_whole_word))
value += "w"; value += "w";
if (chb_match_single_line->GetValue()) if (CheckBox::GetValue(chb_match_single_line))
value += "s"; value += "s";
chb_match_single_line->Show(chb_regexp->GetValue()); chb_match_single_line->Show(CheckBox::GetValue(chb_regexp));
m_grid_sizer->Layout(); m_grid_sizer->Layout();
edit_substitution(substitution_id, 2, value); edit_substitution(substitution_id, 2, value);
@ -4978,7 +5002,7 @@ void Tab::compatible_widget_reload(PresetDependencies &deps)
bool has_any = ! m_config->option<ConfigOptionStrings>(deps.key_list)->values.empty(); bool has_any = ! m_config->option<ConfigOptionStrings>(deps.key_list)->values.empty();
has_any ? deps.btn->Enable() : deps.btn->Disable(); has_any ? deps.btn->Enable() : deps.btn->Disable();
deps.checkbox->SetValue(! has_any); CheckBox::SetValue(deps.checkbox, !has_any);
field->toggle(! has_any); field->toggle(! has_any);
} }

View File

@ -51,6 +51,8 @@
#include "OptionsGroup.hpp" #include "OptionsGroup.hpp"
#include "libslic3r/Preset.hpp" #include "libslic3r/Preset.hpp"
class CheckBox;
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
@ -202,7 +204,7 @@ protected:
struct PresetDependencies { struct PresetDependencies {
Preset::Type type = Preset::TYPE_INVALID; Preset::Type type = Preset::TYPE_INVALID;
wxCheckBox *checkbox = nullptr; wxWindow *checkbox = nullptr;
ScalableButton *btn = nullptr; ScalableButton *btn = nullptr;
std::string key_list; // "compatible_printers" std::string key_list; // "compatible_printers"
std::string key_condition; std::string key_condition;
@ -473,7 +475,7 @@ class TabFilament : public Tab
void create_extruder_combobox(); void create_extruder_combobox();
void update_volumetric_flow_preset_hints(); void update_volumetric_flow_preset_hints();
std::map<std::string, wxCheckBox*> m_overrides_options; std::map<std::string, wxWindow*> m_overrides_options;
public: public:
TabFilament(wxBookCtrlBase* parent) : TabFilament(wxBookCtrlBase* parent) :
Tab(parent, _(L("Filament Settings")), Slic3r::Preset::TYPE_FILAMENT) {} Tab(parent, _(L("Filament Settings")), Slic3r::Preset::TYPE_FILAMENT) {}

View File

@ -0,0 +1,47 @@
#include "BitmapToggleButton.hpp"
#include <wx/settings.h>
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());
}

View File

@ -0,0 +1,17 @@
#ifndef slic3r_GUI_BitmapToggleButton_hpp_
#define slic3r_GUI_BitmapToggleButton_hpp_
#include <wx/tglbtn.h>
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_

View File

@ -1,7 +1,8 @@
#include "Button.hpp" #include "Button.hpp"
#include "Label.hpp"
#include <wx/dcgraph.h> #include <wx/dcgraph.h>
#include <wx/dc.h>
#include <wx/dcclient.h>
BEGIN_EVENT_TABLE(Button, StaticBox) BEGIN_EVENT_TABLE(Button, StaticBox)
@ -36,23 +37,20 @@ Button::Button()
std::make_pair(*wxBLACK, (int) StateColor::Normal)); 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() : Button()
{ {
Create(parent, text, icon, style, iconSize); 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); StaticBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style);
state_handler.attach({&text_color}); state_handler.attach({&text_color});
state_handler.update_binds(); state_handler.update_binds();
//BBS set default font
SetFont(Label::Body_14);
wxWindow::SetLabel(text); wxWindow::SetLabel(text);
if (!icon.IsEmpty()) { if (!icon.IsEmpty()) {
//BBS set button icon default size to 20 this->active_icon = ScalableBitmap(this, icon.ToStdString(), iconSize);
this->active_icon = ScalableBitmap(this, icon.ToStdString(), iconSize > 0 ? iconSize : 20);
} }
messureSize(); messureSize();
return true; return true;
@ -68,8 +66,7 @@ void Button::SetLabel(const wxString& label)
void Button::SetIcon(const wxString& icon) void Button::SetIcon(const wxString& icon)
{ {
if (!icon.IsEmpty()) { if (!icon.IsEmpty()) {
//BBS set button icon default size to 20 this->active_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_size());
this->active_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_cnt());
} }
else else
{ {
@ -81,8 +78,7 @@ void Button::SetIcon(const wxString& icon)
void Button::SetInactiveIcon(const wxString &icon) void Button::SetInactiveIcon(const wxString &icon)
{ {
if (!icon.IsEmpty()) { if (!icon.IsEmpty()) {
// BBS set button icon default size to 20 this->inactive_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_size());
this->inactive_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_cnt());
} else { } else {
this->inactive_icon = ScalableBitmap(); this->inactive_icon = ScalableBitmap();
} }
@ -129,12 +125,12 @@ void Button::SetCanFocus(bool canFocus) { this->canFocus = canFocus; }
void Button::Rescale() void Button::Rescale()
{ {
if (this->active_icon.bmp().IsOk()) /* if (this->active_icon.bmp().IsOk())
this->active_icon.msw_rescale(); this->active_icon.msw_rescale();
if (this->inactive_icon.bmp().IsOk()) if (this->inactive_icon.bmp().IsOk())
this->inactive_icon.msw_rescale(); this->inactive_icon.msw_rescale();
*/
messureSize(); messureSize();
} }
@ -162,6 +158,7 @@ void Button::render(wxDC& dc)
ScalableBitmap icon; ScalableBitmap icon;
if (m_selected || ((states & (int)StateColor::State::Hovered) != 0)) if (m_selected || ((states & (int)StateColor::State::Hovered) != 0))
// if (m_selected || (states & (int)StateColor::State::Hovered))
icon = active_icon; icon = active_icon;
else else
icon = inactive_icon; icon = inactive_icon;
@ -171,7 +168,7 @@ void Button::render(wxDC& dc)
//BBS norrow size between text and icon //BBS norrow size between text and icon
szContent.x += padding; szContent.x += padding;
} }
szIcon = icon.GetBmpSize(); szIcon = icon.GetSize();
szContent.x += szIcon.x; szContent.x += szIcon.x;
if (szIcon.y > szContent.y) if (szIcon.y > szContent.y)
szContent.y = szIcon.y; szContent.y = szIcon.y;
@ -190,7 +187,7 @@ void Button::render(wxDC& dc)
wxPoint pt = rcContent.GetLeftTop(); wxPoint pt = rcContent.GetLeftTop();
if (icon.bmp().IsOk()) { if (icon.bmp().IsOk()) {
pt.y += (rcContent.height - szIcon.y) / 2; 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 //BBS norrow size between text and icon
pt.x += szIcon.x + padding; pt.x += szIcon.x + padding;
pt.y = rcContent.y; pt.y = rcContent.y;
@ -220,7 +217,7 @@ void Button::messureSize()
//BBS norrow size between text and icon //BBS norrow size between text and icon
szContent.x += 5; szContent.x += 5;
} }
wxSize szIcon = this->active_icon.GetBmpSize(); wxSize szIcon = this->active_icon.GetSize();
szContent.x += szIcon.x; szContent.x += szIcon.x;
if (szIcon.y > szContent.y) if (szIcon.y > szContent.y)
szContent.y = szIcon.y; szContent.y = szIcon.y;

View File

@ -24,9 +24,9 @@ class Button : public StaticBox
public: public:
Button(); 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; void SetLabel(const wxString& label) override;

View File

@ -1,31 +1,25 @@
#include "CheckBox.hpp" #include "CheckBox.hpp"
#include "../wxExtensions.hpp" //#include "../wxExtensions.hpp"
CheckBox::CheckBox(wxWindow* parent) const int px_cnt = 16;
: wxBitmapToggleButton(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
, m_on(this, "check_on", 18) CheckBox::CheckBox(wxWindow* parent, const wxString& name)
, m_half(this, "check_half", 18) : BitmapToggleButton(parent, name, wxID_ANY)
, m_off(this, "check_off", 18) , m_on(this, "check_on", px_cnt)
, m_on_disabled(this, "check_on_disabled", 18) , m_off(this, "check_off", px_cnt)
, m_half_disabled(this, "check_half_disabled", 18) , m_on_disabled(this, "check_on_disabled", px_cnt)
, m_off_disabled(this, "check_off_disabled", 18) , m_off_disabled(this, "check_off_disabled", px_cnt)
, m_on_focused(this, "check_on_focused", 18) , m_on_focused(this, "check_on_focused", px_cnt)
, m_half_focused(this, "check_half_focused", 18) , m_off_focused(this, "check_off_focused", px_cnt)
, m_off_focused(this, "check_off_focused", 18)
{ {
//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 #ifdef __WXOSX__ // State not fully implement on MacOS
Bind(wxEVT_SET_FOCUS, &CheckBox::updateBitmap, this); Bind(wxEVT_SET_FOCUS, &CheckBox::updateBitmap, this);
Bind(wxEVT_KILL_FOCUS, &CheckBox::updateBitmap, this); Bind(wxEVT_KILL_FOCUS, &CheckBox::updateBitmap, this);
Bind(wxEVT_ENTER_WINDOW, &CheckBox::updateBitmap, this); Bind(wxEVT_ENTER_WINDOW, &CheckBox::updateBitmap, this);
Bind(wxEVT_LEAVE_WINDOW, &CheckBox::updateBitmap, this); Bind(wxEVT_LEAVE_WINDOW, &CheckBox::updateBitmap, this);
#endif #endif
SetSize(m_on.GetBmpSize());
SetMinSize(m_on.GetBmpSize());
update(); update();
} }
@ -35,61 +29,59 @@ void CheckBox::SetValue(bool value)
update(); update();
} }
void CheckBox::SetHalfChecked(bool value) void CheckBox::Update()
{ {
m_half_checked = value; update();
update();
} }
void CheckBox::Rescale() 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(); update();
} }
void CheckBox::update() void CheckBox::update()
{ {
SetBitmapLabel((m_half_checked ? m_half : GetValue() ? m_on : m_off).bmp()); const bool val = GetValue();
SetBitmapDisabled((m_half_checked ? m_half_disabled : GetValue() ? m_on_disabled : m_off_disabled).bmp()); const wxBitmapBundle& bmp = (val ? m_on : m_off).bmp();
SetBitmap(bmp);
SetBitmapCurrent(bmp);
SetBitmapDisabled((val ? m_on_disabled : m_off_disabled).bmp());
#ifdef __WXMSW__ #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 #endif
SetBitmapCurrent((m_half_checked ? m_half_focused : GetValue() ? m_on_focused : m_off_focused).bmp());
#ifdef __WXOSX__ #ifdef __WXOSX__
wxCommandEvent e(wxEVT_UPDATE_UI); wxCommandEvent e(wxEVT_UPDATE_UI);
updateBitmap(e); updateBitmap(e);
#endif #endif
update_size();
} }
#ifdef __WXMSW__ #ifdef __WXMSW__
CheckBox::State CheckBox::GetNormalState() const { return State_Normal; } CheckBox::State CheckBox::GetNormalState() const
{
return State_Normal;
}
#endif #endif
#ifdef __WXOSX__
bool CheckBox::Enable(bool enable) bool CheckBox::Enable(bool enable)
{ {
bool result = wxBitmapToggleButton::Enable(enable); bool result = wxBitmapToggleButton::Enable(enable);
#ifdef __WXOSX__
if (result) { if (result) {
m_disable = !enable; m_disable = !enable;
wxCommandEvent e(wxEVT_ACTIVATE); wxCommandEvent e(wxEVT_ACTIVATE);
updateBitmap(e); updateBitmap(e);
} }
#endif
return result; return result;
} }
#ifdef __WXOSX__
wxBitmap CheckBox::DoGetBitmap(State which) const wxBitmap CheckBox::DoGetBitmap(State which) const
{ {
if (m_disable) { if (m_disable) {

View File

@ -2,25 +2,20 @@
#define slic3r_GUI_CheckBox_hpp_ #define slic3r_GUI_CheckBox_hpp_
#include "../wxExtensions.hpp" #include "../wxExtensions.hpp"
#include "BitmapToggleButton.hpp"
#include <wx/tglbtn.h> class CheckBox : public BitmapToggleButton
class CheckBox : public wxBitmapToggleButton
{ {
public: public:
CheckBox(wxWindow * parent = NULL); CheckBox(wxWindow* parent = NULL, const wxString& name = wxEmptyString);
public: public:
void SetValue(bool value) override; void SetValue(bool value) override;
void Update() override;
void SetHalfChecked(bool value = true); bool Enable(bool enable = true) override;
void Rescale(); void Rescale();
#ifdef __WXOSX__
virtual bool Enable(bool enable = true) wxOVERRIDE;
#endif
protected: protected:
#ifdef __WXMSW__ #ifdef __WXMSW__
virtual State GetNormalState() const wxOVERRIDE; virtual State GetNormalState() const wxOVERRIDE;
@ -37,19 +32,14 @@ protected:
#endif #endif
private: private:
void update(); void update() override;
private: ScalableBitmap m_on;
ScalableBitmap m_on; ScalableBitmap m_off;
ScalableBitmap m_half; ScalableBitmap m_on_disabled;
ScalableBitmap m_off; ScalableBitmap m_off_disabled;
ScalableBitmap m_on_disabled; ScalableBitmap m_on_focused;
ScalableBitmap m_half_disabled; ScalableBitmap m_off_focused;
ScalableBitmap m_off_disabled;
ScalableBitmap m_on_focused;
ScalableBitmap m_half_focused;
ScalableBitmap m_off_focused;
bool m_half_checked = false;
}; };
#endif // !slic3r_GUI_CheckBox_hpp_ #endif // !slic3r_GUI_CheckBox_hpp_

View File

@ -1,11 +1,13 @@
#include "ComboBox.hpp" #include "ComboBox.hpp"
#include "Label.hpp" #include "UIColors.hpp"
#include <wx/dcgraph.h> #include <wx/dcgraph.h>
#include "../GUI_App.hpp"
BEGIN_EVENT_TABLE(ComboBox, TextInput) BEGIN_EVENT_TABLE(ComboBox, TextInput)
EVT_LEFT_DOWN(ComboBox::mouseDown) EVT_LEFT_DOWN(ComboBox::mouseDown)
//EVT_MOUSEWHEEL(ComboBox::mouseWheelMoved) //EVT_MOUSEWHEEL(ComboBox::mouseWheelMoved)
EVT_KEY_DOWN(ComboBox::keyDown) EVT_KEY_DOWN(ComboBox::keyDown)
@ -28,27 +30,23 @@ ComboBox::ComboBox(wxWindow * parent,
long style) long style)
: drop(texts, icons) : drop(texts, icons)
{ {
if (style & wxCB_READONLY)
style |= wxRIGHT;
text_off = style & CB_NO_TEXT; text_off = style & CB_NO_TEXT;
TextInput::Create(parent, "", value, (style & CB_NO_DROP_ICON) ? "" : "drop_down", pos, size, TextInput::Create(parent, "", value, (style & CB_NO_DROP_ICON) ? "" : "drop_down", pos, size,
style | wxTE_PROCESS_ENTER); 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(); GetTextCtrl()->Hide();
TextInput::SetFont(Label::Body_14); else
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 {
GetTextCtrl()->Bind(wxEVT_KEY_DOWN, &ComboBox::keyDown, this); 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) { drop.Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &e) {
SetSelection(e.GetInt()); SetSelection(e.GetInt());
e.SetEventObject(this); e.SetEventObject(this);
@ -75,6 +73,8 @@ void ComboBox::SetSelection(int n)
void ComboBox::Rescale() void ComboBox::Rescale()
{ {
SetFont(Slic3r::GUI::wxGetApp().normal_font());
TextInput::Rescale(); TextInput::Rescale();
drop.Rescale(); drop.Rescale();
} }
@ -120,27 +120,74 @@ wxString ComboBox::GetTextLabel() const
bool ComboBox::SetFont(wxFont const& font) bool ComboBox::SetFont(wxFont const& font)
{ {
const bool set_drop_font = drop.SetFont(font);
if (GetTextCtrl() && GetTextCtrl()->IsShown()) if (GetTextCtrl() && GetTextCtrl()->IsShown())
return GetTextCtrl()->SetFont(font); return GetTextCtrl()->SetFont(font) && set_drop_font;
else return TextInput::SetFont(font) && set_drop_font;
return TextInput::SetFont(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); return Append(item, bitmap, nullptr);
} }
int ComboBox::Append(const wxString &item, int ComboBox::Append(const wxString &item,
const wxBitmap &bitmap, const wxBitmapBundle &bitmap,
void * clientData) void * clientData)
{ {
texts.push_back(item); texts.push_back(item);
icons.push_back(bitmap); icons.push_back(bitmap);
datas.push_back(clientData); datas.push_back(clientData);
types.push_back(wxClientData_None); types.push_back(wxClientData_None);
drop.Invalidate(); 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() void ComboBox::DoClear()
@ -174,10 +221,13 @@ void ComboBox::SetString(unsigned int n, wxString const &value)
if (n >= texts.size()) return; if (n >= texts.size()) return;
texts[n] = value; texts[n] = value;
drop.Invalidate(); 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, int ComboBox::DoInsertItems(const wxArrayStringsAdapter &items,
unsigned int pos, unsigned int pos,
@ -185,7 +235,7 @@ int ComboBox::DoInsertItems(const wxArrayStringsAdapter &items,
wxClientDataType type) wxClientDataType type)
{ {
if (pos > texts.size()) return -1; 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]); texts.insert(texts.begin() + pos, items[i]);
icons.insert(icons.begin() + pos, wxNullBitmap); icons.insert(icons.begin() + pos, wxNullBitmap);
datas.insert(datas.begin() + pos, clientData ? clientData[i] : NULL); datas.insert(datas.begin() + pos, clientData ? clientData[i] : NULL);
@ -193,7 +243,7 @@ int ComboBox::DoInsertItems(const wxArrayStringsAdapter &items,
++pos; ++pos;
} }
drop.Invalidate(true); drop.Invalidate(true);
return pos - 1; return int(pos) - 1;
} }
void *ComboBox::DoGetItemClientData(unsigned int n) const { return n < texts.size() ? datas[n] : NULL; } 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) void ComboBox::keyDown(wxKeyEvent& event)
{ {
switch (event.GetKeyCode()) { int key_code = event.GetKeyCode();
switch (key_code) {
#ifndef __WXOSX__
case WXK_RETURN: case WXK_RETURN:
#endif
case WXK_SPACE: case WXK_SPACE:
if (drop_down) { if (drop_down) {
drop.DismissAndNotify(); drop.DismissAndNotify();
@ -251,7 +304,7 @@ void ComboBox::keyDown(wxKeyEvent& event)
case WXK_RIGHT: case WXK_RIGHT:
if ((event.GetKeyCode() == WXK_UP || event.GetKeyCode() == WXK_LEFT) && GetSelection() > 0) { if ((event.GetKeyCode() == WXK_UP || event.GetKeyCode() == WXK_LEFT) && GetSelection() > 0) {
SetSelection(GetSelection() - 1); 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); SetSelection(GetSelection() + 1);
} else { } else {
break; break;

View File

@ -4,13 +4,13 @@
#include "TextInput.hpp" #include "TextInput.hpp"
#include "DropDown.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 #define CB_NO_TEXT DD_NO_TEXT
class ComboBox : public wxWindowWithItems<TextInput, wxItemContainer> class ComboBox : public wxWindowWithItems<TextInput, wxItemContainer>
{ {
std::vector<wxString> texts; std::vector<wxString> texts;
std::vector<wxBitmap> icons; std::vector<wxBitmapBundle> icons;
std::vector<void *> datas; std::vector<void *> datas;
std::vector<wxClientDataType> types; std::vector<wxClientDataType> types;
@ -32,10 +32,18 @@ public:
virtual bool SetFont(wxFont const & font) override; virtual bool SetFont(wxFont const & font) override;
public: bool SetBackgroundColour(const wxColour& colour) override;
int Append(const wxString &item, const wxBitmap &bitmap = wxNullBitmap); 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; unsigned int GetCount() const override;

View File

@ -1,7 +1,15 @@
#include "DropDown.hpp" #include "DropDown.hpp"
#include "Label.hpp" #include "../GUI_App.hpp"
#include "../OptionsGroup.hpp"
#include <wx/dcgraph.h> #include <wx/dcgraph.h>
#include <wx/dcbuffer.h>
#include <wx/dcclient.h>
#include <wx/dcscreen.h>
#include <wx/dcmemory.h>
#include <wx/bitmap.h>
#include <wx/display.h>
wxDEFINE_EVENT(EVT_DISMISS, wxCommandEvent); wxDEFINE_EVENT(EVT_DISMISS, wxCommandEvent);
@ -25,12 +33,13 @@ END_EVENT_TABLE()
*/ */
DropDown::DropDown(std::vector<wxString> &texts, DropDown::DropDown(std::vector<wxString> &texts,
std::vector<wxBitmap> &icons) std::vector<wxBitmapBundle> &icons)
: texts(texts) : texts(texts)
, icons(icons) , icons(icons)
, radius(Slic3r::GUI::wxGetApp().suppress_round_corners() ? 0 : 5)
, state_handler(this) , state_handler(this)
, border_color(0xDBDBDB)
, text_color(0x363636) , text_color(0x363636)
, border_color(0xDBDBDB)
, selector_border_color(std::make_pair(0x00AE42, (int) StateColor::Hovered), , selector_border_color(std::make_pair(0x00AE42, (int) StateColor::Hovered),
std::make_pair(*wxWHITE, (int) StateColor::Normal)) std::make_pair(*wxWHITE, (int) StateColor::Normal))
, selector_background_color(std::make_pair(0xEDFAF2, (int) StateColor::Checked), , selector_background_color(std::make_pair(0xEDFAF2, (int) StateColor::Checked),
@ -40,7 +49,7 @@ DropDown::DropDown(std::vector<wxString> &texts,
DropDown::DropDown(wxWindow * parent, DropDown::DropDown(wxWindow * parent,
std::vector<wxString> &texts, std::vector<wxString> &texts,
std::vector<wxBitmap> &icons, std::vector<wxBitmapBundle> &icons,
long style) long style)
: DropDown(texts, icons) : DropDown(texts, icons)
{ {
@ -51,16 +60,14 @@ void DropDown::Create(wxWindow * parent,
long style) long style)
{ {
wxPopupTransientWindow::Create(parent); wxPopupTransientWindow::Create(parent);
SetBackgroundStyle(wxBG_STYLE_PAINT); if (!wxOSX) SetBackgroundStyle(wxBG_STYLE_PAINT);
SetBackgroundColour(*wxWHITE);
state_handler.attach({&border_color, &text_color, &selector_border_color, &selector_background_color}); state_handler.attach({&border_color, &text_color, &selector_border_color, &selector_background_color});
state_handler.update_binds(); state_handler.update_binds();
if ((style & DD_NO_CHECK_ICON) == 0) if (!(style & DD_NO_CHECK_ICON))
check_bitmap = ScalableBitmap(this, "checked", 16); check_bitmap = ScalableBitmap(this, "checked", 16);
text_off = style & DD_NO_TEXT; text_off = style & DD_NO_TEXT;
// BBS set default font SetFont(parent->GetFont());
SetFont(Label::Body_14);
#ifdef __WXOSX__ #ifdef __WXOSX__
// wxPopupTransientWindow releases mouse on idle, which may cause various problems, // wxPopupTransientWindow releases mouse on idle, which may cause various problems,
// such as losting mouse move, and dismissing soon on first LEFT_DOWN event. // 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); 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(); paintNow();
} }
@ -179,6 +186,28 @@ void DropDown::paintNow()
Refresh(); 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 * Here we do the actual rendering. I put it in a separate
* method so that it can work no matter what type of DC * 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; if (texts.size() == 0) return;
int states = state_handler.states(); int states = state_handler.states();
const wxSize size = GetSize();
if (radius > 0. && !wxOSX)
SetTransparentBG(dc, this);
dc.SetPen(wxPen(border_color.colorForStates(states))); dc.SetPen(wxPen(border_color.colorForStates(states)));
dc.SetBrush(wxBrush(GetBackgroundColour())); dc.SetBrush(wxBrush(GetBackgroundColour()));
// if (GetWindowStyle() & wxBORDER_NONE) // if (GetWindowStyle() & wxBORDER_NONE)
// dc.SetPen(wxNullPen); // 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 // draw background
wxSize size = GetSize(); if (radius == 0.0 || wxOSX)
if (radius == 0) dc.DrawRectangle(rc);
dc.DrawRectangle(0, 0, size.x, size.y);
else else
dc.DrawRoundedRectangle(0, 0, size.x, size.y, radius); dc.DrawRoundedRectangle(rc, radius);
// draw hover rectangle // draw hover rectangle
wxRect rcContent = {{0, offset.y}, rowSize}; wxRect rcContent = {{0, offset.y}, rowSize};
@ -233,8 +271,9 @@ void DropDown::render(wxDC &dc)
} }
// draw position bar // draw position bar
if (rowSize.y * texts.size() > size.y) { const int text_size = int(texts.size());
int height = rowSize.y * 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, wxRect rect = {size.x - 6, -offset.y * size.y / height, 4,
size.y * size.y / height}; size.y * size.y / height};
dc.SetPen(wxPen(border_color.defaultColor())); dc.SetPen(wxPen(border_color.defaultColor()));
@ -247,13 +286,13 @@ void DropDown::render(wxDC &dc)
rcContent.x += 5; rcContent.x += 5;
rcContent.width -= 5; rcContent.width -= 5;
if (check_bitmap.bmp().IsOk()) { if (check_bitmap.bmp().IsOk()) {
auto szBmp = check_bitmap.GetBmpSize(); auto szBmp = check_bitmap.GetSize();
if (selection >= 0) { if (selection >= 0) {
wxPoint pt = rcContent.GetLeftTop(); wxPoint pt = rcContent.GetLeftTop();
pt.y += (rcContent.height - szBmp.y) / 2; pt.y += (rcContent.height - szBmp.y) / 2;
pt.y += rowSize.y * selection; pt.y += rowSize.y * selection;
if (pt.y + szBmp.y > 0 && pt.y < size.y) 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.x += szBmp.x + 5;
rcContent.width -= szBmp.x + 5; rcContent.width -= szBmp.x + 5;
@ -268,17 +307,26 @@ void DropDown::render(wxDC &dc)
if (rcContent.y > size.y) break; if (rcContent.y > size.y) break;
wxPoint pt = rcContent.GetLeftTop(); wxPoint pt = rcContent.GetLeftTop();
auto & icon = icons[i]; auto & icon = icons[i];
const wxSize pref_icon_sz = get_preferred_size(icon, m_parent);
if (iconSize.x > 0) { if (iconSize.x > 0) {
if (icon.IsOk()) { if (icon.IsOk()) {
pt.y += (rcContent.height - icon.GetSize().y) / 2; pt.y += (rcContent.height - pref_icon_sz.y) / 2;
dc.DrawBitmap(icon, pt); #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.x += iconSize.x + 5;
pt.y = rcContent.y; pt.y = rcContent.y;
} else if (icon.IsOk()) { } else if (icon.IsOk()) {
pt.y += (rcContent.height - icon.GetSize().y) / 2; pt.y += (rcContent.height - pref_icon_sz.y) / 2;
dc.DrawBitmap(icon, pt); #ifdef __WXGTK3__
pt.x += icon.GetWidth() + 5; 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; pt.y = rcContent.y;
} }
auto text = texts[i]; auto text = texts[i];
@ -305,7 +353,7 @@ void DropDown::messureSize()
for (size_t i = 0; i < texts.size(); ++i) { for (size_t i = 0; i < texts.size(); ++i) {
wxSize size1 = text_off ? wxSize() : dc.GetMultiLineTextExtent(texts[i]); wxSize size1 = text_off ? wxSize() : dc.GetMultiLineTextExtent(texts[i]);
if (icons[i].IsOk()) { 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 (size2.x > iconSize.x) iconSize = size2;
if (!align_icon) { if (!align_icon) {
size1.x += size2.x + (text_off ? 0 : 5); size1.x += size2.x + (text_off ? 0 : 5);
@ -317,7 +365,7 @@ void DropDown::messureSize()
wxSize szContent = textSize; wxSize szContent = textSize;
szContent.x += 10; szContent.x += 10;
if (check_bitmap.bmp().IsOk()) { if (check_bitmap.bmp().IsOk()) {
auto szBmp = check_bitmap.bmp().GetSize(); auto szBmp = check_bitmap.GetSize();
szContent.x += szBmp.x + 5; szContent.x += szBmp.x + 5;
} }
if (iconSize.x > 0) szContent.x += iconSize.x + (text_off ? 0 : 5); if (iconSize.x > 0) szContent.x += iconSize.x + (text_off ? 0 : 5);

View File

@ -2,24 +2,29 @@
#define slic3r_GUI_DropDown_hpp_ #define slic3r_GUI_DropDown_hpp_
#include <wx/stattext.h> #include <wx/stattext.h>
#include <wx/popupwin.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "../wxExtensions.hpp" #include "../wxExtensions.hpp"
#include "StateHandler.hpp" #include "StateHandler.hpp"
#define DD_NO_CHECK_ICON 0x0001 #define DD_NO_CHECK_ICON 0x0001
#define DD_NO_TEXT 0x0002 #define DD_NO_DROP_ICON 0x0002
#define DD_STYLE_MASK 0x0003 #define DD_NO_TEXT 0x0004
#define DD_STYLE_MASK 0x0008
wxDECLARE_EVENT(EVT_DISMISS, wxCommandEvent); wxDECLARE_EVENT(EVT_DISMISS, wxCommandEvent);
class DropDown : public wxPopupTransientWindow class DropDown : public wxPopupTransientWindow
{ {
std::vector<wxString> & texts; std::vector<wxString> & texts;
std::vector<wxBitmap> & icons; std::vector<wxBitmapBundle> & icons;
bool need_sync = false; bool need_sync = false;
int selection = -1; int selection = -1;
int hover_item = -1; int hover_item = -1;
double radius = 0; double radius;
bool use_content_width = false; bool use_content_width = false;
bool align_icon = false; bool align_icon = false;
bool text_off = false; bool text_off = false;
@ -42,17 +47,16 @@ class DropDown : public wxPopupTransientWindow
public: public:
DropDown(std::vector<wxString> &texts, DropDown(std::vector<wxString> &texts,
std::vector<wxBitmap> &icons); std::vector<wxBitmapBundle> &icons);
DropDown(wxWindow * parent, DropDown(wxWindow * parent,
std::vector<wxString> &texts, std::vector<wxString> &texts,
std::vector<wxBitmap> &icons, std::vector<wxBitmapBundle> &icons,
long style = 0); long style = 0);
void Create(wxWindow * parent, void Create(wxWindow * parent,
long style = 0); long style = 0);
public:
void Invalidate(bool clear = false); void Invalidate(bool clear = false);
int GetSelection() const { return selection; } int GetSelection() const { return selection; }
@ -62,7 +66,6 @@ public:
wxString GetValue() const; wxString GetValue() const;
void SetValue(const wxString &value); void SetValue(const wxString &value);
public:
void SetCornerRadius(double radius); void SetCornerRadius(double radius);
void SetBorderColor(StateColor const & color); void SetBorderColor(StateColor const & color);
@ -77,10 +80,11 @@ public:
void SetAlignIcon(bool align); void SetAlignIcon(bool align);
public:
void Rescale(); void Rescale();
bool HasDismissLongTime(); bool HasDismissLongTime();
static void SetTransparentBG(wxDC& dc, wxWindow* win);
protected: protected:
void OnDismiss() override; void OnDismiss() override;

View File

@ -1,6 +1,8 @@
#include "Label.hpp" #include "Label.hpp"
#include "StaticBox.hpp" #include "StaticBox.hpp"
#include <wx/settings.h>
wxFont Label::sysFont(int size, bool bold) wxFont Label::sysFont(int size, bool bold)
{ {
//#ifdef __linux__ //#ifdef __linux__

View File

@ -2,6 +2,7 @@
#define slic3r_GUI_Label_hpp_ #define slic3r_GUI_Label_hpp_
#include <wx/stattext.h> #include <wx/stattext.h>
#include <wx/dcclient.h>
#define LB_HYPERLINK 0x0001 #define LB_HYPERLINK 0x0001

View File

@ -1,8 +1,14 @@
#include "SpinInput.hpp" #include "SpinInput.hpp"
#include "Label.hpp"
#include "Button.hpp" #include "Button.hpp"
#include "UIColors.hpp"
#include "../GUI_App.hpp"
#include <wx/dcgraph.h> #include <wx/dcgraph.h>
#include <wx/panel.h>
#include <wx/spinctrl.h>
#include <wx/valtext.h>
BEGIN_EVENT_TABLE(SpinInput, wxPanel) 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)) : 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)) , 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_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) int min, int max, int initial)
{ {
StaticBox::Create(parent, wxID_ANY, pos, size); StaticBox::Create(parent, wxID_ANY, pos, size);
SetFont(Label::Body_12);
wxWindow::SetLabel(label); wxWindow::SetLabel(label);
state_handler.attach({&label_color, &text_color}); state_handler.attach({&label_color, &text_color});
state_handler.update_binds(); 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 = new wxTextCtrl(this, wxID_ANY, text, {20, 4}, wxDefaultSize, style | wxBORDER_NONE | wxTE_PROCESS_ENTER, wxTextValidator(wxFILTER_DIGITS));
text_ctrl->SetFont(Label::Body_14); #ifdef __WXOSX__
text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states())); text_ctrl->OSXDisableAllSmartSubstitutions();
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states())); #endif // __WXOSX__
text_ctrl->SetInitialSize(text_ctrl->GetBestSize()); text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
state_handler.attach_child(text_ctrl); state_handler.attach_child(text_ctrl);
text_ctrl->Bind(wxEVT_KILL_FOCUS, &SpinInput::onTextLostFocus, this); 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_TEXT_ENTER, &SpinInput::onTextEnter, this);
text_ctrl->Bind(wxEVT_KEY_DOWN, &SpinInput::keyPressed, this); text_ctrl->Bind(wxEVT_KEY_DOWN, &SpinInput::keyPressed, this);
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu
@ -71,6 +78,12 @@ void SpinInput::Create(wxWindow *parent,
delta = 0; delta = 0;
timer.Bind(wxEVT_TIMER, &SpinInput::onTimer, this); timer.Bind(wxEVT_TIMER, &SpinInput::onTimer, this);
SetFont(Slic3r::GUI::wxGetApp().normal_font());
if (parent) {
SetBackgroundColour(parent->GetBackgroundColour());
SetForegroundColour(parent->GetForegroundColour());
}
long initialFromText; long initialFromText;
if (text.ToLong(&initialFromText)) initial = initialFromText; if (text.ToLong(&initialFromText)) initial = initialFromText;
SetRange(min, max); SetRange(min, max);
@ -114,6 +127,8 @@ void SpinInput::SetValue(const wxString &text)
long value; long value;
if ( text.ToLong(&value) ) if ( text.ToLong(&value) )
SetValue(value); SetValue(value);
else
text_ctrl->SetValue(text);
} }
void SpinInput::SetValue(int value) void SpinInput::SetValue(int value)
@ -129,12 +144,76 @@ int SpinInput::GetValue()const
return val; return val;
} }
wxString SpinInput::GetTextValue() const
{
return text_ctrl->GetValue();
}
void SpinInput::SetRange(int min, int max) void SpinInput::SetRange(int min, int max)
{ {
this->min = min; this->min = min;
this->max = max; 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) void SpinInput::DoSetToolTipText(wxString const &tip)
{ {
wxWindow::DoSetToolTipText(tip); wxWindow::DoSetToolTipText(tip);
@ -143,6 +222,9 @@ void SpinInput::DoSetToolTipText(wxString const &tip)
void SpinInput::Rescale() void SpinInput::Rescale()
{ {
SetFont(Slic3r::GUI::wxGetApp().normal_font());
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
button_inc->Rescale(); button_inc->Rescale();
button_dec->Rescale(); button_dec->Rescale();
messureSize(); messureSize();
@ -183,8 +265,11 @@ void SpinInput::render(wxDC& dc)
// draw seperator of buttons // draw seperator of buttons
wxPoint pt = button_inc->GetPosition(); wxPoint pt = button_inc->GetPosition();
pt.y = size.y / 2; pt.y = size.y / 2;
pt.x += 1;
dc.SetPen(wxPen(border_color.defaultColor())); 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 // draw label
auto label = GetLabel(); auto label = GetLabel();
if (!label.IsEmpty()) { if (!label.IsEmpty()) {
@ -201,31 +286,36 @@ void SpinInput::messureSize()
wxSize size = GetSize(); wxSize size = GetSize();
wxSize textSize = text_ctrl->GetSize(); wxSize textSize = text_ctrl->GetSize();
int h = textSize.y + 8; int h = textSize.y + 8;
if (size.y < h) { if (size.y != h) {
size.y = h; size.y = h;
SetSize(size); SetSize(size);
SetMinSize(size); SetMinSize(size);
} else {
textSize.y = size.y * 14 / 24;
} }
wxSize btnSize = {14, (size.y - 4) / 2}; wxSize btnSize = {14, (size.y - 4) / 2};
btnSize.x = btnSize.x * btnSize.y / 10; btnSize.x = btnSize.x * btnSize.y / 10;
const double scale = this->GetContentScaleFactor();
wxClientDC dc(this); wxClientDC dc(this);
labelSize = dc.GetMultiLineTextExtent(GetLabel()); labelSize = dc.GetMultiLineTextExtent(GetLabel());
textSize.x = size.x - labelSize.x - btnSize.x - 16; textSize.x = size.x - labelSize.x - btnSize.x - 16;
text_ctrl->SetSize(textSize); 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_inc->SetSize(btnSize);
button_dec->SetSize(btnSize); button_dec->SetSize(btnSize);
button_inc->SetPosition({3, size.y / 2 - btnSize.y - 1}); button_inc->SetPosition({size.x - btnSize.x - int(3. * scale), size.y / 2 - btnSize.y/* - 1*/});
button_dec->SetPosition({3, size.y / 2 + 1}); button_dec->SetPosition({size.x - btnSize.x - int(3. * scale), size.y / 2 + 1});
} }
Button *SpinInput::createButton(bool inc) 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->SetCornerRadius(0);
btn->SetInactiveIcon(inc ? "spin_inc" : "spin_dec");
btn->DisableFocusFromKeyboard(); btn->DisableFocusFromKeyboard();
btn->SetSelected(false);
btn->Bind(wxEVT_LEFT_DOWN, [=](auto &e) { btn->Bind(wxEVT_LEFT_DOWN, [=](auto &e) {
delta = inc ? 1 : -1; delta = inc ? 1 : -1;
SetValue(val + delta); SetValue(val + delta);
@ -286,6 +376,13 @@ void SpinInput::onTextEnter(wxCommandEvent &event)
ProcessEventLocally(event); ProcessEventLocally(event);
} }
void SpinInput::onText(wxCommandEvent &event)
{
sendSpinEvent();
event.SetId(GetId());
ProcessEventLocally(event);
}
void SpinInput::mouseWheelMoved(wxMouseEvent &event) void SpinInput::mouseWheelMoved(wxMouseEvent &event)
{ {
auto delta = (event.GetWheelRotation() < 0 == event.IsWheelInverted()) ? 1 : -1; auto delta = (event.GetWheelRotation() < 0 == event.IsWheelInverted()) ? 1 : -1;

View File

@ -11,9 +11,9 @@ class SpinInput : public wxNavigationEnabled<StaticBox>
wxSize labelSize; wxSize labelSize;
StateColor label_color; StateColor label_color;
StateColor text_color; StateColor text_color;
wxTextCtrl * text_ctrl; wxTextCtrl * text_ctrl{nullptr};
Button * button_inc; Button * button_inc {nullptr};
Button * button_dec; Button * button_dec {nullptr};
wxTimer timer; wxTimer timer;
int val; int val;
@ -59,16 +59,27 @@ public:
virtual bool Enable(bool enable = true) wxOVERRIDE; virtual bool Enable(bool enable = true) wxOVERRIDE;
wxTextCtrl * GetTextCtrl() { return text_ctrl; } wxTextCtrl * GetText() { return text_ctrl; }
void SetValue(const wxString &text); void SetValue(const wxString &text);
void SetValue (int value); void SetValue (int value);
int GetValue () const; int GetValue () const;
wxString GetTextValue() const;
void SetRange(int min, int max); 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: protected:
void DoSetToolTipText(wxString const &tip) override; void DoSetToolTipText(wxString const &tip) override;
@ -86,6 +97,7 @@ private:
void keyPressed(wxKeyEvent& event); void keyPressed(wxKeyEvent& event);
void onTimer(wxTimerEvent &evnet); void onTimer(wxTimerEvent &evnet);
void onTextLostFocus(wxEvent &event); void onTextLostFocus(wxEvent &event);
void onText(wxCommandEvent &event);
void onTextEnter(wxCommandEvent &event); void onTextEnter(wxCommandEvent &event);
void sendSpinEvent(); void sendSpinEvent();

View File

@ -1,5 +1,7 @@
#include "StateHandler.hpp" #include "StateHandler.hpp"
#include <wx/window.h>
wxDEFINE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent); wxDEFINE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent);
StateHandler::StateHandler(wxWindow * owner) StateHandler::StateHandler(wxWindow * owner)

View File

@ -2,6 +2,7 @@
#define slic3r_GUI_StateHandler_hpp_ #define slic3r_GUI_StateHandler_hpp_
#include <wx/event.h> #include <wx/event.h>
#include <memory>
#include "StateColor.hpp" #include "StateColor.hpp"

View File

@ -1,11 +1,13 @@
#include "StaticBox.hpp" #include "StaticBox.hpp"
#include "../GUI.hpp" #include "../GUI.hpp"
#include <wx/dcgraph.h> #include <wx/dcgraph.h>
#include <wx/dcbuffer.h>
#include "DropDown.hpp"
#include "UIColors.hpp"
BEGIN_EVENT_TABLE(StaticBox, wxWindow) BEGIN_EVENT_TABLE(StaticBox, wxWindow)
// catch paint events
//EVT_ERASE_BACKGROUND(StaticBox::eraseEvent)
EVT_PAINT(StaticBox::paintEvent) EVT_PAINT(StaticBox::paintEvent)
END_EVENT_TABLE() END_EVENT_TABLE()
@ -20,9 +22,9 @@ StaticBox::StaticBox()
: state_handler(this) : state_handler(this)
, radius(8) , radius(8)
{ {
border_color = StateColor( border_color = StateColor(std::make_pair(clr_border_disabled, (int) StateColor::Disabled),
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Disabled), std::make_pair(clr_border_hovered, (int) StateColor::Hovered),
std::make_pair(0x303A3C, (int) StateColor::Normal)); std::make_pair(clr_border_nornal, (int) StateColor::Normal));
} }
StaticBox::StaticBox(wxWindow* parent, 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); wxWindow::Create(parent, id, pos, size, style);
state_handler.attach({&border_color, &background_color, &background_color2}); state_handler.attach({&border_color, &background_color, &background_color2});
state_handler.update_binds(); state_handler.update_binds();
SetBackgroundColour(GetParentBackgroundColor(parent)); // SetBackgroundColour(GetParentBackgroundColor(parent));
// SetForegroundColour(parent->GetParent()->GetForegroundColour());
return true; return true;
} }
@ -109,21 +112,10 @@ wxColor StaticBox::GetParentBackgroundColor(wxWindow* parent)
return *wxWHITE; 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) void StaticBox::paintEvent(wxPaintEvent& evt)
{ {
// depending on your system you may need to look at double-buffered dcs // depending on your system you may need to look at double-buffered dcs
wxPaintDC dc(this); wxBufferedPaintDC dc(this);//wxPaintDC dc(this);
render(dc); render(dc);
} }
@ -134,29 +126,7 @@ void StaticBox::paintEvent(wxPaintEvent& evt)
*/ */
void StaticBox::render(wxDC& dc) 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); doRender(dc);
#endif
} }
void StaticBox::doRender(wxDC& dc) void StaticBox::doRender(wxDC& dc)
@ -166,35 +136,53 @@ void StaticBox::doRender(wxDC& dc)
if (background_color2.count() == 0) { if (background_color2.count() == 0) {
if ((border_width && border_color.count() > 0) || background_color.count() > 0) { if ((border_width && border_color.count() > 0) || background_color.count() > 0) {
wxRect rc(0, 0, size.x, size.y); wxRect rc(0, 0, size.x, size.y);
if (border_width && border_color.count() > 0) { #ifdef __WXOSX__
if (dc.GetContentScaleFactor() == 1.0) { // On Retina displays all controls are cut on 1px
int d = floor(border_width / 2.0); if (dc.GetContentScaleFactor() > 1.)
int d2 = floor(border_width - 1); rc.Deflate(1, 1);
rc.x += d; #endif //__WXOSX__
rc.width -= d2;
rc.y += d; if (radius > 0.) {
rc.height -= d2; #if 0
} else { DropDown::SetTransparentBG(dc, this);
int d = 1; #else
rc.x += d; #ifdef __WXMSW__
rc.width -= d; wxColour bg_clr = GetParentBackgroundColor(m_parent);
rc.y += d; dc.SetBrush(wxBrush(bg_clr));
rc.height -= d; dc.SetPen(wxPen(bg_clr));
} dc.DrawRectangle(rc);
dc.SetPen(wxPen(border_color.colorForStates(states), border_width)); #endif
} else { #endif
dc.SetPen(wxPen(background_color.colorForStates(states)));
} }
if (background_color.count() > 0) if (background_color.count() > 0)
dc.SetBrush(wxBrush(background_color.colorForStates(states))); dc.SetBrush(wxBrush(background_color.colorForStates(states)));
else else
dc.SetBrush(wxBrush(GetBackgroundColour())); 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); dc.DrawRectangle(rc);
} else
else {
dc.DrawRoundedRectangle(rc, radius - border_width); dc.DrawRoundedRectangle(rc, radius - border_width);
}
} }
} }
else { else {

View File

@ -31,7 +31,7 @@ public:
void SetBorderColorNormal(wxColor const &color); void SetBorderColorNormal(wxColor const &color);
void SetBackgroundColor(StateColor const &color); virtual void SetBackgroundColor(StateColor const &color);
void SetBackgroundColorNormal(wxColor const &color); void SetBackgroundColorNormal(wxColor const &color);
@ -40,15 +40,12 @@ public:
static wxColor GetParentBackgroundColor(wxWindow * parent); static wxColor GetParentBackgroundColor(wxWindow * parent);
protected: protected:
void eraseEvent(wxEraseEvent& evt);
void paintEvent(wxPaintEvent& evt); void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc); void render(wxDC& dc);
virtual void doRender(wxDC& dc); virtual void doRender(wxDC& dc);
protected:
double radius; double radius;
int border_width = 1; int border_width = 1;
StateHandler state_handler; StateHandler state_handler;

View File

@ -1,23 +1,20 @@
#include "SwitchButton.hpp" #include "SwitchButton.hpp"
#include "Label.hpp"
#include "StaticBox.hpp"
#include "../wxExtensions.hpp" #include "../wxExtensions.hpp"
#include "../Utils/MacDarkMode.hpp" #include "../../Utils/MacDarkMode.hpp"
#include <wx/dcgraph.h> #include <wx/dcgraph.h>
#include <wx/dcmemory.h>
#include <wx/dcclient.h>
SwitchButton::SwitchButton(wxWindow* parent, wxWindowID id) SwitchButton::SwitchButton(wxWindow* parent, const wxString& name, wxWindowID id)
: wxBitmapToggleButton(parent, id, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE | wxBU_EXACTFIT) : BitmapToggleButton(parent, name, id)
, m_on(this, "toggle_on", 16) , m_on(this, "toggle_on", 28, 16)
, m_off(this, "toggle_off", 16) , m_off(this, "toggle_off", 28, 16)
, text_color(std::pair{*wxWHITE, (int) StateColor::Checked}, std::pair{0x6B6B6B, (int) StateColor::Normal}) , text_color(std::pair{*wxWHITE, (int) StateColor::Checked}, std::pair{0x6B6B6B, (int) StateColor::Normal})
, track_color(0xD9D9D9) , track_color(0xD9D9D9)
, thumb_color(std::pair{0x00AE42, (int) StateColor::Checked}, std::pair{0xD9D9D9, (int) StateColor::Normal}) , 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(); Rescale();
} }
@ -52,11 +49,7 @@ void SwitchButton::SetValue(bool value)
void SwitchButton::Rescale() void SwitchButton::Rescale()
{ {
if (labels[0].IsEmpty()) { if (!labels[0].IsEmpty()) {
m_on.msw_rescale();
m_off.msw_rescale();
}
else {
#ifdef __WXOSX__ #ifdef __WXOSX__
auto scale = Slic3r::GUI::mac_max_scaling_factor(); auto scale = Slic3r::GUI::mac_max_scaling_factor();
int BS = (int) scale; int BS = (int) scale;
@ -121,14 +114,23 @@ void SwitchButton::Rescale()
#ifdef __WXOSX__ #ifdef __WXOSX__
bmp = wxBitmap(bmp.ConvertToImage(), -1, scale); bmp = wxBitmap(bmp.ConvertToImage(), -1, scale);
#endif #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(); update();
} }
void SwitchButton::update() void SwitchButton::update()
{ {
SetBitmap((GetValue() ? m_on : m_off).bmp()); SetBitmap((GetValue() ? m_on : m_off).bmp());
update_size();
} }

View File

@ -4,12 +4,12 @@
#include "../wxExtensions.hpp" #include "../wxExtensions.hpp"
#include "StateColor.hpp" #include "StateColor.hpp"
#include <wx/tglbtn.h> #include "BitmapToggleButton.hpp"
class SwitchButton : public wxBitmapToggleButton class SwitchButton : public BitmapToggleButton
{ {
public: public:
SwitchButton(wxWindow * parent = NULL, wxWindowID id = wxID_ANY); SwitchButton(wxWindow * parent = NULL, const wxString& name = wxEmptyString, wxWindowID id = wxID_ANY);
public: public:
void SetLabels(wxString const & lbl_on, wxString const & lbl_off); void SetLabels(wxString const & lbl_on, wxString const & lbl_off);
@ -24,8 +24,10 @@ public:
void Rescale(); void Rescale();
void SysColorChange();
private: private:
void update(); void update() override;
private: private:
ScalableBitmap m_on; ScalableBitmap m_on;

View File

@ -1,7 +1,10 @@
#include "TextInput.hpp" #include "TextInput.hpp"
#include "Label.hpp" #include "UIColors.hpp"
#include <wx/dcgraph.h> #include <wx/dcgraph.h>
#include <wx/panel.h>
#include "slic3r/GUI/GUI_App.hpp"
BEGIN_EVENT_TABLE(TextInput, wxPanel) BEGIN_EVENT_TABLE(TextInput, wxPanel)
@ -21,12 +24,9 @@ TextInput::TextInput()
, text_color(std::make_pair(0x909090, (int) StateColor::Disabled), , text_color(std::make_pair(0x909090, (int) StateColor::Disabled),
std::make_pair(0x262E30, (int) StateColor::Normal)) std::make_pair(0x262E30, (int) StateColor::Normal))
{ {
radius = 0; if (Slic3r::GUI::wxGetApp().suppress_round_corners())
radius = 0;
border_width = 1; 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, TextInput::TextInput(wxWindow * parent,
@ -52,15 +52,21 @@ void TextInput::Create(wxWindow * parent,
text_ctrl = nullptr; text_ctrl = nullptr;
StaticBox::Create(parent, wxID_ANY, pos, size, style); StaticBox::Create(parent, wxID_ANY, pos, size, style);
wxWindow::SetLabel(label); wxWindow::SetLabel(label);
style &= ~wxRIGHT;
state_handler.attach({&label_color, & text_color}); state_handler.attach({&label_color, &text_color});
state_handler.update_binds(); 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->SetInitialSize(text_ctrl->GetBestSize());
text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states())); if (parent) {
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states())); SetBackgroundColour(parent->GetBackgroundColour());
SetForegroundColour(parent->GetForegroundColour());
}
state_handler.attach_child(text_ctrl); state_handler.attach_child(text_ctrl);
text_ctrl->Bind(wxEVT_KILL_FOCUS, [this](auto &e) { text_ctrl->Bind(wxEVT_KILL_FOCUS, [this](auto &e) {
OnEdit(); OnEdit();
e.SetId(GetId()); e.SetId(GetId());
@ -73,8 +79,9 @@ void TextInput::Create(wxWindow * parent,
ProcessEventLocally(e); ProcessEventLocally(e);
}); });
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu
if (!icon.IsEmpty()) { if (!icon.IsEmpty()) {
this->icon = ScalableBitmap(this, icon.ToStdString(), 16); this->drop_down_icon = ScalableBitmap(this, icon.ToStdString(), 16);
} }
messureSize(); messureSize();
} }
@ -92,10 +99,54 @@ void TextInput::SetLabel(const wxString& label)
Refresh(); Refresh();
} }
void TextInput::SetIcon(const wxBitmap &icon) bool TextInput::SetBackgroundColour(const wxColour& colour)
{ {
this->icon.bmp() = icon; const int clr_background_disabled = Slic3r::GUI::wxGetApp().dark_mode() ? clr_background_disabled_dark : clr_background_disabled_light;
Rescale(); 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) void TextInput::SetLabelColor(StateColor const &color)
@ -106,18 +157,41 @@ void TextInput::SetLabelColor(StateColor const &color)
void TextInput::SetTextColor(StateColor const& color) void TextInput::SetTextColor(StateColor const& color)
{ {
text_color= color; text_color = color;
state_handler.update_binds(); 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() void TextInput::Rescale()
{ {
if (!this->icon.name().empty()) if (text_ctrl)
this->icon.msw_rescale(); text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
messureSize(); messureSize();
Refresh(); 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 TextInput::Enable(bool enable)
{ {
bool result = text_ctrl->Enable(enable) && wxWindow::Enable(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; if (sizeFlags & wxSIZE_USE_EXISTING) return;
wxSize size = GetSize(); wxSize size = GetSize();
wxPoint textPos = {5, 0}; wxPoint textPos = {5, 0};
if (this->icon.bmp().IsOk()) { if (this->icon.IsOk()) {
wxSize szIcon = this->icon.GetBmpSize(); wxSize szIcon = get_preferred_size(icon, m_parent);
textPos.x += szIcon.x; 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; bool align_right = GetWindowStyle() & wxRIGHT;
if (align_right) if (align_right)
textPos.x += labelSize.x; textPos.x += labelSize.x;
if (text_ctrl) { if (text_ctrl) {
wxSize textSize = text_ctrl->GetSize(); 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->SetSize(textSize);
text_ctrl->SetPosition({textPos.x, (size.y - textSize.y) / 2}); text_ctrl->SetPosition({textPos.x, (size.y - textSize.y) / 2});
} }
@ -190,22 +270,36 @@ void TextInput::render(wxDC& dc)
bool align_right = GetWindowStyle() & wxRIGHT; bool align_right = GetWindowStyle() & wxRIGHT;
// start draw // start draw
wxPoint pt = {5, 0}; wxPoint pt = {5, 0};
if (icon.bmp().IsOk()) { if (icon.IsOk()) {
wxSize szIcon = icon.GetBmpSize(); wxSize szIcon = get_preferred_size(icon, m_parent);
pt.y = (size.y - szIcon.y) / 2; pt.y = (size.y - szIcon.y) / 2;
dc.DrawBitmap(icon.bmp(), pt); #ifdef __WXGTK3__
pt.x += szIcon.x + 0; 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(); auto text = wxWindow::GetLabel();
if (!text.IsEmpty()) { if (!text.IsEmpty()) {
wxSize textSize = text_ctrl->GetSize(); wxSize textSize = text_ctrl->GetSize();
if (align_right) { 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.x += textSize.x;
pt.y = (size.y + textSize.y) / 2 - labelSize.y; 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.SetTextForeground(label_color.colorForStates(states));
dc.SetFont(GetFont()); dc.SetFont(GetFont());
@ -218,11 +312,11 @@ void TextInput::messureSize()
wxSize size = GetSize(); wxSize size = GetSize();
wxClientDC dc(this); wxClientDC dc(this);
labelSize = dc.GetTextExtent(wxWindow::GetLabel()); labelSize = dc.GetTextExtent(wxWindow::GetLabel());
wxSize textSize = text_ctrl->GetSize();
int h = textSize.y + 8; const wxSize textSize = text_ctrl->GetSize();
if (size.y < h) { const wxSize iconSize = drop_down_icon.bmp().IsOk() ? drop_down_icon.GetSize() : wxSize(0, 0);
size.y = h; size.y = ((textSize.y > iconSize.y) ? textSize.y : iconSize.y) + 8;
}
wxSize minSize = size; wxSize minSize = size;
minSize.x = GetMinWidth(); minSize.x = GetMinWidth();
SetMinSize(minSize); SetMinSize(minSize);

View File

@ -8,10 +8,11 @@ class TextInput : public wxNavigationEnabled<StaticBox>
{ {
wxSize labelSize; wxSize labelSize;
ScalableBitmap icon; wxBitmapBundle icon;
ScalableBitmap drop_down_icon;
StateColor label_color; StateColor label_color;
StateColor text_color; StateColor text_color;
wxTextCtrl * text_ctrl; wxTextCtrl* text_ctrl{nullptr};
static const int TextInputWidth = 200; static const int TextInputWidth = 200;
static const int TextInputHeight = 50; static const int TextInputHeight = 50;
@ -40,22 +41,38 @@ public:
void SetLabel(const wxString& label); void SetLabel(const wxString& label);
void SetIcon(const wxBitmap & icon); void SetIcon(const wxBitmapBundle& icon);
void SetLabelColor(StateColor const &color); void SetLabelColor(StateColor const &color);
void SetBGColor(StateColor const &color);
void SetTextColor(StateColor const &color); void SetTextColor(StateColor const &color);
void SetCtrlSize(wxSize const& size);
virtual void Rescale(); virtual void Rescale();
bool SetFont(const wxFont &font) override;
virtual bool Enable(bool enable = true) override; virtual bool Enable(bool enable = true) override;
virtual void SetMinSize(const wxSize& size) 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 *GetTextCtrl() { return text_ctrl; }
wxTextCtrl const *GetTextCtrl() const { return text_ctrl; } wxTextCtrl const *GetTextCtrl() const { return text_ctrl; }
void SetValue(const wxString& value);
wxString GetValue();
void SetSelection(long from, long to);
protected: protected:
virtual void OnEdit() {} virtual void OnEdit() {}
@ -64,6 +81,9 @@ protected:
void DoSetToolTipText(wxString const &tip) override; void DoSetToolTipText(wxString const &tip) override;
StateColor GetTextColor() const { return text_color; }
StateColor GetBorderColor() const { return border_color; }
private: private:
void paintEvent(wxPaintEvent& evt); void paintEvent(wxPaintEvent& evt);

View File

@ -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_

View File

@ -422,10 +422,12 @@ static int scale()
} }
#endif // __WXGTK2__ #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__ #ifdef __WXGTK2__
px_cnt *= scale(); width *= scale();
if (height > 0)
height *= scale();
#endif // __WXGTK2__ #endif // __WXGTK2__
static Slic3r::GUI::BitmapCache cache; 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; std::string bmp_name = bmp_name_in;
boost::replace_last(bmp_name, ".png", ""); boost::replace_last(bmp_name, ".png", "");
if (height < 0)
height = width;
// Try loading an SVG first, then PNG if SVG is not found: // 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) { if (bmp == nullptr) {
bmp = cache.from_png(bmp_name, px_cnt, px_cnt); bmp = cache.from_png(bmp_name, width, height);
if (!bmp) if (!bmp)
// Neither SVG nor PNG has been found, raise error // Neither SVG nor PNG has been found, raise error
throw Slic3r::RuntimeError("Could not load bitmap: " + bmp_name); throw Slic3r::RuntimeError("Could not load bitmap: " + bmp_name);
@ -658,7 +663,7 @@ void ModeButton::SetState(const bool state)
void ModeButton::update_bitmap() 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); SetBitmap(m_bmp);
SetBitmapCurrent(m_bmp); SetBitmapCurrent(m_bmp);
@ -785,19 +790,28 @@ void MenuWithSeparators::SetSecondSeparator()
// PrusaBitmap // PrusaBitmap
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
ScalableBitmap::ScalableBitmap( wxWindow *parent, ScalableBitmap::ScalableBitmap( wxWindow *parent,
const std::string& icon_name/* = ""*/, const std::string& icon_name,
const int px_cnt/* = 16*/, const int width/* = 16*/,
const int height/* = -1*/,
const bool grayscale/* = false*/): const bool grayscale/* = false*/):
m_parent(parent), m_icon_name(icon_name), 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); 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() 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 wxSize& size /* = wxDefaultSize*/,
const wxPoint& pos /* = wxDefaultPosition*/, const wxPoint& pos /* = wxDefaultPosition*/,
long style /*= wxBU_EXACTFIT | wxNO_BORDER*/, long style /*= wxBU_EXACTFIT | wxNO_BORDER*/,
int bmp_px_cnt/* = 16*/) : int width/* = 16*/,
int height/* = -1*/) :
m_parent(parent), m_parent(parent),
m_current_icon_name(icon_name), 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)) m_has_border(!(style & wxNO_BORDER))
{ {
Create(parent, id, label, pos, size, style); Create(parent, id, label, pos, size, style);
Slic3r::GUI::wxGetApp().UpdateDarkUI(this); Slic3r::GUI::wxGetApp().UpdateDarkUI(this);
if (!icon_name.empty()) { if (!icon_name.empty()) {
SetBitmap(*get_bmp_bundle(icon_name, m_px_cnt)); SetBitmap(*get_bmp_bundle(icon_name, width, height));
if (!label.empty()) if (!label.empty())
SetBitmapMargins(int(0.5* em_unit(parent)), 0); SetBitmapMargins(int(0.5* em_unit(parent)), 0);
} }
@ -842,7 +858,8 @@ ScalableButton::ScalableButton( wxWindow * parent,
long style /*= wxBU_EXACTFIT | wxNO_BORDER*/) : long style /*= wxBU_EXACTFIT | wxNO_BORDER*/) :
m_parent(parent), m_parent(parent),
m_current_icon_name(bitmap.name()), 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)) m_has_border(!(style& wxNO_BORDER))
{ {
Create(parent, id, label, wxDefaultPosition, wxDefaultSize, style); 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()) if (m_current_icon_name.empty())
return false; 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); SetBitmap(bmp);
SetBitmapCurrent(bmp); SetBitmapCurrent(bmp);
SetBitmapPressed(bmp); SetBitmapPressed(bmp);
@ -891,13 +908,13 @@ void ScalableButton::sys_color_changed()
{ {
Slic3r::GUI::wxGetApp().UpdateDarkUI(this, m_has_border); 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); SetBitmap(bmp);
SetBitmapCurrent(bmp); SetBitmapCurrent(bmp);
SetBitmapPressed(bmp); SetBitmapPressed(bmp);
SetBitmapFocus(bmp); SetBitmapFocus(bmp);
if (!m_disabled_icon_name.empty()) 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()) if (!GetLabelText().IsEmpty())
SetBitmapMargins(int(0.5 * em_unit(m_parent)), 0); SetBitmapMargins(int(0.5 * em_unit(m_parent)), 0);
} }

View File

@ -54,7 +54,7 @@ void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<
int em_unit(wxWindow* win); int em_unit(wxWindow* win);
int mode_icon_px_size(); 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_empty_bmp_bundle(int width, int height);
wxBitmapBundle* get_solid_bmp_bundle(int width, int height, const std::string& color); 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; } 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 // ScalableBitmap
@ -141,8 +152,14 @@ class ScalableBitmap
public: public:
ScalableBitmap() {}; ScalableBitmap() {};
ScalableBitmap( wxWindow *parent, ScalableBitmap( wxWindow *parent,
const std::string& icon_name = "", const std::string& icon_name,
const int px_cnt = 16, 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); const bool grayscale = false);
~ScalableBitmap() {} ~ScalableBitmap() {}
@ -153,15 +170,10 @@ public:
wxBitmap get_bitmap() { return m_bmp.GetBitmapFor(m_parent); } wxBitmap get_bitmap() { return m_bmp.GetBitmapFor(m_parent); }
wxWindow* parent() const { return m_parent;} wxWindow* parent() const { return m_parent;}
const std::string& name() const { return m_icon_name; } 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 { void SetBitmap(const wxBitmapBundle& bmp) { m_bmp = bmp; }
#ifdef __WIN32__ wxSize GetSize() const { return get_preferred_size(m_bmp, m_parent); }
return m_bmp.GetPreferredBitmapSizeFor(m_parent);
#else
return m_bmp.GetDefaultSize();
#endif
}
int GetWidth() const { return GetSize().GetWidth(); } int GetWidth() const { return GetSize().GetWidth(); }
int GetHeight() const { return GetSize().GetHeight(); } int GetHeight() const { return GetSize().GetHeight(); }
@ -170,7 +182,8 @@ private:
wxBitmapBundle m_bmp = wxBitmapBundle(); wxBitmapBundle m_bmp = wxBitmapBundle();
wxBitmap m_bitmap = wxBitmap(); wxBitmap m_bitmap = wxBitmap();
std::string m_icon_name = ""; 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 wxSize& size = wxDefaultSize,
const wxPoint& pos = wxDefaultPosition, const wxPoint& pos = wxDefaultPosition,
long style = wxBU_EXACTFIT | wxNO_BORDER, long style = wxBU_EXACTFIT | wxNO_BORDER,
int bmp_px_cnt = 16); int width = 16,
int height = -1);
ScalableButton( ScalableButton(
wxWindow * parent, wxWindow * parent,
@ -256,7 +270,8 @@ private:
protected: protected:
// bitmap dimensions // bitmap dimensions
int m_px_cnt{ 16 }; int m_bmp_width{ 16 };
int m_bmp_height{ -1 };
bool m_has_border {false}; bool m_has_border {false};
}; };