Merge branch 'ys_ui'

This commit is contained in:
Lukas Matena 2023-10-18 16:32:21 +02:00
commit bec6b8d032
84 changed files with 4700 additions and 381 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-width="1.75" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 207 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

@ -70,7 +70,7 @@ CopyrightsDialog::CopyrightsDialog()
m_html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, m_html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition,
wxSize(40 * em_unit(), 20 * em_unit()), wxHW_SCROLLBAR_AUTO); wxSize(40 * em_unit(), 20 * em_unit()), wxHW_SCROLLBAR_AUTO);
wxFont font = get_default_font(this); wxFont font = this->GetFont();// get_default_font(this);
const int fs = font.GetPointSize(); const int fs = font.GetPointSize();
const int fs2 = static_cast<int>(1.2f*fs); const int fs2 = static_cast<int>(1.2f*fs);
int size[] = { fs, fs, fs, fs, fs2, fs2, fs2 }; int size[] = { fs, fs, fs, fs, fs2, fs2, fs2 };
@ -83,6 +83,7 @@ CopyrightsDialog::CopyrightsDialog()
m_html->Bind(wxEVT_HTML_LINK_CLICKED, &CopyrightsDialog::onLinkClicked, this); m_html->Bind(wxEVT_HTML_LINK_CLICKED, &CopyrightsDialog::onLinkClicked, this);
wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCLOSE); wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCLOSE);
wxGetApp().SetWindowVariantForButton(buttons->GetCancelButton());
wxGetApp().UpdateDlgDarkUI(this, true); wxGetApp().UpdateDlgDarkUI(this, true);
this->SetEscapeId(wxID_CLOSE); this->SetEscapeId(wxID_CLOSE);
this->Bind(wxEVT_BUTTON, &CopyrightsDialog::onCloseDialog, this, wxID_CLOSE); this->Bind(wxEVT_BUTTON, &CopyrightsDialog::onCloseDialog, this, wxID_CLOSE);
@ -244,7 +245,7 @@ AboutDialog::AboutDialog()
wxStaticText* title = new wxStaticText(this, wxID_ANY, wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME, wxDefaultPosition, wxDefaultSize); wxStaticText* title = new wxStaticText(this, wxID_ANY, wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME, wxDefaultPosition, wxDefaultSize);
wxFont title_font = GUI::wxGetApp().bold_font(); wxFont title_font = GUI::wxGetApp().bold_font();
title_font.SetFamily(wxFONTFAMILY_ROMAN); title_font.SetFamily(wxFONTFAMILY_ROMAN);
title_font.SetPointSize(24); title_font.SetPointSize(int(2.5 * title_font.GetPointSize()));//title_font.SetPointSize(24);
title->SetFont(title_font); title->SetFont(title_font);
vsizer->Add(title, 0, wxALIGN_LEFT | wxTOP, 10); vsizer->Add(title, 0, wxALIGN_LEFT | wxTOP, 10);
} }
@ -267,7 +268,7 @@ AboutDialog::AboutDialog()
m_html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO/*NEVER*/); m_html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO/*NEVER*/);
{ {
m_html->SetMinSize(wxSize(-1, 16 * wxGetApp().em_unit())); m_html->SetMinSize(wxSize(-1, 16 * wxGetApp().em_unit()));
wxFont font = get_default_font(this); wxFont font = wxGetApp().normal_font();// get_default_font(this);
const auto text_clr = wxGetApp().get_label_clr_default(); const auto text_clr = wxGetApp().get_label_clr_default();
const auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue())); const auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue()));
const auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue())); const auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()));
@ -309,16 +310,19 @@ AboutDialog::AboutDialog()
wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCLOSE); wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCLOSE);
wxGetApp().SetWindowVariantForButton(buttons->GetCancelButton());
m_copy_rights_btn_id = NewControlId(); m_copy_rights_btn_id = NewControlId();
auto copy_rights_btn = new wxButton(this, m_copy_rights_btn_id, _L("Portions copyright")+dots); auto copy_rights_btn = new wxButton(this, m_copy_rights_btn_id, _L("Portions copyright")+dots);
buttons->Insert(0, copy_rights_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5); buttons->Insert(0, copy_rights_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5);
copy_rights_btn->Bind(wxEVT_BUTTON, &AboutDialog::onCopyrightBtn, this); copy_rights_btn->Bind(wxEVT_BUTTON, &AboutDialog::onCopyrightBtn, this);
wxGetApp().SetWindowVariantForButton(copy_rights_btn);
m_copy_version_btn_id = NewControlId(); m_copy_version_btn_id = NewControlId();
auto copy_version_btn = new wxButton(this, m_copy_version_btn_id, _L("Copy Version Info")); auto copy_version_btn = new wxButton(this, m_copy_version_btn_id, _L("Copy Version Info"));
buttons->Insert(1, copy_version_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5); buttons->Insert(1, copy_version_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5);
copy_version_btn->Bind(wxEVT_BUTTON, &AboutDialog::onCopyToClipboard, this); copy_version_btn->Bind(wxEVT_BUTTON, &AboutDialog::onCopyToClipboard, this);
wxGetApp().SetWindowVariantForButton(copy_version_btn);
wxGetApp().UpdateDlgDarkUI(this, true); wxGetApp().UpdateDlgDarkUI(this, true);

View File

@ -150,7 +150,10 @@ void BedShapeDialog::build_dialog(const ConfigOptionPoints& default_pt, const Co
auto main_sizer = new wxBoxSizer(wxVERTICAL); auto main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->Add(m_panel, 1, wxEXPAND); main_sizer->Add(m_panel, 1, wxEXPAND);
main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); wxStdDialogButtonSizer* buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
wxGetApp().SetWindowVariantForButton(buttons->GetAffirmativeButton());
wxGetApp().SetWindowVariantForButton(buttons->GetCancelButton());
main_sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10);
wxGetApp().UpdateDlgDarkUI(this, true); wxGetApp().UpdateDlgDarkUI(this, true);
@ -214,6 +217,7 @@ void BedShapePanel::build_panel(const ConfigOptionPoints& default_pt, const Conf
line.full_width = 1; line.full_width = 1;
line.widget = [this](wxWindow* parent) { line.widget = [this](wxWindow* parent) {
wxButton* shape_btn = new wxButton(parent, wxID_ANY, _L("Load shape from STL...")); wxButton* shape_btn = new wxButton(parent, wxID_ANY, _L("Load shape from STL..."));
wxGetApp().SetWindowVariantForButton(shape_btn);
wxSizer* shape_sizer = new wxBoxSizer(wxHORIZONTAL); wxSizer* shape_sizer = new wxBoxSizer(wxHORIZONTAL);
shape_sizer->Add(shape_btn, 1, wxEXPAND); shape_sizer->Add(shape_btn, 1, wxEXPAND);
@ -294,6 +298,7 @@ wxPanel* BedShapePanel::init_texture_panel()
line.full_width = 1; line.full_width = 1;
line.widget = [this](wxWindow* parent) { line.widget = [this](wxWindow* parent) {
wxButton* load_btn = new wxButton(parent, wxID_ANY, _L("Load...")); wxButton* load_btn = new wxButton(parent, wxID_ANY, _L("Load..."));
wxGetApp().SetWindowVariantForButton(load_btn);
wxSizer* load_sizer = new wxBoxSizer(wxHORIZONTAL); wxSizer* load_sizer = new wxBoxSizer(wxHORIZONTAL);
load_sizer->Add(load_btn, 1, wxEXPAND); load_sizer->Add(load_btn, 1, wxEXPAND);
@ -303,6 +308,7 @@ wxPanel* BedShapePanel::init_texture_panel()
filename_sizer->Add(filename_lbl, 1, wxEXPAND); filename_sizer->Add(filename_lbl, 1, wxEXPAND);
wxButton* remove_btn = new wxButton(parent, wxID_ANY, _L("Remove")); wxButton* remove_btn = new wxButton(parent, wxID_ANY, _L("Remove"));
wxGetApp().SetWindowVariantForButton(remove_btn);
wxSizer* remove_sizer = new wxBoxSizer(wxHORIZONTAL); wxSizer* remove_sizer = new wxBoxSizer(wxHORIZONTAL);
remove_sizer->Add(remove_btn, 1, wxEXPAND); remove_sizer->Add(remove_btn, 1, wxEXPAND);
@ -365,6 +371,7 @@ wxPanel* BedShapePanel::init_model_panel()
line.full_width = 1; line.full_width = 1;
line.widget = [this](wxWindow* parent) { line.widget = [this](wxWindow* parent) {
wxButton* load_btn = new wxButton(parent, wxID_ANY, _L("Load...")); wxButton* load_btn = new wxButton(parent, wxID_ANY, _L("Load..."));
wxGetApp().SetWindowVariantForButton(load_btn);
wxSizer* load_sizer = new wxBoxSizer(wxHORIZONTAL); wxSizer* load_sizer = new wxBoxSizer(wxHORIZONTAL);
load_sizer->Add(load_btn, 1, wxEXPAND); load_sizer->Add(load_btn, 1, wxEXPAND);
@ -373,6 +380,7 @@ wxPanel* BedShapePanel::init_model_panel()
filename_sizer->Add(filename_lbl, 1, wxEXPAND); filename_sizer->Add(filename_lbl, 1, wxEXPAND);
wxButton* remove_btn = new wxButton(parent, wxID_ANY, _L("Remove")); wxButton* remove_btn = new wxButton(parent, wxID_ANY, _L("Remove"));
wxGetApp().SetWindowVariantForButton(remove_btn);
wxSizer* remove_sizer = new wxBoxSizer(wxHORIZONTAL); wxSizer* remove_sizer = new wxBoxSizer(wxHORIZONTAL);
remove_sizer->Add(remove_btn, 1, wxEXPAND); remove_sizer->Add(remove_btn, 1, wxEXPAND);

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

@ -141,7 +141,7 @@ ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db
// text // text
html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO); html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO);
{ {
wxFont font = get_default_font(this); wxFont font = this->GetFont();// get_default_font(this);
#ifdef __WXMSW__ #ifdef __WXMSW__
const int fs = font.GetPointSize(); const int fs = font.GetPointSize();
const int fs1 = static_cast<int>(0.8f*fs); const int fs1 = static_cast<int>(0.8f*fs);
@ -160,7 +160,8 @@ ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db
} }
wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCLOSE); wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCLOSE);
wxGetApp().UpdateDarkUI(static_cast<wxButton*>(this->FindWindowById(wxID_CLOSE, this))); wxGetApp().SetWindowVariantForButton(buttons->GetCancelButton());
wxGetApp().UpdateDarkUI(buttons->GetCancelButton());
this->SetEscapeId(wxID_CLOSE); this->SetEscapeId(wxID_CLOSE);
this->Bind(wxEVT_BUTTON, &ConfigSnapshotDialog::onCloseDialog, this, wxID_CLOSE); this->Bind(wxEVT_BUTTON, &ConfigSnapshotDialog::onCloseDialog, this, wxID_CLOSE);
vsizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3); vsizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3);

View File

@ -423,6 +423,10 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
title_sizer->Add(sel_all, 0, wxRIGHT, BTN_SPACING); title_sizer->Add(sel_all, 0, wxRIGHT, BTN_SPACING);
title_sizer->Add(sel_none); title_sizer->Add(sel_none);
wxGetApp().SetWindowVariantForButton(sel_all_std);
wxGetApp().SetWindowVariantForButton(sel_all);
wxGetApp().SetWindowVariantForButton(sel_none);
wxGetApp().UpdateDarkUI(sel_all_std); wxGetApp().UpdateDarkUI(sel_all_std);
wxGetApp().UpdateDarkUI(sel_all); wxGetApp().UpdateDarkUI(sel_all);
wxGetApp().UpdateDarkUI(sel_none); wxGetApp().UpdateDarkUI(sel_none);
@ -748,6 +752,9 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin
wxGetApp().UpdateDarkUI(sel_all); wxGetApp().UpdateDarkUI(sel_all);
wxGetApp().UpdateDarkUI(sel_none); wxGetApp().UpdateDarkUI(sel_none);
wxGetApp().SetWindowVariantForButton(sel_all);
wxGetApp().SetWindowVariantForButton(sel_none);
grid->Add(new wxBoxSizer(wxHORIZONTAL)); grid->Add(new wxBoxSizer(wxHORIZONTAL));
grid->Add(new wxBoxSizer(wxHORIZONTAL)); grid->Add(new wxBoxSizer(wxHORIZONTAL));
grid->Add(new wxBoxSizer(wxHORIZONTAL)); grid->Add(new wxBoxSizer(wxHORIZONTAL));
@ -861,10 +868,8 @@ void PageMaterials::set_compatible_printers_html_window(const std::vector<std::s
"</style>" "</style>"
"<body bgcolor= %s>" "<body bgcolor= %s>"
"<font color=%s>" "<font color=%s>"
"<font size=\"3\">"
"%s<br /><br />%s" "%s<br /><br />%s"
"</font>" "</font>"
"</font>"
"</body>" "</body>"
"</html>" "</html>"
, bgr_clr_str , bgr_clr_str
@ -886,7 +891,6 @@ void PageMaterials::set_compatible_printers_html_window(const std::vector<std::s
"</style>" "</style>"
"<body bgcolor= %s>" "<body bgcolor= %s>"
"<font color=%s>" "<font color=%s>"
"<font size=\"3\">"
"%s<br /><br />%s" "%s<br /><br />%s"
"<table>" "<table>"
"<tr>" "<tr>"
@ -907,15 +911,13 @@ void PageMaterials::set_compatible_printers_html_window(const std::vector<std::s
"</tr>" "</tr>"
"</table>" "</table>"
"</font>" "</font>"
"</font>"
"</body>" "</body>"
"</html>" "</html>"
); );
} }
} }
wxFont font = wxGetApp().normal_font();// get_default_font_for_dpi(this, get_dpi_for_window(this));
wxFont font = get_default_font_for_dpi(this, get_dpi_for_window(this));
const int fs = font.GetPointSize(); const int fs = font.GetPointSize();
int size[] = { fs,fs,fs,fs,fs,fs,fs }; int size[] = { fs,fs,fs,fs,fs,fs,fs };
html_window->SetFonts(font.GetFaceName(), font.GetFaceName(), size); html_window->SetFonts(font.GetFaceName(), font.GetFaceName(), size);
@ -1342,8 +1344,7 @@ PageUpdate::PageUpdate(ConfigWizard *parent)
, preset_update(true) , preset_update(true)
{ {
const AppConfig *app_config = wxGetApp().app_config; const AppConfig *app_config = wxGetApp().app_config;
auto boldfont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); auto boldfont = wxGetApp().bold_font();
boldfont.SetWeight(wxFONTWEIGHT_BOLD);
auto *box_slic3r = new wxCheckBox(this, wxID_ANY, _L("Check for application updates")); auto *box_slic3r = new wxCheckBox(this, wxID_ANY, _L("Check for application updates"));
box_slic3r->SetValue(app_config->get("notify_release") != "none"); box_slic3r->SetValue(app_config->get("notify_release") != "none");
@ -1422,6 +1423,7 @@ Worker::Worker(wxWindow* parent)
this->Add(m_input_path, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5); this->Add(m_input_path, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5);
auto* button_path = new wxButton(m_parent, wxID_ANY, _L("Browse")); auto* button_path = new wxButton(m_parent, wxID_ANY, _L("Browse"));
wxGetApp().SetWindowVariantForButton(button_path);
this->Add(button_path, 0, wxEXPAND | wxTOP | wxLEFT, 5); this->Add(button_path, 0, wxEXPAND | wxTOP | wxLEFT, 5);
button_path->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) { button_path->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) {
boost::filesystem::path chosen_dest(boost::nowide::narrow(m_input_path->GetValue())); boost::filesystem::path chosen_dest(boost::nowide::narrow(m_input_path->GetValue()));
@ -1979,7 +1981,7 @@ void PageDiameters::apply_custom_config(DynamicPrintConfig &config)
set_extrusion_width("solid_infill_extrusion_width", 0.45); set_extrusion_width("solid_infill_extrusion_width", 0.45);
} }
class SpinCtrlDouble: public wxSpinCtrlDouble class SpinCtrlDouble: public ::SpinInputDouble
{ {
public: public:
SpinCtrlDouble(wxWindow* parent) SpinCtrlDouble(wxWindow* parent)
@ -1989,10 +1991,7 @@ public:
#else #else
long style = wxSP_ARROW_KEYS; long style = wxSP_ARROW_KEYS;
#endif #endif
Create(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, style); Create(parent, "", wxEmptyString, wxDefaultPosition, wxSize(6* wxGetApp().em_unit(), -1), style);
#ifdef _WIN32
wxGetApp().UpdateDarkUI(this->GetText());
#endif
this->Refresh(); this->Refresh();
} }
~SpinCtrlDouble() {} ~SpinCtrlDouble() {}
@ -3352,6 +3351,12 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
wxGetApp().UpdateDarkUI(p->btn_finish); wxGetApp().UpdateDarkUI(p->btn_finish);
wxGetApp().UpdateDarkUI(p->btn_cancel); wxGetApp().UpdateDarkUI(p->btn_cancel);
wxGetApp().SetWindowVariantForButton(p->btn_sel_all);
wxGetApp().SetWindowVariantForButton(p->btn_prev);
wxGetApp().SetWindowVariantForButton(p->btn_next);
wxGetApp().SetWindowVariantForButton(p->btn_finish);
wxGetApp().SetWindowVariantForButton(p->btn_cancel);
const auto prusa_it = p->bundles.find("PrusaResearch"); const auto prusa_it = p->bundles.find("PrusaResearch");
wxCHECK_RET(prusa_it != p->bundles.cend(), "Vendor PrusaResearch not found"); wxCHECK_RET(prusa_it != p->bundles.cend(), "Vendor PrusaResearch not found");
const VendorProfile *vendor_prusa = prusa_it->second.vendor_profile; const VendorProfile *vendor_prusa = prusa_it->second.vendor_profile;

View File

@ -32,6 +32,7 @@
#include "SavePresetDialog.hpp" #include "SavePresetDialog.hpp"
#include "wxExtensions.hpp" #include "wxExtensions.hpp"
#include "Widgets/SpinInput.hpp"
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
@ -510,8 +511,8 @@ struct PageDiameters: ConfigWizardPage
struct PageTemperatures: ConfigWizardPage struct PageTemperatures: ConfigWizardPage
{ {
wxSpinCtrlDouble *spin_extr; ::SpinInputDouble *spin_extr;
wxSpinCtrlDouble *spin_bed; ::SpinInputDouble *spin_bed;
PageTemperatures(ConfigWizard *parent); PageTemperatures(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config); virtual void apply_custom_config(DynamicPrintConfig &config);

View File

@ -154,7 +154,14 @@ bool BitmapTextRenderer::Render(wxRect rect, wxDC *dc, int state)
// workaround for Windows DarkMode : Don't respect to the state & wxDATAVIEW_CELL_SELECTED to avoid update of the text color // workaround for Windows DarkMode : Don't respect to the state & wxDATAVIEW_CELL_SELECTED to avoid update of the text color
RenderText(m_value.GetText(), xoffset, rect, dc, state & wxDATAVIEW_CELL_SELECTED ? 0 :state); RenderText(m_value.GetText(), xoffset, rect, dc, state & wxDATAVIEW_CELL_SELECTED ? 0 :state);
#else #else
{
wxDataViewCtrl* const view = GetView();
if (GetAttr().HasFont())
dc->SetFont(GetAttr().GetEffectiveFont(view->GetFont()));
else
dc->SetFont(view->GetFont());
RenderText(m_value.GetText(), xoffset, rect, dc, state); RenderText(m_value.GetText(), xoffset, rect, dc, state);
}
#endif #endif
return true; return true;
@ -165,22 +172,22 @@ wxSize BitmapTextRenderer::GetSize() const
if (!m_value.GetText().empty()) if (!m_value.GetText().empty())
{ {
wxSize size; wxSize size;
#if defined(SUPPORTS_MARKUP) && defined(wxHAS_GENERIC_DATAVIEWCTRL)
if (m_markupText)
{
wxDataViewCtrl* const view = GetView(); wxDataViewCtrl* const view = GetView();
wxClientDC dc(view); wxClientDC dc(view);
if (GetAttr().HasFont()) if (GetAttr().HasFont())
dc.SetFont(GetAttr().GetEffectiveFont(view->GetFont())); dc.SetFont(GetAttr().GetEffectiveFont(view->GetFont()));
else
dc.SetFont(view->GetFont());
#if defined(SUPPORTS_MARKUP) && defined(wxHAS_GENERIC_DATAVIEWCTRL)
if (m_markupText)
size = m_markupText->Measure(dc); size = m_markupText->Measure(dc);
else
#endif // SUPPORTS_MARKUP && wxHAS_GENERIC_DATAVIEWCTRL
size = dc.GetTextExtent(m_value.GetText());
int lines = m_value.GetText().Freq('\n') + 1; int lines = m_value.GetText().Freq('\n') + 1;
size.SetHeight(size.GetHeight() * lines); size.SetHeight(size.GetHeight() * lines);
}
else
#endif // SUPPORTS_MARKUP && wxHAS_GENERIC_DATAVIEWCTRL
size = GetTextExtent(m_value.GetText());
if (m_value.GetBitmap().IsOk()) if (m_value.GetBitmap().IsOk())
size.x += m_value.GetBitmap().GetWidth() + 4; size.x += m_value.GetBitmap().GetWidth() + 4;

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) {
{
// # On OSX / Cocoa, wxSpinCtrl::GetValue() doesn't return the new value
// # when it was changed from the text control, so the on_change callback
// # gets the old one, and on_kill_focus resets the control to the old value.
// # As a workaround, we get the new value from $event->GetString and store
// # here temporarily so that we can return it from get_value()
long value; long value;
const bool parsed = e.GetString().ToLong(&value); if (!e.GetString().ToLong(&value))
if (!parsed || value < INT_MIN || value > INT_MAX) return;
if (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,21 +1518,19 @@ 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 : "); wxSize label_sz = wxSize(int(field_size.x / 2), field_size.y);
auto static_text_y = new wxStaticText(m_parent, wxID_ANY, " y : "); auto static_text_x = new wxStaticText(m_parent, wxID_ANY, "x : ", wxDefaultPosition, label_sz, wxALIGN_RIGHT);
auto static_text_y = new wxStaticText(m_parent, wxID_ANY, "y : ", wxDefaultPosition, label_sz, wxALIGN_RIGHT);
static_text_x->SetFont(Slic3r::GUI::wxGetApp().normal_font()); static_text_x->SetFont(Slic3r::GUI::wxGetApp().normal_font());
static_text_x->SetBackgroundStyle(wxBG_STYLE_PAINT); static_text_x->SetBackgroundStyle(wxBG_STYLE_PAINT);
static_text_y->SetFont(Slic3r::GUI::wxGetApp().normal_font()); static_text_y->SetFont(Slic3r::GUI::wxGetApp().normal_font());
@ -1483,9 +1541,9 @@ void PointCtrl::BUILD()
wxGetApp().UpdateDarkUI(static_text_x, false, true); wxGetApp().UpdateDarkUI(static_text_x, false, true);
wxGetApp().UpdateDarkUI(static_text_y, false, true); wxGetApp().UpdateDarkUI(static_text_y, false, true);
temp->Add(static_text_x, 0, wxALIGN_CENTER_VERTICAL, 0); temp->Add(static_text_x);
temp->Add(x_textctrl); temp->Add(x_textctrl);
temp->Add(static_text_y, 0, wxALIGN_CENTER_VERTICAL, 0); temp->Add(static_text_y);
temp->Add(y_textctrl); temp->Add(y_textctrl);
x_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(x_textctrl); }), x_textctrl->GetId()); x_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(x_textctrl); }), x_textctrl->GetId());
@ -1527,7 +1585,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 +1597,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,7 +390,14 @@ 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;
}
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; m_disable_change_event = false;
} }
*/ */
@ -386,11 +406,16 @@ public:
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

@ -817,11 +817,13 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
p->hex_picker = new wxFilePickerCtrl(panel, wxID_ANY, wxEmptyString, /*wxFileSelectorPromptStr*/_L("Select a file"), p->hex_picker = new wxFilePickerCtrl(panel, wxID_ANY, wxEmptyString, /*wxFileSelectorPromptStr*/_L("Select a file"),
"Hex files (*.hex)|*.hex|All files|*.*"); "Hex files (*.hex)|*.hex|All files|*.*");
p->hex_picker->GetPickerCtrl()->SetLabelText(_(L("Browse"))); p->hex_picker->GetPickerCtrl()->SetLabelText(_(L("Browse")));
GUI::wxGetApp().SetWindowVariantForButton(static_cast<wxButton*>(p->hex_picker->GetPickerCtrl()));
auto *label_port_picker = new wxStaticText(panel, wxID_ANY, _(L("Serial port:"))); auto *label_port_picker = new wxStaticText(panel, wxID_ANY, _(L("Serial port:")));
p->port_picker = new wxComboBox(panel, wxID_ANY); p->port_picker = new wxComboBox(panel, wxID_ANY);
p->txt_port_autodetect = new wxStaticText(panel, wxID_ANY, _(L("Autodetected"))); p->txt_port_autodetect = new wxStaticText(panel, wxID_ANY, _(L("Autodetected")));
p->btn_rescan = new wxButton(panel, wxID_ANY, _(L("Rescan"))); p->btn_rescan = new wxButton(panel, wxID_ANY, _(L("Rescan")));
GUI::wxGetApp().SetWindowVariantForButton(p->btn_rescan);
auto *port_sizer = new wxBoxSizer(wxHORIZONTAL); auto *port_sizer = new wxBoxSizer(wxHORIZONTAL);
port_sizer->Add(p->port_picker, 1, wxEXPAND | wxRIGHT, SPACING); port_sizer->Add(p->port_picker, 1, wxEXPAND | wxRIGHT, SPACING);
port_sizer->Add(p->btn_rescan, 0); port_sizer->Add(p->btn_rescan, 0);
@ -864,7 +866,9 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
vsizer->Add(p->spoiler, 1, wxEXPAND | wxBOTTOM, SPACING); vsizer->Add(p->spoiler, 1, wxEXPAND | wxBOTTOM, SPACING);
p->btn_close = new wxButton(panel, wxID_CLOSE, _(L("Close"))); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac p->btn_close = new wxButton(panel, wxID_CLOSE, _(L("Close"))); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
GUI::wxGetApp().SetWindowVariantForButton(p->btn_close);
p->btn_flash = new wxButton(panel, wxID_ANY, p->btn_flash_label_ready); p->btn_flash = new wxButton(panel, wxID_ANY, p->btn_flash_label_ready);
GUI::wxGetApp().SetWindowVariantForButton(p->btn_flash);
p->btn_flash->Disable(); p->btn_flash->Disable();
auto *bsizer = new wxBoxSizer(wxHORIZONTAL); auto *bsizer = new wxBoxSizer(wxHORIZONTAL);
bsizer->Add(p->btn_close); bsizer->Add(p->btn_close);

View File

@ -6247,7 +6247,7 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale()
#if ENABLE_RETINA_GL #if ENABLE_RETINA_GL
new_scale /= m_retina_helper->get_scale_factor(); new_scale /= m_retina_helper->get_scale_factor();
#endif #endif
if (fabs(new_scale - scale) > 0.01) // scale is changed by 1% and more if (fabs(new_scale - scale) > 0.015) // scale is changed by 1.5% and more
wxGetApp().set_auto_toolbar_icon_scale(new_scale); wxGetApp().set_auto_toolbar_icon_scale(new_scale);
} }

View File

@ -1093,6 +1093,16 @@ bool GUI_App::OnInit()
} }
} }
static int get_app_font_pt_size(const AppConfig* app_config)
{
if (!app_config->has("font_pt_size"))
return -1;
const int font_pt_size = atoi(app_config->get("font_pt_size").c_str());
const int max_font_pt_size = wxGetApp().get_max_font_pt_size();
return (font_pt_size > max_font_pt_size) ? max_font_pt_size : font_pt_size;
}
bool GUI_App::on_init_inner() bool GUI_App::on_init_inner()
{ {
// Set initialization of image handlers before any UI actions - See GH issue #7469 // Set initialization of image handlers before any UI actions - See GH issue #7469
@ -1326,7 +1336,7 @@ bool GUI_App::on_init_inner()
if (!delayed_error_load_presets.empty()) if (!delayed_error_load_presets.empty())
show_error(nullptr, delayed_error_load_presets); show_error(nullptr, delayed_error_load_presets);
mainframe = new MainFrame(app_config->has("font_size") ? atoi(app_config->get("font_size").c_str()) : -1); mainframe = new MainFrame(get_app_font_pt_size(app_config));
// hide settings tabs after first Layout // hide settings tabs after first Layout
if (is_editor()) if (is_editor())
mainframe->select_tab(size_t(0)); mainframe->select_tab(size_t(0));
@ -1649,6 +1659,30 @@ void GUI_App::UpdateAllStaticTextDarkUI(wxWindow* parent)
#endif #endif
} }
void GUI_App::SetWindowVariantForButton(wxButton* btn)
{
#ifdef __APPLE__
// This is a limit imposed by OSX. The way the native button widget is drawn only allows it to be stretched horizontally,
// and the vertical size is fixed. (see https://stackoverflow.com/questions/29083891/wxpython-button-size-being-ignored-on-osx)
// But standard height is possible to change using SetWindowVariant method (see https://docs.wxwidgets.org/3.0/window_8h.html#a879bccd2c987fedf06030a8abcbba8ac)
if (m_normal_font.GetPointSize() > 15) {
btn->SetWindowVariant(wxWINDOW_VARIANT_LARGE);
btn->SetFont(m_normal_font);
}
#endif
}
int GUI_App::get_max_font_pt_size()
{
const unsigned disp_count = wxDisplay::GetCount();
for (int i = 0; i < disp_count; i++) {
const wxRect display_rect = wxDisplay(i).GetGeometry();
if (display_rect.width >= 2560 && display_rect.height >= 1440)
return 20;
}
return 15;
}
void GUI_App::init_fonts() void GUI_App::init_fonts()
{ {
m_small_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); m_small_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
@ -1756,9 +1790,26 @@ 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();
} }
wxSize GUI_App::get_min_size() const bool GUI_App::suppress_round_corners() const
{ {
return wxSize(76*m_em_unit, 49 * m_em_unit); return true;// app_config->get("suppress_round_corners") == "1";
}
wxSize GUI_App::get_min_size(wxWindow* display_win) const
{
wxSize min_size(76*m_em_unit, 49 * m_em_unit);
const wxDisplay display = wxDisplay(display_win);
wxRect display_rect = display.GetGeometry();
display_rect.width *= 0.75;
display_rect.height *= 0.75;
if (min_size.x > display_rect.GetWidth())
min_size.x = display_rect.GetWidth();
if (min_size.y > display_rect.GetHeight())
min_size.y = display_rect.GetHeight();
return min_size;
} }
float GUI_App::toolbar_icon_scale(const bool is_limited/* = false*/) const float GUI_App::toolbar_icon_scale(const bool is_limited/* = false*/) const
@ -1833,7 +1884,7 @@ void GUI_App::recreate_GUI(const wxString& msg_name)
dlg.Update(10, _L("Recreating") + dots); dlg.Update(10, _L("Recreating") + dots);
MainFrame *old_main_frame = mainframe; MainFrame *old_main_frame = mainframe;
mainframe = new MainFrame(app_config->has("font_size") ? atoi(app_config->get("font_size").c_str()) : -1); mainframe = new MainFrame(get_app_font_pt_size(app_config));
if (is_editor()) if (is_editor())
// hide settings tabs after first Layout // hide settings tabs after first Layout
mainframe->select_tab(size_t(0)); mainframe->select_tab(size_t(0));
@ -2124,6 +2175,9 @@ int GUI_App::GetSingleChoiceIndex(const wxString& message,
#ifdef _WIN32 #ifdef _WIN32
wxSingleChoiceDialog dialog(nullptr, message, caption, choices); wxSingleChoiceDialog dialog(nullptr, message, caption, choices);
wxGetApp().UpdateDlgDarkUI(&dialog); wxGetApp().UpdateDlgDarkUI(&dialog);
auto children = dialog.GetChildren();
for (auto child : children)
child->SetFont(normal_font());
dialog.SetSelection(initialSelection); dialog.SetSelection(initialSelection);
return dialog.ShowModal() == wxID_OK ? dialog.GetSelection() : -1; return dialog.ShowModal() == wxID_OK ? dialog.GetSelection() : -1;
@ -2955,7 +3009,8 @@ ObjectSettings* GUI_App::obj_settings()
ObjectList* GUI_App::obj_list() ObjectList* GUI_App::obj_list()
{ {
return sidebar().obj_list(); // If this method is called before plater_ has been initialized, return nullptr (to avoid a crash)
return plater_ ? sidebar().obj_list() : nullptr;
} }
ObjectLayers* GUI_App::obj_layers() ObjectLayers* GUI_App::obj_layers()

View File

@ -214,6 +214,7 @@ public:
void UpdateDVCDarkUI(wxDataViewCtrl* dvc, bool highlited = false); void UpdateDVCDarkUI(wxDataViewCtrl* dvc, bool highlited = false);
// update color mode for panel including all static texts controls // update color mode for panel including all static texts controls
void UpdateAllStaticTextDarkUI(wxWindow* parent); void UpdateAllStaticTextDarkUI(wxWindow* parent);
void SetWindowVariantForButton(wxButton* btn);
void init_fonts(); void init_fonts();
void update_fonts(const MainFrame *main_frame = nullptr); void update_fonts(const MainFrame *main_frame = nullptr);
void set_label_clr_modified(const wxColour& clr); void set_label_clr_modified(const wxColour& clr);
@ -248,7 +249,9 @@ 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;
wxSize get_min_size() const; bool suppress_round_corners() const;
wxSize get_min_size(wxWindow* display_win) const;
int get_max_font_pt_size();
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;
void check_printer_presets(); void check_printer_presets();

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,7 +24,6 @@ class wxComboBox;
class wxStaticText; class wxStaticText;
class LockButton; class LockButton;
class wxStaticBitmap; class wxStaticBitmap;
class wxCheckBox;
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
@ -30,6 +32,9 @@ namespace GUI {
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

@ -96,13 +96,13 @@ public:
if (font_point_size > 0) if (font_point_size > 0)
m_normal_font.SetPointSize(font_point_size); m_normal_font.SetPointSize(font_point_size);
else if (parent)
m_normal_font.SetPointSize(parent->GetFont().GetPointSize());
/* Because of default window font is a primary display font, /* Because of default window font is a primary display font,
* We should set correct font for window before getting em_unit value. * We should set correct font for window before getting em_unit value.
*/ */
#ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
this->SetFont(m_normal_font); this->SetFont(m_normal_font);
#endif
this->CenterOnParent(); this->CenterOnParent();
#ifdef _WIN32 #ifdef _WIN32
update_dark_ui(this); update_dark_ui(this);
@ -111,7 +111,13 @@ public:
// Linux specific issue : get_dpi_for_window(this) still doesn't responce to the Display's scale in new wxWidgets(3.1.3). // Linux specific issue : get_dpi_for_window(this) still doesn't responce to the Display's scale in new wxWidgets(3.1.3).
// So, calculate the m_em_unit value from the font size, as before // So, calculate the m_em_unit value from the font size, as before
#if !defined(__WXGTK__) #if !defined(__WXGTK__)
m_em_unit = std::max<size_t>(10, 10.0f * m_scale_factor); #ifdef _WIN32
const double font_to_em_koef = 10./9.;// Default font point size on Windows is 9 pt
#else // ifdef __WXOSX__
const double font_to_em_koef = 10./11.;// Default font point size on OSX is 11 pt
#endif
m_em_unit_from_font_size = int(font_to_em_koef * m_normal_font.GetPointSize());
m_em_unit = std::max<int>(10, int(m_scale_factor * m_em_unit_from_font_size));
#else #else
// initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window. // initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window.
m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1); m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
@ -178,7 +184,6 @@ public:
float prev_scale_factor() const { return m_prev_scale_factor; } float prev_scale_factor() const { return m_prev_scale_factor; }
int em_unit() const { return m_em_unit; } int em_unit() const { return m_em_unit; }
// int font_size() const { return m_font_size; }
const wxFont& normal_font() const { return m_normal_font; } const wxFont& normal_font() const { return m_normal_font; }
void enable_force_rescale() { m_force_rescale = true; } void enable_force_rescale() { m_force_rescale = true; }
@ -197,7 +202,7 @@ protected:
private: private:
float m_scale_factor; float m_scale_factor;
int m_em_unit; int m_em_unit;
// int m_font_size; int m_em_unit_from_font_size {10};
wxFont m_normal_font; wxFont m_normal_font;
float m_prev_scale_factor; float m_prev_scale_factor;
@ -206,14 +211,6 @@ private:
int m_new_font_point_size; int m_new_font_point_size;
// void recalc_font()
// {
// wxClientDC dc(this);
// const auto metrics = dc.GetFontMetrics();
// m_font_size = metrics.height;
// m_em_unit = metrics.averageWidth;
// }
// check if new scale is differ from previous // check if new scale is differ from previous
bool is_new_scale_factor() const { return fabs(m_scale_factor - m_prev_scale_factor) > 0.001; } bool is_new_scale_factor() const { return fabs(m_scale_factor - m_prev_scale_factor) > 0.001; }
@ -254,7 +251,7 @@ private:
m_normal_font = this->GetFont(); m_normal_font = this->GetFont();
// update em_unit value for new window font // update em_unit value for new window font
m_em_unit = std::max<int>(10, 10.0f * m_scale_factor); m_em_unit = std::max<int>(10, int(m_scale_factor * m_em_unit_from_font_size));
// rescale missed controls sizes and images // rescale missed controls sizes and images
on_dpi_changed(suggested_rect); on_dpi_changed(suggested_rect);

View File

@ -98,10 +98,12 @@ GalleryDialog::GalleryDialog(wxWindow* parent) :
#endif #endif
wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK | wxCLOSE); wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK | wxCLOSE);
m_ok_btn = static_cast<wxButton*>(FindWindowById(wxID_OK, this)); wxGetApp().SetWindowVariantForButton(buttons->GetCancelButton());
m_ok_btn = buttons->GetAffirmativeButton();
wxGetApp().SetWindowVariantForButton(m_ok_btn);
m_ok_btn->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(!m_selected_items.empty()); }); m_ok_btn->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(!m_selected_items.empty()); });
static_cast<wxButton*>(FindWindowById(wxID_CLOSE, this))->Bind(wxEVT_BUTTON, [this](wxCommandEvent&){ this->EndModal(wxID_CLOSE); }); buttons->GetCancelButton()->Bind(wxEVT_BUTTON, [this](wxCommandEvent&){ this->EndModal(wxID_CLOSE); });
this->SetEscapeId(wxID_CLOSE); this->SetEscapeId(wxID_CLOSE);
auto add_btn = [this, buttons]( size_t pos, int& ID, wxString title, wxString tooltip, auto add_btn = [this, buttons]( size_t pos, int& ID, wxString title, wxString tooltip,
void (GalleryDialog::* method)(wxEvent&), void (GalleryDialog::* method)(wxEvent&),
@ -109,6 +111,7 @@ GalleryDialog::GalleryDialog(wxWindow* parent) :
ID = NewControlId(); ID = NewControlId();
wxButton* btn = new wxButton(this, ID, title); wxButton* btn = new wxButton(this, ID, title);
btn->SetToolTip(tooltip); btn->SetToolTip(tooltip);
wxGetApp().SetWindowVariantForButton(btn);
btn->Bind(wxEVT_UPDATE_UI, [enable_fn](wxUpdateUIEvent& evt) { evt.Enable(enable_fn()); }); btn->Bind(wxEVT_UPDATE_UI, [enable_fn](wxUpdateUIEvent& evt) { evt.Enable(enable_fn()); });
buttons->Insert(pos, btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W); buttons->Insert(pos, btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W);
this->Bind(wxEVT_BUTTON, method, this, ID); this->Bind(wxEVT_BUTTON, method, this, ID);

View File

@ -50,7 +50,8 @@ KBShortcutsDialog::KBShortcutsDialog()
} }
wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK); wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK);
wxGetApp().UpdateDarkUI(static_cast<wxButton*>(this->FindWindowById(wxID_OK, this))); wxGetApp().SetWindowVariantForButton(buttons->GetAffirmativeButton());
wxGetApp().UpdateDarkUI(buttons->GetAffirmativeButton());
this->SetEscapeId(wxID_OK); this->SetEscapeId(wxID_OK);
main_sizer->Add(buttons, 0, wxEXPAND | wxALL, 5); main_sizer->Add(buttons, 0, wxEXPAND | wxALL, 5);

View File

@ -213,7 +213,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
sizer->SetSizeHints(this); sizer->SetSizeHints(this);
Fit(); Fit();
const wxSize min_size = wxGetApp().get_min_size(); //wxSize(76*wxGetApp().em_unit(), 49*wxGetApp().em_unit()); const wxSize min_size = wxGetApp().get_min_size(this);
#ifdef __APPLE__ #ifdef __APPLE__
// Using SetMinSize() on Mac messes up the window position in some cases // Using SetMinSize() on Mac messes up the window position in some cases
// cf. https://groups.google.com/forum/#!topic/wx-users/yUKPBBfXWO0 // cf. https://groups.google.com/forum/#!topic/wx-users/yUKPBBfXWO0
@ -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,9 +740,9 @@ 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
#ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList wxGetApp().UpdateDarkUI(m_tabpanel);
m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font()); m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font());
#endif
m_tabpanel->Hide(); m_tabpanel->Hide();
m_settings_dialog.set_tabpanel(m_tabpanel); m_settings_dialog.set_tabpanel(m_tabpanel);
@ -1107,7 +1107,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())
@ -2304,16 +2303,6 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe)
if (wxGetApp().is_gcode_viewer()) if (wxGetApp().is_gcode_viewer())
return; return;
#if defined(__WXMSW__)
// ys_FIXME! temporary workaround for correct font scaling
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
#else
this->SetFont(wxGetApp().normal_font());
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#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.
#if _WIN32 #if _WIN32
{ {

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 {
@ -83,6 +85,7 @@ void MsgDialog::SetButtonLabel(wxWindowID btn_id, const wxString& label, bool se
wxButton* MsgDialog::add_button(wxWindowID btn_id, bool set_focus /*= false*/, const wxString& label/* = wxString()*/) wxButton* MsgDialog::add_button(wxWindowID btn_id, bool set_focus /*= false*/, const wxString& label/* = wxString()*/)
{ {
wxButton* btn = new wxButton(this, btn_id, label); wxButton* btn = new wxButton(this, btn_id, label);
wxGetApp().SetWindowVariantForButton(btn);
if (set_focus) { if (set_focus) {
btn->SetFocus(); btn->SetFocus();
// For non-MSW platforms SetFocus is not enought to use it as default, when the dialog is closed by ENTER // For non-MSW platforms SetFocus is not enought to use it as default, when the dialog is closed by ENTER
@ -268,7 +271,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

@ -184,7 +184,7 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_
m_add_preset_btn->SetToolTip(_L("Add preset for this printer device")); m_add_preset_btn->SetToolTip(_L("Add preset for this printer device"));
m_add_preset_btn->Bind(wxEVT_BUTTON, &PhysicalPrinterDialog::AddPreset, this); m_add_preset_btn->Bind(wxEVT_BUTTON, &PhysicalPrinterDialog::AddPreset, this);
m_printer_name = new wxTextCtrl(this, wxID_ANY, printer_name, wxDefaultPosition, wxDefaultSize); m_printer_name = new ::TextInput(this,printer_name);
wxGetApp().UpdateDarkUI(m_printer_name); wxGetApp().UpdateDarkUI(m_printer_name);
m_printer_name->Bind(wxEVT_TEXT, [this](wxEvent&) { this->update_full_printer_names(); }); m_printer_name->Bind(wxEVT_TEXT, [this](wxEvent&) { this->update_full_printer_names(); });
@ -242,7 +242,7 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_
if (new_printer) { if (new_printer) {
m_printer_name->SetFocus(); m_printer_name->SetFocus();
m_printer_name->SelectAll(); m_printer_name->GetTextCtrl()->SelectAll();
} }
this->Fit(); this->Fit();
@ -508,7 +508,7 @@ void PhysicalPrinterDialog::update(bool printer_change)
supports_multiple_printers = opt && opt->value == htRepetier; supports_multiple_printers = opt && opt->value == htRepetier;
if (opt->value == htPrusaConnect) { // automatically show default prusaconnect address if (opt->value == htPrusaConnect) { // automatically show default prusaconnect address
if (Field* printhost_field = m_optgroup->get_field("print_host"); printhost_field) { if (Field* printhost_field = m_optgroup->get_field("print_host"); printhost_field) {
if (wxTextCtrl* temp = dynamic_cast<wxTextCtrl*>(printhost_field->getWindow()); temp && temp->GetValue().IsEmpty()) { if (text_ctrl* temp = dynamic_cast<text_ctrl*>(printhost_field->getWindow()); temp && temp->GetValue().IsEmpty()) {
temp->SetValue(L"https://connect.prusa3d.com"); temp->SetValue(L"https://connect.prusa3d.com");
} }
} }
@ -674,7 +674,7 @@ void PhysicalPrinterDialog::update_full_printer_names()
InfoDialog(this, format_wxstr("%1%: \"%2%\" ", _L("Unexpected character"), str), InfoDialog(this, format_wxstr("%1%: \"%2%\" ", _L("Unexpected character"), str),
_L("The following characters are not allowed in the name") + ": " + unusable_symbols).ShowModal(); _L("The following characters are not allowed in the name") + ": " + unusable_symbols).ShowModal();
m_printer_name->SetValue(printer_name); m_printer_name->SetValue(printer_name);
m_printer_name->SetInsertionPointEnd(); m_printer_name->GetTextCtrl()->SetInsertionPointEnd();
return; return;
} }
} }

View File

@ -10,10 +10,10 @@
#include <wx/gdicmn.h> #include <wx/gdicmn.h>
#include "libslic3r/Preset.hpp" #include "libslic3r/Preset.hpp"
#include "Widgets/TextInput.hpp"
#include "GUI_Utils.hpp" #include "GUI_Utils.hpp"
class wxString; class wxString;
class wxTextCtrl;
class wxStaticText; class wxStaticText;
class ScalableButton; class ScalableButton;
class wxBoxSizer; class wxBoxSizer;
@ -67,7 +67,7 @@ class PhysicalPrinterDialog : public DPIDialog
wxString m_default_name; wxString m_default_name;
DynamicPrintConfig* m_config { nullptr }; DynamicPrintConfig* m_config { nullptr };
wxTextCtrl* m_printer_name { nullptr }; ::TextInput* m_printer_name { nullptr };
std::vector<PresetForPrinter*> m_presets; std::vector<PresetForPrinter*> m_presets;
ConfigOptionsGroup* m_optgroup { nullptr }; ConfigOptionsGroup* m_optgroup { nullptr };

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;
@ -509,7 +511,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) :
auto wiping_dialog_btn = [this](wxWindow* parent) { auto wiping_dialog_btn = [this](wxWindow* parent) {
m_wiping_dialog_button = new wxButton(parent, wxID_ANY, _L("Purging volumes") + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); m_wiping_dialog_button = new wxButton(parent, wxID_ANY, _L("Purging volumes") + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
m_wiping_dialog_button->SetFont(wxGetApp().normal_font()); wxGetApp().SetWindowVariantForButton(m_wiping_dialog_button);
wxGetApp().UpdateDarkUI(m_wiping_dialog_button, true); wxGetApp().UpdateDarkUI(m_wiping_dialog_button, true);
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
@ -787,6 +789,7 @@ void Sidebar::priv::hide_rich_tip(wxButton* btn)
Sidebar::Sidebar(Plater *parent) Sidebar::Sidebar(Plater *parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(42 * wxGetApp().em_unit(), -1)), p(new priv(parent)) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(42 * wxGetApp().em_unit(), -1)), p(new priv(parent))
{ {
SetFont(wxGetApp().normal_font());
p->scrolled = new wxScrolledWindow(this); p->scrolled = new wxScrolledWindow(this);
// p->scrolled->SetScrollbars(0, 100, 1, 2); // ys_DELETE_after_testing. pixelsPerUnitY = 100 from https://github.com/prusa3d/PrusaSlicer/commit/8f019e5fa992eac2c9a1e84311c990a943f80b01, // p->scrolled->SetScrollbars(0, 100, 1, 2); // ys_DELETE_after_testing. pixelsPerUnitY = 100 from https://github.com/prusa3d/PrusaSlicer/commit/8f019e5fa992eac2c9a1e84311c990a943f80b01,
// but this cause the bad layout of the sidebar, when all infoboxes appear. // but this cause the bad layout of the sidebar, when all infoboxes appear.
@ -794,13 +797,12 @@ Sidebar::Sidebar(Plater *parent)
// But if we set this value to 5, layout will be better // But if we set this value to 5, layout will be better
p->scrolled->SetScrollRate(0, 5); p->scrolled->SetScrollRate(0, 5);
SetFont(wxGetApp().normal_font());
#ifndef __APPLE__ #ifndef __APPLE__
#ifdef _WIN32 #ifdef _WIN32
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
@ -937,6 +939,7 @@ Sidebar::Sidebar(Plater *parent)
#endif //__APPLE__ #endif //__APPLE__
ScalableBitmap bmp = ScalableBitmap(this, icon_name, bmp_px_cnt); ScalableBitmap bmp = ScalableBitmap(this, icon_name, bmp_px_cnt);
*btn = new ScalableButton(this, wxID_ANY, bmp, "", wxBU_EXACTFIT); *btn = new ScalableButton(this, wxID_ANY, bmp, "", wxBU_EXACTFIT);
wxGetApp().SetWindowVariantForButton((*btn));
#ifdef _WIN32 #ifdef _WIN32
(*btn)->Bind(wxEVT_ENTER_WINDOW, [tooltip, btn, this](wxMouseEvent& event) { (*btn)->Bind(wxEVT_ENTER_WINDOW, [tooltip, btn, this](wxMouseEvent& event) {
@ -968,6 +971,7 @@ Sidebar::Sidebar(Plater *parent)
auto init_btn = [this](wxButton **btn, wxString label, const int button_height) { auto init_btn = [this](wxButton **btn, wxString label, const int button_height) {
*btn = new wxButton(this, wxID_ANY, label, wxDefaultPosition, *btn = new wxButton(this, wxID_ANY, label, wxDefaultPosition,
wxSize(-1, button_height), wxBU_EXACTFIT); wxSize(-1, button_height), wxBU_EXACTFIT);
wxGetApp().SetWindowVariantForButton((*btn));
(*btn)->SetFont(wxGetApp().bold_font()); (*btn)->SetFont(wxGetApp().bold_font());
wxGetApp().UpdateDarkUI((*btn), true); wxGetApp().UpdateDarkUI((*btn), true);
}; };
@ -977,7 +981,7 @@ Sidebar::Sidebar(Plater *parent)
enable_buttons(false); enable_buttons(false);
auto *btns_sizer = new wxBoxSizer(wxVERTICAL); auto *btns_sizer = new wxBoxSizer(wxHORIZONTAL);
auto* complect_btns_sizer = new wxBoxSizer(wxHORIZONTAL); auto* complect_btns_sizer = new wxBoxSizer(wxHORIZONTAL);
complect_btns_sizer->Add(p->btn_export_gcode, 1, wxEXPAND); complect_btns_sizer->Add(p->btn_export_gcode, 1, wxEXPAND);
@ -986,8 +990,8 @@ Sidebar::Sidebar(Plater *parent)
// complect_btns_sizer->Add(p->btn_eject_device); // complect_btns_sizer->Add(p->btn_eject_device);
btns_sizer->Add(p->btn_reslice, 0, wxEXPAND | wxTOP, margin_5); btns_sizer->Add(p->btn_reslice, 1, wxEXPAND | wxTOP | wxBOTTOM, margin_5);
btns_sizer->Add(complect_btns_sizer, 0, wxEXPAND | wxTOP, margin_5); btns_sizer->Add(complect_btns_sizer, 1, wxEXPAND | wxTOP | wxBOTTOM, margin_5);
auto *sizer = new wxBoxSizer(wxVERTICAL); auto *sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(p->scrolled, 1, wxEXPAND); sizer->Add(p->scrolled, 1, wxEXPAND);
@ -2090,8 +2094,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
, collapse_toolbar(GLToolbar::Normal, "Collapse") , collapse_toolbar(GLToolbar::Normal, "Collapse")
, m_project_filename(wxEmptyString) , m_project_filename(wxEmptyString)
{ {
this->q->SetFont(Slic3r::GUI::wxGetApp().normal_font());
background_process.set_fff_print(&fff_print); background_process.set_fff_print(&fff_print);
background_process.set_sla_print(&sla_print); background_process.set_sla_print(&sla_print);
background_process.set_gcode_result(&gcode_result); background_process.set_gcode_result(&gcode_result);
@ -4470,7 +4472,10 @@ void Plater::priv::on_action_layersediting(SimpleEvent&)
void Plater::priv::on_object_select(SimpleEvent& evt) void Plater::priv::on_object_select(SimpleEvent& evt)
{ {
wxGetApp().obj_list()->update_selections(); if (auto obj_list = wxGetApp().obj_list())
obj_list->update_selections();
else
return;
selection_changed(); selection_changed();
} }
@ -5298,7 +5303,7 @@ void Sidebar::set_btn_label(const ActionButtonType btn_type, const wxString& lab
// Plater / Public // Plater / Public
Plater::Plater(wxWindow *parent, MainFrame *main_frame) Plater::Plater(wxWindow *parent, MainFrame *main_frame)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxGetApp().get_min_size()) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxGetApp().get_min_size(parent))
, p(new priv(this, main_frame)) , p(new priv(this, main_frame))
{ {
// Initialization performed in the private c-tor // Initialization performed in the private c-tor
@ -6112,7 +6117,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

@ -21,6 +21,8 @@
#include "GLCanvas3D.hpp" #include "GLCanvas3D.hpp"
#include "ConfigWizard.hpp" #include "ConfigWizard.hpp"
#include "Widgets/SpinInput.hpp"
#include <boost/dll/runtime_symbol_info.hpp> #include <boost/dll/runtime_symbol_info.hpp>
#ifdef WIN32 #ifdef WIN32
@ -64,13 +66,25 @@ namespace GUI {
PreferencesDialog::PreferencesDialog(wxWindow* parent) : PreferencesDialog::PreferencesDialog(wxWindow* parent) :
DPIDialog(parent, wxID_ANY, _L("Preferences"), wxDefaultPosition, DPIDialog(parent, wxID_ANY, _L("Preferences"), wxDefaultPosition,
wxDefaultSize, wxDEFAULT_DIALOG_STYLE) wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{ {
#ifdef __WXOSX__ #ifdef __WXOSX__
isOSX = true; isOSX = true;
#endif #endif
build(); build();
wxSize sz = GetSize();
sz.x += em_unit();
const size_t pages_cnt = tabs->GetPageCount();
for (size_t tab_id = 0; tab_id < pages_cnt; tab_id++) {
wxSizer* tab_sizer = tabs->GetPage(tab_id)->GetSizer();
wxScrolledWindow* scrolled = static_cast<wxScrolledWindow*>(tab_sizer->GetItem(size_t(0))->GetWindow());
scrolled->SetScrollRate(0, 5);
}
SetSize(sz);
m_highlighter.set_timer_owner(this, 0); m_highlighter.set_timer_owner(this, 0);
} }
@ -131,14 +145,22 @@ void PreferencesDialog::show(const std::string& highlight_opt_key /*= std::strin
static std::shared_ptr<ConfigOptionsGroup>create_options_tab(const wxString& title, wxBookCtrlBase* tabs) static std::shared_ptr<ConfigOptionsGroup>create_options_tab(const wxString& title, wxBookCtrlBase* tabs)
{ {
wxPanel* tab = new wxPanel(tabs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); wxPanel* tab = new wxPanel(tabs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
tabs->AddPage(tab, _(title)); tabs->AddPage(tab, _(title));
tab->SetFont(wxGetApp().normal_font()); tab->SetFont(wxGetApp().normal_font());
auto scrolled = new wxScrolledWindow(tab);
// Sizer in the scrolled area
auto* scrolled_sizer = new wxBoxSizer(wxVERTICAL);
scrolled->SetSizer(scrolled_sizer);
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(scrolled, 1, wxEXPAND);
sizer->SetSizeHints(tab); sizer->SetSizeHints(tab);
tab->SetSizer(sizer); tab->SetSizer(sizer);
std::shared_ptr<ConfigOptionsGroup> optgroup = std::make_shared<ConfigOptionsGroup>(tab); std::shared_ptr<ConfigOptionsGroup> optgroup = std::make_shared<ConfigOptionsGroup>(scrolled);
optgroup->label_width = 40; optgroup->label_width = 40;
optgroup->set_config_category_and_type(title, int(Preset::TYPE_PREFERENCES)); optgroup->set_config_category_and_type(title, int(Preset::TYPE_PREFERENCES));
return optgroup; return optgroup;
@ -151,6 +173,8 @@ static void activate_options_tab(std::shared_ptr<ConfigOptionsGroup> optgroup)
wxBoxSizer* sizer = static_cast<wxBoxSizer*>(static_cast<wxPanel*>(optgroup->parent())->GetSizer()); wxBoxSizer* sizer = static_cast<wxBoxSizer*>(static_cast<wxPanel*>(optgroup->parent())->GetSizer());
sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10);
optgroup->parent()->Layout();
// apply sercher // apply sercher
wxGetApp().sidebar().get_searcher().append_preferences_options(optgroup->get_lines()); wxGetApp().sidebar().get_searcher().append_preferences_options(optgroup->get_lines());
} }
@ -212,7 +236,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 +247,12 @@ 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)); #ifdef __linux__
tabs->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [this](wxBookCtrlEvent& e) {
e.Skip();
CallAfter([this]() { tabs->GetCurrentPage()->Layout(); });
});
#endif
#endif #endif
// Add "General" tab // Add "General" tab
@ -526,7 +555,14 @@ void PreferencesDialog::build()
#endif #endif
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."),
@ -593,7 +629,7 @@ void PreferencesDialog::build()
activate_options_tab(m_optgroup_other); activate_options_tab(m_optgroup_other);
create_downloader_path_sizer(); create_downloader_path_sizer();
// create_settings_font_widget(); create_settings_font_widget();
#if ENABLE_ENVIRONMENT_MAP #if ENABLE_ENVIRONMENT_MAP
// Add "Render" tab // Add "Render" tab
@ -651,6 +687,8 @@ void PreferencesDialog::build()
sizer->Add(tabs, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5); sizer->Add(tabs, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5);
auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL); auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
wxGetApp().SetWindowVariantForButton(buttons->GetAffirmativeButton());
wxGetApp().SetWindowVariantForButton(buttons->GetCancelButton());
this->Bind(wxEVT_BUTTON, &PreferencesDialog::accept, this, wxID_OK); this->Bind(wxEVT_BUTTON, &PreferencesDialog::accept, this, wxID_OK);
this->Bind(wxEVT_BUTTON, &PreferencesDialog::revert, this, wxID_CANCEL); this->Bind(wxEVT_BUTTON, &PreferencesDialog::revert, this, wxID_CANCEL);
@ -706,7 +744,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_pt_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()) {
@ -887,7 +925,7 @@ void PreferencesDialog::refresh_og(std::shared_ptr<ConfigOptionsGroup> og)
{ {
og->parent()->Layout(); og->parent()->Layout();
tabs->Layout(); tabs->Layout();
this->layout(); // this->layout();
} }
void PreferencesDialog::create_icon_size_slider() void PreferencesDialog::create_icon_size_slider()
@ -1065,24 +1103,29 @@ void PreferencesDialog::create_settings_font_widget()
wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _(title)); wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _(title));
if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT);
const std::string opt_key = "font_size"; const std::string opt_key = "font_pt_size";
m_blinkers[opt_key] = new BlinkingBitmap(parent); m_blinkers[opt_key] = new BlinkingBitmap(parent);
wxSizer* stb_sizer = new wxStaticBoxSizer(stb, wxHORIZONTAL); wxSizer* stb_sizer = new wxStaticBoxSizer(stb, wxHORIZONTAL);
wxStaticText* font_example = new wxStaticText(parent, wxID_ANY, "Application text"); wxStaticText* font_example = new wxStaticText(parent, wxID_ANY, "Application text");
int val = wxGetApp().normal_font().GetPointSize(); int val = wxGetApp().normal_font().GetPointSize();
wxSpinCtrl* size_sc = new wxSpinCtrl(parent, wxID_ANY, format_wxstr("%1%", val), wxDefaultPosition, wxSize(15*em_unit(), -1), wxTE_PROCESS_ENTER | wxSP_ARROW_KEYS SpinInput* size_sc = new SpinInput(parent, format_wxstr("%1%", val), "", wxDefaultPosition, wxSize(15 * em_unit(), -1), wxTE_PROCESS_ENTER | wxSP_ARROW_KEYS
#ifdef _WIN32 #ifdef _WIN32
| wxBORDER_SIMPLE | wxBORDER_SIMPLE
#endif #endif
, 8, 20); , 8, wxGetApp().get_max_font_pt_size());
wxGetApp().UpdateDarkUI(size_sc); wxGetApp().UpdateDarkUI(size_sc);
auto apply_font = [this, font_example, opt_key](const int val, const wxFont& font) { auto apply_font = [this, font_example, opt_key, stb_sizer](const int val, const wxFont& font) {
font_example->SetFont(font); font_example->SetFont(font);
m_values[opt_key] = format("%1%", val); m_values[opt_key] = format("%1%", val);
stb_sizer->Layout();
#ifdef __linux__
CallAfter([this]() { refresh_og(m_optgroup_other); });
#else
refresh_og(m_optgroup_other); refresh_og(m_optgroup_other);
#endif
}; };
auto change_value = [size_sc, apply_font](wxCommandEvent& evt) { auto change_value = [size_sc, apply_font](wxCommandEvent& evt) {

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

@ -487,7 +487,11 @@ SearchDialog::SearchDialog(OptionsSearcher* searcher)
searcher(searcher) searcher(searcher)
{ {
SetFont(GUI::wxGetApp().normal_font()); SetFont(GUI::wxGetApp().normal_font());
#if _WIN32
GUI::wxGetApp().UpdateDarkUI(this); GUI::wxGetApp().UpdateDarkUI(this);
#elif __WXGTK__
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif
default_string = _L("Enter a search term"); default_string = _L("Enter a search term");
int border = 10; int border = 10;
@ -525,9 +529,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

@ -122,13 +122,13 @@ SysInfoDialog::SysInfoDialog()
wxStaticText* title = new wxStaticText(this, wxID_ANY, wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME, wxDefaultPosition, wxDefaultSize); wxStaticText* title = new wxStaticText(this, wxID_ANY, wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME, wxDefaultPosition, wxDefaultSize);
wxFont title_font = wxGetApp().bold_font(); wxFont title_font = wxGetApp().bold_font();
title_font.SetFamily(wxFONTFAMILY_ROMAN); title_font.SetFamily(wxFONTFAMILY_ROMAN);
title_font.SetPointSize(22); title_font.SetPointSize(int(2.5 * title_font.GetPointSize()));//title_font.SetPointSize(22);
title->SetFont(title_font); title->SetFont(title_font);
vsizer->Add(title, 0, wxEXPAND | wxALIGN_LEFT | wxTOP, wxGetApp().em_unit()/*50*/); vsizer->Add(title, 0, wxEXPAND | wxALIGN_LEFT | wxTOP, wxGetApp().em_unit()/*50*/);
} }
// main_info_text // main_info_text
wxFont font = get_default_font(this); wxFont font = GetFont();// get_default_font(this);
const auto text_clr = wxGetApp().get_label_clr_default(); const auto text_clr = wxGetApp().get_label_clr_default();
auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue())); auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue()));
auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue())); auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()));
@ -182,7 +182,9 @@ SysInfoDialog::SysInfoDialog()
} }
wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK); wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK);
wxGetApp().SetWindowVariantForButton(buttons->GetAffirmativeButton());
m_btn_copy_to_clipboard = new wxButton(this, wxID_ANY, _L("Copy to Clipboard"), wxDefaultPosition, wxDefaultSize); m_btn_copy_to_clipboard = new wxButton(this, wxID_ANY, _L("Copy to Clipboard"), wxDefaultPosition, wxDefaultSize);
wxGetApp().SetWindowVariantForButton(m_btn_copy_to_clipboard);
buttons->Insert(0, m_btn_copy_to_clipboard, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5); buttons->Insert(0, m_btn_copy_to_clipboard, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5);
m_btn_copy_to_clipboard->Bind(wxEVT_BUTTON, &SysInfoDialog::onCopyToClipboard, this); m_btn_copy_to_clipboard->Bind(wxEVT_BUTTON, &SysInfoDialog::onCopyToClipboard, this);

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);
#elif __WXOSX__
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);
@ -292,6 +296,9 @@ void Tab::create_preset_tab()
m_treectrl = new wxTreeCtrl(panel, wxID_ANY, wxDefaultPosition, wxSize(20 * m_em_unit, -1), m_treectrl = new wxTreeCtrl(panel, wxID_ANY, wxDefaultPosition, wxSize(20 * m_em_unit, -1),
wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES | wxBORDER_SUNKEN | wxWANTS_CHARS); wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES | wxBORDER_SUNKEN | wxWANTS_CHARS);
m_treectrl->SetFont(wxGetApp().normal_font()); m_treectrl->SetFont(wxGetApp().normal_font());
#ifdef __linux__
m_treectrl->SetBackgroundColour(m_parent->GetBackgroundColour());
#endif
m_left_sizer->Add(m_treectrl, 1, wxEXPAND); m_left_sizer->Add(m_treectrl, 1, wxEXPAND);
// Index of the last icon inserted into m_treectrl // Index of the last icon inserted into m_treectrl
m_icon_count = -1; m_icon_count = -1;
@ -422,10 +429,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 +964,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,8 +1947,10 @@ 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) { line.near_label_widget = [this, optgroup_wk = ConfigOptionsGroupWkp(optgroup), opt_key, opt_index](wxWindow* parent) {
wxCheckBox* check_box = new wxCheckBox(parent, wxID_ANY, ""); wxWindow* check_box = CheckBox::GetNewWin(parent);
wxGetApp().UpdateDarkUI(check_box);
check_box->Bind(wxEVT_CHECKBOX, [optgroup_wk, opt_key, opt_index](wxCommandEvent& evt) { check_box->Bind(wxEVT_CHECKBOX, [optgroup_wk, opt_key, opt_index](wxCommandEvent& evt) {
const bool is_checked = evt.IsChecked(); const bool is_checked = evt.IsChecked();
@ -1953,7 +1963,7 @@ void TabFilament::create_line_with_near_label_widget(ConfigOptionsGroupShp optgr
field->set_na_value(); 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 +1979,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 +2048,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"; });
@ -2229,6 +2249,7 @@ void TabFilament::build()
create_line_with_widget(optgroup.get(), "filament_ramming_parameters", "", [this](wxWindow* parent) { create_line_with_widget(optgroup.get(), "filament_ramming_parameters", "", [this](wxWindow* parent) {
auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
wxGetApp().SetWindowVariantForButton(ramming_dialog_btn);
wxGetApp().UpdateDarkUI(ramming_dialog_btn); wxGetApp().UpdateDarkUI(ramming_dialog_btn);
ramming_dialog_btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); ramming_dialog_btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
ramming_dialog_btn->SetSize(ramming_dialog_btn->GetBestSize()); ramming_dialog_btn->SetSize(ramming_dialog_btn->GetBestSize());
@ -2399,6 +2420,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 +2430,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,7 +2439,15 @@ 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()
{ {
@ -3685,6 +3716,7 @@ void Tab::rebuild_page_tree()
continue; continue;
auto itemId = m_treectrl->AppendItem(rootItem, translate_category(p->title(), m_type), p->iconID()); auto itemId = m_treectrl->AppendItem(rootItem, translate_category(p->title(), m_type), p->iconID());
m_treectrl->SetItemTextColour(itemId, p->get_item_colour()); m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
m_treectrl->SetItemFont(itemId, wxGetApp().normal_font());
if (translate_category(p->title(), m_type) == selected) if (translate_category(p->title(), m_type) == selected)
item = itemId; item = itemId;
} }
@ -4463,9 +4495,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 +4509,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 +4557,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 +4679,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 +4708,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 +5007,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 {
@ -71,7 +73,7 @@ class SubstitutionManager
std::function<void()> m_cb_hide_delete_all_btn{ nullptr }; std::function<void()> m_cb_hide_delete_all_btn{ nullptr };
std::vector<std::string> m_substitutions; std::vector<std::string> m_substitutions;
std::vector<wxCheckBox*> m_chb_match_single_lines; std::vector<wxWindow*> m_chb_match_single_lines;
void validate_length(); void validate_length();
bool is_compatible_with_ui(); bool is_compatible_with_ui();
@ -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

@ -839,13 +839,7 @@ UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, PresetCollection*
void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header) void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header)
{ {
#if defined(__WXMSW__)
// ys_FIXME! temporary workaround for correct font scaling
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
// this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
this->SetFont(wxGetApp().normal_font()); this->SetFont(wxGetApp().normal_font());
#endif // __WXMSW__
int border = 10; int border = 10;
int em = em_unit(); int em = em_unit();
@ -1338,7 +1332,7 @@ void UnsavedChangesDialog::on_dpi_changed(const wxRect& suggested_rect)
{ {
int em = em_unit(); int em = em_unit();
msw_buttons_rescale(this, em, { wxID_CANCEL, m_save_btn_id, m_move_btn_id, m_continue_btn_id }); msw_buttons_rescale(this, em, { wxID_CANCEL, m_save_btn_id, m_move_btn_id, m_continue_btn_id }, 1.5);
const wxSize& size = wxSize(70 * em, 30 * em); const wxSize& size = wxSize(70 * em, 30 * em);
SetMinSize(size); SetMinSize(size);
@ -1485,6 +1479,7 @@ void DiffPresetDialog::create_presets_sizer()
auto add_preset_combobox = [collection, sizer, new_type, this](PresetComboBox** cb_, PresetBundle* preset_bundle) { auto add_preset_combobox = [collection, sizer, new_type, this](PresetComboBox** cb_, PresetBundle* preset_bundle) {
*cb_ = new PresetComboBox(this, new_type, wxSize(em_unit() * 35, -1), preset_bundle); *cb_ = new PresetComboBox(this, new_type, wxSize(em_unit() * 35, -1), preset_bundle);
PresetComboBox*cb = (*cb_); PresetComboBox*cb = (*cb_);
cb->SetFont(this->GetFont());
cb->show_modif_preset_separately(); cb->show_modif_preset_separately();
cb->set_selection_changed_function([this, new_type, preset_bundle, cb](int selection) { cb->set_selection_changed_function([this, new_type, preset_bundle, cb](int selection) {
std::string preset_name = Preset::remove_suffix_modified(cb->GetString(selection).ToUTF8().data()); std::string preset_name = Preset::remove_suffix_modified(cb->GetString(selection).ToUTF8().data());
@ -1549,6 +1544,7 @@ void DiffPresetDialog::create_info_lines()
void DiffPresetDialog::create_tree() void DiffPresetDialog::create_tree()
{ {
m_tree = new DiffViewCtrl(this, wxSize(em_unit() * 65, em_unit() * 40)); m_tree = new DiffViewCtrl(this, wxSize(em_unit() * 65, em_unit() * 40));
m_tree->SetFont(this->GetFont());
m_tree->AppendToggleColumn_(L"\u2714", DiffModel::colToggle, wxLinux ? 9 : 6); m_tree->AppendToggleColumn_(L"\u2714", DiffModel::colToggle, wxLinux ? 9 : 6);
m_tree->AppendBmpTextColumn("", DiffModel::colIconText, 35); m_tree->AppendBmpTextColumn("", DiffModel::colIconText, 35);
m_tree->AppendBmpTextColumn(_L("Left Preset Value"), DiffModel::colOldValue, 15); m_tree->AppendBmpTextColumn(_L("Left Preset Value"), DiffModel::colOldValue, 15);
@ -1670,17 +1666,9 @@ void DiffPresetDialog::complete_dialog_creation()
} }
DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe) DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe)
: DPIDialog(mainframe, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), : DPIDialog(mainframe, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER, "diff_presets_dialog", mainframe->normal_font().GetPointSize()),
m_pr_technology(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology()) m_pr_technology(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology())
{ {
#if defined(__WXMSW__)
// ys_FIXME! temporary workaround for correct font scaling
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
// this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
this->SetFont(mainframe->normal_font());
#endif // __WXMSW__
// Init bundles // Init bundles
assert(wxGetApp().preset_bundle); assert(wxGetApp().preset_bundle);

View File

@ -0,0 +1,46 @@
#include "BitmapToggleButton.hpp"
#include <wx/settings.h>
BitmapToggleButton::BitmapToggleButton(wxWindow* parent, const wxString& label, wxWindowID id)
{
if (label.IsEmpty())
wxBitmapToggleButton::Create(parent, id, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE | wxBU_EXACTFIT);
else {
#ifdef __linux__
wxSize label_size = parent->GetTextExtent(label);
wxSize def_size = wxSize(label_size.GetX() + 20, label_size.GetY());
#else
wxSize def_size = wxDefaultSize;
#endif
// Call Create() from wxToggleButton instead of wxBitmapToggleButton to allow add Label text under Linux
wxToggleButton::Create(parent, id, label, wxDefaultPosition, def_size, wxBORDER_NONE | wxBU_EXACTFIT);
}
#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()
{
#ifndef __WXGTK__
wxSize best_sz = GetBestSize();
SetSize(best_sz);
#endif
}

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

@ -0,0 +1,300 @@
#include "Button.hpp"
#include <wx/dcgraph.h>
#include <wx/dc.h>
#include <wx/dcclient.h>
BEGIN_EVENT_TABLE(Button, StaticBox)
EVT_LEFT_DOWN(Button::mouseDown)
EVT_LEFT_UP(Button::mouseReleased)
EVT_MOUSE_CAPTURE_LOST(Button::mouseCaptureLost)
EVT_KEY_DOWN(Button::keyDownUp)
EVT_KEY_UP(Button::keyDownUp)
// catch paint events
EVT_PAINT(Button::paintEvent)
END_EVENT_TABLE()
/*
* Called by the system of by wxWidgets when the panel needs
* to be redrawn. You can also trigger this call by
* calling Refresh()/Update().
*/
Button::Button()
: paddingSize(10, 8)
{
background_color = StateColor(
std::make_pair(0xF0F0F0, (int) StateColor::Disabled),
std::make_pair(0x37EE7C, (int) StateColor::Hovered | StateColor::Checked),
std::make_pair(0x00AE42, (int) StateColor::Checked),
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Hovered),
std::make_pair(*wxWHITE, (int) StateColor::Normal));
text_color = StateColor(
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Disabled),
std::make_pair(*wxBLACK, (int) StateColor::Normal));
}
Button::Button(wxWindow* parent, wxString text, wxString icon, long style, wxSize iconSize/* = wxSize(16, 16)*/)
: Button()
{
Create(parent, text, icon, style, iconSize);
}
bool Button::Create(wxWindow* parent, wxString text, wxString icon, long style, wxSize iconSize/* = wxSize(16, 16)*/)
{
StaticBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style);
state_handler.attach({&text_color});
state_handler.update_binds();
wxWindow::SetLabel(text);
if (!icon.IsEmpty()) {
this->active_icon = ScalableBitmap(this, icon.ToStdString(), iconSize);
}
messureSize();
return true;
}
void Button::SetLabel(const wxString& label)
{
wxWindow::SetLabel(label);
messureSize();
Refresh();
}
void Button::SetIcon(const wxString& icon)
{
if (!icon.IsEmpty()) {
this->active_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_size());
}
else
{
this->active_icon = ScalableBitmap();
}
Refresh();
}
void Button::SetInactiveIcon(const wxString &icon)
{
if (!icon.IsEmpty()) {
this->inactive_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_size());
} else {
this->inactive_icon = ScalableBitmap();
}
Refresh();
}
void Button::SetMinSize(const wxSize& size)
{
minSize = size;
messureSize();
}
void Button::SetPaddingSize(const wxSize& size)
{
paddingSize = size;
messureSize();
}
void Button::SetTextColor(StateColor const& color)
{
text_color = color;
state_handler.update_binds();
Refresh();
}
void Button::SetTextColorNormal(wxColor const &color)
{
text_color.setColorForStates(color, 0);
Refresh();
}
bool Button::Enable(bool enable)
{
bool result = wxWindow::Enable(enable);
if (result) {
wxCommandEvent e(EVT_ENABLE_CHANGED);
e.SetEventObject(this);
GetEventHandler()->ProcessEvent(e);
}
return result;
}
void Button::SetCanFocus(bool canFocus) { this->canFocus = canFocus; }
void Button::Rescale()
{
/* if (this->active_icon.bmp().IsOk())
this->active_icon.msw_rescale();
if (this->inactive_icon.bmp().IsOk())
this->inactive_icon.msw_rescale();
*/
messureSize();
}
void Button::paintEvent(wxPaintEvent& evt)
{
// depending on your system you may need to look at double-buffered dcs
wxPaintDC dc(this);
render(dc);
}
/*
* Here we do the actual rendering. I put it in a separate
* method so that it can work no matter what type of DC
* (e.g. wxPaintDC or wxClientDC) is used.
*/
void Button::render(wxDC& dc)
{
StaticBox::render(dc);
int states = state_handler.states();
wxSize size = GetSize();
dc.SetBrush(*wxTRANSPARENT_BRUSH);
// calc content size
wxSize szIcon;
wxSize szContent = textSize;
ScalableBitmap icon;
if (m_selected || ((states & (int)StateColor::State::Hovered) != 0))
// if (m_selected || (states & (int)StateColor::State::Hovered))
icon = active_icon;
else
icon = inactive_icon;
int padding = 5;
if (icon.bmp().IsOk()) {
if (szContent.y > 0) {
//BBS norrow size between text and icon
szContent.x += padding;
}
szIcon = icon.GetSize();
szContent.x += szIcon.x;
if (szIcon.y > szContent.y)
szContent.y = szIcon.y;
if (szContent.x > size.x) {
int d = std::min(padding, szContent.x - size.x);
padding -= d;
szContent.x -= d;
}
}
// move to center
wxRect rcContent = { {0, 0}, size };
wxSize offset = (size - szContent) / 2;
if (offset.x < 0) offset.x = 0;
rcContent.Deflate(offset.x, offset.y);
// start draw
wxPoint pt = rcContent.GetLeftTop();
if (icon.bmp().IsOk()) {
pt.y += (rcContent.height - szIcon.y) / 2;
dc.DrawBitmap(icon.get_bitmap(), pt);
//BBS norrow size between text and icon
pt.x += szIcon.x + padding;
pt.y = rcContent.y;
}
auto text = GetLabel();
if (!text.IsEmpty()) {
if (pt.x + textSize.x > size.x)
text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, size.x - pt.x);
pt.y += (rcContent.height - textSize.y) / 2;
dc.SetFont(GetFont());
dc.SetTextForeground(text_color.colorForStates(states));
dc.DrawText(text, pt);
}
}
void Button::messureSize()
{
wxClientDC dc(this);
textSize = dc.GetTextExtent(GetLabel());
if (minSize.GetWidth() > 0) {
wxWindow::SetMinSize(minSize);
return;
}
wxSize szContent = textSize;
if (this->active_icon.bmp().IsOk()) {
if (szContent.y > 0) {
//BBS norrow size between text and icon
szContent.x += 5;
}
wxSize szIcon = this->active_icon.GetSize();
szContent.x += szIcon.x;
if (szIcon.y > szContent.y)
szContent.y = szIcon.y;
}
wxSize size = szContent + paddingSize * 2;
if (minSize.GetHeight() > 0)
size.SetHeight(minSize.GetHeight());
wxWindow::SetMinSize(size);
}
void Button::mouseDown(wxMouseEvent& event)
{
event.Skip();
pressedDown = true;
if (canFocus)
SetFocus();
CaptureMouse();
}
void Button::mouseReleased(wxMouseEvent& event)
{
event.Skip();
if (pressedDown) {
pressedDown = false;
if (HasCapture())
ReleaseMouse();
if (wxRect({0, 0}, GetSize()).Contains(event.GetPosition()))
sendButtonEvent();
}
}
void Button::mouseCaptureLost(wxMouseCaptureLostEvent &event)
{
wxMouseEvent evt;
mouseReleased(evt);
}
void Button::keyDownUp(wxKeyEvent &event)
{
if (event.GetKeyCode() == WXK_SPACE || event.GetKeyCode() == WXK_RETURN) {
wxMouseEvent evt(event.GetEventType() == wxEVT_KEY_UP ? wxEVT_LEFT_UP : wxEVT_LEFT_DOWN);
event.SetEventObject(this);
GetEventHandler()->ProcessEvent(evt);
return;
}
if (event.GetEventType() == wxEVT_KEY_DOWN &&
(event.GetKeyCode() == WXK_TAB || event.GetKeyCode() == WXK_LEFT || event.GetKeyCode() == WXK_RIGHT
|| event.GetKeyCode() == WXK_UP || event.GetKeyCode() == WXK_DOWN))
HandleAsNavigationKey(event);
else
event.Skip();
}
void Button::sendButtonEvent()
{
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
event.SetEventObject(this);
GetEventHandler()->ProcessEvent(event);
}
#ifdef __WIN32__
WXLRESULT Button::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
if (nMsg == WM_GETDLGCODE) { return DLGC_WANTMESSAGE; }
if (nMsg == WM_KEYDOWN) {
wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, wParam, lParam));
switch (wParam) {
case WXK_RETURN: { // WXK_RETURN key is handled by default button
GetEventHandler()->ProcessEvent(event);
return 0;
}
}
}
return wxWindow::MSWWindowProc(nMsg, wParam, lParam);
}
#endif
bool Button::AcceptsFocus() const { return canFocus; }

View File

@ -0,0 +1,78 @@
#ifndef slic3r_GUI_Button_hpp_
#define slic3r_GUI_Button_hpp_
#include "../wxExtensions.hpp"
#include "StaticBox.hpp"
class Button : public StaticBox
{
wxSize textSize;
wxSize minSize; // set by outer
wxSize paddingSize;
ScalableBitmap active_icon;
ScalableBitmap inactive_icon;
StateColor text_color;
bool pressedDown = false;
bool m_selected = true;
bool canFocus = true;
static const int buttonWidth = 200;
static const int buttonHeight = 50;
public:
Button();
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, wxSize iconSize = wxSize(16, 16));
void SetLabel(const wxString& label) override;
void SetIcon(const wxString& icon);
void SetInactiveIcon(const wxString& icon);
void SetMinSize(const wxSize& size) override;
void SetPaddingSize(const wxSize& size);
void SetTextColor(StateColor const &color);
void SetTextColorNormal(wxColor const &color);
void SetSelected(bool selected = true) { m_selected = selected; }
bool Enable(bool enable = true) override;
void SetCanFocus(bool canFocus) override;
void Rescale();
protected:
#ifdef __WIN32__
WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) override;
#endif
bool AcceptsFocus() const override;
private:
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
void messureSize();
// some useful events
void mouseDown(wxMouseEvent& event);
void mouseReleased(wxMouseEvent& event);
void mouseCaptureLost(wxMouseCaptureLostEvent &event);
void keyDownUp(wxKeyEvent &event);
void sendButtonEvent();
DECLARE_EVENT_TABLE()
};
#endif // !slic3r_GUI_Button_hpp_

View File

@ -0,0 +1,117 @@
#include "CheckBox.hpp"
//#include "../wxExtensions.hpp"
const int px_cnt = 16;
CheckBox::CheckBox(wxWindow* parent, const wxString& name)
: BitmapToggleButton(parent, name, wxID_ANY)
, m_on(this, "check_on", px_cnt)
, m_off(this, "check_off", px_cnt)
, m_on_disabled(this, "check_on_disabled", px_cnt)
, m_off_disabled(this, "check_off_disabled", px_cnt)
, m_on_focused(this, "check_on_focused", px_cnt)
, m_off_focused(this, "check_off_focused", px_cnt)
{
#ifdef __WXOSX__ // State not fully implement on MacOS
Bind(wxEVT_SET_FOCUS, &CheckBox::updateBitmap, this);
Bind(wxEVT_KILL_FOCUS, &CheckBox::updateBitmap, this);
Bind(wxEVT_ENTER_WINDOW, &CheckBox::updateBitmap, this);
Bind(wxEVT_LEAVE_WINDOW, &CheckBox::updateBitmap, this);
#endif
update();
}
void CheckBox::SetValue(bool value)
{
wxBitmapToggleButton::SetValue(value);
update();
}
void CheckBox::Update()
{
update();
}
void CheckBox::Rescale()
{
update();
}
void CheckBox::update()
{
const bool val = GetValue();
const wxBitmapBundle& bmp = (val ? m_on : m_off).bmp();
SetBitmap(bmp);
SetBitmapCurrent(bmp);
SetBitmapDisabled((val ? m_on_disabled : m_off_disabled).bmp());
#ifdef __WXMSW__
SetBitmapFocus((val ? m_on_focused : m_off_focused).bmp());
#endif
#ifdef __WXOSX__
wxCommandEvent e(wxEVT_UPDATE_UI);
updateBitmap(e);
#endif
update_size();
}
#ifdef __WXMSW__
CheckBox::State CheckBox::GetNormalState() const
{
return State_Normal;
}
#endif
bool CheckBox::Enable(bool enable)
{
bool result = wxBitmapToggleButton::Enable(enable);
#ifdef __WXOSX__
if (result) {
m_disable = !enable;
wxCommandEvent e(wxEVT_ACTIVATE);
updateBitmap(e);
}
#endif
return result;
}
#ifdef __WXOSX__
wxBitmap CheckBox::DoGetBitmap(State which) const
{
if (m_disable) {
return wxBitmapToggleButton::DoGetBitmap(State_Disabled);
}
if (m_focus) {
return wxBitmapToggleButton::DoGetBitmap(State_Current);
}
return wxBitmapToggleButton::DoGetBitmap(which);
}
void CheckBox::updateBitmap(wxEvent & evt)
{
evt.Skip();
if (evt.GetEventType() == wxEVT_ENTER_WINDOW) {
m_hover = true;
} else if (evt.GetEventType() == wxEVT_LEAVE_WINDOW) {
m_hover = false;
} else {
if (evt.GetEventType() == wxEVT_SET_FOCUS) {
m_focus = true;
} else if (evt.GetEventType() == wxEVT_KILL_FOCUS) {
m_focus = false;
}
wxMouseEvent e;
if (m_hover)
OnEnterWindow(e);
else
OnLeaveWindow(e);
}
}
#endif

View File

@ -0,0 +1,45 @@
#ifndef slic3r_GUI_CheckBox_hpp_
#define slic3r_GUI_CheckBox_hpp_
#include "../wxExtensions.hpp"
#include "BitmapToggleButton.hpp"
class CheckBox : public BitmapToggleButton
{
public:
CheckBox(wxWindow* parent = NULL, const wxString& name = wxEmptyString);
public:
void SetValue(bool value) override;
void Update() override;
bool Enable(bool enable = true) override;
void Rescale();
protected:
#ifdef __WXMSW__
virtual State GetNormalState() const wxOVERRIDE;
#endif
#ifdef __WXOSX__
virtual wxBitmap DoGetBitmap(State which) const wxOVERRIDE;
void updateBitmap(wxEvent & evt);
bool m_disable = false;
bool m_hover = false;
bool m_focus = false;
#endif
private:
void update() override;
ScalableBitmap m_on;
ScalableBitmap m_off;
ScalableBitmap m_on_disabled;
ScalableBitmap m_off_disabled;
ScalableBitmap m_on_focused;
ScalableBitmap m_off_focused;
};
#endif // !slic3r_GUI_CheckBox_hpp_

View File

@ -0,0 +1,354 @@
#include "ComboBox.hpp"
#include "UIColors.hpp"
#include <wx/dcgraph.h>
#include "../GUI_App.hpp"
BEGIN_EVENT_TABLE(ComboBox, TextInput)
EVT_LEFT_DOWN(ComboBox::mouseDown)
//EVT_MOUSEWHEEL(ComboBox::mouseWheelMoved)
EVT_KEY_DOWN(ComboBox::keyDown)
// catch paint events
END_EVENT_TABLE()
/*
* Called by the system of by wxWidgets when the panel needs
* to be redrawn. You can also trigger this call by
* calling Refresh()/Update().
*/
ComboBox::ComboBox(wxWindow * parent,
wxWindowID id,
const wxString &value,
const wxPoint & pos,
const wxSize & size,
int n,
const wxString choices[],
long style)
: drop(texts, icons)
{
text_off = style & CB_NO_TEXT;
TextInput::Create(parent, "", value, (style & CB_NO_DROP_ICON) ? "" : "drop_down", pos, size,
style | wxTE_PROCESS_ENTER);
drop.Create(this, style);
SetFont(Slic3r::GUI::wxGetApp().normal_font());
if (style & wxCB_READONLY)
GetTextCtrl()->Hide();
else
GetTextCtrl()->Bind(wxEVT_KEY_DOWN, &ComboBox::keyDown, this);
SetBorderColor(TextInput::GetBorderColor());
if (parent) {
SetBackgroundColour(parent->GetBackgroundColour());
SetForegroundColour(parent->GetForegroundColour());
}
drop.Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &e) {
SetSelection(e.GetInt());
e.SetEventObject(this);
e.SetId(GetId());
GetEventHandler()->ProcessEvent(e);
});
drop.Bind(EVT_DISMISS, [this](auto &) {
drop_down = false;
wxCommandEvent e(wxEVT_COMBOBOX_CLOSEUP);
GetEventHandler()->ProcessEvent(e);
});
for (int i = 0; i < n; ++i) Append(choices[i]);
}
int ComboBox::GetSelection() const { return drop.GetSelection(); }
void ComboBox::SetSelection(int n)
{
drop.SetSelection(n);
SetLabel(drop.GetValue());
if (drop.selection >= 0)
SetIcon(icons[drop.selection]);
}
void ComboBox::Rescale()
{
SetFont(Slic3r::GUI::wxGetApp().normal_font());
TextInput::Rescale();
drop.Rescale();
}
wxString ComboBox::GetValue() const
{
return drop.GetSelection() >= 0 ? drop.GetValue() : GetLabel();
}
void ComboBox::SetValue(const wxString &value)
{
drop.SetValue(value);
SetLabel(value);
if (drop.selection >= 0)
SetIcon(icons[drop.selection]);
}
void ComboBox::SetLabel(const wxString &value)
{
if (GetTextCtrl()->IsShown() || text_off)
GetTextCtrl()->SetValue(value);
else
TextInput::SetLabel(value);
}
wxString ComboBox::GetLabel() const
{
if (GetTextCtrl()->IsShown() || text_off)
return GetTextCtrl()->GetValue();
else
return TextInput::GetLabel();
}
void ComboBox::SetTextLabel(const wxString& label)
{
TextInput::SetLabel(label);
}
wxString ComboBox::GetTextLabel() const
{
return TextInput::GetLabel();
}
bool ComboBox::SetFont(wxFont const& font)
{
const bool set_drop_font = drop.SetFont(font);
if (GetTextCtrl() && GetTextCtrl()->IsShown())
return GetTextCtrl()->SetFont(font) && set_drop_font;
return TextInput::SetFont(font) && set_drop_font;
}
bool ComboBox::SetBackgroundColour(const wxColour& colour)
{
TextInput::SetBackgroundColour(colour);
drop.SetBackgroundColour(colour);
drop.SetSelectorBackgroundColor(background_color);
return true;
}
bool ComboBox::SetForegroundColour(const wxColour& colour)
{
TextInput::SetForegroundColour(colour);
drop.SetTextColor(TextInput::GetTextColor());
return true;
}
void ComboBox::SetBorderColor(StateColor const& color)
{
TextInput::SetBorderColor(color);
drop.SetBorderColor(color);
drop.SetSelectorBorderColor(color);
}
int ComboBox::Append(const wxString &item, const wxBitmapBundle &bitmap)
{
return Append(item, bitmap, nullptr);
}
int ComboBox::Append(const wxString &item,
const wxBitmapBundle &bitmap,
void * clientData)
{
texts.push_back(item);
icons.push_back(bitmap);
datas.push_back(clientData);
types.push_back(wxClientData_None);
drop.Invalidate();
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()
{
texts.clear();
icons.clear();
datas.clear();
types.clear();
drop.Invalidate(true);
}
void ComboBox::DoDeleteOneItem(unsigned int pos)
{
if (pos >= texts.size()) return;
texts.erase(texts.begin() + pos);
icons.erase(icons.begin() + pos);
datas.erase(datas.begin() + pos);
types.erase(types.begin() + pos);
drop.Invalidate(true);
}
unsigned int ComboBox::GetCount() const { return texts.size(); }
wxString ComboBox::GetString(unsigned int n) const
{
return n < texts.size() ? texts[n] : wxString{};
}
void ComboBox::SetString(unsigned int n, wxString const &value)
{
if (n >= texts.size()) return;
texts[n] = value;
drop.Invalidate();
if (int(n) == drop.GetSelection()) SetLabel(value);
}
wxBitmap ComboBox::GetItemBitmap(unsigned int n)
{
return icons[n].GetBitmapFor(m_parent);
}
int ComboBox::DoInsertItems(const wxArrayStringsAdapter &items,
unsigned int pos,
void ** clientData,
wxClientDataType type)
{
if (pos > texts.size()) return -1;
for (size_t i = 0; i < items.GetCount(); ++i) {
texts.insert(texts.begin() + pos, items[i]);
icons.insert(icons.begin() + pos, wxNullBitmap);
datas.insert(datas.begin() + pos, clientData ? clientData[i] : NULL);
types.insert(types.begin() + pos, type);
++pos;
}
drop.Invalidate(true);
return int(pos) - 1;
}
void *ComboBox::DoGetItemClientData(unsigned int n) const { return n < texts.size() ? datas[n] : NULL; }
void ComboBox::DoSetItemClientData(unsigned int n, void *data)
{
if (n < texts.size())
datas[n] = data;
}
void ComboBox::mouseDown(wxMouseEvent &event)
{
SetFocus();
if (drop_down) {
drop.Hide();
} else if (drop.HasDismissLongTime()) {
drop.autoPosition();
drop_down = true;
drop.Popup();
wxCommandEvent e(wxEVT_COMBOBOX_DROPDOWN);
GetEventHandler()->ProcessEvent(e);
}
}
void ComboBox::mouseWheelMoved(wxMouseEvent &event)
{
event.Skip();
if (drop_down) return;
auto delta = (event.GetWheelRotation() < 0 == event.IsWheelInverted()) ? -1 : 1;
unsigned int n = GetSelection() + delta;
if (n < GetCount()) {
SetSelection((int) n);
sendComboBoxEvent();
}
}
void ComboBox::keyDown(wxKeyEvent& event)
{
int key_code = event.GetKeyCode();
switch (key_code) {
#ifndef __WXOSX__
case WXK_RETURN:
#endif
case WXK_SPACE:
if (drop_down) {
drop.DismissAndNotify();
} else if (drop.HasDismissLongTime()) {
drop.autoPosition();
drop_down = true;
drop.Popup();
wxCommandEvent e(wxEVT_COMBOBOX_DROPDOWN);
GetEventHandler()->ProcessEvent(e);
}
break;
case WXK_UP:
case WXK_DOWN:
case WXK_LEFT:
case WXK_RIGHT:
if ((event.GetKeyCode() == WXK_UP || event.GetKeyCode() == WXK_LEFT) && GetSelection() > 0) {
SetSelection(GetSelection() - 1);
} else if ((event.GetKeyCode() == WXK_DOWN || event.GetKeyCode() == WXK_RIGHT) && GetSelection() + 1 < int(texts.size())) {
SetSelection(GetSelection() + 1);
} else {
break;
}
{
wxCommandEvent e(wxEVT_COMBOBOX);
e.SetEventObject(this);
e.SetId(GetId());
e.SetInt(GetSelection());
GetEventHandler()->ProcessEvent(e);
}
break;
case WXK_TAB:
HandleAsNavigationKey(event);
break;
default:
event.Skip();
break;
}
}
void ComboBox::OnEdit()
{
auto value = GetTextCtrl()->GetValue();
SetValue(value);
}
#ifdef __WIN32__
WXLRESULT ComboBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
if (nMsg == WM_GETDLGCODE) {
return DLGC_WANTALLKEYS;
}
return TextInput::MSWWindowProc(nMsg, wParam, lParam);
}
#endif
void ComboBox::sendComboBoxEvent()
{
wxCommandEvent event(wxEVT_COMBOBOX, GetId());
event.SetEventObject(this);
event.SetInt(drop.GetSelection());
event.SetString(drop.GetValue());
GetEventHandler()->ProcessEvent(event);
}

View File

@ -0,0 +1,100 @@
#ifndef slic3r_GUI_ComboBox_hpp_
#define slic3r_GUI_ComboBox_hpp_
#include "TextInput.hpp"
#include "DropDown.hpp"
#define CB_NO_DROP_ICON DD_NO_DROP_ICON
#define CB_NO_TEXT DD_NO_TEXT
class ComboBox : public wxWindowWithItems<TextInput, wxItemContainer>
{
std::vector<wxString> texts;
std::vector<wxBitmapBundle> icons;
std::vector<void *> datas;
std::vector<wxClientDataType> types;
DropDown drop;
bool drop_down = false;
bool text_off = false;
public:
ComboBox(wxWindow * parent,
wxWindowID id,
const wxString &value = wxEmptyString,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
int n = 0,
const wxString choices[] = NULL,
long style = 0);
DropDown & GetDropDown() { return drop; }
virtual bool SetFont(wxFont const & font) override;
bool SetBackgroundColour(const wxColour& colour) override;
bool SetForegroundColour(const wxColour& colour) override;
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;
int GetSelection() const override;
void SetSelection(int n) override;
virtual void Rescale() override;
wxString GetValue() const;
void SetValue(const wxString &value);
void SetLabel(const wxString &label) override;
wxString GetLabel() const override;
void SetTextLabel(const wxString &label);
wxString GetTextLabel() const;
wxString GetString(unsigned int n) const override;
void SetString(unsigned int n, wxString const &value) override;
wxBitmap GetItemBitmap(unsigned int n);
protected:
virtual int DoInsertItems(const wxArrayStringsAdapter &items,
unsigned int pos,
void ** clientData,
wxClientDataType type) override;
virtual void DoClear() override;
void DoDeleteOneItem(unsigned int pos) override;
void *DoGetItemClientData(unsigned int n) const override;
void DoSetItemClientData(unsigned int n, void *data) override;
void OnEdit() override;
#ifdef __WIN32__
WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) override;
#endif
private:
// some useful events
void mouseDown(wxMouseEvent &event);
void mouseWheelMoved(wxMouseEvent &event);
void keyDown(wxKeyEvent &event);
void sendComboBoxEvent();
DECLARE_EVENT_TABLE()
};
#endif // !slic3r_GUI_ComboBox_hpp_

View File

@ -0,0 +1,527 @@
#include "DropDown.hpp"
#include "../GUI_App.hpp"
#include "../OptionsGroup.hpp"
#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>
#ifdef __WXGTK__
#include <gtk/gtk.h>
#endif
wxDEFINE_EVENT(EVT_DISMISS, wxCommandEvent);
BEGIN_EVENT_TABLE(DropDown, wxPopupTransientWindow)
EVT_LEFT_DOWN(DropDown::mouseDown)
EVT_LEFT_UP(DropDown::mouseReleased)
EVT_MOUSE_CAPTURE_LOST(DropDown::mouseCaptureLost)
EVT_MOTION(DropDown::mouseMove)
EVT_MOUSEWHEEL(DropDown::mouseWheelMoved)
// catch paint events
EVT_PAINT(DropDown::paintEvent)
END_EVENT_TABLE()
/*
* Called by the system of by wxWidgets when the panel needs
* to be redrawn. You can also trigger this call by
* calling Refresh()/Update().
*/
DropDown::DropDown(std::vector<wxString> &texts,
std::vector<wxBitmapBundle> &icons)
: texts(texts)
, icons(icons)
, radius(Slic3r::GUI::wxGetApp().suppress_round_corners() ? 0 : 5)
, state_handler(this)
, text_color(0x363636)
, border_color(0xDBDBDB)
, selector_border_color(std::make_pair(0x00AE42, (int) StateColor::Hovered),
std::make_pair(*wxWHITE, (int) StateColor::Normal))
, selector_background_color(std::make_pair(0xEDFAF2, (int) StateColor::Checked),
std::make_pair(*wxWHITE, (int) StateColor::Normal))
{
}
DropDown::DropDown(wxWindow * parent,
std::vector<wxString> &texts,
std::vector<wxBitmapBundle> &icons,
long style)
: DropDown(texts, icons)
{
Create(parent, style);
}
void DropDown::Create(wxWindow * parent,
long style)
{
wxPopupTransientWindow::Create(parent);
if (!wxOSX) SetBackgroundStyle(wxBG_STYLE_PAINT);
state_handler.attach({&border_color, &text_color, &selector_border_color, &selector_background_color});
state_handler.update_binds();
if (!(style & DD_NO_CHECK_ICON))
check_bitmap = ScalableBitmap(this, "checked", 16);
text_off = style & DD_NO_TEXT;
SetFont(parent->GetFont());
#ifdef __WXOSX__
// wxPopupTransientWindow releases mouse on idle, which may cause various problems,
// such as losting mouse move, and dismissing soon on first LEFT_DOWN event.
Bind(wxEVT_IDLE, [] (wxIdleEvent & evt) {});
#endif
}
void DropDown::Invalidate(bool clear)
{
if (clear) {
selection = hover_item = -1;
offset = wxPoint();
}
assert(selection < (int) texts.size());
need_sync = true;
}
void DropDown::SetSelection(int n)
{
if (n >= (int) texts.size())
n = -1;
if (selection == n) return;
selection = n;
paintNow();
}
wxString DropDown::GetValue() const
{
return selection >= 0 ? texts[selection] : wxString();
}
void DropDown::SetValue(const wxString &value)
{
auto i = std::find(texts.begin(), texts.end(), value);
selection = i == texts.end() ? -1 : std::distance(texts.begin(), i);
}
void DropDown::SetCornerRadius(double radius_in)
{
radius = radius_in;
paintNow();
}
void DropDown::SetBorderColor(StateColor const &color)
{
border_color = color;
state_handler.update_binds();
paintNow();
}
void DropDown::SetSelectorBorderColor(StateColor const &color)
{
selector_border_color = color;
state_handler.update_binds();
paintNow();
}
void DropDown::SetTextColor(StateColor const &color)
{
text_color = color;
state_handler.update_binds();
paintNow();
}
void DropDown::SetSelectorBackgroundColor(StateColor const &color)
{
selector_background_color = color;
state_handler.update_binds();
paintNow();
}
void DropDown::SetUseContentWidth(bool use)
{
if (use_content_width == use)
return;
use_content_width = use;
need_sync = true;
messureSize();
}
void DropDown::SetAlignIcon(bool align) { align_icon = align; }
void DropDown::Rescale()
{
need_sync = true;
}
bool DropDown::HasDismissLongTime()
{
auto now = boost::posix_time::microsec_clock::universal_time();
return !IsShown() &&
(now - dismissTime).total_milliseconds() >= 200;
}
void DropDown::paintEvent(wxPaintEvent& evt)
{
// depending on your system you may need to look at double-buffered dcs
wxBufferedPaintDC dc(this);
render(dc);
}
/*
* Alternatively, you can use a clientDC to paint on the panel
* at any time. Using this generally does not free you from
* catching paint events, since it is possible that e.g. the window
* manager throws away your drawing when the window comes to the
* background, and expects you will redraw it when the window comes
* back (by sending a paint event).
*/
void DropDown::paintNow()
{
// depending on your system you may need to look at double-buffered dcs
//wxClientDC dc(this);
//render(dc);
Refresh();
}
void DropDown::SetTransparentBG(wxDC& dc, wxWindow* win)
{
const wxSize size = win->GetSize();
const wxPoint screen_pos = win->GetScreenPosition();
wxScreenDC screen_dc;
#ifdef __WXMSW__
// Draw screen_dc to dc for transparent background
dc.Blit(0, 0, size.x, size.y, &screen_dc, screen_pos.x, screen_pos.y);
#else
// See https://forums.wxwidgets.org/viewtopic.php?f=1&t=49318
wxClientDC client_dc(win);
client_dc.Blit(0, 0, size.x, size.y, &screen_dc, screen_pos.x, screen_pos.y);
wxBitmap bmp(size.x, size.y);
wxMemoryDC mem_dc(bmp);
mem_dc.Blit(0, 0, size.x, size.y, &client_dc, 0, 0);
mem_dc.SelectObject(wxNullBitmap);
dc.DrawBitmap(bmp, 0, 0);
#endif //__WXMSW__
}
/*
* Here we do the actual rendering. I put it in a separate
* method so that it can work no matter what type of DC
* (e.g. wxPaintDC or wxClientDC) is used.
*/
void DropDown::render(wxDC &dc)
{
if (texts.size() == 0) return;
int states = state_handler.states();
const wxSize size = GetSize();
if (radius > 0. && !wxOSX)
SetTransparentBG(dc, this);
dc.SetPen(wxPen(border_color.colorForStates(states)));
dc.SetBrush(wxBrush(GetBackgroundColour()));
// if (GetWindowStyle() & wxBORDER_NONE)
// dc.SetPen(wxNullPen);
wxRect rc(0, 0, size.x, size.y);
if (wxOSX && dc.GetContentScaleFactor() > 1.0)
// On Retina displays all controls are cut on 1px
rc.x = rc.y = 1;
// draw background
if (radius == 0.0 || wxOSX)
dc.DrawRectangle(rc);
else
dc.DrawRoundedRectangle(rc, radius);
// draw hover rectangle
wxRect rcContent = {{0, offset.y}, rowSize};
if (hover_item >= 0 && (states & StateColor::Hovered)) {
rcContent.y += rowSize.y * hover_item;
if (rcContent.GetBottom() > 0 && rcContent.y < size.y) {
if (selection == hover_item)
dc.SetBrush(wxBrush(selector_background_color.colorForStates(states | StateColor::Checked)));
dc.SetPen(wxPen(selector_border_color.colorForStates(states)));
rcContent.Deflate(4, 1);
dc.DrawRectangle(rcContent);
rcContent.Inflate(4, 1);
}
rcContent.y = offset.y;
}
// draw checked rectangle
if (selection >= 0 && (selection != hover_item || (states & StateColor::Hovered) == 0)) {
rcContent.y += rowSize.y * selection;
if (rcContent.GetBottom() > 0 && rcContent.y < size.y) {
dc.SetBrush(wxBrush(selector_background_color.colorForStates(states | StateColor::Checked)));
dc.SetPen(wxPen(selector_background_color.colorForStates(states)));
rcContent.Deflate(4, 1);
dc.DrawRectangle(rcContent);
rcContent.Inflate(4, 1);
}
rcContent.y = offset.y;
}
dc.SetBrush(*wxTRANSPARENT_BRUSH);
{
wxSize offset = (rowSize - textSize) / 2;
rcContent.Deflate(0, offset.y);
}
// draw position bar
const int text_size = int(texts.size());
if (rowSize.y * text_size > size.y) {
int height = rowSize.y * text_size;
wxRect rect = {size.x - 6, -offset.y * size.y / height, 4,
size.y * size.y / height};
dc.SetPen(wxPen(border_color.defaultColor()));
dc.SetBrush(wxBrush(*wxLIGHT_GREY));
dc.DrawRoundedRectangle(rect, 2);
rcContent.width -= 6;
}
// draw check icon
rcContent.x += 5;
rcContent.width -= 5;
if (check_bitmap.bmp().IsOk()) {
auto szBmp = check_bitmap.GetSize();
if (selection >= 0) {
wxPoint pt = rcContent.GetLeftTop();
pt.y += (rcContent.height - szBmp.y) / 2;
pt.y += rowSize.y * selection;
if (pt.y + szBmp.y > 0 && pt.y < size.y)
dc.DrawBitmap(check_bitmap.get_bitmap(), pt);
}
rcContent.x += szBmp.x + 5;
rcContent.width -= szBmp.x + 5;
}
// draw texts & icons
dc.SetTextForeground(text_color.colorForStates(states));
for (int i = 0; i < texts.size(); ++i) {
if (rcContent.GetBottom() < 0) {
rcContent.y += rowSize.y;
continue;
}
if (rcContent.y > size.y) break;
wxPoint pt = rcContent.GetLeftTop();
auto & icon = icons[i];
const wxSize pref_icon_sz = get_preferred_size(icon, m_parent);
if (iconSize.x > 0) {
if (icon.IsOk()) {
pt.y += (rcContent.height - pref_icon_sz.y) / 2;
#ifdef __WXGTK3__
dc.DrawBitmap(icon.GetBitmap(pref_icon_sz), pt);
#else
dc.DrawBitmap(icon.GetBitmapFor(m_parent), pt);
#endif
}
pt.x += iconSize.x + 5;
pt.y = rcContent.y;
} else if (icon.IsOk()) {
pt.y += (rcContent.height - pref_icon_sz.y) / 2;
#ifdef __WXGTK3__
dc.DrawBitmap(icon.GetBitmap(pref_icon_sz), pt);
#else
dc.DrawBitmap(icon.GetBitmapFor(m_parent), pt);
#endif
pt.x += pref_icon_sz.GetWidth() + 5;
pt.y = rcContent.y;
}
auto text = texts[i];
if (!text_off && !text.IsEmpty()) {
wxSize tSize = dc.GetMultiLineTextExtent(text);
if (pt.x + tSize.x > rcContent.GetRight()) {
text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END,
rcContent.GetRight() - pt.x);
}
pt.y += (rcContent.height - textSize.y) / 2;
dc.SetFont(GetFont());
dc.DrawText(text, pt);
}
rcContent.y += rowSize.y;
}
}
void DropDown::messureSize()
{
if (!need_sync) return;
textSize = wxSize();
iconSize = wxSize();
wxClientDC dc(GetParent() ? GetParent() : this);
for (size_t i = 0; i < texts.size(); ++i) {
wxSize size1 = text_off ? wxSize() : dc.GetMultiLineTextExtent(texts[i]);
if (icons[i].IsOk()) {
wxSize size2 = get_preferred_size(icons[i], m_parent);
if (size2.x > iconSize.x) iconSize = size2;
if (!align_icon) {
size1.x += size2.x + (text_off ? 0 : 5);
}
}
if (size1.x > textSize.x) textSize = size1;
}
if (!align_icon) iconSize.x = 0;
wxSize szContent = textSize;
szContent.x += 10;
if (check_bitmap.bmp().IsOk()) {
auto szBmp = check_bitmap.GetSize();
szContent.x += szBmp.x + 5;
}
if (iconSize.x > 0) szContent.x += iconSize.x + (text_off ? 0 : 5);
if (iconSize.y > szContent.y) szContent.y = iconSize.y;
szContent.y += 10;
if (texts.size() > 15) szContent.x += 6;
if (GetParent()) {
auto x = GetParent()->GetSize().x;
if (!use_content_width || x > szContent.x)
szContent.x = x;
}
rowSize = szContent;
szContent.y *= std::min((size_t)15, texts.size());
szContent.y += texts.size() > 15 ? rowSize.y / 2 : 0;
wxWindow::SetSize(szContent);
#ifdef __WXGTK__
// Gtk has a wrapper window for popup widget
gtk_window_resize(GTK_WINDOW(m_widget), szContent.x, szContent.y);
#endif
need_sync = false;
}
void DropDown::autoPosition()
{
messureSize();
wxPoint pos = GetParent()->ClientToScreen(wxPoint(0, -6));
wxPoint old = GetPosition();
wxSize size = GetSize();
Position(pos, {0, GetParent()->GetSize().y + 12});
if (old != GetPosition()) {
size = rowSize;
size.y *= std::min((size_t)15, texts.size());
size.y += texts.size() > 15 ? rowSize.y / 2 : 0;
if (size != GetSize()) {
wxWindow::SetSize(size);
offset = wxPoint();
Position(pos, {0, GetParent()->GetSize().y + 12});
}
}
if (GetPosition().y > pos.y) {
// may exceed
auto drect = wxDisplay(GetParent()).GetGeometry();
if (GetPosition().y + size.y + 10 > drect.GetBottom()) {
if (use_content_width && texts.size() <= 15) size.x += 6;
size.y = drect.GetBottom() - GetPosition().y - 10;
wxWindow::SetSize(size);
if (selection >= 0) {
if (offset.y + rowSize.y * (selection + 1) > size.y)
offset.y = size.y - rowSize.y * (selection + 1);
else if (offset.y + rowSize.y * selection < 0)
offset.y = -rowSize.y * selection;
}
}
}
}
void DropDown::mouseDown(wxMouseEvent& event)
{
// Receivce unexcepted LEFT_DOWN on Mac after OnDismiss
if (!IsShown())
return;
// force calc hover item again
mouseMove(event);
pressedDown = true;
CaptureMouse();
dragStart = event.GetPosition();
}
void DropDown::mouseReleased(wxMouseEvent& event)
{
if (pressedDown) {
dragStart = wxPoint();
pressedDown = false;
if (HasCapture())
ReleaseMouse();
if (hover_item >= 0) { // not moved
sendDropDownEvent();
DismissAndNotify();
}
}
}
void DropDown::mouseCaptureLost(wxMouseCaptureLostEvent &event)
{
wxMouseEvent evt;
mouseReleased(evt);
}
void DropDown::mouseMove(wxMouseEvent &event)
{
wxPoint pt = event.GetPosition();
if (pressedDown) {
wxPoint pt2 = offset + pt - dragStart;
dragStart = pt;
if (pt2.y > 0)
pt2.y = 0;
else if (pt2.y + rowSize.y * texts.size() < GetSize().y)
pt2.y = GetSize().y - rowSize.y * texts.size();
if (pt2.y != offset.y) {
offset = pt2;
hover_item = -1; // moved
} else {
return;
}
}
if (!pressedDown || hover_item >= 0) {
int hover = (pt.y - offset.y) / rowSize.y;
if (hover >= (int) texts.size()) hover = -1;
if (hover == hover_item) return;
hover_item = hover;
if (hover >= 0)
SetToolTip(texts[hover]);
}
paintNow();
}
void DropDown::mouseWheelMoved(wxMouseEvent &event)
{
auto delta = event.GetWheelRotation() > 0 ? rowSize.y : -rowSize.y;
wxPoint pt2 = offset + wxPoint{0, delta};
if (pt2.y > 0)
pt2.y = 0;
else if (pt2.y + rowSize.y * texts.size() < GetSize().y)
pt2.y = GetSize().y - rowSize.y * texts.size();
if (pt2.y != offset.y) {
offset = pt2;
} else {
return;
}
int hover = (event.GetPosition().y - offset.y) / rowSize.y;
if (hover >= (int) texts.size()) hover = -1;
if (hover != hover_item) {
hover_item = hover;
if (hover >= 0) SetToolTip(texts[hover]);
}
paintNow();
}
// currently unused events
void DropDown::sendDropDownEvent()
{
selection = hover_item;
wxCommandEvent event(wxEVT_COMBOBOX, GetId());
event.SetEventObject(this);
event.SetInt(selection);
event.SetString(GetValue());
GetEventHandler()->ProcessEvent(event);
}
void DropDown::OnDismiss()
{
dismissTime = boost::posix_time::microsec_clock::universal_time();
hover_item = -1;
wxCommandEvent e(EVT_DISMISS);
GetEventHandler()->ProcessEvent(e);
}

View File

@ -0,0 +1,115 @@
#ifndef slic3r_GUI_DropDown_hpp_
#define slic3r_GUI_DropDown_hpp_
#include <wx/stattext.h>
#include <wx/popupwin.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "../wxExtensions.hpp"
#include "StateHandler.hpp"
#define DD_NO_CHECK_ICON 0x0001
#define DD_NO_DROP_ICON 0x0002
#define DD_NO_TEXT 0x0004
#define DD_STYLE_MASK 0x0008
wxDECLARE_EVENT(EVT_DISMISS, wxCommandEvent);
class DropDown : public wxPopupTransientWindow
{
std::vector<wxString> & texts;
std::vector<wxBitmapBundle> & icons;
bool need_sync = false;
int selection = -1;
int hover_item = -1;
double radius;
bool use_content_width = false;
bool align_icon = false;
bool text_off = false;
wxSize textSize;
wxSize iconSize;
wxSize rowSize;
StateHandler state_handler;
StateColor text_color;
StateColor border_color;
StateColor selector_border_color;
StateColor selector_background_color;
ScalableBitmap check_bitmap;
bool pressedDown = false;
boost::posix_time::ptime dismissTime;
wxPoint offset; // x not used
wxPoint dragStart;
public:
DropDown(std::vector<wxString> &texts,
std::vector<wxBitmapBundle> &icons);
DropDown(wxWindow * parent,
std::vector<wxString> &texts,
std::vector<wxBitmapBundle> &icons,
long style = 0);
void Create(wxWindow * parent,
long style = 0);
void Invalidate(bool clear = false);
int GetSelection() const { return selection; }
void SetSelection(int n);
wxString GetValue() const;
void SetValue(const wxString &value);
void SetCornerRadius(double radius);
void SetBorderColor(StateColor const & color);
void SetSelectorBorderColor(StateColor const & color);
void SetTextColor(StateColor const &color);
void SetSelectorBackgroundColor(StateColor const &color);
void SetUseContentWidth(bool use);
void SetAlignIcon(bool align);
void Rescale();
bool HasDismissLongTime();
static void SetTransparentBG(wxDC& dc, wxWindow* win);
protected:
void OnDismiss() override;
private:
void paintEvent(wxPaintEvent& evt);
void paintNow();
void render(wxDC& dc);
friend class ComboBox;
void messureSize();
void autoPosition();
// some useful events
void mouseDown(wxMouseEvent& event);
void mouseReleased(wxMouseEvent &event);
void mouseCaptureLost(wxMouseCaptureLostEvent &event);
void mouseMove(wxMouseEvent &event);
void mouseWheelMoved(wxMouseEvent &event);
void sendDropDownEvent();
DECLARE_EVENT_TABLE()
};
#endif // !slic3r_GUI_DropDown_hpp_

View File

@ -0,0 +1,126 @@
#include "Label.hpp"
#include "StaticBox.hpp"
#include <wx/settings.h>
wxFont Label::sysFont(int size, bool bold)
{
//#ifdef __linux__
// return wxFont{};
//#endif
#ifndef __APPLE__
size = size * 4 / 5;
#endif
auto face = wxString::FromUTF8("HarmonyOS Sans SC");
wxFont font{size, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL, false, face};
font.SetFaceName(face);
if (!font.IsOk()) {
font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
if (bold) font.MakeBold();
font.SetPointSize(size);
}
return font;
}
wxFont Label::Head_24;
wxFont Label::Head_20;
wxFont Label::Head_18;
wxFont Label::Head_16;
wxFont Label::Head_15;
wxFont Label::Head_14;
wxFont Label::Head_13;
wxFont Label::Head_12;
wxFont Label::Head_10;
wxFont Label::Body_16;
wxFont Label::Body_15;
wxFont Label::Body_14;
wxFont Label::Body_13;
wxFont Label::Body_12;
wxFont Label::Body_11;
wxFont Label::Body_10;
wxFont Label::Body_9;
void Label::initSysFont()
{
Head_24 = Label::sysFont(24, true);
Head_20 = Label::sysFont(20, true);
Head_18 = Label::sysFont(18, true);
Head_16 = Label::sysFont(16, true);
Head_15 = Label::sysFont(15, true);
Head_14 = Label::sysFont(14, true);
Head_13 = Label::sysFont(13, true);
Head_12 = Label::sysFont(12, true);
Head_10 = Label::sysFont(10, true);
Body_16 = Label::sysFont(16, false);
Body_15 = Label::sysFont(15, false);
Body_14 = Label::sysFont(14, false);
Body_13 = Label::sysFont(13, false);
Body_12 = Label::sysFont(12, false);
Body_11 = Label::sysFont(11, false);
Body_10 = Label::sysFont(10, false);
Body_9 = Label::sysFont(9, false);
}
wxSize Label::split_lines(wxDC &dc, int width, const wxString &text, wxString &multiline_text)
{
multiline_text = text;
if (width > 0 && dc.GetTextExtent(text).x > width) {
size_t start = 0;
while (true) {
size_t idx = size_t(-1);
for (size_t i = start; i < multiline_text.Len(); i++) {
if (multiline_text[i] == ' ') {
if (dc.GetTextExtent(multiline_text.SubString(start, i)).x < width)
idx = i;
else {
if (idx == size_t(-1)) idx = i;
break;
}
}
}
if (idx == size_t(-1)) break;
multiline_text[idx] = '\n';
start = idx + 1;
if (dc.GetTextExtent(multiline_text.Mid(start)).x < width) break;
}
}
return dc.GetMultiLineTextExtent(multiline_text);
}
Label::Label(wxWindow *parent, wxString const &text, long style) : Label(parent, Body_14, text, style) {}
Label::Label(wxWindow *parent, wxFont const &font, wxString const &text, long style)
: wxStaticText(parent, wxID_ANY, text, wxDefaultPosition, wxDefaultSize, style)
{
this->font = font;
SetFont(font);
SetBackgroundColour(StaticBox::GetParentBackgroundColor(parent));
Bind(wxEVT_ENTER_WINDOW, [this](auto &e) {
if (GetWindowStyle() & LB_HYPERLINK) {
SetFont(this->font.Underlined());
Refresh();
}
});
Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) {
SetFont(this->font);
Refresh();
});
}
void Label::SetWindowStyleFlag(long style)
{
if (style == GetWindowStyle())
return;
wxStaticText::SetWindowStyleFlag(style);
if (style & LB_HYPERLINK) {
this->color = GetForegroundColour();
static wxColor clr_url("#00AE42");
SetForegroundColour(clr_url);
} else {
SetForegroundColour(this->color);
SetFont(this->font);
}
Refresh();
}

View File

@ -0,0 +1,50 @@
#ifndef slic3r_GUI_Label_hpp_
#define slic3r_GUI_Label_hpp_
#include <wx/stattext.h>
#include <wx/dcclient.h>
#define LB_HYPERLINK 0x0001
class Label : public wxStaticText
{
public:
Label(wxWindow *parent, wxString const &text = {}, long style = 0);
Label(wxWindow *parent, wxFont const &font, wxString const &text = {}, long style = 0);
void SetWindowStyleFlag(long style) override;
private:
wxFont font;
wxColour color;
public:
static wxFont Head_24;
static wxFont Head_20;
static wxFont Head_18;
static wxFont Head_16;
static wxFont Head_15;
static wxFont Head_14;
static wxFont Head_13;
static wxFont Head_12;
static wxFont Head_10;
static wxFont Body_16;
static wxFont Body_15;
static wxFont Body_14;
static wxFont Body_13;
static wxFont Body_12;
static wxFont Body_10;
static wxFont Body_11;
static wxFont Body_9;
static void initSysFont();
static wxFont sysFont(int size, bool bold = false);
static wxSize split_lines(wxDC &dc, int width, const wxString &text, wxString &multiline_text);
};
#endif // !slic3r_GUI_Label_hpp_

View File

@ -0,0 +1,633 @@
#include "SpinInput.hpp"
#include "Button.hpp"
#include "UIColors.hpp"
#include "../GUI_App.hpp"
#include <wx/dcgraph.h>
#include <wx/panel.h>
#include <wx/spinctrl.h>
#include <wx/valtext.h>
BEGIN_EVENT_TABLE(SpinInputBase, wxPanel)
EVT_KEY_DOWN(SpinInputBase::keyPressed)
EVT_MOUSEWHEEL(SpinInputBase::mouseWheelMoved)
EVT_PAINT(SpinInputBase::paintEvent)
END_EVENT_TABLE()
/*
* Called by the system of by wxWidgets when the panel needs
* to be redrawn. You can also trigger this call by
* calling Refresh()/Update().
*/
SpinInputBase::SpinInputBase()
: 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))
{
if (Slic3r::GUI::wxGetApp().suppress_round_corners())
radius = 0;
border_width = 1;
}
Button * SpinInputBase::create_button(ButtonId id)
{
auto btn = new Button(this, "", id == ButtonId::btnIncrease ? "spin_inc_act" : "spin_dec_act", wxBORDER_NONE, wxSize(12, 7));
btn->SetCornerRadius(0);
btn->SetInactiveIcon(id == ButtonId::btnIncrease ? "spin_inc" : "spin_dec");
btn->DisableFocusFromKeyboard();
btn->SetSelected(false);
bind_inc_dec_button(btn, id);
return btn;
}
void SpinInputBase::SetCornerRadius(double radius)
{
this->radius = radius;
Refresh();
}
void SpinInputBase::SetLabel(const wxString &label)
{
wxWindow::SetLabel(label);
messureSize();
Refresh();
}
void SpinInputBase::SetLabelColor(StateColor const &color)
{
label_color = color;
state_handler.update_binds();
}
void SpinInputBase::SetTextColor(StateColor const &color)
{
text_color = color;
state_handler.update_binds();
}
void SpinInputBase::SetSize(wxSize const &size)
{
wxWindow::SetSize(size);
Rescale();
}
wxString SpinInputBase::GetTextValue() const
{
return text_ctrl->GetValue();
}
void SpinInput::SetRange(int min, int max)
{
this->min = min;
this->max = max;
}
void SpinInputBase::SetSelection(long from, long to)
{
if (text_ctrl)
text_ctrl->SetSelection(from, to);
}
bool SpinInputBase::SetFont(wxFont const& font)
{
if (text_ctrl)
return text_ctrl->SetFont(font);
return StaticBox::SetFont(font);
}
bool SpinInputBase::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 SpinInputBase::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 SpinInputBase::SetBorderColor(StateColor const &color)
{
StaticBox::SetBorderColor(color);
if (button_inc)
button_inc->SetBorderColor(color);
if (button_dec)
button_dec->SetBorderColor(color);
}
void SpinInputBase::DoSetToolTipText(wxString const &tip)
{
wxWindow::DoSetToolTipText(tip);
text_ctrl->SetToolTip(tip);
}
void SpinInputBase::Rescale()
{
SetFont(Slic3r::GUI::wxGetApp().normal_font());
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
button_inc->Rescale();
button_dec->Rescale();
messureSize();
}
bool SpinInputBase::Enable(bool enable)
{
bool result = text_ctrl->Enable(enable) && wxWindow::Enable(enable);
if (result) {
wxCommandEvent e(EVT_ENABLE_CHANGED);
e.SetEventObject(this);
GetEventHandler()->ProcessEvent(e);
text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states()));
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states()));
button_inc->Enable(enable);
button_dec->Enable(enable);
}
return result;
}
void SpinInputBase::paintEvent(wxPaintEvent& evt)
{
// depending on your system you may need to look at double-buffered dcs
wxPaintDC dc(this);
render(dc);
}
/*
* Here we do the actual rendering. I put it in a separate
* method so that it can work no matter what type of DC
* (e.g. wxPaintDC or wxClientDC) is used.
*/
void SpinInputBase::render(wxDC& dc)
{
StaticBox::render(dc);
int states = state_handler.states();
wxSize size = GetSize();
// draw seperator of buttons
wxPoint pt = button_inc->GetPosition();
pt.y = size.y / 2;
dc.SetPen(wxPen(border_color.defaultColor()));
const double scale = dc.GetContentScaleFactor();
const int btn_w = button_inc->GetSize().GetWidth();
dc.DrawLine(pt, pt + wxSize{ btn_w - int(scale), 0});
// draw label
auto label = GetLabel();
if (!label.IsEmpty()) {
pt.x = size.x - labelSize.x - 5;
pt.y = (size.y - labelSize.y) / 2;
dc.SetFont(GetFont());
dc.SetTextForeground(label_color.colorForStates(states));
dc.DrawText(label, pt);
}
}
void SpinInputBase::messureSize()
{
wxSize size = GetSize();
wxSize textSize = text_ctrl->GetSize();
int h = textSize.y + 8;
if (size.y != h) {
size.y = h;
SetSize(size);
SetMinSize(size);
}
wxSize btnSize = {14, (size.y - 4) / 2};
btnSize.x = btnSize.x * btnSize.y / 10;
const double scale = this->GetContentScaleFactor();
wxClientDC dc(this);
labelSize = dc.GetMultiLineTextExtent(GetLabel());
textSize.x = size.x - labelSize.x - btnSize.x - 16;
text_ctrl->SetSize(textSize);
text_ctrl->SetPosition({int(3. * scale), (size.y - textSize.y) / 2});
button_inc->SetSize(btnSize);
button_dec->SetSize(btnSize);
button_inc->SetPosition({size.x - btnSize.x - int(3. * scale), size.y / 2 - btnSize.y/* - 1*/});
button_dec->SetPosition({size.x - btnSize.x - int(3. * scale), size.y / 2 + 1});
}
void SpinInputBase::onText(wxCommandEvent &event)
{
sendSpinEvent();
event.SetId(GetId());
ProcessEventLocally(event);
}
void SpinInputBase::sendSpinEvent()
{
wxCommandEvent event(wxEVT_SPINCTRL, GetId());
event.SetEventObject(this);
GetEventHandler()->ProcessEvent(event);
}
// SpinInput
SpinInput::SpinInput(wxWindow *parent,
wxString text,
wxString label,
const wxPoint &pos,
const wxSize & size,
long style,
int min, int max, int initial)
: SpinInputBase()
{
Create(parent, text, label, pos, size, style, min, max, initial);
}
void SpinInput::Create(wxWindow *parent,
wxString text,
wxString label,
const wxPoint &pos,
const wxSize & size,
long style,
int min, int max, int initial)
{
StaticBox::Create(parent, wxID_ANY, pos, size);
wxWindow::SetLabel(label);
state_handler.attach({&label_color, &text_color});
state_handler.update_binds();
text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {20, 4}, wxDefaultSize, style | wxBORDER_NONE | wxTE_PROCESS_ENTER, wxTextValidator(wxFILTER_DIGITS));
#ifdef __WXOSX__
text_ctrl->OSXDisableAllSmartSubstitutions();
#endif // __WXOSX__
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
state_handler.attach_child(text_ctrl);
text_ctrl->Bind(wxEVT_KILL_FOCUS, &SpinInput::onTextLostFocus, this);
text_ctrl->Bind(wxEVT_TEXT, &SpinInput::onText, this);
text_ctrl->Bind(wxEVT_TEXT_ENTER, &SpinInput::onTextEnter, this);
text_ctrl->Bind(wxEVT_KEY_DOWN, &SpinInput::keyPressed, this);
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu
button_inc = create_button(ButtonId::btnIncrease);
button_dec = create_button(ButtonId::btnDecrease);
delta = 0;
timer.Bind(wxEVT_TIMER, &SpinInput::onTimer, this);
SetFont(Slic3r::GUI::wxGetApp().normal_font());
if (parent) {
SetBackgroundColour(parent->GetBackgroundColour());
SetForegroundColour(parent->GetForegroundColour());
}
long initialFromText;
if (text.ToLong(&initialFromText)) initial = initialFromText;
SetRange(min, max);
SetValue(initial);
messureSize();
}
void SpinInput::bind_inc_dec_button(Button *btn, ButtonId id)
{
btn->Bind(wxEVT_LEFT_DOWN, [this, btn, id](auto& e) {
delta = id == ButtonId::btnIncrease ? 1 : -1;
SetValue(val + delta);
text_ctrl->SetFocus();
btn->CaptureMouse();
delta *= 8;
timer.Start(100);
sendSpinEvent();
});
btn->Bind(wxEVT_LEFT_DCLICK, [this, btn, id](auto& e) {
delta = id == ButtonId::btnIncrease ? 1 : -1;
btn->CaptureMouse();
SetValue(val + delta);
sendSpinEvent();
});
btn->Bind(wxEVT_LEFT_UP, [this, btn](auto& e) {
btn->ReleaseMouse();
timer.Stop();
text_ctrl->SelectAll();
delta = 0;
});
}
void SpinInput::SetValue(const wxString &text)
{
long value;
if ( text.ToLong(&value) )
SetValue(value);
else
text_ctrl->SetValue(text);
}
void SpinInput::SetValue(int value)
{
if (value < min) value = min;
else if (value > max) value = max;
this->val = value;
text_ctrl->SetValue(wxString::FromDouble(value));
}
int SpinInput::GetValue()const
{
return val;
}
void SpinInput::onTimer(wxTimerEvent &evnet) {
if (delta < -1 || delta > 1) {
delta /= 2;
return;
}
SetValue(val + delta);
sendSpinEvent();
}
void SpinInput::onTextLostFocus(wxEvent &event)
{
timer.Stop();
for (auto * child : GetChildren())
if (auto btn = dynamic_cast<Button*>(child))
if (btn->HasCapture())
btn->ReleaseMouse();
wxCommandEvent e;
onTextEnter(e);
// pass to outer
event.SetId(GetId());
ProcessEventLocally(event);
e.Skip();
}
void SpinInput::onTextEnter(wxCommandEvent &event)
{
long value;
if (!text_ctrl->GetValue().ToLong(&value))
value = val;
if (value != val) {
SetValue(value);
sendSpinEvent();
}
event.SetId(GetId());
ProcessEventLocally(event);
}
void SpinInput::mouseWheelMoved(wxMouseEvent &event)
{
auto delta = (event.GetWheelRotation() < 0 == event.IsWheelInverted()) ? 1 : -1;
SetValue(val + delta);
sendSpinEvent();
text_ctrl->SetFocus();
}
void SpinInput::keyPressed(wxKeyEvent &event)
{
switch (event.GetKeyCode()) {
case WXK_UP:
case WXK_DOWN:
long value;
if (!text_ctrl->GetValue().ToLong(&value)) { value = val; }
if (event.GetKeyCode() == WXK_DOWN && value > min) {
--value;
} else if (event.GetKeyCode() == WXK_UP && value + 1 < max) {
++value;
}
if (value != val) {
SetValue(value);
sendSpinEvent();
}
break;
default: event.Skip(); break;
}
}
// SpinInputDouble
SpinInputDouble::SpinInputDouble(wxWindow * parent,
wxString text,
wxString label,
const wxPoint &pos,
const wxSize & size,
long style,
double min, double max, double initial,
double inc)
: SpinInputBase()
{
Create(parent, text, label, pos, size, style, min, max, initial, inc);
}
void SpinInputDouble::Create(wxWindow *parent,
wxString text,
wxString label,
const wxPoint &pos,
const wxSize & size,
long style,
double min, double max, double initial,
double inc)
{
StaticBox::Create(parent, wxID_ANY, pos, size);
wxWindow::SetLabel(label);
state_handler.attach({&label_color, &text_color});
state_handler.update_binds();
text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {20, 4}, wxDefaultSize, style | wxBORDER_NONE | wxTE_PROCESS_ENTER, wxTextValidator(wxFILTER_DIGITS));
#ifdef __WXOSX__
text_ctrl->OSXDisableAllSmartSubstitutions();
#endif // __WXOSX__
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
state_handler.attach_child(text_ctrl);
text_ctrl->Bind(wxEVT_KILL_FOCUS, &SpinInputDouble::onTextLostFocus, this);
text_ctrl->Bind(wxEVT_TEXT, &SpinInputDouble::onText, this);
text_ctrl->Bind(wxEVT_TEXT_ENTER, &SpinInputDouble::onTextEnter, this);
text_ctrl->Bind(wxEVT_KEY_DOWN, &SpinInputDouble::keyPressed, this);
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu
button_inc = create_button(ButtonId::btnIncrease);
button_dec = create_button(ButtonId::btnDecrease);
delta = 0;
timer.Bind(wxEVT_TIMER, &SpinInputDouble::onTimer, this);
SetFont(Slic3r::GUI::wxGetApp().normal_font());
if (parent) {
SetBackgroundColour(parent->GetBackgroundColour());
SetForegroundColour(parent->GetForegroundColour());
}
double initialFromText;
if (text.ToDouble(&initialFromText)) initial = initialFromText;
SetRange(min, max);
SetIncrement(inc);
SetValue(initial);
messureSize();
}
void SpinInputDouble::bind_inc_dec_button(Button *btn, ButtonId id)
{
btn->Bind(wxEVT_LEFT_DOWN, [this, btn, id](auto& e) {
delta = id == ButtonId::btnIncrease ? inc : -inc;
SetValue(val + delta);
text_ctrl->SetFocus();
btn->CaptureMouse();
delta *= 8;
timer.Start(100);
sendSpinEvent();
});
btn->Bind(wxEVT_LEFT_DCLICK, [this, btn, id](auto& e) {
delta = id == ButtonId::btnIncrease ? inc : -inc;
btn->CaptureMouse();
SetValue(val + delta);
sendSpinEvent();
});
btn->Bind(wxEVT_LEFT_UP, [this, btn](auto& e) {
btn->ReleaseMouse();
timer.Stop();
text_ctrl->SelectAll();
delta = 0;
});
}
void SpinInputDouble::SetValue(const wxString &text)
{
double value;
if ( text.ToDouble(&value) )
SetValue(value);
else
text_ctrl->SetValue(text);
}
void SpinInputDouble::SetValue(double value)
{
if (Slic3r::is_approx(value, val))
return;
if (value < min) value = min;
else if (value > max) value = max;
this->val = value;
wxString str_val = wxString::FromDouble(value, digits);
text_ctrl->SetValue(str_val);
}
double SpinInputDouble::GetValue()const
{
return val;
}
void SpinInputDouble::SetRange(double min, double max)
{
this->min = min;
this->max = max;
}
void SpinInputDouble::SetIncrement(double inc_in)
{
inc = inc_in;
}
void SpinInputDouble::SetDigits(unsigned digits_in)
{
digits = int(digits_in);
}
void SpinInputDouble::onTimer(wxTimerEvent &evnet) {
if (delta < -inc || delta > inc) {
delta /= 2;
return;
}
SetValue(val + delta);
sendSpinEvent();
}
void SpinInputDouble::onTextLostFocus(wxEvent &event)
{
timer.Stop();
for (auto * child : GetChildren())
if (auto btn = dynamic_cast<Button*>(child))
if (btn->HasCapture())
btn->ReleaseMouse();
wxCommandEvent e;
onTextEnter(e);
// pass to outer
event.SetId(GetId());
ProcessEventLocally(event);
e.Skip();
}
void SpinInputDouble::onTextEnter(wxCommandEvent &event)
{
double value;
if (!text_ctrl->GetValue().ToDouble(&value))
val = value;
if (!Slic3r::is_approx(value, val)) {
SetValue(value);
sendSpinEvent();
}
event.SetId(GetId());
ProcessEventLocally(event);
}
void SpinInputDouble::mouseWheelMoved(wxMouseEvent &event)
{
auto delta = (event.GetWheelRotation() < 0 == event.IsWheelInverted()) ? inc : -inc;
SetValue(val + delta);
sendSpinEvent();
text_ctrl->SetFocus();
}
void SpinInputDouble::keyPressed(wxKeyEvent &event)
{
switch (event.GetKeyCode()) {
case WXK_UP:
case WXK_DOWN:
double value;
if (!text_ctrl->GetValue().ToDouble(&value))
val = value;
if (event.GetKeyCode() == WXK_DOWN && value > min) {
value -= inc;
} else if (event.GetKeyCode() == WXK_UP && value + inc < max) {
value += inc;
}
if (!Slic3r::is_approx(value, val)) {
SetValue(value);
sendSpinEvent();
}
break;
default: event.Skip(); break;
}
}

View File

@ -0,0 +1,190 @@
#ifndef slic3r_GUI_SpinInput_hpp_
#define slic3r_GUI_SpinInput_hpp_
#include <wx/textctrl.h>
#include "StaticBox.hpp"
class Button;
class SpinInputBase : public wxNavigationEnabled<StaticBox>
{
protected:
wxSize labelSize;
StateColor label_color;
StateColor text_color;
wxTextCtrl * text_ctrl{nullptr};
Button * button_inc {nullptr};
Button * button_dec {nullptr};
wxTimer timer;
static const int SpinInputWidth = 200;
static const int SpinInputHeight = 50;
enum class ButtonId
{
btnIncrease,
btnDecrease
};
public:
SpinInputBase();
void SetCornerRadius(double radius);
void SetLabel(const wxString &label) wxOVERRIDE;
void SetLabelColor(StateColor const &color);
void SetTextColor(StateColor const &color);
void SetSize(wxSize const &size);
void Rescale();
virtual bool Enable(bool enable = true) wxOVERRIDE;
wxTextCtrl * GetText() { return text_ctrl; }
virtual void SetValue(const wxString &text) = 0;
wxString GetTextValue() const;
bool SetFont(wxFont const& font) override;
bool SetBackgroundColour(const wxColour& colour) override;
bool SetForegroundColour(const wxColour& colour) override;
void SetBorderColor(StateColor const& color);
void SetSelection(long from, long to);
protected:
void DoSetToolTipText(wxString const &tip) override;
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
void messureSize();
Button *create_button(ButtonId id);
virtual void bind_inc_dec_button(Button *btn, ButtonId id) = 0;
// some useful events
virtual void mouseWheelMoved(wxMouseEvent& event) = 0;
virtual void keyPressed(wxKeyEvent& event) = 0;
virtual void onTimer(wxTimerEvent &evnet) = 0;
virtual void onTextLostFocus(wxEvent &event) = 0;
virtual void onTextEnter(wxCommandEvent &event) = 0;
void onText(wxCommandEvent &event);
void sendSpinEvent();
DECLARE_EVENT_TABLE()
};
class SpinInput : public SpinInputBase
{
int val;
int min;
int max;
int delta;
public:
SpinInput(wxWindow * parent,
wxString text,
wxString label = "",
const wxPoint &pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = 0,
int min = 0, int max = 100, int initial = 0);
void Create(wxWindow * parent,
wxString text,
wxString label = "",
const wxPoint &pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = 0,
int min = 0,
int max = 100,
int initial = 0);
void SetValue(const wxString &text) override;
void SetValue (int value);
int GetValue () const;
void SetRange(int min, int max);
int GetMin() const { return this->min; }
int GetMax() const { return this->max; }
protected:
void bind_inc_dec_button(Button* btn, ButtonId id) override;
// some useful events
void mouseWheelMoved(wxMouseEvent& event) override;
void keyPressed(wxKeyEvent& event) override;
void onTimer(wxTimerEvent& evnet) override;
void onTextLostFocus(wxEvent& event) override;
void onTextEnter(wxCommandEvent& event) override;
};
class SpinInputDouble : public SpinInputBase
{
double val;
double min;
double max;
double inc;
double delta;
int digits {-1};
public:
SpinInputDouble() : SpinInputBase() {}
SpinInputDouble(wxWindow* parent,
wxString text,
wxString label = "",
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = 0,
double min = 0.,
double max = 100.,
double initial = 0.,
double inc = 1.);
void Create(wxWindow* parent,
wxString text,
wxString label = "",
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = 0,
double min = 0.,
double max = 100.,
double initial = 0.,
double inc = 1.);
void SetValue(const wxString& text) override;
void SetValue(double value);
double GetValue() const;
//wxString GetTextValue() const override;
void SetRange(double min, double max);
void SetIncrement(double inc);
void SetDigits(unsigned digits);
double GetMin() const { return this->min; }
double GetMax() const { return this->max; }
protected:
void bind_inc_dec_button(Button* btn, ButtonId id) override;
// some useful events
void mouseWheelMoved(wxMouseEvent& event) override;
void keyPressed(wxKeyEvent& event) override;
void onTimer(wxTimerEvent& evnet) override;
void onTextLostFocus(wxEvent& event) override;
void onTextEnter(wxCommandEvent& event) override;
};
#endif // !slic3r_GUI_SpinInput_hpp_

View File

@ -0,0 +1,93 @@
#include "StateColor.hpp"
StateColor::StateColor(wxColour const &color) { append(color, 0); }
StateColor::StateColor(wxString const &color) { append(color, 0); }
StateColor::StateColor(unsigned long color) { append(color, 0); }
void StateColor::append(wxColour const & color, int states)
{
statesList_.push_back(states);
colors_.push_back(color);
}
void StateColor::append(wxString const & color, int states)
{
wxColour c1(color);
append(c1, states);
}
void StateColor::append(unsigned long color, int states)
{
if ((color & 0xff000000) == 0)
color |= 0xff000000;
wxColour cl; cl.SetRGBA(color & 0xff00ff00 | ((color & 0xff) << 16) | ((color >> 16) & 0xff));
append(cl, states);
}
void StateColor::clear()
{
statesList_.clear();
colors_.clear();
}
int StateColor::states() const
{
int states = 0;
for (auto s : statesList_) states |= s;
states = (states & 0xffff) | (states >> 16);
if (takeFocusedAsHovered_ && (states & Hovered))
states |= Focused;
return states;
}
wxColour StateColor::defaultColor() {
return colorForStates(0);
}
wxColour StateColor::colorForStates(int states)
{
bool focused = takeFocusedAsHovered_ && (states & Focused);
for (int i = 0; i < statesList_.size(); ++i) {
int s = statesList_[i];
int on = s & 0xffff;
int off = s >> 16;
if ((on & states) == on && (off & ~states) == off) {
return colors_[i];
}
if (focused && (on & Hovered)) {
on |= Focused;
on &= ~Hovered;
if ((on & states) == on && (off & ~states) == off) {
return colors_[i];
}
}
}
return wxColour(0, 0, 0, 0);
}
int StateColor::colorIndexForStates(int states)
{
for (int i = 0; i < statesList_.size(); ++i) {
int s = statesList_[i];
int on = s & 0xffff;
int off = s >> 16;
if ((on & states) == on && (off & ~states) == off) { return i; }
}
return -1;
}
bool StateColor::setColorForStates(wxColour const &color, int states)
{
for (int i = 0; i < statesList_.size(); ++i) {
if (statesList_[i] == states) {
colors_[i] = color;
return true;
}
}
return false;
}
void StateColor::setTakeFocusedAsHovered(bool set) { takeFocusedAsHovered_ = set; }

View File

@ -0,0 +1,84 @@
#ifndef slic3r_GUI_StateColor_hpp_
#define slic3r_GUI_StateColor_hpp_
#include <wx/colour.h>
class StateColor
{
public:
enum State {
Normal = 0,
Enabled = 1,
Checked = 2,
Focused = 4,
Hovered = 8,
Pressed = 16,
Disabled = 1 << 16,
NotChecked = 2 << 16,
NotFocused = 4 << 16,
NotHovered = 8 << 16,
NotPressed = 16 << 16,
};
public:
template<typename ...Colors>
StateColor(std::pair<Colors, int>... colors) {
fill(colors...);
}
// single color
StateColor(wxColour const & color);
// single color
StateColor(wxString const &color);
// single color
StateColor(unsigned long color);
public:
void append(wxColour const & color, int states);
void append(wxString const &color, int states);
void append(unsigned long color, int states);
void clear();
public:
int count() const { return statesList_.size(); }
int states() const;
public:
wxColour defaultColor();
wxColour colorForStates(int states);
int colorIndexForStates(int states);
bool setColorForStates(wxColour const & color, int states);
void setTakeFocusedAsHovered(bool set);
private:
template<typename Color, typename ...Colors>
void fill(std::pair<Color, int> color, std::pair<Colors, int>... colors) {
fillOne(color);
fill(colors...);
}
template<typename Color>
void fillOne(std::pair<Color, int> color) {
append(color.first, color.second);
}
void fill() {
}
private:
std::vector<int> statesList_;
std::vector<wxColour> colors_;
bool takeFocusedAsHovered_ = true;
};
#endif // !slic3r_GUI_StateColor_hpp_

View File

@ -0,0 +1,124 @@
#include "StateHandler.hpp"
#include <wx/window.h>
wxDEFINE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent);
StateHandler::StateHandler(wxWindow * owner)
: owner_(owner)
{
owner_->PushEventHandler(this);
if (owner->IsEnabled())
states_ |= Enabled;
if (owner->HasFocus())
states_ |= Focused;
}
StateHandler::~StateHandler() { owner_->RemoveEventHandler(this); }
void StateHandler::attach(StateColor const &color)
{
colors_.push_back(&color);
}
void StateHandler::attach(std::vector<StateColor const *> const & colors)
{
colors_.insert(colors_.end(), colors.begin(), colors.end());
}
void StateHandler::attach_child(wxWindow *child)
{
auto ch = new StateHandler(this, child);
children_.emplace_back(ch);
ch->update_binds();
states2_ |= ch->states();
}
void StateHandler::remove_child(wxWindow *child)
{
children_.erase(std::remove_if(children_.begin(), children_.end(),
[child](auto &c) { return c->owner_ == child; }), children_.end());
states2_ = 0;
for (auto & c : children_) states2_ |= c->states();
}
void StateHandler::update_binds()
{
int bind_states = parent_ ? (parent_->bind_states_ & ~Enabled) : 0;
for (auto c : colors_) {
bind_states |= c->states();
}
bind_states = bind_states | (bind_states >> 16);
int diff = bind_states ^ bind_states_;
State states[] = {Enabled, Checked, Focused, Hovered, Pressed};
wxEventType events[] = {EVT_ENABLE_CHANGED, wxEVT_CHECKBOX, wxEVT_SET_FOCUS, wxEVT_ENTER_WINDOW, wxEVT_LEFT_DOWN};
wxEventType events2[] = {{0}, {0}, wxEVT_KILL_FOCUS, wxEVT_LEAVE_WINDOW, wxEVT_LEFT_UP};
for (int i = 0; i < 5; ++i) {
int s = states[i];
if (diff & s) {
if (bind_states & s) {
Bind(events[i], &StateHandler::changed, this);
if (events2[i])
Bind(events2[i], &StateHandler::changed, this);
} else {
Unbind(events[i], &StateHandler::changed, this);
if (events2[i])
owner_->Unbind(events2[i], &StateHandler::changed, this);
}
}
}
bind_states_ = bind_states;
for (auto &c : children_) c->update_binds();
}
StateHandler::StateHandler(StateHandler *parent, wxWindow *owner)
: StateHandler(owner)
{
states_ &= ~Enabled;
parent_ = parent;
}
void StateHandler::changed(wxEvent &event)
{
event.Skip();
wxEventType events[] = {EVT_ENABLE_CHANGED, wxEVT_CHECKBOX, wxEVT_SET_FOCUS, wxEVT_ENTER_WINDOW, wxEVT_LEFT_DOWN};
wxEventType events2[] = {{0}, {0}, wxEVT_KILL_FOCUS, wxEVT_LEAVE_WINDOW, wxEVT_LEFT_UP};
int old = states_;
// some events are from another window (ex: text_ctrl of TextInput), save state in states2_ to avoid conflicts
for (int i = 0; i < 5; ++i) {
if (events2[i]) {
if (event.GetEventType() == events[i]) {
states_ |= 1 << i;
break;
} else if (event.GetEventType() == events2[i]) {
states_ &= ~(1 << i);
break;
}
}
else {
if (event.GetEventType() == events[i]) {
states_ ^= (1 << i);
break;
}
}
}
if (old != states_ && (old | states2_) != (states_ | states2_)) {
if (parent_)
parent_->changed(states_ | states2_);
else
owner_->Refresh();
}
}
void StateHandler::changed(int)
{
int old = states2_;
states2_ = 0;
for (auto &c : children_) states2_ |= c->states();
if (old != states2_ && (old | states_) != (states_ | states2_)) {
if (parent_)
parent_->changed(states_ | states2_);
else
owner_->Refresh();
}
}

View File

@ -0,0 +1,62 @@
#ifndef slic3r_GUI_StateHandler_hpp_
#define slic3r_GUI_StateHandler_hpp_
#include <wx/event.h>
#include <memory>
#include "StateColor.hpp"
wxDECLARE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent);
class StateHandler : public wxEvtHandler
{
public:
enum State {
Enabled = 1,
Checked = 2,
Focused = 4,
Hovered = 8,
Pressed = 16,
Disabled = 1 << 16,
NotChecked = 2 << 16,
NotFocused = 4 << 16,
NotHovered = 8 << 16,
NotPressed = 16 << 16,
};
public:
StateHandler(wxWindow * owner);
~StateHandler();
public:
void attach(StateColor const & color);
void attach(std::vector<StateColor const *> const & colors);
void attach_child(wxWindow *child);
void remove_child(wxWindow *child);
void update_binds();
int states() const { return states_ | states2_; }
private:
StateHandler(StateHandler * parent, wxWindow *owner);
void changed(wxEvent &event);
void changed(int state2);
private:
wxWindow * owner_;
std::vector<StateColor const *> colors_;
int bind_states_ = 0;
int states_ = 0;
int states2_ = 0; // from children
std::vector<std::unique_ptr<StateHandler>> children_;
StateHandler * parent_ = nullptr;
};
#endif // !slic3r_GUI_StateHandler_hpp_

View File

@ -0,0 +1,208 @@
#include "StaticBox.hpp"
#include "../GUI.hpp"
#include <wx/dcgraph.h>
#include <wx/dcbuffer.h>
#include "DropDown.hpp"
#include "UIColors.hpp"
BEGIN_EVENT_TABLE(StaticBox, wxWindow)
EVT_PAINT(StaticBox::paintEvent)
END_EVENT_TABLE()
/*
* Called by the system of by wxWidgets when the panel needs
* to be redrawn. You can also trigger this call by
* calling Refresh()/Update().
*/
StaticBox::StaticBox()
: state_handler(this)
, radius(8)
{
border_color = StateColor(std::make_pair(clr_border_disabled, (int) StateColor::Disabled),
#ifndef __WXMSW__
std::make_pair(clr_border_nornal, (int) StateColor::Focused),
#endif
std::make_pair(clr_border_hovered, (int) StateColor::Hovered),
std::make_pair(clr_border_nornal, (int) StateColor::Normal));
#ifndef __WXMSW__
border_color.setTakeFocusedAsHovered(false);
#endif
}
StaticBox::StaticBox(wxWindow* parent,
wxWindowID id,
const wxPoint & pos,
const wxSize & size, long style)
: StaticBox()
{
Create(parent, id, pos, size, style);
}
bool StaticBox::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
{
if (style & wxBORDER_NONE)
border_width = 0;
wxWindow::Create(parent, id, pos, size, style);
state_handler.attach({&border_color, &background_color, &background_color2});
state_handler.update_binds();
// SetBackgroundColour(GetParentBackgroundColor(parent));
// SetForegroundColour(parent->GetParent()->GetForegroundColour());
return true;
}
void StaticBox::SetCornerRadius(double radius)
{
this->radius = radius;
Refresh();
}
void StaticBox::SetBorderWidth(int width)
{
border_width = width;
Refresh();
}
void StaticBox::SetBorderColor(StateColor const &color)
{
border_color = color;
state_handler.update_binds();
Refresh();
}
void StaticBox::SetBorderColorNormal(wxColor const &color)
{
border_color.setColorForStates(color, 0);
Refresh();
}
void StaticBox::SetBackgroundColor(StateColor const &color)
{
background_color = color;
state_handler.update_binds();
Refresh();
}
void StaticBox::SetBackgroundColorNormal(wxColor const &color)
{
background_color.setColorForStates(color, 0);
Refresh();
}
void StaticBox::SetBackgroundColor2(StateColor const &color)
{
background_color2 = color;
state_handler.update_binds();
Refresh();
}
wxColor StaticBox::GetParentBackgroundColor(wxWindow* parent)
{
if (auto box = dynamic_cast<StaticBox*>(parent)) {
if (box->background_color.count() > 0) {
if (box->background_color2.count() == 0)
return box->background_color.defaultColor();
auto s = box->background_color.defaultColor();
auto e = box->background_color2.defaultColor();
int r = (s.Red() + e.Red()) / 2;
int g = (s.Green() + e.Green()) / 2;
int b = (s.Blue() + e.Blue()) / 2;
return wxColor(r, g, b);
}
}
if (parent)
return parent->GetBackgroundColour();
return *wxWHITE;
}
void StaticBox::paintEvent(wxPaintEvent& evt)
{
// depending on your system you may need to look at double-buffered dcs
wxBufferedPaintDC dc(this);//wxPaintDC dc(this);
render(dc);
}
/*
* Here we do the actual rendering. I put it in a separate
* method so that it can work no matter what type of DC
* (e.g. wxPaintDC or wxClientDC) is used.
*/
void StaticBox::render(wxDC& dc)
{
doRender(dc);
}
void StaticBox::doRender(wxDC& dc)
{
wxSize size = GetSize();
int states = state_handler.states();
if (background_color2.count() == 0) {
if ((border_width && border_color.count() > 0) || background_color.count() > 0) {
wxRect rc(0, 0, size.x, size.y);
#ifdef __WXOSX__
// On Retina displays all controls are cut on 1px
if (dc.GetContentScaleFactor() > 1.)
rc.Deflate(1, 1);
#endif //__WXOSX__
if (radius > 0.) {
#if 0
DropDown::SetTransparentBG(dc, this);
#else
#ifdef __WXMSW__
wxColour bg_clr = GetParentBackgroundColor(m_parent);
dc.SetBrush(wxBrush(bg_clr));
dc.SetPen(wxPen(bg_clr));
dc.DrawRectangle(rc);
#endif
#endif
}
if (background_color.count() > 0)
dc.SetBrush(wxBrush(background_color.colorForStates(states)));
else
dc.SetBrush(wxBrush(GetBackgroundColour()));
if (border_width && border_color.count() > 0) {
#ifdef __WXOSX__
const double bw = (double)border_width;
#else
const double bw = dc.GetContentScaleFactor() * (double)border_width;
#endif //__WXOSX__
{
int d = floor(bw / 2.0);
int d2 = floor(bw - 1);
rc.x += d;
rc.width -= d2;
rc.y += d;
rc.height -= d2;
}
dc.SetPen(wxPen(border_color.colorForStates(states), bw));
} else {
dc.SetPen(wxPen(background_color.colorForStates(states)));
}
if (radius == 0.)
dc.DrawRectangle(rc);
else
dc.DrawRoundedRectangle(rc, radius - border_width);
}
}
else {
wxColor start = background_color.colorForStates(states);
wxColor stop = background_color2.colorForStates(states);
int r = start.Red(), g = start.Green(), b = start.Blue();
int dr = (int) stop.Red() - r, dg = (int) stop.Green() - g, db = (int) stop.Blue() - b;
int lr = 0, lg = 0, lb = 0;
for (int y = 0; y < size.y; ++y) {
dc.SetPen(wxPen(wxColor(r, g, b)));
dc.DrawLine(0, y, size.x, y);
lr += dr; while (lr >= size.y) { ++r, lr -= size.y; } while (lr <= -size.y) { --r, lr += size.y; }
lg += dg; while (lg >= size.y) { ++g, lg -= size.y; } while (lg <= -size.y) { --g, lg += size.y; }
lb += db; while (lb >= size.y) { ++b, lb -= size.y; } while (lb <= -size.y) { --b, lb += size.y; }
}
}
}

View File

@ -0,0 +1,59 @@
#ifndef slic3r_GUI_StaticBox_hpp_
#define slic3r_GUI_StaticBox_hpp_
#include "../wxExtensions.hpp"
#include "StateHandler.hpp"
#include <wx/window.h>
class StaticBox : public wxWindow
{
public:
StaticBox();
StaticBox(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = 0);
bool Create(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = 0);
void SetCornerRadius(double radius);
void SetBorderWidth(int width);
void SetBorderColor(StateColor const & color);
void SetBorderColorNormal(wxColor const &color);
virtual void SetBackgroundColor(StateColor const &color);
void SetBackgroundColorNormal(wxColor const &color);
void SetBackgroundColor2(StateColor const &color);
static wxColor GetParentBackgroundColor(wxWindow * parent);
protected:
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
virtual void doRender(wxDC& dc);
double radius;
int border_width = 1;
StateHandler state_handler;
StateColor border_color;
StateColor background_color;
StateColor background_color2;
DECLARE_EVENT_TABLE()
};
#endif // !slic3r_GUI_StaticBox_hpp_

View File

@ -0,0 +1,136 @@
#include "SwitchButton.hpp"
#include "../wxExtensions.hpp"
#include "../../Utils/MacDarkMode.hpp"
#include <wx/dcgraph.h>
#include <wx/dcmemory.h>
#include <wx/dcclient.h>
SwitchButton::SwitchButton(wxWindow* parent, const wxString& name, wxWindowID id)
: BitmapToggleButton(parent, name, id)
, m_on(this, "toggle_on", 28, 16)
, m_off(this, "toggle_off", 28, 16)
, text_color(std::pair{*wxWHITE, (int) StateColor::Checked}, std::pair{0x6B6B6B, (int) StateColor::Normal})
, track_color(0xD9D9D9)
, thumb_color(std::pair{0x00AE42, (int) StateColor::Checked}, std::pair{0xD9D9D9, (int) StateColor::Normal})
{
Rescale();
}
void SwitchButton::SetLabels(wxString const& lbl_on, wxString const& lbl_off)
{
labels[0] = lbl_on;
labels[1] = lbl_off;
Rescale();
}
void SwitchButton::SetTextColor(StateColor const& color)
{
text_color = color;
}
void SwitchButton::SetTrackColor(StateColor const& color)
{
track_color = color;
}
void SwitchButton::SetThumbColor(StateColor const& color)
{
thumb_color = color;
}
void SwitchButton::SetValue(bool value)
{
if (value != GetValue())
wxBitmapToggleButton::SetValue(value);
update();
}
void SwitchButton::Rescale()
{
if (!labels[0].IsEmpty()) {
#ifdef __WXOSX__
auto scale = Slic3r::GUI::mac_max_scaling_factor();
int BS = (int) scale;
#else
constexpr int BS = 1;
#endif
wxSize thumbSize;
wxSize trackSize;
wxClientDC dc(this);
#ifdef __WXOSX__
dc.SetFont(dc.GetFont().Scaled(scale));
#endif
wxSize textSize[2];
{
textSize[0] = dc.GetTextExtent(labels[0]);
textSize[1] = dc.GetTextExtent(labels[1]);
}
{
thumbSize = textSize[0];
auto size = textSize[1];
if (size.x > thumbSize.x) thumbSize.x = size.x;
else size.x = thumbSize.x;
thumbSize.x += BS * 12;
thumbSize.y += BS * 6;
trackSize.x = thumbSize.x + size.x + BS * 10;
trackSize.y = thumbSize.y + BS * 2;
auto maxWidth = GetMaxWidth();
#ifdef __WXOSX__
maxWidth *= scale;
#endif
if (trackSize.x > maxWidth) {
thumbSize.x -= (trackSize.x - maxWidth) / 2;
trackSize.x = maxWidth;
}
}
for (int i = 0; i < 2; ++i) {
wxMemoryDC memdc(&dc);
wxBitmap bmp(trackSize.x, trackSize.y);
memdc.SelectObject(bmp);
memdc.SetBackground(wxBrush(GetBackgroundColour()));
memdc.Clear();
memdc.SetFont(dc.GetFont());
auto state = i == 0 ? StateColor::Enabled : (StateColor::Checked | StateColor::Enabled);
{
#ifdef __WXMSW__
wxGCDC dc2(memdc);
#else
wxDC &dc2(memdc);
#endif
dc2.SetBrush(wxBrush(track_color.colorForStates(state)));
dc2.SetPen(wxPen(track_color.colorForStates(state)));
dc2.DrawRoundedRectangle(wxRect({0, 0}, trackSize), trackSize.y / 2);
dc2.SetBrush(wxBrush(thumb_color.colorForStates(StateColor::Checked | StateColor::Enabled)));
dc2.SetPen(wxPen(thumb_color.colorForStates(StateColor::Checked | StateColor::Enabled)));
dc2.DrawRoundedRectangle(wxRect({ i == 0 ? BS : (trackSize.x - thumbSize.x - BS), BS}, thumbSize), thumbSize.y / 2);
}
memdc.SetTextForeground(text_color.colorForStates(state ^ StateColor::Checked));
memdc.DrawText(labels[0], {BS + (thumbSize.x - textSize[0].x) / 2, BS + (thumbSize.y - textSize[0].y) / 2});
memdc.SetTextForeground(text_color.colorForStates(state));
memdc.DrawText(labels[1], {trackSize.x - thumbSize.x - BS + (thumbSize.x - textSize[1].x) / 2, BS + (thumbSize.y - textSize[1].y) / 2});
memdc.SelectObject(wxNullBitmap);
#ifdef __WXOSX__
bmp = wxBitmap(bmp.ConvertToImage(), -1, scale);
#endif
(i == 0 ? m_off : m_on).SetBitmap(bmp);
}
}
update();
}
void SwitchButton::SysColorChange()
{
m_on.sys_color_changed();
m_off.sys_color_changed();
update();
}
void SwitchButton::update()
{
SetBitmap((GetValue() ? m_on : m_off).bmp());
update_size();
}

View File

@ -0,0 +1,42 @@
#ifndef slic3r_GUI_SwitchButton_hpp_
#define slic3r_GUI_SwitchButton_hpp_
#include "../wxExtensions.hpp"
#include "StateColor.hpp"
#include "BitmapToggleButton.hpp"
class SwitchButton : public BitmapToggleButton
{
public:
SwitchButton(wxWindow * parent = NULL, const wxString& name = wxEmptyString, wxWindowID id = wxID_ANY);
public:
void SetLabels(wxString const & lbl_on, wxString const & lbl_off);
void SetTextColor(StateColor const &color);
void SetTrackColor(StateColor const &color);
void SetThumbColor(StateColor const &color);
void SetValue(bool value) override;
void Rescale();
void SysColorChange();
private:
void update() override;
private:
ScalableBitmap m_on;
ScalableBitmap m_off;
wxString labels[2];
StateColor text_color;
StateColor track_color;
StateColor thumb_color;
};
#endif // !slic3r_GUI_SwitchButton_hpp_

View File

@ -0,0 +1,324 @@
#include "TextInput.hpp"
#include "UIColors.hpp"
#include <wx/dcgraph.h>
#include <wx/panel.h>
#include "slic3r/GUI/GUI_App.hpp"
BEGIN_EVENT_TABLE(TextInput, wxPanel)
EVT_PAINT(TextInput::paintEvent)
END_EVENT_TABLE()
/*
* Called by the system of by wxWidgets when the panel needs
* to be redrawn. You can also trigger this call by
* calling Refresh()/Update().
*/
TextInput::TextInput()
: 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))
{
if (Slic3r::GUI::wxGetApp().suppress_round_corners())
radius = 0;
border_width = 1;
}
TextInput::TextInput(wxWindow * parent,
wxString text,
wxString label,
wxString icon,
const wxPoint &pos,
const wxSize & size,
long style)
: TextInput()
{
Create(parent, text, label, icon, pos, size, style);
}
void TextInput::Create(wxWindow * parent,
wxString text,
wxString label,
wxString icon,
const wxPoint &pos,
const wxSize & size,
long style)
{
text_ctrl = nullptr;
StaticBox::Create(parent, wxID_ANY, pos, size, style);
wxWindow::SetLabel(label);
state_handler.attach({&label_color, &text_color});
state_handler.update_binds();
text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {4, 4}, size, style | wxBORDER_NONE);
#ifdef __WXOSX__
text_ctrl->OSXDisableAllSmartSubstitutions();
#endif // __WXOSX__
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
if (parent) {
SetBackgroundColour(parent->GetBackgroundColour());
SetForegroundColour(parent->GetForegroundColour());
}
state_handler.attach_child(text_ctrl);
text_ctrl->Bind(wxEVT_KILL_FOCUS, [this](auto &e) {
OnEdit();
e.SetId(GetId());
ProcessEventLocally(e);
e.Skip();
});
text_ctrl->Bind(wxEVT_TEXT_ENTER, [this](auto &e) {
OnEdit();
e.SetId(GetId());
ProcessEventLocally(e);
});
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu
if (!icon.IsEmpty()) {
this->drop_down_icon = ScalableBitmap(this, icon.ToStdString(), 16);
}
messureSize();
}
void TextInput::SetCornerRadius(double radius)
{
this->radius = radius;
Refresh();
}
void TextInput::SetLabel(const wxString& label)
{
wxWindow::SetLabel(label);
messureSize();
Refresh();
}
bool TextInput::SetBackgroundColour(const wxColour& colour)
{
const int clr_background_disabled = Slic3r::GUI::wxGetApp().dark_mode() ? clr_background_disabled_dark : clr_background_disabled_light;
const StateColor clr_state( std::make_pair(clr_background_disabled, (int)StateColor::Disabled),
std::make_pair(clr_background_focused, (int)StateColor::Checked),
std::make_pair(colour, (int)StateColor::Focused),
std::make_pair(colour, (int)StateColor::Normal));
SetBackgroundColor(clr_state);
if (text_ctrl)
text_ctrl->SetBackgroundColour(colour);
return true;
}
bool TextInput::SetForegroundColour(const wxColour& colour)
{
const StateColor clr_state( std::make_pair(clr_foreground_disabled, (int)StateColor::Disabled),
std::make_pair(colour, (int)StateColor::Normal));
SetLabelColor(clr_state);
SetTextColor (clr_state);
return true;
}
void TextInput::SetValue(const wxString& value)
{
if (text_ctrl)
text_ctrl->SetValue(value);
}
wxString TextInput::GetValue()
{
if (text_ctrl)
return text_ctrl->GetValue();
return wxEmptyString;
}
void TextInput::SetSelection(long from, long to)
{
if (text_ctrl)
text_ctrl->SetSelection(from, to);
}
void TextInput::SetIcon(const wxBitmapBundle& icon_in)
{
icon = icon_in;
}
void TextInput::SetLabelColor(StateColor const &color)
{
label_color = color;
state_handler.update_binds();
}
void TextInput::SetTextColor(StateColor const& color)
{
text_color = color;
state_handler.update_binds();
if (text_ctrl)
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states()));
}
void TextInput::SetBGColor(StateColor const& color)
{
background_color = color;
state_handler.update_binds();
}
void TextInput::SetCtrlSize(wxSize const& size)
{
StaticBox::SetInitialSize(size);
Rescale();
}
void TextInput::Rescale()
{
if (text_ctrl)
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
messureSize();
Refresh();
}
bool TextInput::SetFont(const wxFont& font)
{
bool ret = StaticBox::SetFont(font);
if (text_ctrl)
return ret && text_ctrl->SetFont(font);
return ret;
}
bool TextInput::Enable(bool enable)
{
bool result = text_ctrl->Enable(enable) && wxWindow::Enable(enable);
if (result) {
wxCommandEvent e(EVT_ENABLE_CHANGED);
e.SetEventObject(this);
GetEventHandler()->ProcessEvent(e);
text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states()));
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states()));
}
return result;
}
void TextInput::SetMinSize(const wxSize& size)
{
wxSize size2 = size;
if (size2.y < 0) {
#ifdef __WXMAC__
if (GetPeer()) // peer is not ready in Create on mac
#endif
size2.y = GetSize().y;
}
wxWindow::SetMinSize(size2);
}
void TextInput::DoSetSize(int x, int y, int width, int height, int sizeFlags)
{
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
if (sizeFlags & wxSIZE_USE_EXISTING) return;
wxSize size = GetSize();
wxPoint textPos = {5, 0};
if (this->icon.IsOk()) {
wxSize szIcon = get_preferred_size(icon, m_parent);
textPos.x += szIcon.x;
}
wxSize dd_icon_size = wxSize(0,0);
if (this->drop_down_icon.bmp().IsOk())
dd_icon_size = this->drop_down_icon.GetSize();
bool align_right = GetWindowStyle() & wxRIGHT;
if (align_right)
textPos.x += labelSize.x;
if (text_ctrl) {
wxSize textSize = text_ctrl->GetSize();
wxClientDC dc(this);
const int r_shift = int((dd_icon_size.x == 0 ? 3. : 2.) * dc.GetContentScaleFactor());
textSize.x = size.x - textPos.x - labelSize.x - dd_icon_size.x - r_shift;
text_ctrl->SetSize(textSize);
text_ctrl->SetPosition({textPos.x, (size.y - textSize.y) / 2});
}
}
void TextInput::DoSetToolTipText(wxString const &tip)
{
wxWindow::DoSetToolTipText(tip);
text_ctrl->SetToolTip(tip);
}
void TextInput::paintEvent(wxPaintEvent &evt)
{
// depending on your system you may need to look at double-buffered dcs
wxPaintDC dc(this);
render(dc);
}
/*
* Here we do the actual rendering. I put it in a separate
* method so that it can work no matter what type of DC
* (e.g. wxPaintDC or wxClientDC) is used.
*/
void TextInput::render(wxDC& dc)
{
StaticBox::render(dc);
int states = state_handler.states();
wxSize size = GetSize();
bool align_right = GetWindowStyle() & wxRIGHT;
// start draw
wxPoint pt = {5, 0};
if (icon.IsOk()) {
wxSize szIcon = get_preferred_size(icon, m_parent);
pt.y = (size.y - szIcon.y) / 2;
#ifdef __WXGTK3__
dc.DrawBitmap(icon.GetBitmap(szIcon), pt);
#else
dc.DrawBitmap(icon.GetBitmapFor(m_parent), pt);
#endif
pt.x += szIcon.x + 5;
}
// drop_down_icon draw
wxPoint pt_r = {size.x, 0};
if (drop_down_icon.bmp().IsOk()) {
wxSize szIcon = drop_down_icon.GetSize();
pt_r.x -= szIcon.x + 2;
pt_r.y = (size.y - szIcon.y) / 2;
dc.DrawBitmap(drop_down_icon.get_bitmap(), pt_r);
}
auto text = wxWindow::GetLabel();
if (!text.IsEmpty()) {
wxSize textSize = text_ctrl->GetSize();
if (align_right) {
pt.x += textSize.x;
pt.y = (size.y + textSize.y) / 2 - labelSize.y;
} else {
if (pt.x + labelSize.x > pt_r.x)
text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, pt_r.x - pt.x);
pt.y = (size.y - labelSize.y) / 2;
}
dc.SetTextForeground(label_color.colorForStates(states));
dc.SetFont(GetFont());
dc.DrawText(text, pt);
}
}
void TextInput::messureSize()
{
wxSize size = GetSize();
wxClientDC dc(this);
labelSize = dc.GetTextExtent(wxWindow::GetLabel());
const wxSize textSize = text_ctrl->GetSize();
const wxSize iconSize = drop_down_icon.bmp().IsOk() ? drop_down_icon.GetSize() : wxSize(0, 0);
size.y = ((textSize.y > iconSize.y) ? textSize.y : iconSize.y) + 8;
wxSize minSize = size;
minSize.x = GetMinWidth();
SetMinSize(minSize);
SetSize(size);
}

View File

@ -0,0 +1,97 @@
#ifndef slic3r_GUI_TextInput_hpp_
#define slic3r_GUI_TextInput_hpp_
#include <wx/textctrl.h>
#include "StaticBox.hpp"
class TextInput : public wxNavigationEnabled<StaticBox>
{
wxSize labelSize;
wxBitmapBundle icon;
ScalableBitmap drop_down_icon;
StateColor label_color;
StateColor text_color;
wxTextCtrl* text_ctrl{nullptr};
static const int TextInputWidth = 200;
static const int TextInputHeight = 50;
public:
TextInput();
TextInput(wxWindow * parent,
wxString text,
wxString label = "",
wxString icon = "",
const wxPoint &pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = 0);
public:
void Create(wxWindow * parent,
wxString text,
wxString label = "",
wxString icon = "",
const wxPoint &pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = 0);
void SetCornerRadius(double radius);
void SetLabel(const wxString& label);
void SetIcon(const wxBitmapBundle& icon);
void SetLabelColor(StateColor const &color);
void SetBGColor(StateColor const &color);
void SetTextColor(StateColor const &color);
void SetCtrlSize(wxSize const& size);
virtual void Rescale();
bool SetFont(const wxFont &font) override;
virtual bool Enable(bool enable = true) override;
virtual void SetMinSize(const wxSize& size) override;
bool SetBackgroundColour(const wxColour &colour) override;
bool SetForegroundColour(const wxColour &colour) override;
wxTextCtrl *GetTextCtrl() { return text_ctrl; }
wxTextCtrl const *GetTextCtrl() const { return text_ctrl; }
void SetValue(const wxString& value);
wxString GetValue();
void SetSelection(long from, long to);
protected:
virtual void OnEdit() {}
virtual void DoSetSize(
int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
void DoSetToolTipText(wxString const &tip) override;
StateColor GetTextColor() const { return text_color; }
StateColor GetBorderColor() const { return border_color; }
private:
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
void messureSize();
DECLARE_EVENT_TABLE()
};
#endif // !slic3r_GUI_TextInput_hpp_

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

@ -15,17 +15,20 @@
#include <wx/sizer.h> #include <wx/sizer.h>
int scale(const int val) { return val * Slic3r::GUI::wxGetApp().em_unit(); } using namespace Slic3r::GUI;
int scale(const int val) { return val * wxGetApp().em_unit(); }
int ITEM_WIDTH() { return scale(6); } int ITEM_WIDTH() { return scale(6); }
static void update_ui(wxWindow* window) static void update_ui(wxWindow* window)
{ {
Slic3r::GUI::wxGetApp().UpdateDarkUI(window); wxGetApp().UpdateDarkUI(window);
} }
RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters)
: wxDialog(parent, wxID_ANY, _(L("Ramming customization")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE/* | wxRESIZE_BORDER*/) : wxDialog(parent, wxID_ANY, _(L("Ramming customization")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE/* | wxRESIZE_BORDER*/)
{ {
SetFont(wxGetApp().normal_font());
update_ui(this); update_ui(this);
m_panel_ramming = new RammingPanel(this,parameters); m_panel_ramming = new RammingPanel(this,parameters);
@ -42,7 +45,10 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters)
auto main_sizer = new wxBoxSizer(wxVERTICAL); auto main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->Add(m_panel_ramming, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5); main_sizer->Add(m_panel_ramming, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5);
main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxTOP | wxBOTTOM, 10); auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
wxGetApp().SetWindowVariantForButton(buttons->GetAffirmativeButton());
wxGetApp().SetWindowVariantForButton(buttons->GetCancelButton());
main_sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP | wxBOTTOM, 10);
SetSizer(main_sizer); SetSizer(main_sizer);
main_sizer->SetSizeHints(this); main_sizer->SetSizeHints(this);
@ -56,8 +62,7 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters)
EndModal(wxID_OK); EndModal(wxID_OK);
},wxID_OK); },wxID_OK);
this->Show(); this->Show();
// wxMessageDialog dlg(this, _(L("Ramming denotes the rapid extrusion just before a tool change in a single-extruder MM printer. Its purpose is to " MessageDialog dlg(this, _(L("Ramming denotes the rapid extrusion just before a tool change in a single-extruder MM printer. Its purpose is to "
Slic3r::GUI::MessageDialog dlg(this, _(L("Ramming denotes the rapid extrusion just before a tool change in a single-extruder MM printer. Its purpose is to "
"properly shape the end of the unloaded filament so it does not prevent insertion of the new filament and can itself " "properly shape the end of the unloaded filament so it does not prevent insertion of the new filament and can itself "
"be reinserted later. This phase is important and different materials can require different extrusion speeds to get " "be reinserted later. This phase is important and different materials can require different extrusion speeds to get "
"the good shape. For this reason, the extrusion rates during ramming are adjustable.\n\nThis is an expert-level " "the good shape. For this reason, the extrusion rates during ramming are adjustable.\n\nThis is an expert-level "
@ -104,10 +109,11 @@ RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters)
#endif #endif
sizer_chart->Add(m_chart, 0, wxALL, 5); sizer_chart->Add(m_chart, 0, wxALL, 5);
m_widget_time = new wxSpinCtrlDouble(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),style,0.,5.0,3.,0.5); m_widget_time = new ::SpinInputDouble(this,"", wxEmptyString, wxDefaultPosition, wxSize(ITEM_WIDTH(), -1), style, 0., 5., 3., 0.5);
m_widget_volume = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),style,0,10000,0); m_widget_time->SetDigits(2);
m_widget_ramming_line_width_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),style,10,200,100); m_widget_volume = new ::SpinInput(this,"",wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),style,0,10000,0);
m_widget_ramming_step_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),style,10,200,100); m_widget_ramming_line_width_multiplicator = new ::SpinInput(this,"",wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),style,10,200,100);
m_widget_ramming_step_multiplicator = new ::SpinInput(this,"",wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),style,10,200,100);
#ifdef _WIN32 #ifdef _WIN32
update_ui(m_widget_time->GetText()); update_ui(m_widget_time->GetText());
@ -131,7 +137,6 @@ RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters)
sizer_param->Add(gsizer_param, 0, wxTOP, scale(10)); sizer_param->Add(gsizer_param, 0, wxTOP, scale(10));
m_widget_time->SetValue(m_chart->get_time()); m_widget_time->SetValue(m_chart->get_time());
m_widget_time->SetDigits(2);
m_widget_volume->SetValue(m_chart->get_volume()); m_widget_volume->SetValue(m_chart->get_volume());
m_widget_volume->Disable(); m_widget_volume->Disable();
m_widget_ramming_line_width_multiplicator->SetValue(m_ramming_line_width_multiplicator); m_widget_ramming_line_width_multiplicator->SetValue(m_ramming_line_width_multiplicator);
@ -147,8 +152,9 @@ RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters)
sizer->SetSizeHints(this); sizer->SetSizeHints(this);
SetSizer(sizer); SetSizer(sizer);
m_widget_time->Bind(wxEVT_TEXT,[this](wxCommandEvent&) {m_chart->set_xy_range(m_widget_time->GetValue(),-1);}); m_widget_time->Bind(wxEVT_SPINCTRL,[this](wxCommandEvent&) { m_chart->set_xy_range(m_widget_time->GetValue(),-1); });
m_widget_time->Bind(wxEVT_CHAR,[](wxKeyEvent&){}); // do nothing - prevents the user to change the value m_widget_time->Bind(wxEVT_CHAR,[](wxKeyEvent&){}); // do nothing - prevents the user to change the value
m_widget_time->GetText()->Bind(wxEVT_CHAR,[](wxKeyEvent&){}); // do nothing - prevents the user to change the value
m_widget_volume->Bind(wxEVT_CHAR,[](wxKeyEvent&){}); // do nothing - prevents the user to change the value m_widget_volume->Bind(wxEVT_CHAR,[](wxKeyEvent&){}); // do nothing - prevents the user to change the value
Bind(EVT_WIPE_TOWER_CHART_CHANGED,[this](wxCommandEvent&) {m_widget_volume->SetValue(m_chart->get_volume()); m_widget_time->SetValue(m_chart->get_time());} ); Bind(EVT_WIPE_TOWER_CHART_CHANGED,[this](wxCommandEvent&) {m_widget_volume->SetValue(m_chart->get_volume()); m_widget_time->SetValue(m_chart->get_time());} );
Refresh(true); // erase background Refresh(true); // erase background
@ -178,9 +184,11 @@ std::string RammingPanel::get_parameters()
WipingDialog::WipingDialog(wxWindow* parent, const std::vector<float>& matrix, const std::vector<float>& extruders, const std::vector<std::string>& extruder_colours) WipingDialog::WipingDialog(wxWindow* parent, const std::vector<float>& matrix, const std::vector<float>& extruders, const std::vector<std::string>& extruder_colours)
: wxDialog(parent, wxID_ANY, _(L("Wipe tower - Purging volume adjustment")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE/* | wxRESIZE_BORDER*/) : wxDialog(parent, wxID_ANY, _(L("Wipe tower - Purging volume adjustment")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE/* | wxRESIZE_BORDER*/)
{ {
SetFont(wxGetApp().normal_font());
update_ui(this); update_ui(this);
auto widget_button = new wxButton(this,wxID_ANY,"-",wxPoint(0,0),wxDefaultSize); auto widget_button = new wxButton(this,wxID_ANY,"-",wxPoint(0,0),wxDefaultSize);
update_ui(widget_button); update_ui(widget_button);
wxGetApp().SetWindowVariantForButton(widget_button);
m_panel_wiping = new WipingPanel(this,matrix,extruders, extruder_colours, widget_button); m_panel_wiping = new WipingPanel(this,matrix,extruders, extruder_colours, widget_button);
auto main_sizer = new wxBoxSizer(wxVERTICAL); auto main_sizer = new wxBoxSizer(wxVERTICAL);
@ -191,7 +199,10 @@ WipingDialog::WipingDialog(wxWindow* parent, const std::vector<float>& matrix, c
main_sizer->Add(m_panel_wiping, 0, wxEXPAND | wxALL, 5); main_sizer->Add(m_panel_wiping, 0, wxEXPAND | wxALL, 5);
main_sizer->Add(widget_button, 0, wxALIGN_CENTER_HORIZONTAL | wxCENTER | wxBOTTOM, 5); main_sizer->Add(widget_button, 0, wxALIGN_CENTER_HORIZONTAL | wxCENTER | wxBOTTOM, 5);
main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
wxGetApp().SetWindowVariantForButton(buttons->GetAffirmativeButton());
wxGetApp().SetWindowVariantForButton(buttons->GetCancelButton());
main_sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10);
SetSizer(main_sizer); SetSizer(main_sizer);
main_sizer->SetSizeHints(this); main_sizer->SetSizeHints(this);
@ -314,9 +325,9 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector<float>& matrix, con
gridsizer_simple->Add(new wxStaticText(m_page_simple, wxID_ANY, wxString(_(L("unloaded")))), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); gridsizer_simple->Add(new wxStaticText(m_page_simple, wxID_ANY, wxString(_(L("unloaded")))), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
gridsizer_simple->Add(new wxStaticText(m_page_simple,wxID_ANY,wxString(_(L("loaded")))), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); gridsizer_simple->Add(new wxStaticText(m_page_simple,wxID_ANY,wxString(_(L("loaded")))), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
auto add_spin_ctrl = [this](std::vector<wxSpinCtrl*>& vec, float initial) auto add_spin_ctrl = [this](std::vector<::SpinInput*>& vec, float initial)
{ {
wxSpinCtrl* spin_ctrl = new wxSpinCtrl(m_page_simple, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(ITEM_WIDTH(), -1), style | wxALIGN_RIGHT, 0, 300, (int)initial); ::SpinInput* spin_ctrl = new ::SpinInput(m_page_simple, "", wxEmptyString, wxDefaultPosition, wxSize(ITEM_WIDTH(), -1), style | wxALIGN_RIGHT, 0, 300, (int)initial);
update_ui(spin_ctrl); update_ui(spin_ctrl);
vec.push_back(spin_ctrl); vec.push_back(spin_ctrl);
@ -444,8 +455,7 @@ bool WipingPanel::advanced_matches_simple() {
// Switches the dialog from simple to advanced mode and vice versa // Switches the dialog from simple to advanced mode and vice versa
void WipingPanel::toggle_advanced(bool user_action) { void WipingPanel::toggle_advanced(bool user_action) {
if (m_advanced && !advanced_matches_simple() && user_action) { if (m_advanced && !advanced_matches_simple() && user_action) {
// if (wxMessageDialog(this,wxString(_(L("Switching to simple settings will discard changes done in the advanced mode!\n\nDo you want to proceed?"))), if (MessageDialog(this, _L("Switching to simple settings will discard changes done in the advanced mode!\n\nDo you want to proceed?"),
if (Slic3r::GUI::MessageDialog(this, _L("Switching to simple settings will discard changes done in the advanced mode!\n\nDo you want to proceed?"),
_L("Warning"),wxYES_NO|wxICON_EXCLAMATION).ShowModal() != wxID_YES) _L("Warning"),wxYES_NO|wxICON_EXCLAMATION).ShowModal() != wxID_YES)
return; return;
} }

View File

@ -12,6 +12,7 @@
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
#include "RammingChart.hpp" #include "RammingChart.hpp"
#include "Widgets/SpinInput.hpp"
class RammingPanel : public wxPanel { class RammingPanel : public wxPanel {
@ -22,10 +23,10 @@ public:
private: private:
Chart* m_chart = nullptr; Chart* m_chart = nullptr;
wxSpinCtrl* m_widget_volume = nullptr; ::SpinInput* m_widget_volume = nullptr;
wxSpinCtrl* m_widget_ramming_line_width_multiplicator = nullptr; ::SpinInput* m_widget_ramming_line_width_multiplicator = nullptr;
wxSpinCtrl* m_widget_ramming_step_multiplicator = nullptr; ::SpinInput* m_widget_ramming_step_multiplicator = nullptr;
wxSpinCtrlDouble* m_widget_time = nullptr; ::SpinInputDouble* m_widget_time = nullptr;
int m_ramming_step_multiplicator; int m_ramming_step_multiplicator;
int m_ramming_line_width_multiplicator; int m_ramming_line_width_multiplicator;
@ -60,8 +61,8 @@ private:
void fill_in_matrix(); void fill_in_matrix();
bool advanced_matches_simple(); bool advanced_matches_simple();
std::vector<wxSpinCtrl*> m_old; std::vector<::SpinInput*> m_old;
std::vector<wxSpinCtrl*> m_new; std::vector<::SpinInput*> m_new;
std::vector<std::vector<wxTextCtrl*>> edit_boxes; std::vector<std::vector<wxTextCtrl*>> edit_boxes;
std::vector<wxColour> m_colours; std::vector<wxColour> m_colours;
unsigned int m_number_of_extruders = 0; unsigned int m_number_of_extruders = 0;

View File

@ -372,9 +372,9 @@ void edit_tooltip(wxString& tooltip)
/* Function for rescale of buttons in Dialog under MSW if dpi is changed. /* Function for rescale of buttons in Dialog under MSW if dpi is changed.
* btn_ids - vector of buttons identifiers * btn_ids - vector of buttons identifiers
*/ */
void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<int>& btn_ids) void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<int>& btn_ids, double height_koef/* = 1.*/)
{ {
const wxSize& btn_size = wxSize(-1, int(2.5f * em_unit + 0.5f)); const wxSize& btn_size = wxSize(-1, int(2.5 * em_unit * height_koef + 0.5f));
for (int btn_id : btn_ids) { for (int btn_id : btn_ids) {
// There is a case [FirmwareDialog], when we have wxControl instead of wxButton // There is a case [FirmwareDialog], when we have wxControl instead of wxButton
@ -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

@ -50,11 +50,11 @@ void enable_menu_item(wxUpdateUIEvent& evt, std::function<bool()> const cb_condi
class wxDialog; class wxDialog;
void edit_tooltip(wxString& tooltip); void edit_tooltip(wxString& tooltip);
void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<int>& btn_ids); void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<int>& btn_ids, double height_koef = 1.);
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};
}; };