diff options
author | bubnikv <bubnikv@gmail.com> | 2019-04-26 18:42:51 +0300 |
---|---|---|
committer | bubnikv <bubnikv@gmail.com> | 2019-04-26 18:42:51 +0300 |
commit | 16560f6e27854cfb915218f7e9af22d30aa49ab1 (patch) | |
tree | c4a6390cfd4027fbd3745028a5d4281910acc46e /src/slic3r | |
parent | 6526a8fcafaf2453e5b69ef65409a1bf728b63de (diff) | |
parent | 127a78d953bcfcc5d617a42520eae9dc68db96ac (diff) |
Merge remote-tracking branch 'remotes/origin/master' into vb_wold_object_manipulation
Diffstat (limited to 'src/slic3r')
53 files changed, 2387 insertions, 1365 deletions
diff --git a/src/slic3r/GUI/AboutDialog.cpp b/src/slic3r/GUI/AboutDialog.cpp index 86b12a95f..b1a2556e7 100644 --- a/src/slic3r/GUI/AboutDialog.cpp +++ b/src/slic3r/GUI/AboutDialog.cpp @@ -32,8 +32,11 @@ void AboutDialogLogo::onRepaint(wxEvent &event) } AboutDialog::AboutDialog() - : wxDialog(NULL, wxID_ANY, wxString::Format(_(L("About %s")), SLIC3R_APP_NAME), wxDefaultPosition, wxDefaultSize, wxCAPTION) + : DPIDialog(NULL, wxID_ANY, wxString::Format(_(L("About %s")), SLIC3R_APP_NAME), wxDefaultPosition, + wxDefaultSize, /*wxCAPTION*/wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { + SetFont(wxGetApp().normal_font()); + wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); SetBackgroundColour(bgr_clr); wxBoxSizer* hsizer = new wxBoxSizer(wxHORIZONTAL); @@ -42,8 +45,9 @@ AboutDialog::AboutDialog() main_sizer->Add(hsizer, 0, wxEXPAND | wxALL, 20); // logo - auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap(this, "Slic3r_192px.png", 192)); - hsizer->Add(logo, 1, wxALIGN_CENTER_VERTICAL); + m_logo_bitmap = ScalableBitmap(this, "Slic3r_192px.png", 192); + m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bitmap.bmp()); + hsizer->Add(m_logo, 1, wxALIGN_CENTER_VERTICAL); wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL); hsizer->Add(vsizer, 2, wxEXPAND|wxLEFT, 20); @@ -51,8 +55,7 @@ AboutDialog::AboutDialog() // title { wxStaticText* title = new wxStaticText(this, wxID_ANY, SLIC3R_APP_NAME, wxDefaultPosition, wxDefaultSize); - wxFont title_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); - title_font.SetWeight(wxFONTWEIGHT_BOLD); + wxFont title_font = GUI::wxGetApp().bold_font(); title_font.SetFamily(wxFONTFAMILY_ROMAN); title_font.SetPointSize(24); title->SetFont(title_font); @@ -63,9 +66,9 @@ AboutDialog::AboutDialog() { auto version_string = _(L("Version"))+ " " + std::string(SLIC3R_VERSION); wxStaticText* version = new wxStaticText(this, wxID_ANY, version_string.c_str(), wxDefaultPosition, wxDefaultSize); - wxFont version_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + wxFont version_font = GetFont(); #ifdef __WXMSW__ - version_font.SetPointSize(9); + version_font.SetPointSize(version_font.GetPointSize()-1); #else version_font.SetPointSize(11); #endif @@ -74,18 +77,18 @@ AboutDialog::AboutDialog() } // text - wxHtmlWindow* 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*/); { - html->SetMinSize(wxSize(-1, 16 * wxGetApp().em_unit())); - wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + m_html->SetMinSize(wxSize(-1, 16 * wxGetApp().em_unit())); + wxFont font = GetFont(); const auto text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); const int fs = font.GetPointSize()-1; int size[] = {fs,fs,fs,fs,fs,fs,fs}; - html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); - html->SetBorders(2); + m_html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); + m_html->SetBorders(2); const auto text = wxString::Format( "<html>" "<body bgcolor= %s link= %s>" @@ -101,9 +104,9 @@ AboutDialog::AboutDialog() "</font>" "</body>" "</html>", bgr_clr_str, text_clr_str, text_clr_str); - html->SetPage(text); - vsizer->Add(html, 1, wxEXPAND | wxBOTTOM, 10); - html->Bind(wxEVT_HTML_LINK_CLICKED, &AboutDialog::onLinkClicked, this); + m_html->SetPage(text); + vsizer->Add(m_html, 1, wxEXPAND | wxBOTTOM, 10); + m_html->Bind(wxEVT_HTML_LINK_CLICKED, &AboutDialog::onLinkClicked, this); } wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCLOSE); @@ -118,6 +121,31 @@ AboutDialog::AboutDialog() main_sizer->SetSizeHints(this); } +void AboutDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + m_logo_bitmap.msw_rescale(); + m_logo->SetBitmap(m_logo_bitmap.bmp()); + + const wxFont& font = GetFont(); + const int fs = font.GetPointSize() - 1; + int font_size[] = { fs, fs, fs, fs, fs, fs, fs }; + m_html->SetFonts(font.GetFaceName(), font.GetFaceName(), font_size); + + const int& em = em_unit(); + + msw_buttons_rescale(this, em, { wxID_CLOSE }); + + m_html->SetMinSize(wxSize(-1, 16 * em)); + m_html->Refresh(); + + const wxSize& size = wxSize(65 * em, 30 * em); + + SetMinSize(size); + Fit(); + + Refresh(); +} + void AboutDialog::onLinkClicked(wxHtmlLinkEvent &event) { wxLaunchDefaultBrowser(event.GetLinkInfo().GetHref()); diff --git a/src/slic3r/GUI/AboutDialog.hpp b/src/slic3r/GUI/AboutDialog.hpp index 01f7564c5..7019b21f6 100644 --- a/src/slic3r/GUI/AboutDialog.hpp +++ b/src/slic3r/GUI/AboutDialog.hpp @@ -7,6 +7,9 @@ #include <wx/intl.h> #include <wx/html/htmlwin.h> +#include "GUI_Utils.hpp" +#include "wxExtensions.hpp" + namespace Slic3r { namespace GUI { @@ -20,10 +23,16 @@ private: void onRepaint(wxEvent &event); }; -class AboutDialog : public wxDialog +class AboutDialog : public DPIDialog { + ScalableBitmap m_logo_bitmap; + wxHtmlWindow* m_html; + wxStaticBitmap* m_logo; public: AboutDialog(); + +protected: + void on_dpi_changed(const wxRect &suggested_rect) override; private: void onLinkClicked(wxHtmlLinkEvent &event); diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 7bbf1ac7f..00ebf117c 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -18,6 +18,7 @@ namespace GUI { void BedShapeDialog::build_dialog(ConfigOptionPoints* default_pt) { + SetFont(wxGetApp().normal_font()); m_panel = new BedShapePanel(this); m_panel->build_panel(default_pt); @@ -36,6 +37,22 @@ void BedShapeDialog::build_dialog(ConfigOptionPoints* default_pt) })); } +void BedShapeDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + const int& em = em_unit(); + m_panel->m_shape_options_book->SetMinSize(wxSize(25 * em, -1)); + + for (auto og : m_panel->m_optgroups) + og->msw_rescale(); + + const wxSize& size = wxSize(50 * em, -1); + + SetMinSize(size); + SetSize(size); + + Refresh(); +} + void BedShapePanel::build_panel(ConfigOptionPoints* default_pt) { // on_change(nullptr); @@ -125,7 +142,7 @@ ConfigOptionsGroupShp BedShapePanel::init_shape_options_page(wxString title) ConfigOptionsGroupShp optgroup; optgroup = std::make_shared<ConfigOptionsGroup>(panel, _(L("Settings"))); - optgroup->label_width = 10*wxGetApp().em_unit();//100; + optgroup->label_width = 10; optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) { update_shape(); }; diff --git a/src/slic3r/GUI/BedShapeDialog.hpp b/src/slic3r/GUI/BedShapeDialog.hpp index 538fccc34..72e50a05d 100644 --- a/src/slic3r/GUI/BedShapeDialog.hpp +++ b/src/slic3r/GUI/BedShapeDialog.hpp @@ -16,11 +16,8 @@ namespace GUI { using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>; class BedShapePanel : public wxPanel { - wxChoicebook* m_shape_options_book; Bed_2D* m_canvas; - std::vector <ConfigOptionsGroupShp> m_optgroups; - public: BedShapePanel(wxWindow* parent) : wxPanel(parent, wxID_ANY) {} ~BedShapePanel() {} @@ -35,18 +32,25 @@ public: // Returns the resulting bed shape polygon. This value will be stored to the ini file. std::vector<Vec2d> GetValue() { return m_canvas->m_bed_shape; } + + wxChoicebook* m_shape_options_book; + std::vector <ConfigOptionsGroupShp> m_optgroups; + }; -class BedShapeDialog : public wxDialog +class BedShapeDialog : public DPIDialog { BedShapePanel* m_panel; public: - BedShapeDialog(wxWindow* parent) : wxDialog(parent, wxID_ANY, _(L("Bed Shape")), + BedShapeDialog(wxWindow* parent) : DPIDialog(parent, wxID_ANY, _(L("Bed Shape")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) {} ~BedShapeDialog() {} void build_dialog(ConfigOptionPoints* default_pt); std::vector<Vec2d> GetValue() { return m_panel->GetValue(); } + +protected: + void on_dpi_changed(const wxRect &suggested_rect) override; }; } // GUI diff --git a/src/slic3r/GUI/BitmapCache.cpp b/src/slic3r/GUI/BitmapCache.cpp index bb4145107..db116a5dd 100644 --- a/src/slic3r/GUI/BitmapCache.cpp +++ b/src/slic3r/GUI/BitmapCache.cpp @@ -23,6 +23,8 @@ void BitmapCache::clear() { for (std::pair<const std::string, wxBitmap*> &bitmap : m_map) delete bitmap.second; + + m_map.clear(); } static wxBitmap wxImage_to_wxBitmap_with_alpha(wxImage &&image, float scale = 1.0f) @@ -259,9 +261,6 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_ wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency) { - width = width * 0.1f * Slic3r::GUI::wxGetApp().em_unit() + 0.5f; - height = height * 0.1f * Slic3r::GUI::wxGetApp().em_unit() + 0.5f; - wxImage image(width, height); image.InitAlpha(); unsigned char* imgdata = image.GetData(); diff --git a/src/slic3r/GUI/ButtonsDescription.cpp b/src/slic3r/GUI/ButtonsDescription.cpp index fb4c24286..9def34749 100644 --- a/src/slic3r/GUI/ButtonsDescription.cpp +++ b/src/slic3r/GUI/ButtonsDescription.cpp @@ -7,6 +7,7 @@ #include "GUI.hpp" #include "GUI_App.hpp" #include "I18N.hpp" +#include "wxExtensions.hpp" namespace Slic3r { namespace GUI { @@ -23,7 +24,7 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, t_icon_descriptions* ic // Icon description for (auto pair : *m_icon_descriptions) { - auto icon = new wxStaticBitmap(this, wxID_ANY, *pair.first); + auto icon = new wxStaticBitmap(this, wxID_ANY, /***/pair.first->bmp()); grid_sizer->Add(icon, -1, wxALIGN_CENTRE_VERTICAL); std::istringstream f(pair.second); diff --git a/src/slic3r/GUI/ButtonsDescription.hpp b/src/slic3r/GUI/ButtonsDescription.hpp index 81baaf191..69005d2a5 100644 --- a/src/slic3r/GUI/ButtonsDescription.hpp +++ b/src/slic3r/GUI/ButtonsDescription.hpp @@ -4,10 +4,12 @@ #include <wx/dialog.h> #include <vector> +class ScalableBitmap; + namespace Slic3r { namespace GUI { -using t_icon_descriptions = std::vector<std::pair<wxBitmap*, std::string>>; +using t_icon_descriptions = std::vector<std::pair<ScalableBitmap*, std::string>>; class ButtonsDescription : public wxDialog { @@ -15,8 +17,6 @@ class ButtonsDescription : public wxDialog public: ButtonsDescription(wxWindow* parent, t_icon_descriptions* icon_descriptions); ~ButtonsDescription() {} - - }; } // GUI diff --git a/src/slic3r/GUI/ConfigSnapshotDialog.cpp b/src/slic3r/GUI/ConfigSnapshotDialog.cpp index 205e84f57..bdf80c27c 100644 --- a/src/slic3r/GUI/ConfigSnapshotDialog.cpp +++ b/src/slic3r/GUI/ConfigSnapshotDialog.cpp @@ -6,6 +6,7 @@ #include "libslic3r/Utils.hpp" #include "GUI_App.hpp" +#include "wxExtensions.hpp" namespace Slic3r { namespace GUI { @@ -66,7 +67,7 @@ static wxString generate_html_row(const Config::Snapshot &snapshot, bool row_eve } if (! compatible) { - text += "<p align=\"right\">" + _(L("Incompatible with this Slic3r")) + "</p>"; + text += "<p align=\"right\">" + wxString::Format(_(L("Incompatible with this %s")), SLIC3R_APP_NAME) + "</p>"; } else if (! snapshot_active) text += "<p align=\"right\"><a href=\"" + snapshot.id + "\">" + _(L("Activate")) + "</a></p>"; @@ -95,21 +96,26 @@ static wxString generate_html_page(const Config::SnapshotDB &snapshot_db, const } ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db, const wxString &on_snapshot) - : wxDialog(NULL, wxID_ANY, _(L("Configuration Snapshots")), wxDefaultPosition, + : DPIDialog(NULL, wxID_ANY, _(L("Configuration Snapshots")), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 40 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX) { + this->SetFont(wxGetApp().normal_font()); this->SetBackgroundColour(*wxWHITE); wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL); this->SetSizer(vsizer); // text - wxHtmlWindow* html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO); + html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO); { - wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + wxFont font = wxGetApp().normal_font();//wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); #ifdef __WXMSW__ - int size[] = {8,8,8,8,11,11,11}; + const int fs = font.GetPointSize(); + const int fs1 = static_cast<int>(0.8f*fs); + const int fs2 = static_cast<int>(1.1f*fs); + int size[] = {fs1, fs1, fs1, fs1, fs2, fs2, fs2}; +// int size[] = {8,8,8,8,11,11,11}; #else int size[] = {11,11,11,11,14,14,14}; #endif @@ -127,6 +133,28 @@ ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db vsizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3); } +void ConfigSnapshotDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + wxFont font = GetFont(); + const int fs = font.GetPointSize(); + const int fs1 = static_cast<int>(0.8f*fs); + const int fs2 = static_cast<int>(1.1f*fs); + int font_size[] = { fs1, fs1, fs1, fs1, fs2, fs2, fs2 }; + + html->SetFonts(font.GetFaceName(), font.GetFaceName(), font_size); + html->Refresh(); + + const int& em = em_unit(); + + msw_buttons_rescale(this, em, { wxID_CLOSE}); + + const wxSize& size = wxSize(45 * em, 40 * em); + SetMinSize(size); + Fit(); + + Refresh(); +} + void ConfigSnapshotDialog::onLinkClicked(wxHtmlLinkEvent &event) { m_snapshot_to_activate = event.GetLinkInfo().GetHref(); diff --git a/src/slic3r/GUI/ConfigSnapshotDialog.hpp b/src/slic3r/GUI/ConfigSnapshotDialog.hpp index f43fb8ed1..9b8b69ecf 100644 --- a/src/slic3r/GUI/ConfigSnapshotDialog.hpp +++ b/src/slic3r/GUI/ConfigSnapshotDialog.hpp @@ -2,6 +2,7 @@ #define slic3r_GUI_ConfigSnapshotDialog_hpp_ #include "GUI.hpp" +#include "GUI_Utils.hpp" #include <wx/wx.h> #include <wx/intl.h> @@ -14,18 +15,23 @@ namespace Config { class SnapshotDB; } -class ConfigSnapshotDialog : public wxDialog +class ConfigSnapshotDialog : public DPIDialog { public: ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db, const wxString &id); const std::string& snapshot_to_activate() const { return m_snapshot_to_activate; } +protected: + void on_dpi_changed(const wxRect &suggested_rect) override; + private: void onLinkClicked(wxHtmlLinkEvent &event); void onCloseDialog(wxEvent &); // If set, it contains a snapshot ID to be restored after the dialog closes. std::string m_snapshot_to_activate; + + wxHtmlWindow* html; }; } // namespace GUI diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 5da320830..93cf1c73f 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -18,6 +18,7 @@ #include <wx/dataview.h> #include <wx/notebook.h> #include <wx/display.h> +#include <wx/filefn.h> #include <wx/debug.h> #include "libslic3r/Utils.hpp" @@ -81,11 +82,17 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt for (const auto &model : models) { if (! filter(model)) { continue; } - wxBitmap bitmap(GUI::from_u8(Slic3r::var((boost::format("printers/%1%_%2%.png") % vendor.id % model.id).str())), wxBITMAP_TYPE_PNG); + wxBitmap bitmap; + int bitmap_width = 0; + const wxString bitmap_file = GUI::from_u8(Slic3r::var((boost::format("printers/%1%_%2%.png") % vendor.id % model.id).str())); + if (wxFileExists(bitmap_file)) { + bitmap.LoadFile(bitmap_file, wxBITMAP_TYPE_PNG); + bitmap_width = bitmap.GetWidth(); + } auto *title = new wxStaticText(this, wxID_ANY, model.name, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); title->SetFont(font_name); - const int wrap_width = std::max((int)MODEL_MIN_WRAP, bitmap.GetWidth()); + const int wrap_width = std::max((int)MODEL_MIN_WRAP, bitmap_width); title->Wrap(wrap_width); current_row_width += wrap_width; @@ -187,6 +194,9 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt title_sizer->Add(sel_all_std, 0, wxRIGHT, BTN_SPACING); title_sizer->Add(sel_all, 0, wxRIGHT, BTN_SPACING); title_sizer->Add(sel_none); + + // fill button indexes used later for buttons rescaling + m_button_indexes = { sel_all_std->GetId(), sel_all->GetId(), sel_none->GetId() }; } sizer->Add(title_sizer, 0, wxEXPAND | wxBOTTOM, BTN_SPACING); @@ -399,16 +409,20 @@ PageUpdate::PageUpdate(ConfigWizard *parent) auto *box_slic3r = new wxCheckBox(this, wxID_ANY, _(L("Check for application updates"))); box_slic3r->SetValue(app_config->get("version_check") == "1"); append(box_slic3r); - append_text(wxString::Format(_(L("If enabled, Slic3r checks for new versions of %s online. When a new version becomes available, " - "a notification is displayed at the next application startup (never during program usage). " - "This is only a notification mechanisms, no automatic installation is done.")), SLIC3R_APP_NAME)); + append_text(wxString::Format(_(L( + "If enabled, %s checks for new application versions online. When a new version becomes available, " + "a notification is displayed at the next application startup (never during program usage). " + "This is only a notification mechanisms, no automatic installation is done.")), SLIC3R_APP_NAME)); append_spacer(VERTICAL_SPACING); auto *box_presets = new wxCheckBox(this, wxID_ANY, _(L("Update built-in Presets automatically"))); box_presets->SetValue(app_config->get("preset_update") == "1"); append(box_presets); - append_text(_(L("If enabled, Slic3r downloads updates of built-in system presets in the background. These updates are downloaded into a separate temporary location. When a new preset version becomes available it is offered at application startup."))); + append_text(wxString::Format(_(L( + "If enabled, %s downloads updates of built-in system presets in the background." + "These updates are downloaded into a separate temporary location." + "When a new preset version becomes available it is offered at application startup.")), SLIC3R_APP_NAME)); const auto text_bold = _(L("Updates are never applied without user's consent and never overwrite user's customized settings.")); auto *label_bold = new wxStaticText(this, wxID_ANY, text_bold); label_bold->SetFont(boldfont); @@ -635,19 +649,24 @@ void PageTemperatures::apply_custom_config(DynamicPrintConfig &config) ConfigWizardIndex::ConfigWizardIndex(wxWindow *parent) : wxPanel(parent) - // XXX: use create_scaled_bitmap: + /* #ys_FIXME_delete_after_testing by VK , bg(GUI::from_u8(Slic3r::var("Slic3r_192px_transparent.png")), wxBITMAP_TYPE_PNG) , bullet_black(GUI::from_u8(Slic3r::var("bullet_black.png")), wxBITMAP_TYPE_PNG) , bullet_blue(GUI::from_u8(Slic3r::var("bullet_blue.png")), wxBITMAP_TYPE_PNG) , bullet_white(GUI::from_u8(Slic3r::var("bullet_white.png")), wxBITMAP_TYPE_PNG) + */ + , bg(ScalableBitmap(parent, "Slic3r_192px_transparent.png", 192)) + , bullet_black(ScalableBitmap(parent, "bullet_black.png")) + , bullet_blue(ScalableBitmap(parent, "bullet_blue.png")) + , bullet_white(ScalableBitmap(parent, "bullet_white.png")) , item_active(0) , item_hover(-1) , last_page((size_t)-1) { - SetMinSize(bg.GetSize()); + SetMinSize(bg.bmp().GetSize()); const wxSize size = GetTextExtent("m"); - em = size.x; + em_w = size.x; em_h = size.y; // Add logo bitmap. @@ -656,7 +675,10 @@ ConfigWizardIndex::ConfigWizardIndex(wxWindow *parent) // In some cases it didn't work at all. And so wxStaticBitmap is used here instead, // because it has all the platform quirks figured out. auto *sizer = new wxBoxSizer(wxVERTICAL); + /* #ys_FIXME_delete_after_testing by VK auto *logo = new wxStaticBitmap(this, wxID_ANY, bg); + */ + logo = new wxStaticBitmap(this, wxID_ANY, bg.bmp()); sizer->AddStretchSpacer(); sizer->Add(logo); SetSizer(sizer); @@ -764,8 +786,12 @@ void ConfigWizardIndex::on_paint(wxPaintEvent & evt) wxPaintDC dc(this); + /* #ys_FIXME_delete_after_testing by VK const auto bullet_w = bullet_black.GetSize().GetWidth(); const auto bullet_h = bullet_black.GetSize().GetHeight(); + */ + const auto bullet_w = bullet_black.bmp().GetSize().GetWidth(); + const auto bullet_h = bullet_black.bmp().GetSize().GetHeight(); const int yoff_icon = bullet_h < em_h ? (em_h - bullet_h) / 2 : 0; const int yoff_text = bullet_h > em_h ? (bullet_h - em_h) / 2 : 0; const int yinc = item_height(); @@ -775,15 +801,21 @@ void ConfigWizardIndex::on_paint(wxPaintEvent & evt) unsigned y = 0; for (size_t i = 0; i < items.size(); i++) { const Item& item = items[i]; - unsigned x = em/2 + item.indent * em; + unsigned x = em_w/2 + item.indent * em_w; if (i == item_active || item_hover >= 0 && i == (size_t)item_hover) { + /*#ys_FIXME_delete_after_testing by VK dc.DrawBitmap(bullet_blue, x, y + yoff_icon, false); } else if (i < item_active) { dc.DrawBitmap(bullet_black, x, y + yoff_icon, false); } else if (i > item_active) { dc.DrawBitmap(bullet_white, x, y + yoff_icon, false); } + */ + dc.DrawBitmap(bullet_blue.bmp(), x, y + yoff_icon, false); + } + else if (i < item_active) { dc.DrawBitmap(bullet_black.bmp(), x, y + yoff_icon, false); } + else if (i > item_active) { dc.DrawBitmap(bullet_white.bmp(), x, y + yoff_icon, false); } - x += + bullet_w + em/2; + x += + bullet_w + em_w/2; const auto text_size = dc.GetTextExtent(item.label); dc.DrawText(item.label, x, y + yoff_text); @@ -794,6 +826,7 @@ void ConfigWizardIndex::on_paint(wxPaintEvent & evt) if (GetMinSize().x < index_width) { CallAfter([this, index_width]() { SetMinSize(wxSize(index_width, GetMinSize().y)); + Refresh(); }); } } @@ -813,6 +846,18 @@ void ConfigWizardIndex::on_mouse_move(wxMouseEvent &evt) evt.Skip(); } +void ConfigWizardIndex::msw_rescale() +{ + bg.msw_rescale(); + SetMinSize(bg.bmp().GetSize()); + logo->SetBitmap(bg.bmp()); + + bullet_black.msw_rescale(); + bullet_blue.msw_rescale(); + bullet_white.msw_rescale(); + Refresh(); +} + // priv @@ -987,9 +1032,10 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese // Public ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) - : wxDialog(parent, wxID_ANY, _(name().ToStdString()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) + : DPIDialog(parent, wxID_ANY, _(name().ToStdString()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) , p(new priv(this)) { + this->SetFont(wxGetApp().normal_font()); p->run_reason = reason; p->load_vendors(); @@ -1014,8 +1060,8 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) topsizer->AddSpacer(INDEX_MARGIN); topsizer->Add(p->hscroll, 1, wxEXPAND); - auto *btn_sel_all = new wxButton(this, wxID_ANY, _(L("Select all standard printers"))); - p->btnsizer->Add(btn_sel_all); + p->btn_sel_all = new wxButton(this, wxID_ANY, _(L("Select all standard printers"))); + p->btnsizer->Add(p->btn_sel_all); p->btn_prev = new wxButton(this, wxID_ANY, _(L("< &Back"))); p->btn_next = new wxButton(this, wxID_ANY, _(L("&Next >"))); @@ -1073,7 +1119,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) 9*disp_rect.width / 10, 9*disp_rect.height / 10); - const int width_hint = p->index->GetSize().GetWidth() + p->page_fff->get_width() + 300; // XXX: magic constant, I found no better solution + const int width_hint = p->index->GetSize().GetWidth() + p->page_fff->get_width() + 30 * p->em(); // XXX: magic constant, I found no better solution if (width_hint < window_rect.width) { window_rect.x += (window_rect.width - width_hint) / 2; window_rect.width = width_hint; @@ -1087,7 +1133,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) p->btn_finish->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { this->EndModal(wxID_OK); }); p->btn_finish->Hide(); - btn_sel_all->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { + p->btn_sel_all->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { p->page_fff->select_all(true, false); p->page_msla->select_all(true, false); p->index->go_to(p->page_update); @@ -1133,5 +1179,25 @@ const wxString& ConfigWizard::name(const bool from_menu/* = false*/) return from_menu ? config_wizard_name_menu : config_wizard_name; } +void ConfigWizard::on_dpi_changed(const wxRect &suggested_rect) +{ + p->index->msw_rescale(); + + const int& em = em_unit(); + + msw_buttons_rescale(this, em, { wxID_APPLY, + wxID_CANCEL, + p->btn_sel_all->GetId(), + p->btn_next->GetId(), + p->btn_prev->GetId() }); + + for (auto printer_picker: p->page_fff->printer_pickers) + msw_buttons_rescale(this, em, printer_picker->get_button_indexes()); + + // FIXME VK SetSize(???) + + Refresh(); +} + } } diff --git a/src/slic3r/GUI/ConfigWizard.hpp b/src/slic3r/GUI/ConfigWizard.hpp index c9ee05529..b707e525b 100644 --- a/src/slic3r/GUI/ConfigWizard.hpp +++ b/src/slic3r/GUI/ConfigWizard.hpp @@ -5,6 +5,8 @@ #include <wx/dialog.h> +#include "GUI_Utils.hpp" + namespace Slic3r { class PresetBundle; @@ -13,7 +15,7 @@ class PresetUpdater; namespace GUI { -class ConfigWizard: public wxDialog +class ConfigWizard: public DPIDialog { public: // Why is the Wizard run @@ -35,6 +37,10 @@ public: bool run(PresetBundle *preset_bundle, const PresetUpdater *updater); static const wxString& name(const bool from_menu = false); + +protected: + void on_dpi_changed(const wxRect &suggested_rect) override ; + private: struct priv; std::unique_ptr<priv> p; diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index df7602adf..95411e2aa 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -69,8 +69,11 @@ struct PrinterPicker: wxPanel void on_checkbox(const Checkbox *cbox, bool checked); int get_width() const { return width; } + const std::vector<int>& get_button_indexes() { return m_button_indexes; } private: int width; + + std::vector<int> m_button_indexes; }; struct ConfigWizardPage: wxPanel @@ -210,7 +213,9 @@ public: void go_to(ConfigWizardPage *page); void clear(); + void msw_rescale(); + int em() const { return em_w; } private: struct Item { @@ -221,20 +226,29 @@ private: bool operator==(ConfigWizardPage *page) const { return this->page == page; } }; - int em; + int em_w; int em_h; - + /* #ys_FIXME_delete_after_testing by VK const wxBitmap bg; const wxBitmap bullet_black; const wxBitmap bullet_blue; const wxBitmap bullet_white; + */ + ScalableBitmap bg; + ScalableBitmap bullet_black; + ScalableBitmap bullet_blue; + ScalableBitmap bullet_white; + wxStaticBitmap* logo; std::vector<Item> items; size_t item_active; ssize_t item_hover; size_t last_page; - int item_height() const { return std::max(bullet_black.GetSize().GetHeight(), em) + em; } + /* #ys_FIXME_delete_after_testing by VK + int item_height() const { return std::max(bullet_black.GetSize().GetHeight(), em_w) + em_w; } + */ + int item_height() const { return std::max(bullet_black.bmp().GetSize().GetHeight(), em_w) + em_w; } void on_paint(wxPaintEvent &evt); void on_mouse_move(wxMouseEvent &evt); @@ -256,6 +270,7 @@ struct ConfigWizard::priv wxBoxSizer *btnsizer = nullptr; ConfigWizardPage *page_current = nullptr; ConfigWizardIndex *index = nullptr; + wxButton *btn_sel_all = nullptr; wxButton *btn_prev = nullptr; wxButton *btn_next = nullptr; wxButton *btn_finish = nullptr; @@ -286,6 +301,8 @@ struct ConfigWizard::priv void on_custom_setup(bool custom_wanted); void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater); + + int em() const { return index->em(); } }; diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index d8ed9f27a..cb414fa79 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -21,21 +21,11 @@ wxString double_to_string(double const value, const int max_precision /*= 4*/) void Field::PostInitialize() { auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - m_Undo_btn = new MyButton(m_parent, wxID_ANY, "", wxDefaultPosition,wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); - m_Undo_to_sys_btn = new MyButton(m_parent, wxID_ANY, "", wxDefaultPosition,wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); - if (wxMSW) { - m_Undo_btn->SetBackgroundColour(color); - m_Undo_btn->SetBackgroundStyle(wxBG_STYLE_PAINT); - m_Undo_to_sys_btn->SetBackgroundColour(color); - m_Undo_to_sys_btn->SetBackgroundStyle(wxBG_STYLE_PAINT); - } - m_Undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_initial_value(); })); - m_Undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_sys_value(); })); + m_Undo_btn = new RevertButton(m_parent, "bullet_white.png"); + m_Undo_to_sys_btn = new RevertButton(m_parent, "bullet_white.png"); - //set default bitmap - wxBitmap bmp = create_scaled_bitmap(m_parent, "bullet_white.png"); - set_undo_bitmap(&bmp); - set_undo_to_sys_bitmap(&bmp); + m_Undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_initial_value(); })); + m_Undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_sys_value(); })); switch (m_opt.type) { @@ -53,6 +43,9 @@ void Field::PostInitialize() break; } + // initialize m_unit_value + m_em_unit = em_unit(m_parent); + BUILD(); } @@ -95,6 +88,7 @@ wxString Field::get_tooltip_text(const wxString& default_string) { wxString tooltip_text(""); wxString tooltip = _(m_opt.tooltip); + edit_tooltip(tooltip); if (tooltip.length() > 0) tooltip_text = tooltip + "\n" + _(L("default value")) + "\t: " + (boost::iends_with(m_opt_id, "_gcode") ? "\n" : "") + default_string + @@ -200,8 +194,8 @@ bool is_defined_input_value(wxWindow* win, const ConfigOptionType& type) void TextCtrl::BUILD() { auto size = wxSize(wxDefaultSize); - if (m_opt.height >= 0) size.SetHeight(m_opt.height); - if (m_opt.width >= 0) size.SetWidth(m_opt.width); + if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); + if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); wxString text_value = wxString(""); @@ -345,6 +339,21 @@ boost::any& TextCtrl::get_value() return m_value; } +void TextCtrl::msw_rescale() +{ + Field::msw_rescale(); + auto size = wxSize(wxDefaultSize); + if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); + if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); + + if (size != wxDefaultSize) + { + wxTextCtrl* field = dynamic_cast<wxTextCtrl*>(window); + field->SetMinSize(size); + } + +} + void TextCtrl::enable() { dynamic_cast<wxTextCtrl*>(window)->Enable(); dynamic_cast<wxTextCtrl*>(window)->SetEditable(true); } void TextCtrl::disable() { dynamic_cast<wxTextCtrl*>(window)->Disable(); dynamic_cast<wxTextCtrl*>(window)->SetEditable(false); } @@ -359,15 +368,16 @@ void TextCtrl::change_field_value(wxEvent& event) void CheckBox::BUILD() { auto size = wxSize(wxDefaultSize); - if (m_opt.height >= 0) size.SetHeight(m_opt.height); - if (m_opt.width >= 0) size.SetWidth(m_opt.width); + if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); + if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); bool check_value = m_opt.type == coBool ? m_opt.default_value->getBool() : m_opt.type == coBools ? static_cast<const ConfigOptionBools*>(m_opt.default_value)->get_at(m_opt_idx) : false; - auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size); + // Set Label as a string of at least one space simbol to correct system scaling of a CheckBox + auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(" "), wxDefaultPosition, size); temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); temp->SetBackgroundStyle(wxBG_STYLE_PAINT); temp->SetValue(check_value); @@ -392,12 +402,20 @@ boost::any& CheckBox::get_value() return m_value; } +void CheckBox::msw_rescale() +{ + Field::msw_rescale(); + + wxCheckBox* field = dynamic_cast<wxCheckBox*>(window); + field->SetMinSize(wxSize(-1, int(1.5f*field->GetFont().GetPixelSize().y +0.5f))); +} + int undef_spin_val = -9999; //! Probably, It's not necessary void SpinCtrl::BUILD() { auto size = wxSize(wxDefaultSize); - if (m_opt.height >= 0) size.SetHeight(m_opt.height); - if (m_opt.width >= 0) size.SetWidth(m_opt.width); + if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); + if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); wxString text_value = wxString(""); int default_value = 0; @@ -475,6 +493,11 @@ void SpinCtrl::BUILD() { else tmp_value = -9999; #ifdef __WXOSX__ propagate_value(); + + // Forcibly set the input value for SpinControl, since the value + // inserted from the clipboard is not updated under OSX + if (tmp_value > -9999) + dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value); #endif }), temp->GetId()); @@ -492,10 +515,18 @@ void SpinCtrl::propagate_value() on_change_field(); } +void SpinCtrl::msw_rescale() +{ + Field::msw_rescale(); + + wxSpinCtrl* field = dynamic_cast<wxSpinCtrl*>(window); + field->SetMinSize(wxSize(-1, int(1.9f*field->GetFont().GetPixelSize().y))); +} + void Choice::BUILD() { - wxSize size(15 * wxGetApp().em_unit(), -1); - if (m_opt.height >= 0) size.SetHeight(m_opt.height); - if (m_opt.width >= 0) size.SetWidth(m_opt.width); + wxSize size(m_width * m_em_unit, -1); + if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); + if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); wxBitmapComboBox* temp; if (!m_opt.gui_type.empty() && m_opt.gui_type.compare("select_open") != 0) { @@ -804,11 +835,55 @@ boost::any& Choice::get_value() return m_value; } +void Choice::msw_rescale() +{ + Field::msw_rescale(); + + wxBitmapComboBox* field = dynamic_cast<wxBitmapComboBox*>(window); + + const wxString selection = field->GetString(field->GetSelection()); + + /* To correct scaling (set new controll size) of a wxBitmapCombobox + * we need to refill control with new bitmaps. So, in our case : + * 1. clear conrol + * 2. add content + * 3. add scaled "empty" bitmap to the at least one item + */ + field->Clear(); + wxSize size(wxDefaultSize); + size.SetWidth((m_opt.width > 0 ? m_opt.width : m_width) * m_em_unit); + + // Set rescaled min height to correct layout + field->SetMinSize(wxSize(-1, int(1.5f*field->GetFont().GetPixelSize().y + 0.5f))); + // Set rescaled size + field->SetSize(size); + + size_t idx, counter = idx = 0; + if (m_opt.enum_labels.empty() && m_opt.enum_values.empty()) {} + else{ + for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels) { + const wxString& str = _(el); + field->Append(str); + if (el.compare(selection) == 0) + idx = counter; + ++counter; + } + } + + wxBitmap empty_bmp(1, field->GetFont().GetPixelSize().y + 2); + empty_bmp.SetWidth(0); + field->SetItemBitmap(0, empty_bmp); + + idx == m_opt.enum_values.size() ? + field->SetValue(selection) : + field->SetSelection(idx); +} + void ColourPicker::BUILD() { auto size = wxSize(wxDefaultSize); - if (m_opt.height >= 0) size.SetHeight(m_opt.height); - if (m_opt.width >= 0) size.SetWidth(m_opt.width); + if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); + if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); // Validate the color wxString clr_str(static_cast<const ConfigOptionStrings*>(m_opt.default_value)->get_at(m_opt_idx)); @@ -843,7 +918,7 @@ void PointCtrl::BUILD() { auto temp = new wxBoxSizer(wxHORIZONTAL); - const wxSize field_size(4 * wxGetApp().em_unit(), -1); + const wxSize field_size(4 * m_em_unit, -1); auto default_pt = static_cast<const ConfigOptionPoints*>(m_opt.default_value)->values.at(0); double val = default_pt(0); @@ -886,6 +961,16 @@ void PointCtrl::BUILD() y_textctrl->SetToolTip(get_tooltip_text(X+", "+Y)); } +void PointCtrl::msw_rescale() +{ + Field::msw_rescale(); + + const wxSize field_size(4 * m_em_unit, -1); + + x_textctrl->SetMinSize(field_size); + y_textctrl->SetMinSize(field_size); +} + void PointCtrl::propagate_value(wxTextCtrl* win) { if (!win->GetValue().empty()) @@ -931,8 +1016,8 @@ boost::any& PointCtrl::get_value() void StaticText::BUILD() { auto size = wxSize(wxDefaultSize); - if (m_opt.height >= 0) size.SetHeight(m_opt.height); - if (m_opt.width >= 0) size.SetWidth(m_opt.width); + if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); + if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); const wxString legend(static_cast<const ConfigOptionString*>(m_opt.default_value)->value); auto temp = new wxStaticText(m_parent, wxID_ANY, legend, wxDefaultPosition, size, wxST_ELLIPSIZE_MIDDLE); @@ -946,6 +1031,21 @@ void StaticText::BUILD() temp->SetToolTip(get_tooltip_text(legend)); } +void StaticText::msw_rescale() +{ + Field::msw_rescale(); + + auto size = wxSize(wxDefaultSize); + if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); + if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); + + if (size != wxDefaultSize) + { + wxStaticText* field = dynamic_cast<wxStaticText*>(window); + field->SetSize(size); + } +} + void SliderCtrl::BUILD() { auto size = wxSize(wxDefaultSize); diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 128d60d47..88ea39036 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -19,6 +19,7 @@ #include "libslic3r/Utils.hpp" #include "GUI.hpp" +#include "wxExtensions.hpp" #ifdef __WXMSW__ #define wxMSW true @@ -36,19 +37,24 @@ using t_back_to_init = std::function<void(const std::string&)>; wxString double_to_string(double const value, const int max_precision = 4); -class MyButton : public wxButton +class RevertButton : public ScalableButton { bool hidden = false; // never show button if it's hidden ones public: - MyButton() {} - MyButton(wxWindow* parent, wxWindowID id, const wxString& label = wxEmptyString, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxTextCtrlNameStr) - { - this->Create(parent, id, label, pos, size, style, validator, name); - } +// RevertButton() {} +// RevertButton(wxWindow* parent, wxWindowID id, const wxString& label = wxEmptyString, +// const wxPoint& pos = wxDefaultPosition, +// const wxSize& size = wxDefaultSize, long style = 0, +// const wxValidator& validator = wxDefaultValidator, +// const wxString& name = wxTextCtrlNameStr) +// { +// this->Create(parent, id, label, pos, size, style, validator, name); +// } + RevertButton( + wxWindow *parent, + const std::string& icon_name = "" + ) : + ScalableButton(parent, wxID_ANY, icon_name) {} // overridden from wxWindow base class virtual bool @@ -154,19 +160,19 @@ public: return std::move(p); //!p; } - bool set_undo_bitmap(const wxBitmap *bmp) { + bool set_undo_bitmap(const ScalableBitmap *bmp) { if (m_undo_bitmap != bmp) { m_undo_bitmap = bmp; - m_Undo_btn->SetBitmap(*bmp); + m_Undo_btn->SetBitmap_(*bmp); return true; } return false; } - bool set_undo_to_sys_bitmap(const wxBitmap *bmp) { + bool set_undo_to_sys_bitmap(const ScalableBitmap *bmp) { if (m_undo_to_sys_bitmap != bmp) { m_undo_to_sys_bitmap = bmp; - m_Undo_to_sys_btn->SetBitmap(*bmp); + m_Undo_to_sys_btn->SetBitmap_(*bmp); return true; } return false; @@ -211,15 +217,23 @@ public: m_side_text = side_text; } + virtual void msw_rescale() { + m_Undo_to_sys_btn->msw_rescale(); + m_Undo_btn->msw_rescale(); + + // update em_unit value + m_em_unit = em_unit(m_parent); + } + protected: - MyButton* m_Undo_btn = nullptr; + RevertButton* m_Undo_btn = nullptr; // Bitmap and Tooltip text for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one. - const wxBitmap* m_undo_bitmap = nullptr; - const wxString* m_undo_tooltip = nullptr; - MyButton* m_Undo_to_sys_btn = nullptr; + const ScalableBitmap* m_undo_bitmap = nullptr; + const wxString* m_undo_tooltip = nullptr; + RevertButton* m_Undo_to_sys_btn = nullptr; // Bitmap and Tooltip text for m_Undo_to_sys_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one. - const wxBitmap* m_undo_to_sys_bitmap = nullptr; - const wxString* m_undo_to_sys_tooltip = nullptr; + const ScalableBitmap* m_undo_to_sys_bitmap = nullptr; + const wxString* m_undo_to_sys_tooltip = nullptr; wxStaticText* m_Label = nullptr; // Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one. @@ -230,6 +244,8 @@ protected: // current value boost::any m_value; + int m_em_unit; + bool bEnterPressed = false; friend class OptionsGroup; @@ -273,6 +289,8 @@ public: } boost::any& get_value() override; + + void msw_rescale() override; virtual void enable(); virtual void disable(); @@ -301,6 +319,8 @@ public: } boost::any& get_value() override; + void msw_rescale() override; + void enable() override { dynamic_cast<wxCheckBox*>(window)->Enable(); } void disable() override { dynamic_cast<wxCheckBox*>(window)->Disable(); } wxWindow* getWindow() override { return window; } @@ -337,6 +357,8 @@ public: return m_value = tmp_value; } + void msw_rescale() override; + void enable() override { dynamic_cast<wxSpinCtrl*>(window)->Enable(); } void disable() override { dynamic_cast<wxSpinCtrl*>(window)->Disable(); } wxWindow* getWindow() override { return window; } @@ -344,6 +366,7 @@ public: class Choice : public Field { using Field::Field; + int m_width{ 15 }; public: Choice(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {} Choice(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} @@ -363,6 +386,8 @@ public: void set_values(const std::vector<std::string> &values); boost::any& get_value() override; + void msw_rescale() override; + void enable() override { dynamic_cast<wxBitmapComboBox*>(window)->Enable(); }; void disable() override{ dynamic_cast<wxBitmapComboBox*>(window)->Disable(); }; wxWindow* getWindow() override { return window; } @@ -414,6 +439,8 @@ public: void set_value(const boost::any& value, bool change_event = false); boost::any& get_value() override; + void msw_rescale() override; + void enable() override { x_textctrl->Enable(); y_textctrl->Enable(); } @@ -446,6 +473,8 @@ public: boost::any& get_value()override { return m_value; } + void msw_rescale() override; + void enable() override { dynamic_cast<wxStaticText*>(window)->Enable(); }; void disable() override{ dynamic_cast<wxStaticText*>(window)->Disable(); }; wxWindow* getWindow() override { return window; } diff --git a/src/slic3r/GUI/FirmwareDialog.cpp b/src/slic3r/GUI/FirmwareDialog.cpp index 8095a3237..5de5626db 100644 --- a/src/slic3r/GUI/FirmwareDialog.cpp +++ b/src/slic3r/GUI/FirmwareDialog.cpp @@ -18,6 +18,7 @@ #include "MsgDialog.hpp" #include "../Utils/HexFile.hpp" #include "../Utils/Serial.hpp" +#include "wxExtensions.hpp" // wx includes need to come after asio because of the WinSock.h problem #include "FirmwareDialog.hpp" @@ -118,6 +119,10 @@ struct FirmwareDialog::priv wxTimer timer_pulse; + int min_width; + int min_height; + int min_height_expanded; + // Async modal dialog during flashing std::mutex mutex; int modal_response; @@ -732,23 +737,21 @@ const char* FirmwareDialog::priv::avr109_dev_name(Avr109Pid usb_pid) { // Public FirmwareDialog::FirmwareDialog(wxWindow *parent) : - wxDialog(parent, wxID_ANY, _(L("Firmware flasher")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), + GUI::DPIDialog(parent, wxID_ANY, _(L("Firmware flasher")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), p(new priv(this)) { - enum { - DIALOG_MARGIN = 15, - SPACING = 10, - MIN_WIDTH = 50, - MIN_HEIGHT = 18, - MIN_HEIGHT_EXPANDED = 40, - }; - const int em = GUI::wxGetApp().em_unit(); - int min_width = MIN_WIDTH * em; - int min_height = MIN_HEIGHT * em; - int min_height_expanded = MIN_HEIGHT_EXPANDED * em; - - wxFont status_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + p->min_width = MIN_WIDTH * em; + p->min_height = MIN_HEIGHT * em; + p->min_height_expanded = MIN_HEIGHT_EXPANDED * em; + + /* get current font from application, + * because of wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) function + * returns font for primary Display + */ + const wxFont& font = GUI::wxGetApp().normal_font(); + SetFont(font); + wxFont status_font = font;//wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); status_font.MakeBold(); wxFont mono_font(wxFontInfo().Family(wxFONTFAMILY_TELETYPE)); mono_font.MakeSmaller(); @@ -819,10 +822,10 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) : auto *topsizer = new wxBoxSizer(wxVERTICAL); topsizer->Add(panel, 1, wxEXPAND | wxALL, DIALOG_MARGIN); - SetMinSize(wxSize(min_width, min_height)); + SetMinSize(wxSize(p->min_width, p->min_height)); SetSizerAndFit(topsizer); const auto size = GetSize(); - SetSize(std::max(size.GetWidth(), static_cast<int>(min_width)), std::max(size.GetHeight(), static_cast<int>(min_height))); + SetSize(std::max(size.GetWidth(), static_cast<int>(p->min_width)), std::max(size.GetHeight(), static_cast<int>(p->min_height))); Layout(); SetEscapeId(wxID_CLOSE); // To close the dialog using "Esc" button @@ -838,11 +841,11 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) : p->spoiler->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, [=](wxCollapsiblePaneEvent &evt) { if (evt.GetCollapsed()) { - this->SetMinSize(wxSize(min_width, min_height)); + this->SetMinSize(wxSize(p->min_width, p->min_height)); const auto new_height = this->GetSize().GetHeight() - this->p->txt_stdout->GetSize().GetHeight(); this->SetSize(this->GetSize().GetWidth(), new_height); } else { - this->SetMinSize(wxSize(min_width, min_height_expanded)); + this->SetMinSize(wxSize(p->min_width, p->min_height_expanded)); } this->Layout(); @@ -897,5 +900,25 @@ void FirmwareDialog::run(wxWindow *parent) dialog.ShowModal(); } +void FirmwareDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + const int& em = em_unit(); + + msw_buttons_rescale(this, em, { p->btn_close->GetId(), + p->btn_rescan->GetId(), + p->btn_flash->GetId(), + p->hex_picker->GetPickerCtrl()->GetId() + }); + + p->min_width = MIN_WIDTH * em; + p->min_height = MIN_HEIGHT * em; + p->min_height_expanded = MIN_HEIGHT_EXPANDED * em; + + const int min_height = p->spoiler->IsExpanded() ? p->min_height_expanded : p->min_height; + SetMinSize(wxSize(p->min_width, min_height)); + Fit(); + + Refresh(); +} } diff --git a/src/slic3r/GUI/FirmwareDialog.hpp b/src/slic3r/GUI/FirmwareDialog.hpp index ad048bf5d..7c688d379 100644 --- a/src/slic3r/GUI/FirmwareDialog.hpp +++ b/src/slic3r/GUI/FirmwareDialog.hpp @@ -4,13 +4,22 @@ #include <memory> #include <wx/dialog.h> +#include "GUI_Utils.hpp" namespace Slic3r { -class FirmwareDialog: public wxDialog +class FirmwareDialog: public GUI::DPIDialog { + enum { + DIALOG_MARGIN = 15, + SPACING = 10, + MIN_WIDTH = 50, + MIN_HEIGHT = /*18*/25, + MIN_HEIGHT_EXPANDED = 40, + }; + public: FirmwareDialog(wxWindow *parent); FirmwareDialog(FirmwareDialog &&) = delete; @@ -20,6 +29,9 @@ public: ~FirmwareDialog(); static void run(wxWindow *parent); + +protected: + void on_dpi_changed(const wxRect &suggested_rect) override; private: struct priv; std::unique_ptr<priv> p; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f8859807f..478cbf1aa 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -703,6 +703,7 @@ void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool m_warnings.erase(it); if (m_warnings.empty()) { // nothing remains to be shown reset(); + m_msg_text = "";// save information for rescaling return; } } @@ -723,6 +724,10 @@ void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool } _generate(text, canvas, red_colored); // GUI::GLTexture::reset() is called at the beginning of generate(...) + + // save information for rescaling + m_msg_text = text; + m_is_colored_red = red_colored; } @@ -789,9 +794,16 @@ bool GLCanvas3D::WarningTexture::_generate(const std::string& msg_utf8, const GL wxString msg = GUI::from_u8(msg_utf8); wxMemoryDC memDC; + +#ifdef __WXMSW__ + // set scaled application normal font as default font + wxFont font = wxGetApp().normal_font(); +#else // select default font const float scale = canvas.get_canvas_size().get_scale_factor(); wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale); +#endif + font.MakeLarger(); font.MakeBold(); memDC.SetFont(font); @@ -892,6 +904,14 @@ void GLCanvas3D::WarningTexture::render(const GLCanvas3D& canvas) const } } +void GLCanvas3D::WarningTexture::msw_rescale(const GLCanvas3D& canvas) +{ + if (m_msg_text.empty()) + return; + + _generate(m_msg_text, canvas, m_is_colored_red); +} + const unsigned char GLCanvas3D::LegendTexture::Squares_Border_Color[3] = { 64, 64, 64 }; const unsigned char GLCanvas3D::LegendTexture::Default_Background_Color[3] = { (unsigned char)(DEFAULT_BG_LIGHT_COLOR[0] * 255.0f), (unsigned char)(DEFAULT_BG_LIGHT_COLOR[1] * 255.0f), (unsigned char)(DEFAULT_BG_LIGHT_COLOR[2] * 255.0f) }; const unsigned char GLCanvas3D::LegendTexture::Error_Background_Color[3] = { (unsigned char)(ERROR_BG_LIGHT_COLOR[0] * 255.0f), (unsigned char)(ERROR_BG_LIGHT_COLOR[1] * 255.0f), (unsigned char)(ERROR_BG_LIGHT_COLOR[2] * 255.0f) }; @@ -961,13 +981,16 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c const int scaled_square_contour = Px_Square_Contour * scale; const int scaled_border = Px_Border * scale; - // select default font - wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale_gl); #ifdef __WXMSW__ + // set scaled application normal font as default font + wxFont font = wxGetApp().normal_font(); + // Disabling ClearType works, but the font returned is very different (much thicker) from the default. // msw_disable_cleartype(font); bool cleartype = is_font_cleartype(font); #else + // select default font + wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale_gl); bool cleartype = false; #endif /* __WXMSW__ */ @@ -3190,6 +3213,11 @@ double GLCanvas3D::get_size_proportional_to_max_bed_size(double factor) const return factor * m_bed.get_bounding_box().max_size(); } +void GLCanvas3D::msw_rescale() +{ + m_warning_texture.msw_rescale(*this); +} + bool GLCanvas3D::_is_shown_on_screen() const { return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false; @@ -3834,7 +3862,8 @@ void GLCanvas3D::_render_gizmos_overlay() const #if ENABLE_RETINA_GL m_gizmos.set_overlay_scale(m_retina_helper->get_scale_factor()); #else - m_gizmos.set_overlay_scale(m_canvas->GetContentScaleFactor()); +// m_gizmos.set_overlay_scale(m_canvas->GetContentScaleFactor()); + m_gizmos.set_overlay_scale(wxGetApp().em_unit()*0.1f);//! #ys_FIXME_experiment #endif /* __WXMSW__ */ m_gizmos.render_overlay(*this, m_selection); @@ -3846,7 +3875,8 @@ void GLCanvas3D::_render_toolbar() const #if ENABLE_RETINA_GL m_toolbar.set_scale(m_retina_helper->get_scale_factor()); #else - m_toolbar.set_scale(m_canvas->GetContentScaleFactor()); +// m_toolbar.set_scale(m_canvas->GetContentScaleFactor()); + m_toolbar.set_scale(wxGetApp().em_unit()*0.1f);//! #ys_FIXME_experiment #endif // ENABLE_RETINA_GL Size cnv_size = get_canvas_size(); @@ -3909,7 +3939,8 @@ void GLCanvas3D::_render_view_toolbar() const #if ENABLE_RETINA_GL m_view_toolbar.set_scale(m_retina_helper->get_scale_factor()); #else - m_view_toolbar.set_scale(m_canvas->GetContentScaleFactor()); +// m_view_toolbar.set_scale(m_canvas->GetContentScaleFactor()); + m_view_toolbar.set_scale(wxGetApp().em_unit()*0.1f); //! #ys_FIXME_experiment #endif // ENABLE_RETINA_GL Size cnv_size = get_canvas_size(); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index e81d46f11..8abc0378e 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -353,6 +353,9 @@ private: void activate(WarningTexture::Warning warning, bool state, const GLCanvas3D& canvas); void render(const GLCanvas3D& canvas) const; + // function used to get an information for rescaling of the warning + void msw_rescale(const GLCanvas3D& canvas); + private: static const unsigned char Background_Color[3]; static const unsigned char Opacity; @@ -360,6 +363,10 @@ private: int m_original_width; int m_original_height; + // information for rescaling of the warning legend + std::string m_msg_text = ""; + bool m_is_colored_red{false}; + // Information about which warnings are currently active. std::vector<Warning> m_warnings; @@ -587,6 +594,8 @@ public: double get_size_proportional_to_max_bed_size(double factor) const; + void msw_rescale(); + private: bool _is_shown_on_screen() const; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 62b8581be..0ffdd576f 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -325,6 +325,17 @@ void GUI_App::init_fonts() #endif /*__WXMAC__*/ } +void GUI_App::update_fonts() +{ + /* Only normal and bold fonts are used for an application rescale, + * because of under MSW small and normal fonts are the same. + * To avoid same rescaling twice, just fill this values + * from rescaled MainFrame + */ + m_normal_font = mainframe->normal_font(); + m_bold_font = mainframe->normal_font().Bold(); +} + void GUI_App::set_label_clr_modified(const wxColour& clr) { m_color_label_modified = clr; auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue()); @@ -652,7 +663,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Check(get_mode() == comAdvanced); }, config_id_base + ConfigMenuModeAdvanced); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Check(get_mode() == comExpert); }, config_id_base + ConfigMenuModeExpert); - local_menu->AppendSubMenu(mode_menu, _(L("Mode")), _(L("Slic3r View Mode"))); + local_menu->AppendSubMenu(mode_menu, _(L("Mode")), wxString::Format(_(L("%s View Mode")), SLIC3R_APP_NAME)); local_menu->AppendSeparator(); local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application &Language"))); local_menu->AppendSeparator(); @@ -669,6 +680,12 @@ void GUI_App::add_config_menu(wxMenuBar *menu) // Take a configuration snapshot. if (check_unsaved_changes()) { wxTextEntryDialog dlg(nullptr, _(L("Taking configuration snapshot")), _(L("Snapshot name"))); + + // set current normal font for dialog children, + // because of just dlg.SetFont(normal_font()) has no result; + for (auto child : dlg.GetChildren()) + child->SetFont(normal_font()); + if (dlg.ShowModal() == wxID_OK) app_config->set("on_snapshot", Slic3r::GUI::Config::SnapshotDB::singleton().take_snapshot( @@ -718,7 +735,6 @@ void GUI_App::add_config_menu(wxMenuBar *menu) get_installed_languages(names, identifiers); if (select_language(names, identifiers)) { save_language(); -// show_info(mainframe->m_tabpanel, _(L("Application will be restarted")), _(L("Attention!"))); _3DScene::remove_all_canvases();// remove all canvas before recreate GUI recreate_GUI(); } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 41805702b..d3c9e0afa 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -98,6 +98,7 @@ public: void init_label_colours(); void update_label_colours_from_appconfig(); void init_fonts(); + void update_fonts(); void set_label_clr_modified(const wxColour& clr); void set_label_clr_sys(const wxColour& clr); @@ -139,6 +140,8 @@ public: bool checked_tab(Tab* tab); void load_current_presets(); + wxString current_language_code() { return m_wxLocale != nullptr ? m_wxLocale->GetCanonicalName() : wxString("en_US"); } + virtual bool OnExceptionInMainLoop(); #ifdef __APPLE__ diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index f65c83abb..dbe8145f3 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -163,7 +163,7 @@ void ObjectList::create_objects_ctrl() m_sizer = new wxBoxSizer(wxVERTICAL); m_sizer->Add(this, 1, wxGROW); - m_objects_model = new PrusaObjectDataViewModel; + m_objects_model = new ObjectDataViewModel; AssociateModel(m_objects_model); m_objects_model->SetAssociatedControl(this); #if wxUSE_DRAG_AND_DROP && wxUSE_UNICODE @@ -173,7 +173,7 @@ void ObjectList::create_objects_ctrl() // column 0(Icon+Text) of the view control: // And Icon can be consisting of several bitmaps - AppendColumn(new wxDataViewColumn(_(L("Name")), new PrusaBitmapTextRenderer(), + AppendColumn(new wxDataViewColumn(_(L("Name")), new BitmapTextRenderer(), 0, 20*wxGetApp().em_unit()/*200*/, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE)); // column 1 of the view control: @@ -203,7 +203,7 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) if (col->GetTitle() == " " && GetSelectedItemsCount()<2) GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); else if (col->GetTitle() == _("Name") && - m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.GetRefData()) { + m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.bmp().GetRefData()) { int obj_idx = m_objects_model->GetIdByItem(item); auto& stats = (*m_objects)[obj_idx]->volumes[0]->mesh.stl.stats; int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + @@ -395,27 +395,71 @@ void ObjectList::update_name_in_model(const wxDataViewItem& item) const void ObjectList::init_icons() { - m_bmp_modifiermesh = create_scaled_bitmap(nullptr, "add_modifier"); - m_bmp_solidmesh = create_scaled_bitmap(nullptr, "add_part"); - m_bmp_support_enforcer = create_scaled_bitmap(nullptr, "support_enforcer"); - m_bmp_support_blocker = create_scaled_bitmap(nullptr, "support_blocker"); - + m_bmp_modifiermesh = ScalableBitmap(nullptr, "add_modifier"); // Add part + m_bmp_solidmesh = ScalableBitmap(nullptr, "add_part"); // Add modifier + m_bmp_support_enforcer = ScalableBitmap(nullptr, "support_enforcer");// Add support enforcer + m_bmp_support_blocker = ScalableBitmap(nullptr, "support_blocker"); // Add support blocker m_bmp_vector.reserve(4); // bitmaps for different types of parts - m_bmp_vector.push_back(&m_bmp_solidmesh); // Add part - m_bmp_vector.push_back(&m_bmp_modifiermesh); // Add modifier - m_bmp_vector.push_back(&m_bmp_support_enforcer); // Add support enforcer - m_bmp_vector.push_back(&m_bmp_support_blocker); // Add support blocker + m_bmp_vector.push_back(&m_bmp_solidmesh.bmp()); + m_bmp_vector.push_back(&m_bmp_modifiermesh.bmp()); + m_bmp_vector.push_back(&m_bmp_support_enforcer.bmp()); + m_bmp_vector.push_back(&m_bmp_support_blocker.bmp()); + + + // Set volumes default bitmaps for the model m_objects_model->SetVolumeBitmaps(m_bmp_vector); // init icon for manifold warning - m_bmp_manifold_warning = create_scaled_bitmap(nullptr, "exclamation"); + m_bmp_manifold_warning = ScalableBitmap(nullptr, "exclamation"); // init bitmap for "Split to sub-objects" context menu - m_bmp_split = create_scaled_bitmap(nullptr, "split_parts_SMALL"); + m_bmp_split = ScalableBitmap(nullptr, "split_parts_SMALL"); // init bitmap for "Add Settings" context menu - m_bmp_cog = create_scaled_bitmap(nullptr, "cog"); + m_bmp_cog = ScalableBitmap(nullptr, "cog"); +} + +void ObjectList::rescale_icons() +{ + m_bmp_vector.clear(); + m_bmp_vector.reserve(4); // bitmaps for different types of parts + for (ScalableBitmap* bitmap : std::vector<ScalableBitmap*> { + &m_bmp_modifiermesh, // Add part + &m_bmp_solidmesh, // Add modifier + &m_bmp_support_enforcer, // Add support enforcer + &m_bmp_support_blocker }) // Add support blocker + { + bitmap->msw_rescale(); + m_bmp_vector.push_back(& bitmap->bmp()); + } + // Set volumes default bitmaps for the model + m_objects_model->SetVolumeBitmaps(m_bmp_vector); + + m_bmp_manifold_warning.msw_rescale(); + m_bmp_split.msw_rescale(); + m_bmp_cog.msw_rescale(); + + + // Update CATEGORY_ICON according to new scale + { + // Note: `this` isn't passed to create_scaled_bitmap() here because of bugs in the widget, + // see note in PresetBundle::load_compatible_bitmaps() + + // ptFFF + CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap(nullptr, "layers"); + CATEGORY_ICON[L("Infill")] = create_scaled_bitmap(nullptr, "infill"); + CATEGORY_ICON[L("Support material")] = create_scaled_bitmap(nullptr, "support"); + CATEGORY_ICON[L("Speed")] = create_scaled_bitmap(nullptr, "time"); + CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap(nullptr, "funnel"); + CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap(nullptr, "funnel"); +// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap(nullptr, "skirt+brim"); +// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap(nullptr, "time"); + CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap(nullptr, "wrench"); + // ptSLA + CATEGORY_ICON[L("Supports")] = create_scaled_bitmap(nullptr, "support"/*"sla_supports"*/); + CATEGORY_ICON[L("Pad")] = create_scaled_bitmap(nullptr, "pad"); + } } @@ -463,8 +507,7 @@ void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& vol items.Add(vol_item); } - m_parts_changed = true; - parts_changed(obj_idx); + changed_object(obj_idx); if (items.size() > 1) { @@ -490,9 +533,7 @@ void ObjectList::paste_objects_into_list(const std::vector<size_t>& object_idxs) items.Add(m_objects_model->GetItemById(object)); } - m_parts_changed = true; wxGetApp().plater()->changed_objects(object_idxs); - m_parts_changed = false; select_items(items); #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME @@ -534,7 +575,7 @@ void ObjectList::OnContextMenu(wxDataViewEvent&) if (title == " ") show_context_menu(); else if (title == _("Name") && pt.x >15 && - m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.GetRefData()) + m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.bmp().GetRefData()) { if (is_windows10()) fix_through_netfabb(); @@ -703,8 +744,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event) select_item(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, m_objects_model->GetParent(item))); - m_parts_changed = true; - parts_changed(m_dragged_data.obj_idx()); + changed_object(m_dragged_data.obj_idx()); m_dragged_data.clear(); } @@ -1000,12 +1040,12 @@ void ObjectList::append_menu_items_add_volume(wxMenu* menu) wxMenuItem* ObjectList::append_menu_item_split(wxMenu* menu) { return append_menu_item(menu, wxID_ANY, _(L("Split to parts")), "", - [this](wxCommandEvent&) { split(); }, m_bmp_split, menu); + [this](wxCommandEvent&) { split(); }, m_bmp_split.bmp(), menu); } wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_) { - PrusaMenu* menu = dynamic_cast<PrusaMenu*>(menu_); + MenuWithSeparators* menu = dynamic_cast<MenuWithSeparators*>(menu_); const wxString menu_name = _(L("Add settings")); // Delete old items from settings popupmenu @@ -1053,7 +1093,7 @@ wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_) if (printer_technology() == ptFFF || menu->GetMenuItems().size() > 0 && !menu->GetMenuItems().back()->IsSeparator()) - menu->m_separator_frst = menu->AppendSeparator(); + menu->SetFirstSeparator(); // Add frequently settings create_freq_settings_popupmenu(menu); @@ -1061,11 +1101,11 @@ wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_) if (mode == comAdvanced) return nullptr; - menu->m_separator_scnd = menu->AppendSeparator(); + menu->SetSecondSeparator(); // Add full settings list auto menu_item = new wxMenuItem(menu, wxID_ANY, menu_name); - menu_item->SetBitmap(m_bmp_cog); + menu_item->SetBitmap(m_bmp_cog.bmp()); menu_item->SetSubMenu(create_settings_popupmenu(menu)); @@ -1290,7 +1330,7 @@ void ObjectList::load_subobject(ModelVolumeType type) wxArrayString part_names; load_part((*m_objects)[obj_idx], part_names, type); - parts_changed(obj_idx); + changed_object(obj_idx); for (int i = 0; i < part_names.size(); ++i) { const wxDataViewItem sel_item = m_objects_model->AddVolumeChild(item, part_names.Item(i), type); @@ -1306,7 +1346,6 @@ void ObjectList::load_part( ModelObject* model_object, { wxWindow* parent = wxGetApp().tab_panel()->GetPage(0); - m_parts_changed = false; wxArrayString input_files; wxGetApp().import_model(parent, input_files); for (int i = 0; i < input_files.size(); ++i) { @@ -1342,8 +1381,6 @@ void ObjectList::load_part( ModelObject* model_object, // set a default extruder value, since user can't add it manually new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); - - m_parts_changed = true; } } } @@ -1486,8 +1523,7 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode // set a default extruder value, since user can't add it manually new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); - m_parts_changed = true; - parts_changed(obj_idx); + changed_object(obj_idx); const auto object_item = m_objects_model->GetTopParent(GetSelection()); select_item(m_objects_model->AddVolumeChild(object_item, name, type)); @@ -1551,8 +1587,7 @@ void ObjectList::del_instances_from_object(const int obj_idx) (*m_objects)[obj_idx]->invalidate_bounding_box(); // ? #ys_FIXME - m_parts_changed = true; - parts_changed(obj_idx); + changed_object(obj_idx); } bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, const int type) @@ -1597,8 +1632,7 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con else return false; - m_parts_changed = true; - parts_changed(obj_idx); + changed_object(obj_idx); return true; } @@ -1648,8 +1682,7 @@ void ObjectList::split() if (parent == item) Expand(parent); - m_parts_changed = true; - parts_changed(obj_idx); + changed_object(obj_idx); } bool ObjectList::get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume) @@ -1706,17 +1739,10 @@ bool ObjectList::can_split_instances() return selection.is_multiple_full_instance() || selection.is_single_full_instance(); } -void ObjectList::part_settings_changed() +// NO_PARAMETERS function call means that changed object index will be determine from Selection() +void ObjectList::changed_object(const int obj_idx/* = -1*/) const { - m_part_settings_changed = true; - wxGetApp().plater()->changed_object(get_selected_obj_idx()); - m_part_settings_changed = false; -} - -void ObjectList::parts_changed(int obj_idx) -{ - wxGetApp().plater()->changed_object(obj_idx); - m_parts_changed = false; + wxGetApp().plater()->changed_object(obj_idx < 0 ? get_selected_obj_idx() : obj_idx); } void ObjectList::part_selection_changed() @@ -1819,7 +1845,7 @@ void ObjectList::add_object_to_list(size_t obj_idx) stats.facets_added + stats.facets_reversed + stats.backwards_edges; if (errors > 0) { wxVariant variant; - variant << PrusaDataViewBitmapText(item_name, m_bmp_manifold_warning); + variant << DataViewBitmapText(item_name, m_bmp_manifold_warning.bmp()); m_objects_model->SetValue(variant, item, 0); } @@ -2439,8 +2465,7 @@ void ObjectList::change_part_type() volume->set_type(new_type); m_objects_model->SetVolumeType(item, new_type); - m_parts_changed = true; - parts_changed(get_selected_obj_idx()); + changed_object(get_selected_obj_idx()); // Update settings showing, if we have it //(we show additional settings for Part and Modifier and hide it for Support Blocker/Enforcer) @@ -2620,7 +2645,7 @@ void ObjectList::rename_item() wxVariant valueOld; m_objects_model->GetValue(valueOld, item, 0); - PrusaDataViewBitmapText bmpText; + DataViewBitmapText bmpText; bmpText << valueOld; // But replace the text with the value entered by user. @@ -2668,11 +2693,29 @@ void ObjectList::update_item_error_icon(const int obj_idx, const int vol_idx) co if (errors == 0) { // delete Error_icon if all errors are fixed wxVariant variant; - variant << PrusaDataViewBitmapText(from_u8(model_object->name), wxNullBitmap); + variant << DataViewBitmapText(from_u8(model_object->name), wxNullBitmap); m_objects_model->SetValue(variant, item, 0); } } +void ObjectList::msw_rescale() +{ + // update min size !!! A width of control shouldn't be a wxDefaultCoord + SetMinSize(wxSize(1, 15 * wxGetApp().em_unit())); + + GetColumn(0)->SetWidth(19 * wxGetApp().em_unit()); + GetColumn(1)->SetWidth(8 * wxGetApp().em_unit()); + GetColumn(2)->SetWidth(int(2 * wxGetApp().em_unit())); + + // rescale all icons, used by ObjectList + rescale_icons(); + + // rescale/update existingitems with bitmaps + m_objects_model->Rescale(); + + Layout(); +} + void ObjectList::ItemValueChanged(wxDataViewEvent &event) { if (event.GetColumn() == 0) @@ -2686,7 +2729,7 @@ void ObjectList::OnEditingDone(wxDataViewEvent &event) if (event.GetColumn() != 0) return; - const auto renderer = dynamic_cast<PrusaBitmapTextRenderer*>(GetColumn(0)->GetRenderer()); + const auto renderer = dynamic_cast<BitmapTextRenderer*>(GetColumn(0)->GetRenderer()); if (renderer->WasCanceled()) show_error(this, _(L("The supplied name is not valid;")) + "\n" + diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index a0343100a..da082d1d4 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -13,8 +13,8 @@ class wxBoxSizer; class wxMenuItem; -class PrusaObjectDataViewModel; -class PrusaMenu; +class ObjectDataViewModel; +class MenuWithSeparators; namespace Slic3r { class ConfigOptionsGroup; @@ -108,18 +108,18 @@ class ObjectList : public wxDataViewCtrl wxBoxSizer *m_sizer {nullptr}; wxWindow *m_parent {nullptr}; - wxBitmap m_bmp_modifiermesh; - wxBitmap m_bmp_solidmesh; - wxBitmap m_bmp_support_enforcer; - wxBitmap m_bmp_support_blocker; - wxBitmap m_bmp_manifold_warning; - wxBitmap m_bmp_cog; - wxBitmap m_bmp_split; - - PrusaMenu m_menu_object; - PrusaMenu m_menu_part; - PrusaMenu m_menu_sla_object; - PrusaMenu m_menu_instance; + ScalableBitmap m_bmp_modifiermesh; + ScalableBitmap m_bmp_solidmesh; + ScalableBitmap m_bmp_support_enforcer; + ScalableBitmap m_bmp_support_blocker; + ScalableBitmap m_bmp_manifold_warning; + ScalableBitmap m_bmp_cog; + ScalableBitmap m_bmp_split; + + MenuWithSeparators m_menu_object; + MenuWithSeparators m_menu_part; + MenuWithSeparators m_menu_sla_object; + MenuWithSeparators m_menu_instance; wxMenuItem* m_menu_item_split { nullptr }; wxMenuItem* m_menu_item_split_part { nullptr }; wxMenuItem* m_menu_item_settings { nullptr }; @@ -139,9 +139,6 @@ class ObjectList : public wxDataViewCtrl // update_settings_items - updating canvas selection is undesirable, // because it would turn off the gizmos (mainly a problem for the SLA gizmo) - bool m_parts_changed = false; - bool m_part_settings_changed = false; - int m_selected_row = 0; wxDataViewItem m_last_selected_item {nullptr}; @@ -157,7 +154,7 @@ public: std::map<std::string, wxBitmap> CATEGORY_ICON; - PrusaObjectDataViewModel *m_objects_model{ nullptr }; + ObjectDataViewModel *m_objects_model{ nullptr }; DynamicPrintConfig *m_config {nullptr}; std::vector<ModelObject*> *m_objects{ nullptr }; @@ -176,6 +173,7 @@ public: void update_extruder_values_for_items(const int max_extruder); void init_icons(); + void rescale_icons(); void set_tooltip_for_item(const wxPoint& pt); @@ -225,11 +223,8 @@ public: wxBoxSizer* get_sizer() {return m_sizer;} int get_selected_obj_idx() const; DynamicPrintConfig& get_item_config(const wxDataViewItem& item) const; - bool is_parts_changed() const { return m_parts_changed; } - bool is_part_settings_changed() const { return m_part_settings_changed; } - void part_settings_changed(); - void parts_changed(int obj_idx); + void changed_object(const int obj_idx = -1) const; void part_selection_changed(); // Add object to the list @@ -291,6 +286,8 @@ public: void paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes); void paste_objects_into_list(const std::vector<size_t>& object_idxs); + void msw_rescale(); + private: void OnChar(wxKeyEvent& event); void OnContextMenu(wxDataViewEvent &event); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 761f29e98..d15779308 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -67,7 +67,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : #endif // __APPLE__ { m_og->set_name(_(L("Object Manipulation"))); - m_og->label_width = 12 * wxGetApp().em_unit();//125; + m_og->label_width = 12;//125; m_og->set_grid_vgap(5); m_og->m_on_change = std::bind(&ObjectManipulation::on_change, this, std::placeholders::_1, std::placeholders::_2); @@ -89,11 +89,11 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : def.label = L("Name"); def.gui_type = "legend"; def.tooltip = L("Object name"); - def.width = 21 * wxGetApp().em_unit(); + def.width = 21; def.default_value = new ConfigOptionString{ " " }; m_og->append_single_option_line(Option(def, "object_name")); - const int field_width = 5 * wxGetApp().em_unit()/*50*/; + const int field_width = 5; // Legend for object modification auto line = Line{ "", "" }; @@ -126,7 +126,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : // Add "uniform scaling" button in front of "Scale" option if (option_name == "Scale") { line.near_label_widget = [this](wxWindow* parent) { - auto btn = new PrusaLockButton(parent, wxID_ANY); + auto btn = new LockButton(parent, wxID_ANY); btn->Bind(wxEVT_BUTTON, [btn, this](wxCommandEvent &event){ event.Skip(); wxTheApp->CallAfter([btn, this]() { set_uniform_scaling(btn->IsLocked()); }); @@ -164,15 +164,13 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : m_og->append_line(add_og_to_object_settings(L("Scale"), "%"), &m_scale_Label); m_og->append_line(add_og_to_object_settings(L("Size"), "mm")); - /* Unused parameter at this time - def.label = L("Place on bed"); - def.type = coBool; - def.tooltip = L("Automatic placing of models on printing bed in Y axis"); - def.gui_type = ""; - def.sidetext = ""; - def.default_value = new ConfigOptionBool{ false }; - m_og->append_single_option_line(Option(def, "place_on_bed")); - */ + // call back for a rescale of button "Set uniform scale" + m_og->rescale_near_label_widget = [this](wxWindow* win) { + auto *ctrl = dynamic_cast<LockButton*>(win); + if (ctrl == nullptr) + return; + ctrl->msw_rescale(); + }; } void ObjectManipulation::Show(const bool show) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 5db9622ce..b92654742 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -7,7 +7,7 @@ #include "GLCanvas3D.hpp" class wxStaticText; -class PrusaLockButton; +class LockButton; namespace Slic3r { namespace GUI { @@ -82,7 +82,7 @@ class ObjectManipulation : public OG_Settings bool m_uniform_scale {true}; // Does the object manipulation panel work in World or Local coordinates? bool m_world_coordinates = true; - PrusaLockButton* m_lock_bnt{ nullptr }; + LockButton* m_lock_bnt{ nullptr }; wxBitmapComboBox* m_word_local_combo = nullptr; #ifndef __APPLE__ diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index 72eeb76de..b7ba2d4fc 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -59,6 +59,8 @@ ObjectSettings::ObjectSettings(wxWindow* parent) : m_settings_list_sizer = new wxBoxSizer(wxVERTICAL); m_og->sizer->Add(m_settings_list_sizer, 1, wxEXPAND | wxLEFT, 5); + + m_bmp_delete = ScalableBitmap(parent, "cross"); } void ObjectSettings::update_settings_list() @@ -77,14 +79,11 @@ void ObjectSettings::update_settings_list() { auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line - auto btn = new wxBitmapButton(parent, wxID_ANY, create_scaled_bitmap(m_parent, "cross"/*"colorchange_delete_on.png"*/), - wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); -#ifdef __WXMSW__ - btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -#endif // __WXMSW__ + auto btn = new ScalableButton(parent, wxID_ANY, m_bmp_delete); + btn->Bind(wxEVT_BUTTON, [opt_key, config, this](wxEvent &event) { config->erase(opt_key); - wxGetApp().obj_list()->part_settings_changed(); + wxGetApp().obj_list()->changed_object(); wxTheApp->CallAfter([this]() { wxWindowUpdateLocker noUpdates(m_parent); update_settings_list(); @@ -123,22 +122,31 @@ void ObjectSettings::update_settings_list() continue; auto optgroup = std::make_shared<ConfigOptionsGroup>(m_og->ctrl_parent(), cat.first, config, false, extra_column); - optgroup->label_width = 15 * wxGetApp().em_unit(); - optgroup->sidetext_width = 5.5 * wxGetApp().em_unit(); + optgroup->label_width = 15; + optgroup->sidetext_width = 5.5; optgroup->m_on_change = [](const t_config_option_key& opt_id, const boost::any& value) { - wxGetApp().obj_list()->part_settings_changed(); }; + wxGetApp().obj_list()->changed_object(); }; for (auto& opt : cat.second) { if (opt == "extruder") continue; Option option = optgroup->get_option(opt); - option.opt.width = 12 * wxGetApp().em_unit(); + option.opt.width = 12; optgroup->append_single_option_line(option); } optgroup->reload_config(); m_settings_list_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0); + + // call back for rescaling of the extracolumn control + optgroup->rescale_extra_column_item = [this](wxWindow* win) { + auto *ctrl = dynamic_cast<ScalableButton*>(win); + if (ctrl == nullptr) + return; + ctrl->SetBitmap_(m_bmp_delete); + }; + m_og_settings.push_back(optgroup); categories.push_back(cat.first); @@ -163,5 +171,13 @@ void ObjectSettings::UpdateAndShow(const bool show) OG_Settings::UpdateAndShow(show); } +void ObjectSettings::msw_rescale() +{ + m_bmp_delete.msw_rescale(); + + for (auto group : m_og_settings) + group->msw_rescale(); +} + } //namespace GUI } //namespace Slic3r
\ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectSettings.hpp b/src/slic3r/GUI/GUI_ObjectSettings.hpp index 12115e208..3d49f13b7 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.hpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.hpp @@ -4,6 +4,7 @@ #include <memory> #include <vector> #include <wx/panel.h> +#include "wxExtensions.hpp" class wxBoxSizer; @@ -37,12 +38,15 @@ class ObjectSettings : public OG_Settings // option groups for settings std::vector <std::shared_ptr<ConfigOptionsGroup>> m_og_settings; + ScalableBitmap m_bmp_delete; + public: ObjectSettings(wxWindow* parent); ~ObjectSettings() {} void update_settings_list(); void UpdateAndShow(const bool show) override; + void msw_rescale(); }; }} diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 206253451..88fea933e 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -396,6 +396,18 @@ void Preview::refresh_print() load_print(true); } +void Preview::msw_rescale() +{ + // rescale slider + if (m_slider) m_slider->msw_rescale(); + + // rescale warning legend on the canvas + get_canvas3d()->msw_rescale(); + + // rescale legend + refresh_print(); +} + void Preview::bind_event_handlers() { this->Bind(wxEVT_SIZE, &Preview::on_size, this); @@ -507,7 +519,7 @@ void Preview::on_checkbox_shells(wxCommandEvent& evt) void Preview::create_double_slider() { - m_slider = new PrusaDoubleSlider(this, wxID_ANY, 0, 0, 0, 100); + m_slider = new DoubleSlider(this, wxID_ANY, 0, 0, 0, 100); m_double_slider_sizer->Add(m_slider, 0, wxEXPAND, 0); // sizer, m_canvas_widget diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index a2929f2e6..2540980f4 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -13,7 +13,7 @@ class wxStaticText; class wxChoice; class wxComboCtrl; class wxCheckBox; -class PrusaDoubleSlider; +class DoubleSlider; namespace Slic3r { @@ -99,7 +99,7 @@ class Preview : public wxPanel bool m_loaded; bool m_enabled; - PrusaDoubleSlider* m_slider {nullptr}; + DoubleSlider* m_slider {nullptr}; public: Preview(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, @@ -120,6 +120,8 @@ public: void reload_print(bool keep_volumes = false); void refresh_print(); + void msw_rescale(); + private: bool init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model); diff --git a/src/slic3r/GUI/GUI_Utils.hpp b/src/slic3r/GUI/GUI_Utils.hpp index e12153625..25cf25b16 100644 --- a/src/slic3r/GUI/GUI_Utils.hpp +++ b/src/slic3r/GUI/GUI_Utils.hpp @@ -16,6 +16,7 @@ #include <wx/panel.h> #include <wx/dcclient.h> #include <wx/debug.h> +#include <wx/settings.h> class wxCheckBox; class wxTopLevelWindow; @@ -58,35 +59,119 @@ public: : P(parent, id, title, pos, size, style, name) { m_scale_factor = (float)get_dpi_for_window(this) / (float)DPI_DEFAULT; + m_normal_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + // An analog of em_unit value from GUI_App. + m_em_unit = std::max<size_t>(10, 10 * m_scale_factor); + + m_prev_scale_factor = m_scale_factor; + recalc_font(); this->Bind(EVT_DPI_CHANGED, [this](const DpiChangedEvent &evt) { m_scale_factor = (float)evt.dpi / (float)DPI_DEFAULT; - on_dpi_changed(evt.rect); + + if (!m_can_rescale) + return; + + if (is_new_scale_factor()) + rescale(evt.rect); + }); + + this->Bind(wxEVT_MOVE_START, [this](wxMoveEvent& event) + { + event.Skip(); + + // Suppress application rescaling, when a MainFrame moving is not ended + m_can_rescale = false; + }); + + this->Bind(wxEVT_MOVE_END, [this](wxMoveEvent& event) + { + event.Skip(); + + m_can_rescale = is_new_scale_factor(); + + // If scale factor is different after moving of MainFrame ... + if (m_can_rescale) + // ... rescale application + rescale(event.GetRect()); + else + // set value to _true_ in purpose of possibility of a display dpi changing from System Settings + m_can_rescale = true; }); } virtual ~DPIAware() {} - float scale_factor() const { return m_scale_factor; } - int em_unit() const { return m_em_unit; } - int font_size() const { return m_font_size; } + float scale_factor() const { return m_scale_factor; } + float prev_scale_factor() const { return m_prev_scale_factor; } + + 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; } protected: virtual void on_dpi_changed(const wxRect &suggested_rect) = 0; private: - int m_scale_factor; + float m_scale_factor; int m_em_unit; int m_font_size; + wxFont m_normal_font; + float m_prev_scale_factor; + bool m_can_rescale{ true }; + void recalc_font() { wxClientDC dc(this); const auto metrics = dc.GetFontMetrics(); m_font_size = metrics.height; - m_em_unit = metrics.averageWidth; +// m_em_unit = metrics.averageWidth; } + + // 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; } + + // recursive function for scaling fonts for all controls in Window + void scale_controls_fonts(wxWindow *window, const float scale_f) + { + auto children = window->GetChildren(); + + for (auto child : children) { + scale_controls_fonts(child, scale_f); + child->SetFont(child->GetFont().Scaled(scale_f)); + } + + window->Layout(); + } + + void rescale(const wxRect &suggested_rect) + { + this->Freeze(); + const float relative_scale_factor = m_scale_factor / m_prev_scale_factor; + + // rescale fonts of all controls + scale_controls_fonts(this, relative_scale_factor); + this->SetFont(this->GetFont().Scaled(relative_scale_factor)); + + + // rescale normal_font value + m_normal_font = m_normal_font.Scaled(relative_scale_factor); + + // An analog of em_unit value from GUI_App. + m_em_unit = std::max<size_t>(10, 10 * m_scale_factor); + + // rescale missed controls sizes and images + on_dpi_changed(suggested_rect); + + this->Layout(); + this->Thaw(); + + // reset previous scale factor from current scale factor value + m_prev_scale_factor = m_scale_factor; + } + }; typedef DPIAware<wxFrame> DPIFrame; diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index 3c2f4182b..2fb453750 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -10,26 +10,28 @@ namespace Slic3r { namespace GUI { KBShortcutsDialog::KBShortcutsDialog() - : wxDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Keyboard Shortcuts")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) + : DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Keyboard Shortcuts")), + wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); auto main_sizer = new wxBoxSizer(wxVERTICAL); // logo - const wxBitmap logo_bmp = create_scaled_bitmap(this, "Slic3r_32px.png", 32); + m_logo_bmp = ScalableBitmap(this, "Slic3r_32px.png", 32); // fonts - wxFont head_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold(); + const wxFont& font = wxGetApp().normal_font(); + const wxFont& bold_font = wxGetApp().bold_font(); + SetFont(font); + + wxFont head_font = bold_font; #ifdef __WXOSX__ head_font.SetPointSize(14); #else - head_font.SetPointSize(12); + head_font.SetPointSize(bold_font.GetPointSize() + 2); #endif // __WXOSX__ - const wxFont& font = wxGetApp().small_font(); - const wxFont& bold_font = wxGetApp().bold_font(); - fill_shortcuts(); auto panel = new wxPanel(this); @@ -43,22 +45,25 @@ KBShortcutsDialog::KBShortcutsDialog() wxBoxSizer* r_sizer = new wxBoxSizer(wxVERTICAL); main_grid_sizer->Add(r_sizer, 0); + m_head_bitmaps.reserve(m_full_shortcuts.size()); + const wxSize topic_size = wxSize(10 * wxGetApp().em_unit(), -1); + for (auto& sc : m_full_shortcuts) { -// auto sizer = sc.first == _(L("Main Shortcuts")) ? l_sizer : r_sizer; - auto sizer = sc.second.second == 0 ? l_sizer : r_sizer; + auto sizer = sc.second.second == szLeft ? l_sizer : r_sizer; wxBoxSizer* hsizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(hsizer, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); // logo - auto *logo = new wxStaticBitmap(panel, wxID_ANY, logo_bmp); - hsizer->Add(logo, 0, wxEXPAND | wxLEFT | wxRIGHT, 15); + m_head_bitmaps.push_back(new wxStaticBitmap(panel, wxID_ANY, m_logo_bmp.bmp())); + hsizer->Add(m_head_bitmaps.back(), 0, wxEXPAND | wxLEFT | wxRIGHT, 15); // head - wxStaticText* head = new wxStaticText(panel, wxID_ANY, sc.first, wxDefaultPosition, wxSize(20 * wxGetApp().em_unit(), -1)); + wxStaticText* head = new wxStaticText(panel, wxID_ANY, sc.first, wxDefaultPosition, topic_size); head->SetFont(head_font); hsizer->Add(head, 0, wxALIGN_CENTER_VERTICAL); + // Shortcuts list auto grid_sizer = new wxFlexGridSizer(2, 5, 15); sizer->Add(grid_sizer, 0, wxEXPAND | wxLEFT| wxRIGHT, 15); @@ -121,7 +126,7 @@ void KBShortcutsDialog::fill_shortcuts() main_shortcuts.push_back(Shortcut("?" ,L("Show keyboard shortcuts list"))); main_shortcuts.push_back(Shortcut(ctrl+"LeftMouse" ,L("Select multiple object/Move multiple object"))); - m_full_shortcuts.push_back(std::make_pair( _(L("Main Shortcuts")), std::make_pair(main_shortcuts, 0) )); + m_full_shortcuts.push_back(std::make_pair(_(L("Main Shortcuts")), std::make_pair(main_shortcuts, szLeft))); Shortcuts plater_shortcuts; @@ -148,7 +153,7 @@ void KBShortcutsDialog::fill_shortcuts() plater_shortcuts.push_back(Shortcut("O", L("Zoom out"))); plater_shortcuts.push_back(Shortcut("ESC", L("Unselect gizmo, keep object selection"))); - m_full_shortcuts.push_back(std::make_pair(_(L("Plater Shortcuts")), std::make_pair(plater_shortcuts, 1))); + m_full_shortcuts.push_back(std::make_pair(_(L("Plater Shortcuts")), std::make_pair(plater_shortcuts, szRight))); // Shortcuts gizmo_shortcuts; @@ -168,7 +173,7 @@ void KBShortcutsDialog::fill_shortcuts() preview_shortcuts.push_back(Shortcut("U", L("Upper Layer"))); preview_shortcuts.push_back(Shortcut("D", L("Lower Layer"))); - m_full_shortcuts.push_back(std::make_pair( _(L("Preview Shortcuts")), std::make_pair(preview_shortcuts, 0) )); + m_full_shortcuts.push_back(std::make_pair(_(L("Preview Shortcuts")), std::make_pair(preview_shortcuts, szLeft))); Shortcuts layers_slider_shortcuts; @@ -181,7 +186,26 @@ void KBShortcutsDialog::fill_shortcuts() layers_slider_shortcuts.push_back(Shortcut("+", L("Add color change marker for current layer"))); layers_slider_shortcuts.push_back(Shortcut("-", L("Delete color change marker for current layer"))); - m_full_shortcuts.push_back(std::make_pair( _(L("Layers Slider Shortcuts")), std::make_pair(layers_slider_shortcuts, 1) )); + m_full_shortcuts.push_back(std::make_pair(_(L("Layers Slider Shortcuts")), std::make_pair(layers_slider_shortcuts, szRight))); +} + +void KBShortcutsDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + m_logo_bmp.msw_rescale(); + + for (wxStaticBitmap* bmp : m_head_bitmaps) + bmp->SetBitmap(m_logo_bmp.bmp()); + + const int em = em_unit(); + + msw_buttons_rescale(this, em, { wxID_OK }); + + const wxSize& size = wxSize(85 * em, 75 * em); + + SetMinSize(size); + Fit(); + + Refresh(); } void KBShortcutsDialog::onCloseDialog(wxEvent &) diff --git a/src/slic3r/GUI/KBShortcutsDialog.hpp b/src/slic3r/GUI/KBShortcutsDialog.hpp index d8905e1ce..66fe7c399 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.hpp +++ b/src/slic3r/GUI/KBShortcutsDialog.hpp @@ -5,24 +5,38 @@ #include <map> #include <vector> +#include "GUI_Utils.hpp" +#include "wxExtensions.hpp" + namespace Slic3r { namespace GUI { -class KBShortcutsDialog : public wxDialog +class KBShortcutsDialog : public DPIDialog { + enum PLACED_SIZER_ID + { + szLeft = 0, + szRight + }; + typedef std::pair<std::string, std::string> Shortcut; typedef std::vector< Shortcut > Shortcuts; - typedef std::vector< std::pair<wxString, std::pair<Shortcuts, int>> > ShortcutsVec; + typedef std::vector< std::pair<wxString, std::pair<Shortcuts, PLACED_SIZER_ID>> > ShortcutsVec; wxString text_info {wxEmptyString}; - ShortcutsVec m_full_shortcuts; + ShortcutsVec m_full_shortcuts; + ScalableBitmap m_logo_bmp; + std::vector<wxStaticBitmap*> m_head_bitmaps; public: KBShortcutsDialog(); void fill_shortcuts(); +protected: + void on_dpi_changed(const wxRect &suggested_rect) override; + private: void onCloseDialog(wxEvent &); }; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 4814a35d9..571b57235 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -258,7 +258,44 @@ bool MainFrame::can_delete_all() const void MainFrame::on_dpi_changed(const wxRect &suggested_rect) { - // TODO + wxGetApp().update_fonts(); + + // _strange_ workaround for correct em_unit calculation + const int new_em_unit = scale_factor() * 10; + wxGetApp().set_em_unit(std::max<size_t>(10, new_em_unit)); + + /* Load default preset bitmaps before a tabpanel initialization, + * but after filling of an em_unit value + */ + wxGetApp().preset_bundle->load_default_preset_bitmaps(this); + + // update Plater + wxGetApp().plater()->msw_rescale(); + + // update Tabs + for (auto tab : wxGetApp().tabs_list) + tab->msw_rescale(); + + // Workarounds for correct Window rendering after rescale + + /* Even if Window is maximized during moving, + * first of all we should imitate Window resizing. So: + * 1. cancel maximization, if it was set + * 2. imitate resizing + * 3. set maximization, if it was set + */ + const bool is_maximized = this->IsMaximized(); + if (is_maximized) + this->Maximize(false); + + /* To correct window rendering (especially redraw of a status bar) + * we should imitate window resizing. + */ + const wxSize& sz = this->GetSize(); + this->SetSize(sz.x + 1, sz.y + 1); + this->SetSize(sz); + + this->Maximize(is_maximized); } void MainFrame::init_menubar() @@ -337,7 +374,7 @@ void MainFrame::init_menubar() append_menu_item(fileMenu, wxID_ANY, _(L("&Repair STL file")) + dots, _(L("Automatically repair an STL file")), [this](wxCommandEvent&) { repair_stl(); }, "wrench"); fileMenu->AppendSeparator(); - append_menu_item(fileMenu, wxID_EXIT, _(L("&Quit")), _(L("Quit Slic3r")), + append_menu_item(fileMenu, wxID_EXIT, _(L("&Quit")), wxString::Format(_(L("Quit %s")), SLIC3R_APP_NAME), [this](wxCommandEvent&) { Close(false); }); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_open->GetId()); @@ -474,9 +511,11 @@ void MainFrame::init_menubar() //# wxTheApp->check_version(1); //# }); //# $versioncheck->Enable(wxTheApp->have_version_check); - append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r &Website")), _(L("Open the Slic3r website in your browser")), + append_menu_item(helpMenu, wxID_ANY, wxString::Format(_(L("%s &Website")), SLIC3R_APP_NAME), + wxString::Format(_(L("Open the %s website in your browser")), SLIC3R_APP_NAME), [this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://slic3r.org/"); }); - append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r &Manual")), _(L("Open the Slic3r manual in your browser")), + append_menu_item(helpMenu, wxID_ANY, wxString::Format(_(L("%s &Manual")), SLIC3R_APP_NAME), + wxString::Format(_(L("Open the %s manual in your browser")), SLIC3R_APP_NAME), [this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://manual.slic3r.org/"); }); helpMenu->AppendSeparator(); append_menu_item(helpMenu, wxID_ANY, _(L("System &Info")), _(L("Show system information")), diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index a5d3a1f6d..a8b2be2bc 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -4,6 +4,7 @@ #include "libslic3r/PrintConfig.hpp" #include <wx/frame.h> +#include <wx/settings.h> #include <wx/string.h> #include <string> diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index 771599b8e..ba2c5ed0c 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -25,12 +25,14 @@ namespace GUI { MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id, wxBitmap bitmap) : wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) - , boldfont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)) + , boldfont(wxGetApp().normal_font()/*wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)*/) , content_sizer(new wxBoxSizer(wxVERTICAL)) , btn_sizer(new wxBoxSizer(wxHORIZONTAL)) { boldfont.SetWeight(wxFONTWEIGHT_BOLD); + this->SetFont(wxGetApp().normal_font()); + auto *topsizer = new wxBoxSizer(wxHORIZONTAL); auto *rightsizer = new wxBoxSizer(wxVERTICAL); @@ -68,7 +70,8 @@ MsgDialog::~MsgDialog() {} // ErrorDialog ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg) - : MsgDialog(parent, _(L("Slic3r error")), _(L("Slic3r has encountered an error")), + : MsgDialog(parent, wxString::Format(_(L("%s error")), SLIC3R_APP_NAME), + wxString::Format(_(L("%s has encountered an error")), SLIC3R_APP_NAME), wxID_NONE) , msg(msg) { diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index a4686d4d2..cdcde972a 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -166,37 +166,45 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n #endif /* __WXGTK__ */ // if we have an extra column, build it - if (extra_column) - grid_sizer->Add(extra_column(this->ctrl_parent(), line), 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3); + if (extra_column) + { + m_extra_column_item_ptrs.push_back(extra_column(this->ctrl_parent(), line)); + grid_sizer->Add(m_extra_column_item_ptrs.back(), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 3); + } // Build a label if we have it wxStaticText* label=nullptr; if (label_width != 0) { if (! line.near_label_widget || ! line.label.IsEmpty()) { + // Only create the label if it is going to be displayed. long label_style = staticbox ? 0 : wxALIGN_RIGHT; - #ifdef __WXGTK__ +#ifdef __WXGTK__ // workaround for correct text align of the StaticBox on Linux // flags wxALIGN_RIGHT and wxALIGN_CENTRE don't work when Ellipsize flags are _not_ given. // Text is properly aligned only when Ellipsize is checked. label_style |= staticbox ? 0 : wxST_ELLIPSIZE_END; - #endif /* __WXGTK__ */ +#endif /* __WXGTK__ */ label = new wxStaticText(this->ctrl_parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ": "), - wxDefaultPosition, wxSize(label_width, -1), label_style); + wxDefaultPosition, wxSize(label_width*wxGetApp().em_unit(), -1), label_style); label->SetBackgroundStyle(wxBG_STYLE_PAINT); - label->SetFont(label_font); - label->Wrap(label_width); // avoid a Linux/GTK bug + label->SetFont(wxGetApp().normal_font()); + label->Wrap(label_width*wxGetApp().em_unit()); // avoid a Linux/GTK bug } - if (! line.near_label_widget) + if (!line.near_label_widget) grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, line.label.IsEmpty() ? 0 : 5); - else if (line.near_label_widget && line.label.IsEmpty()) - grid_sizer->Add(line.near_label_widget(this->ctrl_parent()), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7); else { - // If we're here, we have some widget near the label - // so we need a horizontal sizer to arrange these things - auto sizer = new wxBoxSizer(wxHORIZONTAL); - grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1); - sizer->Add(line.near_label_widget(this->ctrl_parent()), 0, wxRIGHT, 7); - sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5); + m_near_label_widget_ptrs.push_back(line.near_label_widget(this->ctrl_parent())); + + if (line.label.IsEmpty()) + grid_sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7); + else { + // If we're here, we have some widget near the label + // so we need a horizontal sizer to arrange these things + auto sizer = new wxBoxSizer(wxHORIZONTAL); + grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1); + sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT, 7); + sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5); + } } if (label != nullptr && line.label_tooltip != "") label->SetToolTip(line.label_tooltip); @@ -237,14 +245,13 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n wxSizer* sizer_tmp = sizer; // add label if any if (option.label != "") { -// wxString str_label = _(option.label); //! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1 wxString str_label = (option.label == "Top" || option.label == "Bottom") ? _CTX(option.label, "Layers") : _(option.label); label = new wxStaticText(this->ctrl_parent(), wxID_ANY, str_label + ": ", wxDefaultPosition, wxDefaultSize); label->SetBackgroundStyle(wxBG_STYLE_PAINT); - label->SetFont(label_font); + label->SetFont(wxGetApp().normal_font()); sizer_tmp->Add(label, 0, /*wxALIGN_RIGHT |*/ wxALIGN_CENTER_VERTICAL, 0); } @@ -269,9 +276,9 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n // add sidetext if any if (option.sidetext != "") { auto sidetext = new wxStaticText( this->ctrl_parent(), wxID_ANY, _(option.sidetext), wxDefaultPosition, - wxSize(sidetext_width, -1)/*wxDefaultSize*/, wxALIGN_LEFT); + /*wxSize(sidetext_width*wxGetApp().em_unit(), -1)*/wxDefaultSize, wxALIGN_LEFT); sidetext->SetBackgroundStyle(wxBG_STYLE_PAINT); - sidetext->SetFont(sidetext_font); + sidetext->SetFont(wxGetApp().normal_font()); sizer_tmp->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); field->set_side_text_ptr(sidetext); } @@ -303,7 +310,10 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n } Line OptionsGroup::create_single_option_line(const Option& option) const { - Line retval{ _(option.opt.label), _(option.opt.tooltip) }; +// Line retval{ _(option.opt.label), _(option.opt.tooltip) }; + wxString tooltip = _(option.opt.tooltip); + edit_tooltip(tooltip); + Line retval{ _(option.opt.label), tooltip }; Option tmp(option); tmp.opt.label = std::string(""); retval.append_option(tmp); @@ -479,6 +489,59 @@ bool ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) { return true; } +void ConfigOptionsGroup::msw_rescale() +{ + // update bitmaps for extra column items (like "mode markers" or buttons on settings panel) + if (rescale_extra_column_item) + for (auto extra_col : m_extra_column_item_ptrs) + rescale_extra_column_item(extra_col); + + // update bitmaps for near label widgets (like "Set uniform scale" button on settings panel) + if (rescale_near_label_widget) + for (auto near_label_widget : m_near_label_widget_ptrs) + rescale_near_label_widget(near_label_widget); + + // update undo buttons : rescale bitmaps + for (const auto& field : m_fields) + field.second->msw_rescale(); + + const int em = em_unit(parent()); + + // rescale width of label column + if (!m_options_mode.empty() && label_width > 1) + { + const int cols = m_grid_sizer->GetCols(); + const int rows = m_grid_sizer->GetEffectiveRowsCount(); + const int label_col = extra_column == nullptr ? 0 : 1; + + for (int i = 0; i < rows; i++) + { + const wxSizerItem* label_item = m_grid_sizer->GetItem(i*cols+label_col); + if (label_item->IsWindow()) + { + auto label = dynamic_cast<wxStaticText*>(label_item->GetWindow()); + if (label != nullptr) { + const int label_height = int(1.5f*label->GetFont().GetPixelSize().y + 0.5f); + label->SetMinSize(wxSize(label_width*em, /*-1*/label_height)); + } + } + else if (label_item->IsSizer()) // case when we have near_label_widget + { + const wxSizerItem* l_item = label_item->GetSizer()->GetItem(1); + if (l_item->IsWindow()) + { + auto label = dynamic_cast<wxStaticText*>(l_item->GetWindow()); + if (label != nullptr) { + const int label_height = int(1.5f*label->GetFont().GetPixelSize().y + 0.5f); + label->SetMinSize(wxSize(label_width*em, /*-1*/label_height)); + } + } + } + } + m_grid_sizer->Layout(); + } +} + boost::any ConfigOptionsGroup::config_value(const std::string& opt_key, int opt_index, bool deserialize) { if (deserialize) { diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 4eec68a37..fa8a19940 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -72,7 +72,7 @@ private: std::vector<widget_t> m_extra_widgets;//! {std::vector<widget_t>()}; }; -using column_t = std::function<wxWindow*(wxWindow* parent, const Line&)>;//std::function<wxSizer*(const Line&)>; +using column_t = std::function<wxWindow*(wxWindow* parent, const Line&)>; using t_optionfield_map = std::map<t_config_option_key, t_field>; using t_opt_map = std::map< std::string, std::pair<std::string, int> >; @@ -82,7 +82,7 @@ class OptionsGroup { public: const bool staticbox {true}; const wxString title {wxString("")}; - size_t label_width = 20 * wxGetApp().em_unit();// {200}; + size_t label_width = 20 ;// {200}; wxSizer* sizer {nullptr}; column_t extra_column {nullptr}; t_change m_on_change { nullptr }; @@ -94,6 +94,9 @@ public: std::function<DynamicPrintConfig()> m_get_sys_config{ nullptr }; std::function<bool()> have_sys_config{ nullptr }; + std::function<void(wxWindow* win)> rescale_extra_column_item { nullptr }; + std::function<void(wxWindow* win)> rescale_near_label_widget { nullptr }; + wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; int sidetext_width{ -1 }; @@ -193,6 +196,8 @@ protected: std::map<t_config_option_key, Option> m_options; wxWindow* m_parent {nullptr}; std::vector<ConfigOptionMode> m_options_mode; + std::vector<wxWindow*> m_extra_column_item_ptrs; + std::vector<wxWindow*> m_near_label_widget_ptrs; /// Field list, contains unique_ptrs of the derived type. /// using types that need to know what it is beyond the public interface @@ -261,6 +266,7 @@ public: void Hide(); void Show(const bool show); bool update_visibility(ConfigOptionMode mode); + void msw_rescale(); boost::any config_value(const std::string& opt_key, int opt_index, bool deserialize); // return option value from config boost::any get_config_value(const DynamicPrintConfig& config, const std::string& opt_key, int opt_index = -1); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b41b27af8..4280e4dbe 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -111,6 +111,7 @@ public: bool showing_manifold_warning_icon; void show_sizer(bool show); + void msw_rescale(); }; ObjectInfo::ObjectInfo(wxWindow *parent) : @@ -118,10 +119,10 @@ ObjectInfo::ObjectInfo(wxWindow *parent) : { GetStaticBox()->SetFont(wxGetApp().bold_font()); - auto *grid_sizer = new wxFlexGridSizer(4, 5, 5); + auto *grid_sizer = new wxFlexGridSizer(4, 5, 15); grid_sizer->SetFlexibleDirection(wxHORIZONTAL); - grid_sizer->AddGrowableCol(1, 1); - grid_sizer->AddGrowableCol(3, 1); +// grid_sizer->AddGrowableCol(1, 1); +// grid_sizer->AddGrowableCol(3, 1); auto init_info_label = [parent, grid_sizer](wxStaticText **info_label, wxString text_label) { auto *text = new wxStaticText(parent, wxID_ANY, text_label+":"); @@ -160,6 +161,11 @@ void ObjectInfo::show_sizer(bool show) manifold_warning_icon->Show(showing_manifold_warning_icon && show); } +void ObjectInfo::msw_rescale() +{ + manifold_warning_icon->SetBitmap(create_scaled_bitmap(nullptr, "exclamation")); +} + enum SlisedInfoIdx { siFilament_m, @@ -229,7 +235,8 @@ void SlicedInfo::SetTextAndShow(SlisedInfoIdx idx, const wxString& text, const w PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 * wxGetApp().em_unit(), -1), 0, nullptr, wxCB_READONLY), preset_type(preset_type), - last_selected(wxNOT_FOUND) + last_selected(wxNOT_FOUND), + m_em_unit(wxGetApp().em_unit()) { Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &evt) { auto selected_item = this->GetSelection(); @@ -281,11 +288,7 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 * }); } - edit_btn = new wxButton(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); -#ifdef __WINDOWS__ - edit_btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -#endif - edit_btn->SetBitmap(create_scaled_bitmap(this, "cog")); + edit_btn = new ScalableButton(parent, wxID_ANY, "cog"); edit_btn->SetToolTip(_(L("Click to edit preset"))); edit_btn->Bind(wxEVT_BUTTON, ([preset_type, this](wxCommandEvent) @@ -331,6 +334,12 @@ void PresetComboBox::check_selection() this->last_selected = GetSelection(); } +void PresetComboBox::msw_rescale() +{ + m_em_unit = wxGetApp().em_unit(); + edit_btn->msw_rescale(); +} + // Frequently changed parameters class FreqChangedParams : public OG_Settings @@ -428,7 +437,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : option = m_og->get_option("fill_density"); option.opt.label = L("Infill"); - option.opt.width = 6 * wxGetApp().em_unit(); + option.opt.width = 6; option.opt.sidetext = " "; line.append_option(option); @@ -566,7 +575,7 @@ struct Sidebar::priv wxScrolledWindow *scrolled; wxPanel* presets_panel; // Used for MSW better layouts - PrusaModeSizer *mode_sizer; + ModeSizer *mode_sizer; wxFlexGridSizer *sizer_presets; PresetComboBox *combo_print; std::vector<PresetComboBox*> combos_filament; @@ -614,9 +623,9 @@ void Sidebar::priv::show_preset_comboboxes() // Sidebar / public Sidebar::Sidebar(Plater *parent) - : wxPanel(parent), p(new priv(parent)) + : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(40 * wxGetApp().em_unit(), -1)), p(new priv(parent)) { - p->scrolled = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxSize(40 * wxGetApp().em_unit(), -1)); + p->scrolled = new wxScrolledWindow(this, wxID_ANY/*, wxDefaultPosition, wxSize(40 * wxGetApp().em_unit(), -1)*/); p->scrolled->SetScrollbars(0, 20, 1, 2); @@ -625,7 +634,7 @@ Sidebar::Sidebar(Plater *parent) p->scrolled->SetSizer(scrolled_sizer); // Sizer with buttons for mode changing - p->mode_sizer = new PrusaModeSizer(p->scrolled, 2 * wxGetApp().em_unit()); + p->mode_sizer = new ModeSizer(p->scrolled, 2 * wxGetApp().em_unit()); // The preset chooser p->sizer_presets = new wxFlexGridSizer(10, 1, 1, 2); @@ -675,13 +684,8 @@ Sidebar::Sidebar(Plater *parent) init_combo(&p->combo_sla_material, _(L("SLA material")), Preset::TYPE_SLA_MATERIAL, false); init_combo(&p->combo_printer, _(L("Printer")), Preset::TYPE_PRINTER, false); - // calculate width of the preset labels -// p->sizer_presets->Layout(); -// const wxArrayInt& ar = p->sizer_presets->GetColWidths(); -// const int label_width = ar.IsEmpty() ? 10*wxGetApp().em_unit() : ar.front()-4; - const int margin_5 = int(0.5*wxGetApp().em_unit());// 5; - const int margin_10 = int(1.5*wxGetApp().em_unit());// 15; + const int margin_10 = 10;//int(1.5*wxGetApp().em_unit());// 15; p->sizer_params = new wxBoxSizer(wxVERTICAL); @@ -703,10 +707,6 @@ Sidebar::Sidebar(Plater *parent) p->object_settings->Hide(); p->sizer_params->Add(p->object_settings->get_sizer(), 0, wxEXPAND | wxTOP, margin_5); - p->btn_send_gcode = new wxButton(this, wxID_ANY, _(L("Send to printer"))); - p->btn_send_gcode->SetFont(wxGetApp().bold_font()); - p->btn_send_gcode->Hide(); - // Info boxes p->object_info = new ObjectInfo(p->scrolled); p->sliced_info = new SlicedInfo(p->scrolled); @@ -721,10 +721,17 @@ Sidebar::Sidebar(Plater *parent) scrolled_sizer->Add(p->sliced_info, 0, wxEXPAND | wxTOP | wxLEFT, margin_5); // Buttons underneath the scrolled area - p->btn_export_gcode = new wxButton(this, wxID_ANY, _(L("Export G-code")) + dots); - p->btn_export_gcode->SetFont(wxGetApp().bold_font()); - p->btn_reslice = new wxButton(this, wxID_ANY, _(L("Slice now"))); - p->btn_reslice->SetFont(wxGetApp().bold_font()); + + auto init_btn = [this](wxButton **btn, wxString label) { + *btn = new wxButton(this, wxID_ANY, label, wxDefaultPosition, + wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); + (*btn)->SetFont(wxGetApp().bold_font()); + }; + + init_btn(&p->btn_send_gcode, _(L("Send to printer"))); + p->btn_send_gcode->Hide(); + init_btn(&p->btn_export_gcode, _(L("Export G-code")) + dots); + init_btn(&p->btn_reslice, _(L("Slice now"))); enable_buttons(false); auto *btns_sizer = new wxBoxSizer(wxVERTICAL); @@ -781,6 +788,28 @@ void Sidebar::remove_unused_filament_combos(const int current_extruder_count) } } +void Sidebar::update_all_preset_comboboxes() +{ + PresetBundle &preset_bundle = *wxGetApp().preset_bundle; + const auto print_tech = preset_bundle.printers.get_edited_preset().printer_technology(); + + // Update the print choosers to only contain the compatible presets, update the dirty flags. + if (print_tech == ptFFF) + preset_bundle.prints.update_platter_ui(p->combo_print); + else { + preset_bundle.sla_prints.update_platter_ui(p->combo_sla_print); + preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material); + } + // Update the printer choosers, update the dirty flags. + preset_bundle.printers.update_platter_ui(p->combo_printer); + // Update the filament choosers to only contain the compatible presets, update the color preview, + // update the dirty flags. + if (print_tech == ptFFF) { + for (size_t i = 0; i < p->combos_filament.size(); ++i) + preset_bundle.update_platter_filament_ui(i, p->combos_filament[i]); + } +} + void Sidebar::update_presets(Preset::Type preset_type) { PresetBundle &preset_bundle = *wxGetApp().preset_bundle; @@ -820,23 +849,7 @@ void Sidebar::update_presets(Preset::Type preset_type) case Preset::TYPE_PRINTER: { -// wxWindowUpdateLocker noUpdates_scrolled(p->scrolled); - - // Update the print choosers to only contain the compatible presets, update the dirty flags. - if (print_tech == ptFFF) - preset_bundle.prints.update_platter_ui(p->combo_print); - else { - preset_bundle.sla_prints.update_platter_ui(p->combo_sla_print); - preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material); - } - // Update the printer choosers, update the dirty flags. - preset_bundle.printers.update_platter_ui(p->combo_printer); - // Update the filament choosers to only contain the compatible presets, update the color preview, - // update the dirty flags. - if (print_tech == ptFFF) { - for (size_t i = 0; i < p->combos_filament.size(); ++ i) - preset_bundle.update_platter_filament_ui(i, p->combos_filament[i]); - } + update_all_preset_comboboxes(); p->show_preset_comboboxes(); break; } @@ -861,6 +874,37 @@ void Sidebar::update_reslice_btn_tooltip() const p->btn_reslice->SetToolTip(tooltip); } +void Sidebar::msw_rescale() +{ + SetMinSize(wxSize(40 * wxGetApp().em_unit(), -1)); + + p->mode_sizer->msw_rescale(); + + // Rescale preset comboboxes in respect to the current em_unit ... + for (PresetComboBox* combo : std::vector<PresetComboBox*> { p->combo_print, + p->combo_sla_print, + p->combo_sla_material, + p->combo_printer } ) + combo->msw_rescale(); + for (PresetComboBox* combo : p->combos_filament) + combo->msw_rescale(); + + // ... then refill them and set min size to correct layout of the sidebar + update_all_preset_comboboxes(); + + p->frequently_changed_parameters->get_og(true)->msw_rescale(); + p->frequently_changed_parameters->get_og(false)->msw_rescale(); + + p->object_list->msw_rescale(); + + p->object_manipulation->get_og()->msw_rescale(); + p->object_settings->msw_rescale(); + + p->object_info->msw_rescale(); + + p->scrolled->Layout(); +} + ObjectManipulation* Sidebar::obj_manipul() { return p->object_manipulation; @@ -1132,11 +1176,11 @@ struct Plater::priv MainFrame *main_frame; // Object popup menu - PrusaMenu object_menu; + MenuWithSeparators object_menu; // Part popup menu - PrusaMenu part_menu; + MenuWithSeparators part_menu; // SLA-Object popup menu - PrusaMenu sla_object_menu; + MenuWithSeparators sla_object_menu; // Removed/Prepended Items according to the view mode std::vector<wxMenuItem*> items_increase; @@ -3710,22 +3754,16 @@ void Plater::changed_object(int obj_idx) { if (obj_idx < 0) return; - auto list = wxGetApp().obj_list(); - wxASSERT(list != nullptr); - if (list == nullptr) - return; - - if (list->is_parts_changed()) { - // recenter and re - align to Z = 0 - auto model_object = p->model.objects[obj_idx]; - model_object->ensure_on_bed(); - if (this->p->printer_technology == ptSLA) { - // Update the SLAPrint from the current Model, so that the reload_scene() - // pulls the correct data, update the 3D scene. - this->p->update_restart_background_process(true, false); - } else - p->view3D->reload_scene(false); + // recenter and re - align to Z = 0 + auto model_object = p->model.objects[obj_idx]; + model_object->ensure_on_bed(); + if (this->p->printer_technology == ptSLA) { + // Update the SLAPrint from the current Model, so that the reload_scene() + // pulls the correct data, update the 3D scene. + this->p->update_restart_background_process(true, false); } + else + p->view3D->reload_scene(false); // update print this->p->schedule_background_process(); @@ -3736,26 +3774,19 @@ void Plater::changed_objects(const std::vector<size_t>& object_idxs) if (object_idxs.empty()) return; - auto list = wxGetApp().obj_list(); - wxASSERT(list != nullptr); - if (list == nullptr) - return; - - if (list->is_parts_changed()) { - for (int obj_idx : object_idxs) - { - if (obj_idx < p->model.objects.size()) - // recenter and re - align to Z = 0 - p->model.objects[obj_idx]->ensure_on_bed(); - } - if (this->p->printer_technology == ptSLA) { - // Update the SLAPrint from the current Model, so that the reload_scene() - // pulls the correct data, update the 3D scene. - this->p->update_restart_background_process(true, false); - } - else - p->view3D->reload_scene(false); + for (int obj_idx : object_idxs) + { + if (obj_idx < p->model.objects.size()) + // recenter and re - align to Z = 0 + p->model.objects[obj_idx]->ensure_on_bed(); } + if (this->p->printer_technology == ptSLA) { + // Update the SLAPrint from the current Model, so that the reload_scene() + // pulls the correct data, update the 3D scene. + this->p->update_restart_background_process(true, false); + } + else + p->view3D->reload_scene(false); // update print this->p->schedule_background_process(); @@ -3798,6 +3829,18 @@ bool Plater::can_paste_from_clipboard() const return true; } +void Plater::msw_rescale() +{ + p->preview->msw_rescale(); + + p->view3D->get_canvas3d()->msw_rescale(); + + p->sidebar->msw_rescale(); + + Layout(); + GetParent()->Layout(); +} + bool Plater::can_delete() const { return p->can_delete(); } bool Plater::can_delete_all() const { return p->can_delete_all(); } bool Plater::can_increase_instances() const { return p->can_increase_instances(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index f9c5a4d7f..ad5a45adb 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -14,6 +14,7 @@ #include "GLTexture.hpp" class wxButton; +class ScalableButton; class wxBoxSizer; class wxGLCanvas; class wxScrolledWindow; @@ -46,7 +47,7 @@ public: PresetComboBox(wxWindow *parent, Preset::Type preset_type); ~PresetComboBox(); - wxButton* edit_btn { nullptr }; + ScalableButton* edit_btn { nullptr }; enum LabelItemType { LABEL_ITEM_MARKER = 0x4d, @@ -56,14 +57,18 @@ public: void set_label_marker(int item, LabelItemType label_item_type = LABEL_ITEM_MARKER); void set_extruder_idx(const int extr_idx) { extruder_idx = extr_idx; } int get_extruder_idx() const { return extruder_idx; } + int em_unit() const { return m_em_unit; } void check_selection(); + void msw_rescale(); + private: typedef std::size_t Marker; Preset::Type preset_type; int last_selected; int extruder_idx = -1; + int m_em_unit; }; class Sidebar : public wxPanel @@ -79,9 +84,11 @@ public: void init_filament_combo(PresetComboBox **combo, const int extr_idx); void remove_unused_filament_combos(const int current_extruder_count); + void update_all_preset_comboboxes(); void update_presets(Slic3r::Preset::Type preset_type); void update_mode_sizer() const; void update_reslice_btn_tooltip() const; + void msw_rescale(); ObjectManipulation* obj_manipul(); ObjectList* obj_list(); @@ -199,6 +206,8 @@ public: bool can_copy() const; bool can_paste() const; + void msw_rescale(); + private: struct priv; std::unique_ptr<priv> p; diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 8bc747db5..b6a340d08 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -7,7 +7,9 @@ namespace Slic3r { namespace GUI { PreferencesDialog::PreferencesDialog(wxWindow* parent) : - wxDialog(parent, wxID_ANY, _(L("Preferences")), wxDefaultPosition, wxDefaultSize) { + DPIDialog(parent, wxID_ANY, _(L("Preferences")), wxDefaultPosition, + wxDefaultSize, wxDEFAULT_DIALOG_STYLE) +{ build(); } @@ -15,7 +17,7 @@ void PreferencesDialog::build() { auto app_config = get_app_config(); m_optgroup = std::make_shared<ConfigOptionsGroup>(this, _(L("General"))); - m_optgroup->label_width = 40 * wxGetApp().em_unit(); //400; + m_optgroup->label_width = 40; m_optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ m_values[opt_key] = boost::any_cast<bool>(value) ? "1" : "0"; }; @@ -110,6 +112,8 @@ void PreferencesDialog::build() auto sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(m_optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10); + SetFont(wxGetApp().normal_font()); + auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL); wxButton* btn = static_cast<wxButton*>(FindWindowById(wxID_OK, this)); btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { accept(); }); @@ -123,7 +127,7 @@ void PreferencesDialog::accept() { if (m_values.find("no_defaults") != m_values.end() || m_values.find("use_legacy_opengl") != m_values.end()) { - warning_catcher(this, _(L("You need to restart Slic3r to make the changes effective."))); + warning_catcher(this, wxString::Format(_(L("You need to restart %s to make the changes effective.")), SLIC3R_APP_NAME)); } auto app_config = get_app_config(); @@ -138,5 +142,21 @@ void PreferencesDialog::accept() wxGetApp().update_ui_from_settings(); } +void PreferencesDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + m_optgroup->msw_rescale(); + + const int em = em_unit(); + + msw_buttons_rescale(this, em, { wxID_OK, wxID_CANCEL }); + + const wxSize& size = wxSize(47 * em, 28 * em); + + SetMinSize(size); + Fit(); + + Refresh(); +} + } // GUI } // Slic3r
\ No newline at end of file diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index 363daebbc..096a2c906 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -2,6 +2,7 @@ #define slic3r_Preferences_hpp_ #include "GUI.hpp" +#include "GUI_Utils.hpp" #include <wx/dialog.h> #include <map> @@ -11,7 +12,7 @@ namespace GUI { class ConfigOptionsGroup; -class PreferencesDialog : public wxDialog +class PreferencesDialog : public DPIDialog { std::map<std::string, std::string> m_values; std::shared_ptr<ConfigOptionsGroup> m_optgroup; @@ -21,6 +22,9 @@ public: void build(); void accept(); + +protected: + void on_dpi_changed(const wxRect &suggested_rect) override; }; } // GUI diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index bed960a62..9875586ed 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -914,6 +914,16 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) // and draw a red flag in front of the selected preset. bool wide_icons = ! selected_preset.is_compatible && m_bitmap_incompatible != nullptr; + /* It's supposed that standard size of an icon is 16px*16px for 100% scaled display. + * So set sizes for solid_colored icons used for filament preset + * and scale them in respect to em_unit value + */ + const float scale_f = ui->em_unit() * 0.1f; + const int icon_height = 16 * scale_f + 0.5f; + const int icon_width = 16 * scale_f + 0.5f; + const int thin_space_icon_width = 4 * scale_f + 0.5f; + const int wide_space_icon_width = 6 * scale_f + 0.5f; + std::map<wxString, wxBitmap*> nonsys_presets; wxString selected = ""; if (!this->m_presets.front().is_visible) @@ -934,13 +944,13 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) std::vector<wxBitmap> bmps; if (wide_icons) // Paint a red flag for incompatible presets. - bmps.emplace_back(preset.is_compatible ? m_bitmap_cache->mkclear(16, 16) : *m_bitmap_incompatible); + bmps.emplace_back(preset.is_compatible ? m_bitmap_cache->mkclear(icon_width, icon_height) : *m_bitmap_incompatible); // Paint the color bars. - bmps.emplace_back(m_bitmap_cache->mkclear(4, 16)); + bmps.emplace_back(m_bitmap_cache->mkclear(thin_space_icon_width, icon_height)); bmps.emplace_back(*m_bitmap_main_frame); // Paint a lock at the system presets. - bmps.emplace_back(m_bitmap_cache->mkclear(6, 16)); - bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(16, 16)); + bmps.emplace_back(m_bitmap_cache->mkclear(wide_space_icon_width, icon_height)); + bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(icon_width, icon_height)); bmp = m_bitmap_cache->insert(bitmap_key, bmps); } @@ -981,12 +991,12 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) std::vector<wxBitmap> bmps; if (wide_icons) // Paint a red flag for incompatible presets. - bmps.emplace_back(m_bitmap_cache->mkclear(16, 16)); + bmps.emplace_back(m_bitmap_cache->mkclear(icon_width, icon_height)); // Paint the color bars. - bmps.emplace_back(m_bitmap_cache->mkclear(4, 16)); + bmps.emplace_back(m_bitmap_cache->mkclear(thin_space_icon_width, icon_height)); bmps.emplace_back(*m_bitmap_main_frame); // Paint a lock at the system presets. - bmps.emplace_back(m_bitmap_cache->mkclear(6, 16)); + bmps.emplace_back(m_bitmap_cache->mkclear(wide_space_icon_width, icon_height)); bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); bmp = m_bitmap_cache->insert(bitmap_key, bmps); } @@ -996,10 +1006,14 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); ui->check_selection(); - ui->Thaw(); + ui->Thaw(); + + // Update control min size after rescale (changed Display DPI under MSW) + if (ui->GetMinWidth() != 20 * ui->em_unit()) + ui->SetMinSize(wxSize(20 * ui->em_unit(), ui->GetSize().GetHeight())); } -size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible) +size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible, const int em/* = 10*/) { if (ui == nullptr) return 0; @@ -1007,6 +1021,14 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati ui->Clear(); size_t selected_preset_item = 0; + /* It's supposed that standard size of an icon is 16px*16px for 100% scaled display. + * So set sizes for solid_colored(empty) icons used for preset + * and scale them in respect to em_unit value + */ + const float scale_f = em * 0.1f; + const int icon_height = 16 * scale_f + 0.5f; + const int icon_width = 16 * scale_f + 0.5f; + std::map<wxString, wxBitmap*> nonsys_presets; wxString selected = ""; if (!this->m_presets.front().is_visible) @@ -1025,7 +1047,7 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati const wxBitmap* tmp_bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible; bmps.emplace_back((tmp_bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *tmp_bmp); // Paint a lock at the system presets. - bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(16, 16)); + bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(icon_width, icon_height)); bmp = m_bitmap_cache->insert(bitmap_key, bmps); } @@ -1292,6 +1314,11 @@ std::string PresetCollection::path_from_name(const std::string &new_name) const return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string(); } +void PresetCollection::clear_bitmap_cache() +{ + m_bitmap_cache->clear(); +} + wxString PresetCollection::separator(const std::string &label) { return wxString::FromUTF8(PresetCollection::separator_head()) + _(label) + wxString::FromUTF8(PresetCollection::separator_tail()); diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index 41c9ff72b..051a55f66 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -394,7 +394,7 @@ public: // Update the choice UI from the list of presets. // If show_incompatible, all presets are shown, otherwise only the compatible presets are shown. // If an incompatible preset is selected, it is shown as well. - size_t update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible); + size_t update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible, const int em = 10); // Update the choice UI from the list of presets. // Only the compatible presets are shown. // If an incompatible preset is selected, it is shown as well. @@ -412,6 +412,8 @@ public: // Generate a file path from a profile name. Add the ".ini" suffix if it is missing. std::string path_from_name(const std::string &new_name) const; + void clear_bitmap_cache(); + #ifdef __linux__ static const char* separator_head() { return "------- "; } static const char* separator_tail() { return " -------"; } diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index bcf76d958..b2fa0a857 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -1434,6 +1434,14 @@ bool PresetBundle::parse_color(const std::string &scolor, unsigned char *rgb_out void PresetBundle::load_default_preset_bitmaps(wxWindow *window) { + // Clear bitmap cache, before load new scaled default preset bitmaps + m_bitmapCache->clear(); + this->prints.clear_bitmap_cache(); + this->sla_prints.clear_bitmap_cache(); + this->filaments.clear_bitmap_cache(); + this->sla_materials.clear_bitmap_cache(); + this->printers.clear_bitmap_cache(); + this->prints.load_bitmap_default(window, "cog"); this->sla_prints.load_bitmap_default(window, "cog"); this->filaments.load_bitmap_default(window, "spool.png"); @@ -1468,6 +1476,18 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr wxString selected_str = ""; if (!this->filaments().front().is_visible) ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap)); + + /* It's supposed that standard size of an icon is 16px*16px for 100% scaled display. + * So set sizes for solid_colored icons used for filament preset + * and scale them in respect to em_unit value + */ + const float scale_f = ui->em_unit() * 0.1f; + const int icon_height = 16 * scale_f + 0.5f; + const int normal_icon_width = 16 * scale_f + 0.5f; + const int space_icon_width = 2 * scale_f + 0.5f; + const int wide_icon_width = 24 * scale_f + 0.5f; + const int thin_icon_width = 8 * scale_f + 0.5f; + for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++i) { const Preset &preset = this->filaments.preset(i); bool selected = this->filament_presets[idx_extruder] == preset.name; @@ -1491,17 +1511,17 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr std::vector<wxBitmap> bmps; if (wide_icons) // Paint a red flag for incompatible presets. - bmps.emplace_back(preset.is_compatible ? m_bitmapCache->mkclear(16, 16) : *m_bitmapIncompatible); + bmps.emplace_back(preset.is_compatible ? m_bitmapCache->mkclear(normal_icon_width, icon_height) : *m_bitmapIncompatible); // Paint the color bars. parse_color(filament_rgb, rgb); - bmps.emplace_back(m_bitmapCache->mksolid(single_bar ? 24 : 16, 16, rgb)); + bmps.emplace_back(m_bitmapCache->mksolid(single_bar ? wide_icon_width : normal_icon_width, icon_height, rgb)); if (! single_bar) { parse_color(extruder_rgb, rgb); - bmps.emplace_back(m_bitmapCache->mksolid(8, 16, rgb)); + bmps.emplace_back(m_bitmapCache->mksolid(thin_icon_width, icon_height, rgb)); } // Paint a lock at the system presets. - bmps.emplace_back(m_bitmapCache->mkclear(2, 16)); - bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmapLock : m_bitmapCache->mkclear(16, 16)); + bmps.emplace_back(m_bitmapCache->mkclear(space_icon_width, icon_height)); + bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmapLock : m_bitmapCache->mkclear(normal_icon_width, icon_height)); // (preset.is_dirty ? *m_bitmapLockOpen : *m_bitmapLock) : m_bitmapCache->mkclear(16, 16)); bitmap = m_bitmapCache->insert(bitmap_key, bmps); } @@ -1536,6 +1556,10 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr ui->SetToolTip(ui->GetString(selected_preset_item)); ui->check_selection(); ui->Thaw(); + + // Update control min size after rescale (changed Display DPI under MSW) + if (ui->GetMinWidth() != 20 * ui->em_unit()) + ui->SetMinSize(wxSize(20 * ui->em_unit(), ui->GetSize().GetHeight())); } void PresetBundle::set_default_suppressed(bool default_suppressed) diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp index 76185b1ba..2b6e4f2a2 100644 --- a/src/slic3r/GUI/PrintHostDialogs.cpp +++ b/src/slic3r/GUI/PrintHostDialogs.cpp @@ -19,6 +19,7 @@ #include "MsgDialog.hpp" #include "I18N.hpp" #include "../Utils/PrintHost.hpp" +#include "wxExtensions.hpp" namespace fs = boost::filesystem; @@ -131,13 +132,11 @@ wxEvent *PrintHostQueueDialog::Event::Clone() const } PrintHostQueueDialog::PrintHostQueueDialog(wxWindow *parent) - : wxDialog(parent, wxID_ANY, _(L("Print host upload queue")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) + : DPIDialog(parent, wxID_ANY, _(L("Print host upload queue")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) , on_progress_evt(this, EVT_PRINTHOST_PROGRESS, &PrintHostQueueDialog::on_progress, this) , on_error_evt(this, EVT_PRINTHOST_ERROR, &PrintHostQueueDialog::on_error, this) , on_cancel_evt(this, EVT_PRINTHOST_CANCEL, &PrintHostQueueDialog::on_cancel, this) { - enum { HEIGHT = 60, WIDTH = 30, SPACING = 5 }; - const auto em = GetTextExtent("m").x; SetSize(wxSize(HEIGHT * em, WIDTH * em)); @@ -202,6 +201,18 @@ void PrintHostQueueDialog::append_job(const PrintHostJob &job) job_list->AppendItem(fields, static_cast<wxUIntPtr>(ST_NEW)); } +void PrintHostQueueDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + const int& em = em_unit(); + + msw_buttons_rescale(this, em, { wxID_DELETE, wxID_CANCEL, btn_error->GetId() }); + + SetMinSize(wxSize(HEIGHT * em, WIDTH * em)); + + Fit(); + Refresh(); +} + PrintHostQueueDialog::JobState PrintHostQueueDialog::get_state(int idx) { wxCHECK_MSG(idx >= 0 && idx < job_list->GetItemCount(), ST_ERROR, "Out of bounds access to job list"); diff --git a/src/slic3r/GUI/PrintHostDialogs.hpp b/src/slic3r/GUI/PrintHostDialogs.hpp index 105899cf0..427c4f6bf 100644 --- a/src/slic3r/GUI/PrintHostDialogs.hpp +++ b/src/slic3r/GUI/PrintHostDialogs.hpp @@ -41,7 +41,7 @@ private: }; -class PrintHostQueueDialog : public wxDialog +class PrintHostQueueDialog : public DPIDialog { public: class Event : public wxEvent @@ -62,6 +62,10 @@ public: PrintHostQueueDialog(wxWindow *parent); void append_job(const PrintHostJob &job); + +protected: + void on_dpi_changed(const wxRect &suggested_rect) override; + private: enum Column { COL_ID, @@ -81,6 +85,8 @@ private: ST_COMPLETED, }; + enum { HEIGHT = 60, WIDTH = 30, SPACING = 5 }; + wxButton *btn_cancel; wxButton *btn_error; wxDataViewListCtrl *job_list; diff --git a/src/slic3r/GUI/RammingChart.cpp b/src/slic3r/GUI/RammingChart.cpp index 41e5cdfe7..6f71e8616 100644 --- a/src/slic3r/GUI/RammingChart.cpp +++ b/src/slic3r/GUI/RammingChart.cpp @@ -141,6 +141,9 @@ void Chart::mouse_double_clicked(wxMouseEvent& event) { void Chart::recalculate_line() { + m_line_to_draw.clear(); + m_total_volume = 0.f; + std::vector<wxPoint> points; for (auto& but : m_buttons) { points.push_back(wxPoint(math_to_screen(but.get_pos()))); @@ -150,92 +153,88 @@ void Chart::recalculate_line() { break; } } - std::sort(points.begin(),points.end(),[](wxPoint& a,wxPoint& b) { return a.x < b.x; }); - - m_line_to_draw.clear(); - m_total_volume = 0.f; - - - // Cubic spline interpolation: see https://en.wikiversity.org/wiki/Cubic_Spline_Interpolation#Methods - const bool boundary_first_derivative = true; // true - first derivative is 0 at the leftmost and rightmost point - // false - second ---- || ------- - const int N = points.size()-1; // last point can be accessed as N, we have N+1 total points - std::vector<float> diag(N+1); - std::vector<float> mu(N+1); - std::vector<float> lambda(N+1); - std::vector<float> h(N+1); - std::vector<float> rhs(N+1); - - // let's fill in inner equations - for (int i=1;i<=N;++i) h[i] = points[i].x-points[i-1].x; - std::fill(diag.begin(),diag.end(),2.f); - for (int i=1;i<=N-1;++i) { - mu[i] = h[i]/(h[i]+h[i+1]); - lambda[i] = 1.f - mu[i]; - rhs[i] = 6 * ( float(points[i+1].y-points[i].y )/(h[i+1]*(points[i+1].x-points[i-1].x)) - - float(points[i].y -points[i-1].y)/(h[i] *(points[i+1].x-points[i-1].x)) ); - } - - // now fill in the first and last equations, according to boundary conditions: - if (boundary_first_derivative) { - const float endpoints_derivative = 0; - lambda[0] = 1; - mu[N] = 1; - rhs[0] = (6.f/h[1]) * (float(points[0].y-points[1].y)/(points[0].x-points[1].x) - endpoints_derivative); - rhs[N] = (6.f/h[N]) * (endpoints_derivative - float(points[N-1].y-points[N].y)/(points[N-1].x-points[N].x)); - } - else { - lambda[0] = 0; - mu[N] = 0; - rhs[0] = 0; - rhs[N] = 0; - } + + // The calculation wouldn't work in case the ramming is to be turned off completely. + if (points.size()>1) { + std::sort(points.begin(),points.end(),[](wxPoint& a,wxPoint& b) { return a.x < b.x; }); + + // Cubic spline interpolation: see https://en.wikiversity.org/wiki/Cubic_Spline_Interpolation#Methods + const bool boundary_first_derivative = true; // true - first derivative is 0 at the leftmost and rightmost point + // false - second ---- || ------- + const int N = points.size()-1; // last point can be accessed as N, we have N+1 total points + std::vector<float> diag(N+1); + std::vector<float> mu(N+1); + std::vector<float> lambda(N+1); + std::vector<float> h(N+1); + std::vector<float> rhs(N+1); - // the trilinear system is ready to be solved: - for (int i=1;i<=N;++i) { - float multiple = mu[i]/diag[i-1]; // let's subtract proper multiple of above equation - diag[i]-= multiple * lambda[i-1]; - rhs[i] -= multiple * rhs[i-1]; - } - // now the back substitution (vector mu contains invalid values from now on): - rhs[N] = rhs[N]/diag[N]; - for (int i=N-1;i>=0;--i) - rhs[i] = (rhs[i]-lambda[i]*rhs[i+1])/diag[i]; - - - - - unsigned int i=1; - float y=0.f; - for (int x=m_rect.GetLeft(); x<=m_rect.GetRight() ; ++x) { - if (splines) { - if (i<points.size()-1 && points[i].x < x ) { - ++i; - } - if (points[0].x > x) - y = points[0].y; - else - if (points[N].x < x) - y = points[N].y; - else - y = (rhs[i-1]*pow(points[i].x-x,3)+rhs[i]*pow(x-points[i-1].x,3)) / (6*h[i]) + - (points[i-1].y-rhs[i-1]*h[i]*h[i]/6.f) * (points[i].x-x)/h[i] + - (points[i].y -rhs[i] *h[i]*h[i]/6.f) * (x-points[i-1].x)/h[i]; - m_line_to_draw.push_back(y); + // let's fill in inner equations + for (int i=1;i<=N;++i) h[i] = points[i].x-points[i-1].x; + std::fill(diag.begin(),diag.end(),2.f); + for (int i=1;i<=N-1;++i) { + mu[i] = h[i]/(h[i]+h[i+1]); + lambda[i] = 1.f - mu[i]; + rhs[i] = 6 * ( float(points[i+1].y-points[i].y )/(h[i+1]*(points[i+1].x-points[i-1].x)) - + float(points[i].y -points[i-1].y)/(h[i] *(points[i+1].x-points[i-1].x)) ); + } + + // now fill in the first and last equations, according to boundary conditions: + if (boundary_first_derivative) { + const float endpoints_derivative = 0; + lambda[0] = 1; + mu[N] = 1; + rhs[0] = (6.f/h[1]) * (float(points[0].y-points[1].y)/(points[0].x-points[1].x) - endpoints_derivative); + rhs[N] = (6.f/h[N]) * (endpoints_derivative - float(points[N-1].y-points[N].y)/(points[N-1].x-points[N].x)); + } + else { + lambda[0] = 0; + mu[N] = 0; + rhs[0] = 0; + rhs[N] = 0; } - else { - float x_math = screen_to_math(wxPoint(x,0)).m_x; - if (i+2<=points.size() && m_buttons[i+1].get_pos().m_x-0.125 < x_math) - ++i; - m_line_to_draw.push_back(math_to_screen(wxPoint2DDouble(x_math,m_buttons[i].get_pos().m_y)).y); + + // the trilinear system is ready to be solved: + for (int i=1;i<=N;++i) { + float multiple = mu[i]/diag[i-1]; // let's subtract proper multiple of above equation + diag[i]-= multiple * lambda[i-1]; + rhs[i] -= multiple * rhs[i-1]; + } + // now the back substitution (vector mu contains invalid values from now on): + rhs[N] = rhs[N]/diag[N]; + for (int i=N-1;i>=0;--i) + rhs[i] = (rhs[i]-lambda[i]*rhs[i+1])/diag[i]; + + unsigned int i=1; + float y=0.f; + for (int x=m_rect.GetLeft(); x<=m_rect.GetRight() ; ++x) { + if (splines) { + if (i<points.size()-1 && points[i].x < x ) { + ++i; + } + if (points[0].x > x) + y = points[0].y; + else + if (points[N].x < x) + y = points[N].y; + else + y = (rhs[i-1]*pow(points[i].x-x,3)+rhs[i]*pow(x-points[i-1].x,3)) / (6*h[i]) + + (points[i-1].y-rhs[i-1]*h[i]*h[i]/6.f) * (points[i].x-x)/h[i] + + (points[i].y -rhs[i] *h[i]*h[i]/6.f) * (x-points[i-1].x)/h[i]; + m_line_to_draw.push_back(y); + } + else { + float x_math = screen_to_math(wxPoint(x,0)).m_x; + if (i+2<=points.size() && m_buttons[i+1].get_pos().m_x-0.125 < x_math) + ++i; + m_line_to_draw.push_back(math_to_screen(wxPoint2DDouble(x_math,m_buttons[i].get_pos().m_y)).y); + } + + m_line_to_draw.back() = std::max(m_line_to_draw.back(), m_rect.GetTop()-1); + m_line_to_draw.back() = std::min(m_line_to_draw.back(), m_rect.GetBottom()-1); + m_total_volume += (m_rect.GetBottom() - m_line_to_draw.back()) * (visible_area.m_width / m_rect.GetWidth()) * (visible_area.m_height / m_rect.GetHeight()); } - - - m_line_to_draw.back() = std::max(m_line_to_draw.back(), m_rect.GetTop()-1); - m_line_to_draw.back() = std::min(m_line_to_draw.back(), m_rect.GetBottom()-1); - m_total_volume += (m_rect.GetBottom() - m_line_to_draw.back()) * (visible_area.m_width / m_rect.GetWidth()) * (visible_area.m_height / m_rect.GetHeight()); } - + wxPostEvent(this->GetParent(), wxCommandEvent(EVT_WIPE_TOWER_CHART_CHANGED)); Refresh(); } diff --git a/src/slic3r/GUI/SysInfoDialog.cpp b/src/slic3r/GUI/SysInfoDialog.cpp index 2746c643e..162a36c75 100644 --- a/src/slic3r/GUI/SysInfoDialog.cpp +++ b/src/slic3r/GUI/SysInfoDialog.cpp @@ -41,10 +41,12 @@ std::string get_main_info(bool format_as_html) } SysInfoDialog::SysInfoDialog() - : wxDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("System Information")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) + : DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("System Information")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); SetBackgroundColour(bgr_clr); + SetFont(wxGetApp().normal_font()); + wxBoxSizer* hsizer = new wxBoxSizer(wxHORIZONTAL); hsizer->SetMinSize(wxSize(50 * wxGetApp().em_unit(), -1)); @@ -52,8 +54,9 @@ SysInfoDialog::SysInfoDialog() main_sizer->Add(hsizer, 1, wxEXPAND | wxALL, 10); // logo - auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap(this, "Slic3r_192px.png", 192)); - hsizer->Add(logo, 0, wxALIGN_CENTER_VERTICAL); + m_logo_bmp = ScalableBitmap(this, "Slic3r_192px.png", 192); + m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bmp.bmp()); + hsizer->Add(m_logo, 0, wxALIGN_CENTER_VERTICAL); wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL); hsizer->Add(vsizer, 1, wxEXPAND|wxLEFT, 20); @@ -61,8 +64,7 @@ SysInfoDialog::SysInfoDialog() // title { wxStaticText* title = new wxStaticText(this, wxID_ANY, SLIC3R_APP_NAME, wxDefaultPosition, wxDefaultSize); - wxFont title_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); - title_font.SetWeight(wxFONTWEIGHT_BOLD); + wxFont title_font = wxGetApp().bold_font(); title_font.SetFamily(wxFONTFAMILY_ROMAN); title_font.SetPointSize(22); title->SetFont(title_font); @@ -70,7 +72,7 @@ SysInfoDialog::SysInfoDialog() } // main_info_text - wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + wxFont font = wxGetApp().normal_font(); const auto text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); @@ -78,10 +80,10 @@ SysInfoDialog::SysInfoDialog() const int fs = font.GetPointSize() - 1; int size[] = { static_cast<int>(fs*1.5), static_cast<int>(fs*1.4), static_cast<int>(fs*1.3), fs, fs, fs, fs }; - wxHtmlWindow* html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER); + m_html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER); { - html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); - html->SetBorders(2); + m_html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); + m_html->SetBorders(2); const auto text = wxString::Format( "<html>" "<body bgcolor= %s link= %s>" @@ -91,16 +93,16 @@ SysInfoDialog::SysInfoDialog() "</body>" "</html>", bgr_clr_str, text_clr_str, text_clr_str, get_main_info(true)); - html->SetPage(text); - vsizer->Add(html, 1, wxEXPAND | wxBOTTOM, wxGetApp().em_unit()); + m_html->SetPage(text); + vsizer->Add(m_html, 1, wxEXPAND | wxBOTTOM, wxGetApp().em_unit()); } // opengl_info - wxHtmlWindow* opengl_info_html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO); + m_opengl_info_html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO); { - opengl_info_html->SetMinSize(wxSize(-1, 16 * wxGetApp().em_unit())); - opengl_info_html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); - opengl_info_html->SetBorders(10); + m_opengl_info_html->SetMinSize(wxSize(-1, 16 * wxGetApp().em_unit())); + m_opengl_info_html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); + m_opengl_info_html->SetBorders(10); const auto text = wxString::Format( "<html>" "<body bgcolor= %s link= %s>" @@ -110,14 +112,15 @@ SysInfoDialog::SysInfoDialog() "</body>" "</html>", bgr_clr_str, text_clr_str, text_clr_str, _3DScene::get_gl_info(true, true)); - opengl_info_html->SetPage(text); - main_sizer->Add(opengl_info_html, 1, wxEXPAND | wxBOTTOM, 15); + m_opengl_info_html->SetPage(text); + main_sizer->Add(m_opengl_info_html, 1, wxEXPAND | wxBOTTOM, 15); } wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK); - auto btn_copy_to_clipboard = new wxButton(this, wxID_ANY, "Copy to Clipboard", wxDefaultPosition, wxDefaultSize); - buttons->Insert(0, btn_copy_to_clipboard, 0, wxLEFT, 5); - btn_copy_to_clipboard->Bind(wxEVT_BUTTON, &SysInfoDialog::onCopyToClipboard, this); + m_btn_copy_to_clipboard = new wxButton(this, wxID_ANY, "Copy to Clipboard", wxDefaultPosition, wxDefaultSize); + + buttons->Insert(0, m_btn_copy_to_clipboard, 0, wxLEFT, 5); + m_btn_copy_to_clipboard->Bind(wxEVT_BUTTON, &SysInfoDialog::onCopyToClipboard, this); this->SetEscapeId(wxID_OK); this->Bind(wxEVT_BUTTON, &SysInfoDialog::onCloseDialog, this, wxID_OK); @@ -130,6 +133,34 @@ SysInfoDialog::SysInfoDialog() main_sizer->SetSizeHints(this); } +void SysInfoDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + m_logo_bmp.msw_rescale(); + m_logo->SetBitmap(m_logo_bmp.bmp()); + + wxFont font = GetFont(); + const int fs = font.GetPointSize() - 1; + int font_size[] = { static_cast<int>(fs*1.5), static_cast<int>(fs*1.4), static_cast<int>(fs*1.3), fs, fs, fs, fs }; + + m_html->SetFonts(font.GetFaceName(), font.GetFaceName(), font_size); + m_html->Refresh(); + + const int& em = em_unit(); + + msw_buttons_rescale(this, em, { wxID_OK, m_btn_copy_to_clipboard->GetId() }); + + m_opengl_info_html->SetMinSize(wxSize(-1, 16 * em)); + m_opengl_info_html->SetFonts(font.GetFaceName(), font.GetFaceName(), font_size); + m_opengl_info_html->Refresh(); + + const wxSize& size = wxSize(65 * em, 55 * em); + + SetMinSize(size); + Fit(); + + Refresh(); +} + void SysInfoDialog::onCopyToClipboard(wxEvent &) { wxTheClipboard->Open(); diff --git a/src/slic3r/GUI/SysInfoDialog.hpp b/src/slic3r/GUI/SysInfoDialog.hpp index ee1b85ce6..3b1459648 100644 --- a/src/slic3r/GUI/SysInfoDialog.hpp +++ b/src/slic3r/GUI/SysInfoDialog.hpp @@ -4,14 +4,26 @@ #include <wx/wx.h> #include <wx/html/htmlwin.h> +#include "GUI_Utils.hpp" +#include "wxExtensions.hpp" + namespace Slic3r { namespace GUI { -class SysInfoDialog : public wxDialog +class SysInfoDialog : public DPIDialog { - wxString text_info {wxEmptyString}; + ScalableBitmap m_logo_bmp; + wxStaticBitmap* m_logo; + wxHtmlWindow* m_opengl_info_html; + wxHtmlWindow* m_html; + + wxButton* m_btn_copy_to_clipboard; + public: SysInfoDialog(); + +protected: + void on_dpi_changed(const wxRect &suggested_rect) override; private: void onCopyToClipboard(wxEvent &); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index a697c7a71..fb8147ad2 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -110,37 +110,28 @@ void Tab::create_preset_tab() #endif //__WXOSX__ // preset chooser - m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(25 * m_em_unit, -1), 0, 0, wxCB_READONLY); + m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(35 * m_em_unit, -1), 0, 0, wxCB_READONLY); auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); //buttons - wxBitmap bmpMenu; - bmpMenu = create_scaled_bitmap(this, "save"); - m_btn_save_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); - if (wxMSW) m_btn_save_preset->SetBackgroundColour(color); - bmpMenu = create_scaled_bitmap(this, "cross"/*"delete.png"*/); - m_btn_delete_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); - if (wxMSW) m_btn_delete_preset->SetBackgroundColour(color); + m_scaled_buttons.reserve(6); + m_scaled_buttons.reserve(2); + + add_scaled_button(panel, &m_btn_save_preset, "save"); + add_scaled_button(panel, &m_btn_delete_preset, "cross"); m_show_incompatible_presets = false; - m_bmp_show_incompatible_presets = create_scaled_bitmap(this, "flag_red"); - m_bmp_hide_incompatible_presets = create_scaled_bitmap(this, "flag_green"); - m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); - if (wxMSW) m_btn_hide_incompatible_presets->SetBackgroundColour(color); + add_scaled_bitmap(this, m_bmp_show_incompatible_presets, "flag_red"); + add_scaled_bitmap(this, m_bmp_hide_incompatible_presets, "flag_green"); + + add_scaled_button(panel, &m_btn_hide_incompatible_presets, m_bmp_hide_incompatible_presets.name()); m_btn_save_preset->SetToolTip(_(L("Save current ")) + m_title); m_btn_delete_preset->SetToolTip(_(L("Delete this preset"))); m_btn_delete_preset->Disable(); - m_undo_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); - m_undo_to_sys_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); - m_question_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); - if (wxMSW) { - m_undo_btn->SetBackgroundColour(color); - m_undo_to_sys_btn->SetBackgroundColour(color); - m_question_btn->SetBackgroundColour(color); - } + add_scaled_button(panel, &m_question_btn, "question"); m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information \n" "or click this button."))); @@ -148,22 +139,21 @@ void Tab::create_preset_tab() // Determine the theme color of OS (dark or light) auto luma = wxGetApp().get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); // Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field. - m_bmp_value_lock = create_scaled_bitmap(this, luma >= 128 ? "lock_closed" : "lock_closed_white"); - m_bmp_value_unlock = create_scaled_bitmap(this, "lock_open"); + add_scaled_bitmap(this, m_bmp_value_lock , luma >= 128 ? "lock_closed" : "lock_closed_white"); + add_scaled_bitmap(this, m_bmp_value_unlock, "lock_open"); m_bmp_non_system = &m_bmp_white_bullet; // Bitmaps to be shown on the "Undo user changes" button next to each input field. - m_bmp_value_revert = create_scaled_bitmap(this, "undo"); - m_bmp_white_bullet = create_scaled_bitmap(this, luma >= 128 ? "dot" : "dot_white"/*"bullet_white.png"*/); - m_bmp_question = create_scaled_bitmap(this, "question"); + add_scaled_bitmap(this, m_bmp_value_revert, "undo"); + add_scaled_bitmap(this, m_bmp_white_bullet, luma >= 128 ? "dot" : "dot_white"); fill_icon_descriptions(); set_tooltips_text(); - m_undo_btn->SetBitmap(m_bmp_white_bullet); + add_scaled_button(panel, &m_undo_btn, m_bmp_white_bullet.name()); + add_scaled_button(panel, &m_undo_to_sys_btn, m_bmp_white_bullet.name()); + m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_roll_back_value(); })); - m_undo_to_sys_btn->SetBitmap(m_bmp_white_bullet); m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_roll_back_value(true); })); - m_question_btn->SetBitmap(m_bmp_question); m_question_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { auto dlg = new ButtonsDescription(this, &m_icon_descriptions); @@ -183,7 +173,7 @@ void Tab::create_preset_tab() m_default_text_clr = wxGetApp().get_label_clr_default(); // Sizer with buttons for mode changing - m_mode_sizer = new PrusaModeSizer(panel); + m_mode_sizer = new ModeSizer(panel); const float scale_factor = wxGetApp().em_unit()*0.1;// GetContentScaleFactor(); m_hsizer = new wxBoxSizer(wxHORIZONTAL); @@ -259,12 +249,36 @@ void Tab::create_preset_tab() toggle_show_hide_incompatible(); })); + // Fill cache for mode bitmaps + m_mode_bitmap_cache.reserve(3); + m_mode_bitmap_cache.push_back(ScalableBitmap(this, "mode_simple_.png")); + m_mode_bitmap_cache.push_back(ScalableBitmap(this, "mode_middle_.png")); + m_mode_bitmap_cache.push_back(ScalableBitmap(this, "mode_expert_.png")); + // Initialize the DynamicPrintConfig by default keys/values. build(); rebuild_page_tree(); m_complited = true; } +void Tab::add_scaled_button(wxWindow* parent, + ScalableButton** btn, + const std::string& icon_name, + const wxString& label/* = wxEmptyString*/, + long style /*= wxBU_EXACTFIT | wxNO_BORDER*/) +{ + *btn = new ScalableButton(parent, wxID_ANY, icon_name, label, wxDefaultSize, wxDefaultPosition, style); + m_scaled_buttons.push_back(*btn); +} + +void Tab::add_scaled_bitmap(wxWindow* parent, + ScalableBitmap& bmp, + const std::string& icon_name) +{ + bmp = ScalableBitmap(parent, icon_name); + m_scaled_bitmaps.push_back(&bmp); +} + void Tab::load_initial_data() { m_config = &m_presets->get_edited_preset().config; @@ -281,9 +295,8 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str icon_idx = (m_icon_index.find(icon) == m_icon_index.end()) ? -1 : m_icon_index.at(icon); if (icon_idx == -1) { // Add a new icon to the icon list. -// wxIcon img_icon(from_u8(Slic3r::var(icon)), wxBITMAP_TYPE_PNG); -// m_icons->Add(img_icon); - m_icons->Add(create_scaled_bitmap(this, icon)); + m_scaled_icons_list.push_back(ScalableBitmap(this, icon)); + m_icons->Add(m_scaled_icons_list.back().bmp()); icon_idx = ++m_icon_count; m_icon_index[icon] = icon_idx; } @@ -294,7 +307,7 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str #else auto panel = this; #endif - PageShp page(new Page(panel, title, icon_idx)); + PageShp page(new Page(panel, title, icon_idx, m_mode_bitmap_cache)); // page->SetBackgroundStyle(wxBG_STYLE_SYSTEM); #ifdef __WINDOWS__ // page->SetDoubleBuffered(true); @@ -402,8 +415,8 @@ void Tab::update_changed_ui() { bool is_nonsys_value = false; bool is_modified_value = true; - const wxBitmap *sys_icon = &m_bmp_value_lock; - const wxBitmap *icon = &m_bmp_value_revert; + const ScalableBitmap *sys_icon = &m_bmp_value_lock; + const ScalableBitmap *icon = &m_bmp_value_revert; const wxColour *color = &m_sys_label_clr; @@ -595,8 +608,8 @@ void Tab::update_changed_tree_ui() void Tab::update_undo_buttons() { - m_undo_btn->SetBitmap(m_is_modified_values ? m_bmp_value_revert : m_bmp_white_bullet); - m_undo_to_sys_btn->SetBitmap(m_is_nonsys_values ? *m_bmp_non_system : m_bmp_value_lock); + m_undo_btn-> SetBitmap_(m_is_modified_values ? m_bmp_value_revert: m_bmp_white_bullet); + m_undo_to_sys_btn-> SetBitmap_(m_is_nonsys_values ? *m_bmp_non_system : m_bmp_value_lock); m_undo_btn->SetToolTip(m_is_modified_values ? m_ttg_value_revert : m_ttg_white_bullet); m_undo_to_sys_btn->SetToolTip(m_is_nonsys_values ? *m_ttg_non_system : m_ttg_value_lock); @@ -673,7 +686,7 @@ void Tab::update_dirty() void Tab::update_tab_ui() { - m_selected_preset_item = m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets); + m_selected_preset_item = m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets, m_em_unit); } // Load a provied DynamicConfig into the tab, modifying the active preset. @@ -726,6 +739,42 @@ void Tab::update_visibility() update_changed_tree_ui(); } +void Tab::msw_rescale() +{ + m_em_unit = wxGetApp().em_unit(); + + m_mode_sizer->msw_rescale(); + + m_presets_choice->SetSize(35 * m_em_unit, -1); + m_treectrl->SetMinSize(wxSize(20 * m_em_unit, -1)); + + update_tab_ui(); + + // rescale buttons and cached bitmaps + for (const auto btn : m_scaled_buttons) + btn->msw_rescale(); + for (const auto bmp : m_scaled_bitmaps) + bmp->msw_rescale(); + for (ScalableBitmap& bmp : m_mode_bitmap_cache) + bmp.msw_rescale(); + + // rescale icons for tree_ctrl + for (ScalableBitmap& bmp : m_scaled_icons_list) + bmp.msw_rescale(); + // recreate and set new ImageList for tree_ctrl + m_icons->RemoveAll(); + m_icons = new wxImageList(m_scaled_icons_list.front().bmp().GetWidth(), m_scaled_icons_list.front().bmp().GetHeight()); + for (ScalableBitmap& bmp : m_scaled_icons_list) + m_icons->Add(bmp.bmp()); + m_treectrl->AssignImageList(m_icons); + + // rescale options_groups + for (auto page : m_pages) + page->msw_rescale(); + + Layout(); +} + Field* Tab::get_field(const t_config_option_key& opt_key, int opt_index/* = -1*/) const { Field* field = nullptr; @@ -1121,10 +1170,10 @@ void TabPrint::build() optgroup->append_single_option_line("complete_objects"); line = { _(L("Extruder clearance (mm)")), "" }; Option option = optgroup->get_option("extruder_clearance_radius"); - option.opt.width = 60; + option.opt.width = 6; line.append_option(option); option = optgroup->get_option("extruder_clearance_height"); - option.opt.width = 60; + option.opt.width = 6; line.append_option(option); optgroup->append_line(line); @@ -1138,14 +1187,14 @@ void TabPrint::build() optgroup = page->new_optgroup(_(L("Post-processing scripts")), 0); option = optgroup->get_option("post_process"); option.opt.full_width = true; - option.opt.height = 5 * m_em_unit;//50; + option.opt.height = 5;//50; optgroup->append_single_option_line(option); page = add_options_page(_(L("Notes")), "note.png"); optgroup = page->new_optgroup(_(L("Notes")), 0); option = optgroup->get_option("notes"); option.opt.full_width = true; - option.opt.height = 25 * m_em_unit;//250; + option.opt.height = 25;//250; optgroup->append_single_option_line(option); page = add_options_page(_(L("Dependencies")), "wrench.png"); @@ -1458,7 +1507,7 @@ void TabFilament::build() optgroup->append_single_option_line("bridge_fan_speed"); optgroup->append_single_option_line("disable_fan_first_layers"); - optgroup = page->new_optgroup(_(L("Cooling thresholds")), 250); + optgroup = page->new_optgroup(_(L("Cooling thresholds")), 25); optgroup->append_single_option_line("fan_below_layer_time"); optgroup->append_single_option_line("slowdown_below_layer_time"); optgroup->append_single_option_line("min_print_speed"); @@ -1508,8 +1557,8 @@ void TabFilament::build() }; optgroup->append_line(line); - const int gcode_field_height = 15 * m_em_unit; // 150 - const int notes_field_height = 25 * m_em_unit; // 250 + const int gcode_field_height = 15; // 150 + const int notes_field_height = 25; // 250 page = add_options_page(_(L("Custom G-code")), "cog"); optgroup = page->new_optgroup(_(L("Start G-code")), 0); @@ -1606,8 +1655,8 @@ wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticTex { *StaticText = new ogStaticText(parent, ""); - auto font = (new wxSystemSettings)->GetFont(wxSYS_DEFAULT_GUI_FONT); - (*StaticText)->SetFont(font); +// auto font = (new wxSystemSettings)->GetFont(wxSYS_DEFAULT_GUI_FONT); + (*StaticText)->SetFont(wxGetApp().normal_font()); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(*StaticText, 1, wxEXPAND|wxALL, 0); @@ -1629,10 +1678,10 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup) } auto printhost_browse = [=](wxWindow* parent) { - auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse ")) + dots, - wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); + add_scaled_button(parent, &m_printhost_browse_btn, "browse", _(L(" Browse ")) + dots, wxBU_LEFT | wxBU_EXACTFIT); + ScalableButton* btn = m_printhost_browse_btn; btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - btn->SetBitmap(create_scaled_bitmap(this, "browse")); + auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(btn); @@ -1648,10 +1697,9 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup) }; auto print_host_test = [this](wxWindow* parent) { - auto btn = m_print_host_test_btn = new wxButton(parent, wxID_ANY, _(L("Test")), - wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); - btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - btn->SetBitmap(create_scaled_bitmap(this, "test")); + add_scaled_button(parent, &m_print_host_test_btn, "test", _(L("Test")), wxBU_LEFT | wxBU_EXACTFIT); + ScalableButton* btn = m_print_host_test_btn; + btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(btn); @@ -1722,9 +1770,9 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup) line.widget = [this, ca_file_hint] (wxWindow* parent) { auto txt = new wxStaticText(parent, wxID_ANY, wxString::Format("%s\n\n\t%s", - _(L("HTTPS CA File:\n\ -\tOn this system, Slic3r uses HTTPS certificates from the system Certificate Store or Keychain.\n\ -\tTo use a custom CA file, please import your CA file into Certificate Store / Keychain.")), + wxString::Format(_(L("HTTPS CA File:\n\ + \tOn this system, %s uses HTTPS certificates from the system Certificate Store or Keychain.\n\ + \tTo use a custom CA file, please import your CA file into Certificate Store / Keychain.")), SLIC3R_APP_NAME), ca_file_hint)); txt->SetFont(Slic3r::GUI::wxGetApp().normal_font()); auto sizer = new wxBoxSizer(wxHORIZONTAL); @@ -1755,6 +1803,8 @@ void TabPrinter::build_fff() auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter")); m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size(); + wxGetApp().sidebar().update_objects_list_extruder_column(m_initial_extruders_count); + const Preset* parent_preset = m_presets->get_selected_preset_parent(); m_sys_extruders_count = parent_preset == nullptr ? 0 : static_cast<const ConfigOptionFloats*>(parent_preset->config.option("nozzle_diameter"))->values.size(); @@ -1764,9 +1814,9 @@ void TabPrinter::build_fff() Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" }; line.widget = [this](wxWindow* parent) { - auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); - btn->SetFont(wxGetApp().small_font()); - btn->SetBitmap(create_scaled_bitmap(this, "printer_white")); + ScalableButton* btn; + add_scaled_button(parent, &btn, "printer_white", _(L(" Set ")) + dots, wxBU_LEFT | wxBU_EXACTFIT); + btn->SetFont(wxGetApp().normal_font()); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(btn); @@ -1881,7 +1931,7 @@ void TabPrinter::build_fff() m_use_silent_mode = val; } } - build_extruder_pages(); + build_unregular_pages(); update_dirty(); on_value_change(opt_key, value); }); @@ -1893,8 +1943,8 @@ void TabPrinter::build_fff() optgroup->append_single_option_line("use_volumetric_e"); optgroup->append_single_option_line("variable_layer_height"); - const int gcode_field_height = 15 * m_em_unit; // 150 - const int notes_field_height = 25 * m_em_unit; // 250 + const int gcode_field_height = 15; // 150 + const int notes_field_height = 25; // 250 page = add_options_page(_(L("Custom G-code")), "cog"); optgroup = page->new_optgroup(_(L("Start G-code")), 0); option = optgroup->get_option("start_gcode"); @@ -1948,7 +1998,7 @@ void TabPrinter::build_fff() }; optgroup->append_line(line); - build_extruder_pages(); + build_unregular_pages(); #if 0 if (!m_no_controller) @@ -1965,9 +2015,10 @@ void TabPrinter::build_sla() Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" }; line.widget = [this](wxWindow* parent) { - auto btn = new wxButton(parent, wxID_ANY, _(L(" Set ")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); - btn->SetFont(wxGetApp().small_font()); - btn->SetBitmap(create_scaled_bitmap(this, "printer_white")); + ScalableButton* btn; + add_scaled_button(parent, &btn, "printer_white", _(L(" Set ")) + dots, wxBU_LEFT | wxBU_EXACTFIT); + btn->SetFont(wxGetApp().normal_font()); + auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(btn); @@ -2023,7 +2074,7 @@ void TabPrinter::build_sla() optgroup = page->new_optgroup(_(L("Print Host upload"))); build_printhost(optgroup.get()); - const int notes_field_height = 25 * m_em_unit; // 250 + const int notes_field_height = 25; // 250 page = add_options_page(_(L("Notes")), "note.png"); optgroup = page->new_optgroup(_(L("Notes")), 0); @@ -2051,13 +2102,23 @@ void TabPrinter::update_serial_ports() void TabPrinter::extruders_count_changed(size_t extruders_count) { - m_extruders_count = extruders_count; - m_preset_bundle->printers.get_edited_preset().set_num_extruders(extruders_count); - m_preset_bundle->update_multi_material_filament_presets(); - build_extruder_pages(); - reload_config(); - on_value_change("extruders_count", extruders_count); - wxGetApp().sidebar().update_objects_list_extruder_column(extruders_count); + bool is_count_changed = false; + if (m_extruders_count != extruders_count) { + m_extruders_count = extruders_count; + m_preset_bundle->printers.get_edited_preset().set_num_extruders(extruders_count); + m_preset_bundle->update_multi_material_filament_presets(); + is_count_changed = true; + } + + /* This function should be call in any case because of correct updating/rebuilding + * of unregular pages of a Printer Settings + */ + build_unregular_pages(); + + if (is_count_changed) { + on_value_change("extruders_count", extruders_count); + wxGetApp().sidebar().update_objects_list_extruder_column(extruders_count); + } } void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key) @@ -2078,12 +2139,12 @@ PageShp TabPrinter::build_kinematics_page() // Legend for OptionsGroups auto optgroup = page->new_optgroup(""); optgroup->set_show_modified_btns_val(false); - optgroup->label_width = 23 * m_em_unit;// 230; + optgroup->label_width = 23;// 230; auto line = Line{ "", "" }; ConfigOptionDef def; def.type = coString; - def.width = 150; + def.width = 15; def.gui_type = "legend"; def.mode = comAdvanced; def.tooltip = L("Values in this column are for Full Power mode"); @@ -2125,12 +2186,23 @@ PageShp TabPrinter::build_kinematics_page() return page; } - -void TabPrinter::build_extruder_pages() +/* Previous name build_extruder_pages(). + * + * This function was renamed because of now it implements not just an extruder pages building, + * but "Machine limits" and "Single extruder MM setup" too + * (These pages can changes according to the another values of a current preset) + * */ +void TabPrinter::build_unregular_pages() { size_t n_before_extruders = 2; // Count of pages before Extruder pages bool is_marlin_flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlin; + /* ! Freeze/Thaw in this function is needed to avoid call OnPaint() for erased pages + * and be cause of application crash, when try to change Preset in moment, + * when one of unregular pages is selected. + * */ + Freeze(); + // Add/delete Kinematics page according to is_marlin_flavor size_t existed_page = 0; for (int i = n_before_extruders; i < m_pages.size(); ++i) // first make sure it's not there already @@ -2175,12 +2247,11 @@ void TabPrinter::build_extruder_pages() m_has_single_extruder_MM_page = true; } - + // Build missed extruder pages for (auto extruder_idx = m_extruders_count_old; extruder_idx < m_extruders_count; ++extruder_idx) { //# build page - char buf[512]; - sprintf(buf, _CHB(L("Extruder %d")), extruder_idx + 1); - auto page = add_options_page(from_u8(buf), "funnel", true); + const wxString& page_name = wxString::Format(_(L("Extruder %d")), int(extruder_idx + 1)); + auto page = add_options_page(page_name, "funnel", true); m_pages.insert(m_pages.begin() + n_before_extruders + extruder_idx, page); auto optgroup = page->new_optgroup(_(L("Size"))); @@ -2223,8 +2294,13 @@ void TabPrinter::build_extruder_pages() m_pages.erase( m_pages.begin() + n_before_extruders + m_extruders_count, m_pages.begin() + n_before_extruders + m_extruders_count_old); + Thaw(); + m_extruders_count_old = m_extruders_count; rebuild_page_tree(); + + // Reload preset pages with current configuration values + reload_config(); } // this gets executed after preset is loaded and before GUI fields are updated @@ -2492,7 +2568,6 @@ void Tab::rebuild_page_tree() m_treectrl->SelectItem(item); } } -// Thaw(); } void Tab::update_page_tree_visibility() @@ -2728,7 +2803,8 @@ bool Tab::may_switch_to_SLA_preset() void Tab::OnTreeSelChange(wxTreeEvent& event) { - if (m_disable_tree_sel_changed_event) return; + if (m_disable_tree_sel_changed_event) + return; // There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/Slic3r/issues/898 and https://github.com/prusa3d/Slic3r/issues/952. // The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason, @@ -2877,7 +2953,7 @@ void Tab::toggle_show_hide_incompatible() void Tab::update_show_hide_incompatible_button() { - m_btn_hide_incompatible_presets->SetBitmap(m_show_incompatible_presets ? + m_btn_hide_incompatible_presets->SetBitmap_(m_show_incompatible_presets ? m_bmp_show_incompatible_presets : m_bmp_hide_incompatible_presets); m_btn_hide_incompatible_presets->SetToolTip(m_show_incompatible_presets ? "Both compatible an incompatible presets are shown. Click to hide presets not compatible with the current printer." : @@ -2909,10 +2985,8 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep { deps.checkbox = new wxCheckBox(parent, wxID_ANY, _(L("All"))); deps.checkbox->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - deps.btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); - deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - - deps.btn->SetBitmap(create_scaled_bitmap(this, "printer_white")); + add_scaled_button(parent, &deps.btn, "printer_white", _(L(" Set ")) + dots, wxBU_LEFT | wxBU_EXACTFIT); + deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add((deps.checkbox), 0, wxALIGN_CENTER_VERTICAL); @@ -3069,6 +3143,12 @@ void Page::update_visibility(ConfigOptionMode mode) m_show = ret_val; } +void Page::msw_rescale() +{ + for (auto group : m_optgroups) + group->msw_rescale(); +} + Field* Page::get_field(const t_config_option_key& opt_key, int opt_index /*= -1*/) const { Field* field = nullptr; @@ -3092,18 +3172,16 @@ bool Page::set_value(const t_config_option_key& opt_key, const boost::any& value // package Slic3r::GUI::Tab::Page; ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_label_width /*= -1*/) { - auto extra_column = [](wxWindow* parent, const Line& line) + auto extra_column = [this](wxWindow* parent, const Line& line) { std::string bmp_name; const std::vector<Option>& options = line.get_options(); - if (options.size() == 0 || options[0].opt.gui_type == "legend") - bmp_name = "";// "error.png"; - else { - auto mode = options[0].opt.mode; //we assume that we have one option per line - bmp_name = mode == comExpert ? "mode_expert_.png" : - mode == comAdvanced ? "mode_middle_.png" : "mode_simple_.png"; - } - auto bmp = new wxStaticBitmap(parent, wxID_ANY, bmp_name.empty() ? wxNullBitmap : create_scaled_bitmap(parent, bmp_name)); + int mode_id = int(options[0].opt.mode); + const wxBitmap& bitmap = options.size() == 0 || options[0].opt.gui_type == "legend" ? wxNullBitmap : + m_mode_bitmap_cache[mode_id].bmp(); + auto bmp = new wxStaticBitmap(parent, wxID_ANY, bitmap); + bmp->SetClientData((void*)&m_mode_bitmap_cache[mode_id]); + bmp->SetBackgroundStyle(wxBG_STYLE_PAINT); return bmp; }; @@ -3142,6 +3220,14 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la return static_cast<Tab*>(tab)->m_presets->get_selected_preset_parent() != nullptr; }; + optgroup->rescale_extra_column_item = [this](wxWindow* win) { + auto *ctrl = dynamic_cast<wxStaticBitmap*>(win); + if (ctrl == nullptr) + return; + + ctrl->SetBitmap(reinterpret_cast<ScalableBitmap*>(ctrl->GetClientData())->bmp()); + }; + vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); m_optgroups.push_back(optgroup); @@ -3222,7 +3308,7 @@ void TabSLAMaterial::build() optgroup->append_single_option_line("initial_exposure_time"); optgroup = page->new_optgroup(_(L("Corrections"))); - optgroup->label_width = 19 * m_em_unit;//190; + optgroup->label_width = 19;//190; std::vector<std::string> corrections = {"material_correction"}; // std::vector<std::string> axes{ "X", "Y", "Z" }; std::vector<std::string> axes{ "XY", "Z" }; @@ -3232,7 +3318,7 @@ void TabSLAMaterial::build() for (auto& axis : axes) { auto opt = optgroup->get_option(opt_key, id); opt.opt.label = axis; - opt.opt.width = 60; + opt.opt.width = 6; line.append_option(opt); ++id; } @@ -3244,7 +3330,7 @@ void TabSLAMaterial::build() optgroup->label_width = 0; Option option = optgroup->get_option("material_notes"); option.opt.full_width = true; - option.opt.height = 25 * m_em_unit;//250; + option.opt.height = 25;//250; optgroup->append_single_option_line(option); page = add_options_page(_(L("Dependencies")), "wrench.png"); diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 58950990c..ae13cb4b5 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -30,14 +30,14 @@ #include "BedShapeDialog.hpp" #include "Event.hpp" - -class PrusaModeSizer; +#include "wxExtensions.hpp" namespace Slic3r { namespace GUI { -typedef std::pair<wxBitmap*, std::string> t_icon_description; -typedef std::vector<std::pair<wxBitmap*, std::string>> t_icon_descriptions; + +typedef std::pair<ScalableBitmap*, std::string> t_icon_description; +typedef std::vector<std::pair<ScalableBitmap*, std::string>> t_icon_descriptions; // Single Tab page containing a{ vsizer } of{ optgroups } // package Slic3r::GUI::Tab::Page; @@ -50,10 +50,11 @@ class Page : public wxScrolledWindow wxBoxSizer* m_vsizer; bool m_show = true; public: - Page(wxWindow* parent, const wxString title, const int iconID) : + Page(wxWindow* parent, const wxString title, const int iconID, const std::vector<ScalableBitmap>& mode_bmp_cache) : m_parent(parent), m_title(title), - m_iconID(iconID) + m_iconID(iconID), + m_mode_bitmap_cache(mode_bmp_cache) { Create(m_parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); m_vsizer = new wxBoxSizer(wxVERTICAL); @@ -67,6 +68,7 @@ public: // Delayed layout after resizing the main window. bool layout_valid = false; + const std::vector<ScalableBitmap>& m_mode_bitmap_cache; public: std::vector <ConfigOptionsGroupShp> m_optgroups; @@ -79,6 +81,7 @@ public: void set_config(DynamicPrintConfig* config_in) { m_config = config_in; } void reload_config(); void update_visibility(ConfigOptionMode mode); + void msw_rescale(); Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const; bool set_value(const t_config_option_key& opt_key, const boost::any& value); ConfigOptionsGroupShp new_optgroup(const wxString& title, int noncommon_label_width = -1); @@ -119,20 +122,20 @@ protected: std::string m_name; const wxString m_title; wxBitmapComboBox* m_presets_choice; - wxBitmapButton* m_btn_save_preset; - wxBitmapButton* m_btn_delete_preset; - wxBitmapButton* m_btn_hide_incompatible_presets; + ScalableButton* m_btn_save_preset; + ScalableButton* m_btn_delete_preset; + ScalableButton* m_btn_hide_incompatible_presets; wxBoxSizer* m_hsizer; wxBoxSizer* m_left_sizer; wxTreeCtrl* m_treectrl; wxImageList* m_icons; - PrusaModeSizer* m_mode_sizer; + ModeSizer* m_mode_sizer; struct PresetDependencies { Preset::Type type = Preset::TYPE_INVALID; wxCheckBox *checkbox = nullptr; - wxButton *btn = nullptr; + ScalableButton *btn = nullptr; std::string key_list; // "compatible_printers" std::string key_condition; std::string dialog_title; @@ -141,25 +144,27 @@ protected: PresetDependencies m_compatible_printers; PresetDependencies m_compatible_prints; - wxButton* m_undo_btn; - wxButton* m_undo_to_sys_btn; - wxButton* m_question_btn; - wxImageList* m_preset_icons; + ScalableButton* m_undo_btn; + ScalableButton* m_undo_to_sys_btn; + ScalableButton* m_question_btn; // Cached bitmaps. // A "flag" icon to be displayned next to the preset name in the Tab's combo box. - wxBitmap m_bmp_show_incompatible_presets; - wxBitmap m_bmp_hide_incompatible_presets; + ScalableBitmap m_bmp_show_incompatible_presets; + ScalableBitmap m_bmp_hide_incompatible_presets; // Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field. - wxBitmap m_bmp_value_lock; - wxBitmap m_bmp_value_unlock; - wxBitmap m_bmp_white_bullet; + ScalableBitmap m_bmp_value_lock; + ScalableBitmap m_bmp_value_unlock; + ScalableBitmap m_bmp_white_bullet; // The following bitmap points to either m_bmp_value_unlock or m_bmp_white_bullet, depending on whether the current preset has a parent preset. - wxBitmap *m_bmp_non_system; + ScalableBitmap *m_bmp_non_system; // Bitmaps to be shown on the "Undo user changes" button next to each input field. - wxBitmap m_bmp_value_revert; -// wxBitmap m_bmp_value_unmodified; - wxBitmap m_bmp_question; + ScalableBitmap m_bmp_value_revert; + + std::vector<ScalableButton*> m_scaled_buttons = {}; + std::vector<ScalableBitmap*> m_scaled_bitmaps = {}; + std::vector<ScalableBitmap> m_scaled_icons_list = {}; + std::vector<ScalableBitmap> m_mode_bitmap_cache = {}; // Colors for ui "decoration" wxColour m_sys_label_clr; @@ -236,7 +241,11 @@ public: virtual bool supports_printer_technology(const PrinterTechnology tech) = 0; void create_preset_tab(); - void load_current_preset(); + void add_scaled_button(wxWindow* parent, ScalableButton** btn, const std::string& icon_name, + const wxString& label = wxEmptyString, + long style = wxBU_EXACTFIT | wxNO_BORDER); + void add_scaled_bitmap(wxWindow* parent, ScalableBitmap& btn, const std::string& icon_name); + void load_current_preset(); void rebuild_page_tree(); void update_page_tree_visibility(); // Select a new preset, possibly delete the current one. @@ -274,6 +283,7 @@ public: virtual void reload_config(); void update_mode(); void update_visibility(); + void msw_rescale(); Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const; bool set_value(const t_config_option_key& opt_key, const boost::any& value); wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText); @@ -345,8 +355,8 @@ class TabPrinter : public Tab void build_printhost(ConfigOptionsGroup *optgroup); public: wxButton* m_serial_test_btn = nullptr; - wxButton* m_print_host_test_btn = nullptr; - wxButton* m_printhost_browse_btn = nullptr; + ScalableButton* m_print_host_test_btn = nullptr; + ScalableButton* m_printhost_browse_btn = nullptr; size_t m_extruders_count; size_t m_extruders_count_old = 0; @@ -368,7 +378,7 @@ public: void update_serial_ports(); void extruders_count_changed(size_t extruders_count); PageShp build_kinematics_page(); - void build_extruder_pages(); + void build_unregular_pages(); void on_preset_loaded() override; void init_options_list() override; bool supports_printer_technology(const PrinterTechnology /* tech */) override { return true; } diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp index 99288488c..b4943cf46 100644 --- a/src/slic3r/GUI/UpdateDialogs.cpp +++ b/src/slic3r/GUI/UpdateDialogs.cpp @@ -109,7 +109,8 @@ MsgUpdateConfig::~MsgUpdateConfig() {} // MsgDataIncompatible MsgDataIncompatible::MsgDataIncompatible(const std::unordered_map<std::string, wxString> &incompats) : - MsgDialog(nullptr, _(L("Slic3r incompatibility")), _(L("Slic3r configuration is incompatible")), wxID_NONE) + MsgDialog(nullptr, wxString::Format(_(L("%s incompatibility")), SLIC3R_APP_NAME), + wxString::Format(_(L("%s configuration is incompatible")), SLIC3R_APP_NAME), wxID_NONE) { logo->SetBitmap(create_scaled_bitmap(this, "Slic3r_192px_grayscale.png", 192)); @@ -117,9 +118,9 @@ MsgDataIncompatible::MsgDataIncompatible(const std::unordered_map<std::string, w "This version of %s is not compatible with currently installed configuration bundles.\n" "This probably happened as a result of running an older %s after using a newer one.\n\n" - "You may either exit Slic3r and try again with a newer version, or you may re-run the initial configuration. " - "Doing so will create a backup snapshot of the existing configuration before installing files compatible with this Slic3r.\n" - )), SLIC3R_APP_NAME, SLIC3R_APP_NAME)); + "You may either exit %s and try again with a newer version, or you may re-run the initial configuration. " + "Doing so will create a backup snapshot of the existing configuration before installing files compatible with this %s.\n" + )), SLIC3R_APP_NAME, SLIC3R_APP_NAME, SLIC3R_APP_NAME, SLIC3R_APP_NAME)); text->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); content_sizer->Add(text); @@ -144,7 +145,7 @@ MsgDataIncompatible::MsgDataIncompatible(const std::unordered_map<std::string, w content_sizer->Add(versions); content_sizer->AddSpacer(2*VERT_SPACING); - auto *btn_exit = new wxButton(this, wxID_EXIT, _(L("Exit Slic3r"))); + auto *btn_exit = new wxButton(this, wxID_EXIT, wxString::Format(_(L("Exit %s")), SLIC3R_APP_NAME)); btn_sizer->Add(btn_exit); btn_sizer->AddSpacer(HORIZ_SPACING); auto *btn_reconf = new wxButton(this, wxID_REPLACE, _(L("Re-configure"))); @@ -187,7 +188,7 @@ MsgDataLegacy::MsgDataLegacy() : auto *text2 = new wxStaticText(this, wxID_ANY, _(L("For more information please visit our wiki page:"))); static const wxString url("https://github.com/prusa3d/Slic3r/wiki/Slic3r-PE-1.40-configuration-update"); // The wiki page name is intentionally not localized: - auto *link = new wxHyperlinkCtrl(this, wxID_ANY, "Slic3r PE 1.40 configuration update", CONFIG_UPDATE_WIKI_URL); + auto *link = new wxHyperlinkCtrl(this, wxID_ANY, wxString::Format("%s 1.40 configuration update", SLIC3R_APP_NAME), CONFIG_UPDATE_WIKI_URL); content_sizer->Add(text2); content_sizer->Add(link); content_sizer->AddSpacer(VERT_SPACING); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index c0390d1a2..d76e0da93 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -18,6 +18,7 @@ #include "GUI_ObjectList.hpp" #include "libslic3r/GCode/PreviewData.hpp" #include "I18N.hpp" +#include "GUI_Utils.hpp" using Slic3r::GUI::from_u8; @@ -266,160 +267,45 @@ void wxDataViewTreeCtrlComboPopup::OnDataViewTreeCtrlSelection(wxCommandEvent& e cmb->SetText(selected); } -// ---------------------------------------------------------------------------- -// *** PrusaCollapsiblePane *** -// ---------------------------------------------------------------------------- -void PrusaCollapsiblePane::OnStateChange(const wxSize& sz) -{ -#ifdef __WXOSX__ - wxCollapsiblePane::OnStateChange(sz); -#else - SetSize(sz); - - if (this->HasFlag(wxCP_NO_TLW_RESIZE)) - { - // the user asked to explicitly handle the resizing itself... - return; - } - - auto top = GetParent(); //right_panel - if (!top) - return; - - wxSizer *sizer = top->GetSizer(); - if (!sizer) - return; - - const wxSize newBestSize = sizer->ComputeFittingClientSize(top); - top->SetMinClientSize(newBestSize); - - wxWindowUpdateLocker noUpdates_p(top->GetParent()); - // we shouldn't attempt to resize a maximized window, whatever happens - // if (!top->IsMaximized()) - // top->SetClientSize(newBestSize); - top->GetParent()->Layout(); - top->Refresh(); -#endif //__WXOSX__ -} - -// ---------------------------------------------------------------------------- -// *** PrusaCollapsiblePaneMSW *** used only #ifdef __WXMSW__ -// ---------------------------------------------------------------------------- -#ifdef __WXMSW__ -bool PrusaCollapsiblePaneMSW::Create(wxWindow *parent, wxWindowID id, const wxString& label, - const wxPoint& pos, const wxSize& size, long style, const wxValidator& val, const wxString& name) -{ - if (!wxControl::Create(parent, id, pos, size, style, val, name)) - return false; - // m_pStaticLine = NULL; - m_strLabel = label; - - // sizer containing the expand button and possibly a static line - m_sz = new wxBoxSizer(wxHORIZONTAL); - - m_bmp_close.LoadFile(Slic3r::GUI::from_u8(Slic3r::var("disclosure_triangle_close.png")), wxBITMAP_TYPE_PNG); - m_bmp_open.LoadFile(Slic3r::GUI::from_u8(Slic3r::var("disclosure_triangle_open.png")), wxBITMAP_TYPE_PNG); - - m_pDisclosureTriangleButton = new wxButton(this, wxID_ANY, m_strLabel, wxPoint(0, 0), - wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); - UpdateBtnBmp(); - m_pDisclosureTriangleButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) - { - if (event.GetEventObject() != m_pDisclosureTriangleButton) - { - event.Skip(); - return; - } - - Collapse(!IsCollapsed()); - - // this change was generated by the user - send the event - wxCollapsiblePaneEvent ev(this, GetId(), IsCollapsed()); - GetEventHandler()->ProcessEvent(ev); - }); - - m_sz->Add(m_pDisclosureTriangleButton, 0, wxLEFT | wxTOP | wxBOTTOM, GetBorder()); - - // do not set sz as our sizers since we handle the pane window without using sizers - m_pPane = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, - wxTAB_TRAVERSAL | wxNO_BORDER, wxT("wxCollapsiblePanePane")); - - wxColour&& clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - m_pDisclosureTriangleButton->SetBackgroundColour(clr); - this->SetBackgroundColour(clr); - m_pPane->SetBackgroundColour(clr); - - // start as collapsed: - m_pPane->Hide(); - - return true; -} - -void PrusaCollapsiblePaneMSW::UpdateBtnBmp() -{ - if (IsCollapsed()) - m_pDisclosureTriangleButton->SetBitmap(m_bmp_close); - else{ - m_pDisclosureTriangleButton->SetBitmap(m_bmp_open); - // To updating button bitmap it's needed to lost focus on this button, so - // we set focus to mainframe - //GetParent()->GetParent()->GetParent()->SetFocus(); - //or to pane - GetPane()->SetFocus(); - } - Layout(); -} - -void PrusaCollapsiblePaneMSW::SetLabel(const wxString &label) +// edit tooltip : change Slic3r to SLIC3R_APP_KEY +// Temporary workaround for localization +void edit_tooltip(wxString& tooltip) { - m_strLabel = label; - m_pDisclosureTriangleButton->SetLabel(m_strLabel); - Layout(); + tooltip.Replace("Slic3r", SLIC3R_APP_KEY, true); } -bool PrusaCollapsiblePaneMSW::Layout() +/* Function for rescale of buttons in Dialog under MSW if dpi is changed. + * btn_ids - vector of buttons identifiers + */ +void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<int>& btn_ids) { - if (!m_pDisclosureTriangleButton || !m_pPane || !m_sz) - return false; // we need to complete the creation first! - - wxSize oursz(GetSize()); + const wxSize& btn_size = wxSize(-1, int(2.5f * em_unit + 0.5f)); - // move & resize the button and the static line - m_sz->SetDimension(0, 0, oursz.GetWidth(), m_sz->GetMinSize().GetHeight()); - m_sz->Layout(); - - if (IsExpanded()) - { - // move & resize the container window - int yoffset = m_sz->GetSize().GetHeight() + GetBorder(); - m_pPane->SetSize(0, yoffset, - oursz.x, oursz.y - yoffset); - - // this is very important to make the pane window layout show correctly - m_pPane->Layout(); - } - - return true; + for (int btn_id : btn_ids) { + // There is a case [FirmwareDialog], when we have wxControl instead of wxButton + // so let casting everything to the wxControl + wxControl* btn = static_cast<wxControl*>(dlg->FindWindowById(btn_id, dlg)); + if (btn) + btn->SetMinSize(btn_size); + } } -void PrusaCollapsiblePaneMSW::Collapse(bool collapse) +/* Function for getting of em_unit value from correct parent. + * In most of cases it is m_em_unit value from GUI_App, + * but for DPIDialogs it's its own value. + * This value will be used to correct rescale after moving between + * Displays with different HDPI */ +int em_unit(wxWindow* win) { - // optimization - if (IsCollapsed() == collapse) - return; - - InvalidateBestSize(); - - // update our state - m_pPane->Show(!collapse); - - // update button bitmap - UpdateBtnBmp(); - - OnStateChange(GetBestSize()); + if (win) + { + Slic3r::GUI::DPIDialog* dlg = dynamic_cast<Slic3r::GUI::DPIDialog*>(Slic3r::GUI::find_toplevel_parent(win)); + if (dlg) + return dlg->em_unit(); + } + + return Slic3r::GUI::wxGetApp().em_unit(); } -#endif //__WXMSW__ - // If an icon has horizontal orientation (width > height) call this function with is_horizontal = true wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name_in, const int px_cnt/* = 16*/, const bool is_horizontal /* = false*/) @@ -436,7 +322,7 @@ wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name_in, con unsigned int height, width = height = 0; unsigned int& scale_base = is_horizontal ? width : height; - scale_base = (unsigned int)(Slic3r::GUI::wxGetApp().em_unit() * px_cnt * 0.1f + 0.5f); + scale_base = (unsigned int)(em_unit(win) * px_cnt * 0.1f + 0.5f); std::string bmp_name = bmp_name_in; boost::replace_last(bmp_name, ".png", ""); @@ -457,58 +343,76 @@ wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name_in, con // ***************************************************************************** // ---------------------------------------------------------------------------- -// PrusaObjectDataViewModelNode +// ObjectDataViewModelNode // ---------------------------------------------------------------------------- -void PrusaObjectDataViewModelNode::set_object_action_icon() { - m_action_icon = create_scaled_bitmap(nullptr, "advanced_plus"); // FIXME: pass window ptr -} -void PrusaObjectDataViewModelNode::set_part_action_icon() { - m_action_icon = create_scaled_bitmap(nullptr, m_type == itVolume ? "cog" : "set_separate_obj"); // FIXME: pass window ptr +void ObjectDataViewModelNode::set_action_icon() +{ + m_action_icon_name = m_type == itObject ? "advanced_plus" : + m_type == itVolume ? "cog" : "set_separate_obj"; + m_action_icon = create_scaled_bitmap(nullptr, m_action_icon_name); // FIXME: pass window ptr } Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr; -bool PrusaObjectDataViewModelNode::update_settings_digest(const std::vector<std::string>& categories) +void ObjectDataViewModelNode::update_settings_digest_bitmaps() { - if (m_type != itSettings || m_opt_categories == categories) - return false; - - m_opt_categories = categories; - m_name = wxEmptyString; m_bmp = m_empty_bmp; std::map<std::string, wxBitmap>& categories_icon = Slic3r::GUI::wxGetApp().obj_list()->CATEGORY_ICON; - for (auto& cat : m_opt_categories) - m_name += cat + "; "; - if (!m_name.IsEmpty()) - m_name.erase(m_name.Length()-2, 2); // Delete last "; " + std::string scaled_bitmap_name = m_name.ToUTF8().data(); + scaled_bitmap_name += "-em" + std::to_string(Slic3r::GUI::wxGetApp().em_unit()); - wxBitmap *bmp = m_bitmap_cache->find(m_name.ToUTF8().data()); + wxBitmap *bmp = m_bitmap_cache->find(scaled_bitmap_name); if (bmp == nullptr) { std::vector<wxBitmap> bmps; for (auto& cat : m_opt_categories) - bmps.emplace_back(categories_icon.find(cat) == categories_icon.end() ? - wxNullBitmap : categories_icon.at(cat)); - bmp = m_bitmap_cache->insert(m_name.ToUTF8().data(), bmps); + bmps.emplace_back( categories_icon.find(cat) == categories_icon.end() ? + wxNullBitmap : categories_icon.at(cat)); + bmp = m_bitmap_cache->insert(scaled_bitmap_name, bmps); } m_bmp = *bmp; +} + +bool ObjectDataViewModelNode::update_settings_digest(const std::vector<std::string>& categories) +{ + if (m_type != itSettings || m_opt_categories == categories) + return false; + + m_opt_categories = categories; + m_name = wxEmptyString; + + for (auto& cat : m_opt_categories) + m_name += cat + "; "; + if (!m_name.IsEmpty()) + m_name.erase(m_name.Length()-2, 2); // Delete last "; " + + update_settings_digest_bitmaps(); return true; } +void ObjectDataViewModelNode::msw_rescale() +{ + if (!m_action_icon_name.empty()) + m_action_icon = create_scaled_bitmap(nullptr, m_action_icon_name); + + if (!m_opt_categories.empty()) + update_settings_digest_bitmaps(); +} + // ***************************************************************************** // ---------------------------------------------------------------------------- -// PrusaObjectDataViewModel +// ObjectDataViewModel // ---------------------------------------------------------------------------- -PrusaObjectDataViewModel::PrusaObjectDataViewModel() +ObjectDataViewModel::ObjectDataViewModel() { m_bitmap_cache = new Slic3r::GUI::BitmapCache; } -PrusaObjectDataViewModel::~PrusaObjectDataViewModel() +ObjectDataViewModel::~ObjectDataViewModel() { for (auto object : m_objects) delete object; @@ -516,10 +420,10 @@ PrusaObjectDataViewModel::~PrusaObjectDataViewModel() m_bitmap_cache = nullptr; } -wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name, const int extruder) +wxDataViewItem ObjectDataViewModel::Add(const wxString &name, const int extruder) { const wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder); - auto root = new PrusaObjectDataViewModelNode(name, extruder_str); + auto root = new ObjectDataViewModelNode(name, extruder_str); m_objects.push_back(root); // notify control wxDataViewItem child((void*)root); @@ -528,13 +432,13 @@ wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name, const int ext return child; } -wxDataViewItem PrusaObjectDataViewModel::AddVolumeChild(const wxDataViewItem &parent_item, - const wxString &name, - const Slic3r::ModelVolumeType volume_type, - const int extruder/* = 0*/, - const bool create_frst_child/* = true*/) +wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent_item, + const wxString &name, + const Slic3r::ModelVolumeType volume_type, + const int extruder/* = 0*/, + const bool create_frst_child/* = true*/) { - PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID(); + ObjectDataViewModelNode *root = (ObjectDataViewModelNode*)parent_item.GetID(); if (!root) return wxDataViewItem(0); wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder); @@ -546,7 +450,7 @@ wxDataViewItem PrusaObjectDataViewModel::AddVolumeChild(const wxDataViewItem &pa if (create_frst_child && root->m_volumes_cnt == 0) { - const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, *m_volume_bmps[0], extruder_str, 0); + const auto node = new ObjectDataViewModelNode(root, root->m_name, *m_volume_bmps[0], extruder_str, 0); insert_position < 0 ? root->Append(node) : root->Insert(node, insert_position); // notify control const wxDataViewItem child((void*)node); @@ -554,24 +458,28 @@ wxDataViewItem PrusaObjectDataViewModel::AddVolumeChild(const wxDataViewItem &pa root->m_volumes_cnt++; if (insert_position > 0) insert_position++; + + node->m_volume_type = volume_type; } - const auto node = new PrusaObjectDataViewModelNode(root, name, *m_volume_bmps[int(volume_type)], extruder_str, root->m_volumes_cnt); + const auto node = new ObjectDataViewModelNode(root, name, *m_volume_bmps[int(volume_type)], extruder_str, root->m_volumes_cnt); insert_position < 0 ? root->Append(node) : root->Insert(node, insert_position); // notify control const wxDataViewItem child((void*)node); ItemAdded(parent_item, child); root->m_volumes_cnt++; + node->m_volume_type = volume_type; + return child; } -wxDataViewItem PrusaObjectDataViewModel::AddSettingsChild(const wxDataViewItem &parent_item) +wxDataViewItem ObjectDataViewModel::AddSettingsChild(const wxDataViewItem &parent_item) { - PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID(); + ObjectDataViewModelNode *root = (ObjectDataViewModelNode*)parent_item.GetID(); if (!root) return wxDataViewItem(0); - const auto node = new PrusaObjectDataViewModelNode(root, itSettings); + const auto node = new ObjectDataViewModelNode(root, itSettings); root->Insert(node, 0); // notify control const wxDataViewItem child((void*)node); @@ -579,27 +487,27 @@ wxDataViewItem PrusaObjectDataViewModel::AddSettingsChild(const wxDataViewItem & return child; } -int get_istances_root_idx(PrusaObjectDataViewModelNode *parent_node) +int get_istances_root_idx(ObjectDataViewModelNode *parent_node) { // because of istance_root is a last item of the object const int inst_root_idx = parent_node->GetChildCount()-1; - if (inst_root_idx < 0 || parent_node->GetNthChild(inst_root_idx)->m_type == itInstanceRoot) + if (inst_root_idx < 0 || parent_node->GetNthChild(inst_root_idx)->GetType() == itInstanceRoot) return inst_root_idx; return -1; } -wxDataViewItem PrusaObjectDataViewModel::AddInstanceChild(const wxDataViewItem &parent_item, size_t num) +wxDataViewItem ObjectDataViewModel::AddInstanceChild(const wxDataViewItem &parent_item, size_t num) { - PrusaObjectDataViewModelNode *parent_node = (PrusaObjectDataViewModelNode*)parent_item.GetID(); + ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); if (!parent_node) return wxDataViewItem(0); // Check and create/get instances root node const int inst_root_id = get_istances_root_idx(parent_node); - PrusaObjectDataViewModelNode *inst_root_node = inst_root_id < 0 ? - new PrusaObjectDataViewModelNode(parent_node, itInstanceRoot) : + ObjectDataViewModelNode *inst_root_node = inst_root_id < 0 ? + new ObjectDataViewModelNode(parent_node, itInstanceRoot) : parent_node->GetNthChild(inst_root_id); const wxDataViewItem inst_root_item((void*)inst_root_node); @@ -611,10 +519,10 @@ wxDataViewItem PrusaObjectDataViewModel::AddInstanceChild(const wxDataViewItem & } // Add instance nodes - PrusaObjectDataViewModelNode *instance_node = nullptr; + ObjectDataViewModelNode *instance_node = nullptr; size_t counter = 0; while (counter < num) { - instance_node = new PrusaObjectDataViewModelNode(inst_root_node, itInstance); + instance_node = new ObjectDataViewModelNode(inst_root_node, itInstance); inst_root_node->Append(instance_node); // notify control const wxDataViewItem instance_item((void*)instance_node); @@ -625,10 +533,10 @@ wxDataViewItem PrusaObjectDataViewModel::AddInstanceChild(const wxDataViewItem & return wxDataViewItem((void*)instance_node); } -wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) +wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item) { auto ret_item = wxDataViewItem(0); - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); if (!node) // happens if item.IsOk()==false return ret_item; @@ -676,12 +584,12 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) delete node; ItemDeleted(parent, item); - PrusaObjectDataViewModelNode *last_instance_node = node_parent->GetNthChild(0); + ObjectDataViewModelNode *last_instance_node = node_parent->GetNthChild(0); node_parent->GetChildren().Remove(last_instance_node); delete last_instance_node; ItemDeleted(parent, wxDataViewItem(last_instance_node)); - PrusaObjectDataViewModelNode *obj_node = node_parent->GetParent(); + ObjectDataViewModelNode *obj_node = node_parent->GetParent(); obj_node->GetChildren().Remove(node_parent); delete node_parent; ret_item = wxDataViewItem(obj_node); @@ -712,7 +620,7 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) delete node; ItemDeleted(parent, item); - PrusaObjectDataViewModelNode *last_child_node = node_parent->GetNthChild(vol_idx); + ObjectDataViewModelNode *last_child_node = node_parent->GetNthChild(vol_idx); DeleteSettings(wxDataViewItem(last_child_node)); node_parent->GetChildren().Remove(last_child_node); node_parent->m_volumes_cnt = 0; @@ -771,17 +679,17 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) return ret_item; } -wxDataViewItem PrusaObjectDataViewModel::DeleteLastInstance(const wxDataViewItem &parent_item, size_t num) +wxDataViewItem ObjectDataViewModel::DeleteLastInstance(const wxDataViewItem &parent_item, size_t num) { auto ret_item = wxDataViewItem(0); - PrusaObjectDataViewModelNode *parent_node = (PrusaObjectDataViewModelNode*)parent_item.GetID(); + ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); if (!parent_node) return ret_item; const int inst_root_id = get_istances_root_idx(parent_node); if (inst_root_id < 0) return ret_item; wxDataViewItemArray items; - PrusaObjectDataViewModelNode *inst_root_node = parent_node->GetNthChild(inst_root_id); + ObjectDataViewModelNode *inst_root_node = parent_node->GetNthChild(inst_root_id); const wxDataViewItem inst_root_item((void*)inst_root_node); const int inst_cnt = inst_root_node->GetChildCount(); @@ -789,7 +697,7 @@ wxDataViewItem PrusaObjectDataViewModel::DeleteLastInstance(const wxDataViewItem int stop = delete_inst_root_item ? 0 : inst_cnt - num; for (int i = inst_cnt - 1; i >= stop;--i) { - PrusaObjectDataViewModelNode *last_instance_node = inst_root_node->GetNthChild(i); + ObjectDataViewModelNode *last_instance_node = inst_root_node->GetNthChild(i); inst_root_node->GetChildren().Remove(last_instance_node); delete last_instance_node; ItemDeleted(inst_root_item, wxDataViewItem(last_instance_node)); @@ -808,7 +716,7 @@ wxDataViewItem PrusaObjectDataViewModel::DeleteLastInstance(const wxDataViewItem return ret_item; } -void PrusaObjectDataViewModel::DeleteAll() +void ObjectDataViewModel::DeleteAll() { while (!m_objects.empty()) { @@ -818,9 +726,9 @@ void PrusaObjectDataViewModel::DeleteAll() } } -void PrusaObjectDataViewModel::DeleteChildren(wxDataViewItem& parent) +void ObjectDataViewModel::DeleteChildren(wxDataViewItem& parent) { - PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent.GetID(); + ObjectDataViewModelNode *root = (ObjectDataViewModelNode*)parent.GetID(); if (!root) // happens if item.IsOk()==false return; @@ -850,9 +758,9 @@ void PrusaObjectDataViewModel::DeleteChildren(wxDataViewItem& parent) #endif //__WXGTK__ } -void PrusaObjectDataViewModel::DeleteVolumeChildren(wxDataViewItem& parent) +void ObjectDataViewModel::DeleteVolumeChildren(wxDataViewItem& parent) { - PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent.GetID(); + ObjectDataViewModelNode *root = (ObjectDataViewModelNode*)parent.GetID(); if (!root) // happens if item.IsOk()==false return; @@ -884,9 +792,9 @@ void PrusaObjectDataViewModel::DeleteVolumeChildren(wxDataViewItem& parent) #endif //__WXGTK__ } -void PrusaObjectDataViewModel::DeleteSettings(const wxDataViewItem& parent) +void ObjectDataViewModel::DeleteSettings(const wxDataViewItem& parent) { - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)parent.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)parent.GetID(); if (!node) return; // if volume has a "settings"item, than delete it before volume deleting @@ -899,7 +807,7 @@ void PrusaObjectDataViewModel::DeleteSettings(const wxDataViewItem& parent) } } -wxDataViewItem PrusaObjectDataViewModel::GetItemById(int obj_idx) +wxDataViewItem ObjectDataViewModel::GetItemById(int obj_idx) { if (obj_idx >= m_objects.size()) { @@ -910,7 +818,7 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemById(int obj_idx) } -wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volume_idx) +wxDataViewItem ObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volume_idx) { if (obj_idx >= m_objects.size() || obj_idx < 0) { printf("Error! Out of objects range.\n"); @@ -934,7 +842,7 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volu return wxDataViewItem(0); } -wxDataViewItem PrusaObjectDataViewModel::GetItemByInstanceId(int obj_idx, int inst_idx) +wxDataViewItem ObjectDataViewModel::GetItemByInstanceId(int obj_idx, int inst_idx) { if (obj_idx >= m_objects.size() || obj_idx < 0) { printf("Error! Out of objects range.\n"); @@ -945,7 +853,7 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByInstanceId(int obj_idx, int in if (!instances_item) return wxDataViewItem(0); - auto parent = (PrusaObjectDataViewModelNode*)instances_item.GetID();; + auto parent = (ObjectDataViewModelNode*)instances_item.GetID();; for (size_t i = 0; i < parent->GetChildCount(); i++) if (parent->GetNthChild(i)->m_idx == inst_idx) return wxDataViewItem(parent->GetNthChild(i)); @@ -953,11 +861,11 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByInstanceId(int obj_idx, int in return wxDataViewItem(0); } -int PrusaObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) const +int ObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) const { wxASSERT(item.IsOk()); - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); auto it = find(m_objects.begin(), m_objects.end(), node); if (it == m_objects.end()) return -1; @@ -965,44 +873,44 @@ int PrusaObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) const return it - m_objects.begin(); } -int PrusaObjectDataViewModel::GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const +int ObjectDataViewModel::GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const { wxASSERT(item.IsOk()); - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); if (!node || node->m_type != type) return -1; return node->GetIdx(); } -int PrusaObjectDataViewModel::GetObjectIdByItem(const wxDataViewItem& item) const +int ObjectDataViewModel::GetObjectIdByItem(const wxDataViewItem& item) const { return GetIdByItem(GetTopParent(item)); } -int PrusaObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item) const +int ObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item) const { return GetIdByItemAndType(item, itVolume); } -int PrusaObjectDataViewModel::GetInstanceIdByItem(const wxDataViewItem& item) const +int ObjectDataViewModel::GetInstanceIdByItem(const wxDataViewItem& item) const { return GetIdByItemAndType(item, itInstance); } -void PrusaObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx) +void ObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx) { wxASSERT(item.IsOk()); type = itUndef; - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); if (!node || node->GetIdx() <-1 || node->GetIdx() ==-1 && !(node->GetType() & (itObject | itSettings | itInstanceRoot))) return; idx = node->GetIdx(); type = node->GetType(); - PrusaObjectDataViewModelNode *parent_node = node->GetParent(); + ObjectDataViewModelNode *parent_node = node->GetParent(); if (!parent_node) return; if (type == itInstance) parent_node = node->GetParent()->GetParent(); @@ -1015,7 +923,7 @@ void PrusaObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type = itUndef; } -int PrusaObjectDataViewModel::GetRowByItem(const wxDataViewItem& item) const +int ObjectDataViewModel::GetRowByItem(const wxDataViewItem& item) const { if (m_objects.empty()) return -1; @@ -1031,7 +939,7 @@ int PrusaObjectDataViewModel::GetRowByItem(const wxDataViewItem& item) const for (int j = 0; j < m_objects[i]->GetChildCount(); j++) { row_num++; - PrusaObjectDataViewModelNode* cur_node = m_objects[i]->GetNthChild(j); + ObjectDataViewModelNode* cur_node = m_objects[i]->GetNthChild(j); if (item == wxDataViewItem(cur_node)) return row_num; @@ -1053,30 +961,30 @@ int PrusaObjectDataViewModel::GetRowByItem(const wxDataViewItem& item) const return -1; } -wxString PrusaObjectDataViewModel::GetName(const wxDataViewItem &item) const +wxString ObjectDataViewModel::GetName(const wxDataViewItem &item) const { - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); if (!node) // happens if item.IsOk()==false return wxEmptyString; return node->m_name; } -wxBitmap& PrusaObjectDataViewModel::GetBitmap(const wxDataViewItem &item) const +wxBitmap& ObjectDataViewModel::GetBitmap(const wxDataViewItem &item) const { - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); return node->m_bmp; } -void PrusaObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem &item, unsigned int col) const +void ObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem &item, unsigned int col) const { wxASSERT(item.IsOk()); - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); switch (col) { case 0: - variant << PrusaDataViewBitmapText(node->m_name, node->m_bmp); + variant << DataViewBitmapText(node->m_name, node->m_bmp); break; case 1: variant = node->m_extruder; @@ -1089,83 +997,37 @@ void PrusaObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem } } -bool PrusaObjectDataViewModel::SetValue(const wxVariant &variant, const wxDataViewItem &item, unsigned int col) +bool ObjectDataViewModel::SetValue(const wxVariant &variant, const wxDataViewItem &item, unsigned int col) { wxASSERT(item.IsOk()); - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); return node->SetValue(variant, col); } -bool PrusaObjectDataViewModel::SetValue(const wxVariant &variant, const int item_idx, unsigned int col) +bool ObjectDataViewModel::SetValue(const wxVariant &variant, const int item_idx, unsigned int col) { if (item_idx < 0 || item_idx >= m_objects.size()) return false; return m_objects[item_idx]->SetValue(variant, col); } -/* -wxDataViewItem PrusaObjectDataViewModel::MoveChildUp(const wxDataViewItem &item) -{ - auto ret_item = wxDataViewItem(0); - wxASSERT(item.IsOk()); - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - if (!node) // happens if item.IsOk()==false - return ret_item; - auto node_parent = node->GetParent(); - if (!node_parent) // If isn't part, but object - return ret_item; - - auto volume_id = node->GetVolumeId(); - if (0 < volume_id && volume_id < node_parent->GetChildCount()) { - node_parent->SwapChildrens(volume_id - 1, volume_id); - ret_item = wxDataViewItem(node_parent->GetNthChild(volume_id - 1)); - ItemChanged(item); - ItemChanged(ret_item); - } - else - ret_item = wxDataViewItem(node_parent->GetNthChild(0)); - return ret_item; -} - -wxDataViewItem PrusaObjectDataViewModel::MoveChildDown(const wxDataViewItem &item) -{ - auto ret_item = wxDataViewItem(0); - wxASSERT(item.IsOk()); - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - if (!node) // happens if item.IsOk()==false - return ret_item; - - auto node_parent = node->GetParent(); - if (!node_parent) // If isn't part, but object - return ret_item; - - auto volume_id = node->GetVolumeId(); - if (0 <= volume_id && volume_id+1 < node_parent->GetChildCount()) { - node_parent->SwapChildrens(volume_id + 1, volume_id); - ret_item = wxDataViewItem(node_parent->GetNthChild(volume_id + 1)); - ItemChanged(item); - ItemChanged(ret_item); - } - else - ret_item = wxDataViewItem(node_parent->GetNthChild(node_parent->GetChildCount()-1)); - return ret_item; -} -*/ -wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_id, int new_volume_id, const wxDataViewItem &parent) +wxDataViewItem ObjectDataViewModel::ReorganizeChildren( const int current_volume_id, + const int new_volume_id, + const wxDataViewItem &parent) { auto ret_item = wxDataViewItem(0); if (current_volume_id == new_volume_id) return ret_item; wxASSERT(parent.IsOk()); - PrusaObjectDataViewModelNode *node_parent = (PrusaObjectDataViewModelNode*)parent.GetID(); + ObjectDataViewModelNode *node_parent = (ObjectDataViewModelNode*)parent.GetID(); if (!node_parent) // happens if item.IsOk()==false return ret_item; const size_t shift = node_parent->GetChildren().Item(0)->m_type == itSettings ? 1 : 0; - PrusaObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id+shift); + ObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id+shift); node_parent->GetChildren().Remove(deleted_node); ItemDeleted(parent, wxDataViewItem(deleted_node)); node_parent->Insert(deleted_node, new_volume_id+shift); @@ -1184,22 +1046,22 @@ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_i return wxDataViewItem(node_parent->GetNthChild(new_volume_id+shift)); } -bool PrusaObjectDataViewModel::IsEnabled(const wxDataViewItem &item, unsigned int col) const +bool ObjectDataViewModel::IsEnabled(const wxDataViewItem &item, unsigned int col) const { wxASSERT(item.IsOk()); - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); // disable extruder selection for the non "itObject|itVolume" item return !(col == 1 && node->m_extruder.IsEmpty()); } -wxDataViewItem PrusaObjectDataViewModel::GetParent(const wxDataViewItem &item) const +wxDataViewItem ObjectDataViewModel::GetParent(const wxDataViewItem &item) const { // the invisible root node has no parent if (!item.IsOk()) return wxDataViewItem(0); - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); // objects nodes has no parent too if (node->m_type == itObject) @@ -1208,17 +1070,17 @@ wxDataViewItem PrusaObjectDataViewModel::GetParent(const wxDataViewItem &item) c return wxDataViewItem((void*)node->GetParent()); } -wxDataViewItem PrusaObjectDataViewModel::GetTopParent(const wxDataViewItem &item) const +wxDataViewItem ObjectDataViewModel::GetTopParent(const wxDataViewItem &item) const { // the invisible root node has no parent if (!item.IsOk()) return wxDataViewItem(0); - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); if (node->m_type == itObject) return item; - PrusaObjectDataViewModelNode *parent_node = node->GetParent(); + ObjectDataViewModelNode *parent_node = node->GetParent(); while (parent_node->m_type != itObject) { node = parent_node; @@ -1228,19 +1090,19 @@ wxDataViewItem PrusaObjectDataViewModel::GetTopParent(const wxDataViewItem &item return wxDataViewItem((void*)parent_node); } -bool PrusaObjectDataViewModel::IsContainer(const wxDataViewItem &item) const +bool ObjectDataViewModel::IsContainer(const wxDataViewItem &item) const { // the invisible root node can have children if (!item.IsOk()) return true; - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); return node->IsContainer(); } -unsigned int PrusaObjectDataViewModel::GetChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const +unsigned int ObjectDataViewModel::GetChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const { - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)parent.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)parent.GetID(); if (!node) { for (auto object : m_objects) @@ -1256,16 +1118,16 @@ unsigned int PrusaObjectDataViewModel::GetChildren(const wxDataViewItem &parent, unsigned int count = node->GetChildren().GetCount(); for (unsigned int pos = 0; pos < count; pos++) { - PrusaObjectDataViewModelNode *child = node->GetChildren().Item(pos); + ObjectDataViewModelNode *child = node->GetChildren().Item(pos); array.Add(wxDataViewItem((void*)child)); } return count; } -void PrusaObjectDataViewModel::GetAllChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const +void ObjectDataViewModel::GetAllChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const { - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)parent.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)parent.GetID(); if (!node) { for (auto object : m_objects) array.Add(wxDataViewItem((void*)object)); @@ -1275,7 +1137,7 @@ void PrusaObjectDataViewModel::GetAllChildren(const wxDataViewItem &parent, wxDa else { const size_t count = node->GetChildren().GetCount(); for (size_t pos = 0; pos < count; pos++) { - PrusaObjectDataViewModelNode *child = node->GetChildren().Item(pos); + ObjectDataViewModelNode *child = node->GetChildren().Item(pos); array.Add(wxDataViewItem((void*)child)); } } @@ -1289,20 +1151,20 @@ void PrusaObjectDataViewModel::GetAllChildren(const wxDataViewItem &parent, wxDa } } -ItemType PrusaObjectDataViewModel::GetItemType(const wxDataViewItem &item) const +ItemType ObjectDataViewModel::GetItemType(const wxDataViewItem &item) const { if (!item.IsOk()) return itUndef; - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); return node->m_type; } -wxDataViewItem PrusaObjectDataViewModel::GetItemByType(const wxDataViewItem &parent_item, ItemType type) const +wxDataViewItem ObjectDataViewModel::GetItemByType(const wxDataViewItem &parent_item, ItemType type) const { if (!parent_item.IsOk()) return wxDataViewItem(0); - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)parent_item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)parent_item.GetID(); if (node->GetChildCount() == 0) return wxDataViewItem(0); @@ -1314,60 +1176,81 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByType(const wxDataViewItem &par return wxDataViewItem(0); } -wxDataViewItem PrusaObjectDataViewModel::GetSettingsItem(const wxDataViewItem &item) const +wxDataViewItem ObjectDataViewModel::GetSettingsItem(const wxDataViewItem &item) const { return GetItemByType(item, itSettings); } -wxDataViewItem PrusaObjectDataViewModel::GetInstanceRootItem(const wxDataViewItem &item) const +wxDataViewItem ObjectDataViewModel::GetInstanceRootItem(const wxDataViewItem &item) const { return GetItemByType(item, itInstanceRoot); } -bool PrusaObjectDataViewModel::IsSettingsItem(const wxDataViewItem &item) const +bool ObjectDataViewModel::IsSettingsItem(const wxDataViewItem &item) const { if (!item.IsOk()) return false; - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); return node->m_type == itSettings; } - - -void PrusaObjectDataViewModel::UpdateSettingsDigest(const wxDataViewItem &item, +void ObjectDataViewModel::UpdateSettingsDigest(const wxDataViewItem &item, const std::vector<std::string>& categories) { if (!item.IsOk()) return; - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); if (!node->update_settings_digest(categories)) return; ItemChanged(item); } -void PrusaObjectDataViewModel::SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type) +void ObjectDataViewModel::SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type) { if (!item.IsOk() || GetItemType(item) != itVolume) return; - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); node->SetBitmap(*m_volume_bmps[int(type)]); ItemChanged(item); } +void ObjectDataViewModel::Rescale() +{ + wxDataViewItemArray all_items; + GetAllChildren(wxDataViewItem(0), all_items); + + for (wxDataViewItem item : all_items) + { + if (!item.IsOk()) + continue; + + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); + node->msw_rescale(); + + if (node->m_type & itVolume) + node->m_bmp = *m_volume_bmps[node->volume_type()]; + + if (node->m_type & itObject && node->m_bmp.IsOk()) + node->m_bmp = create_scaled_bitmap(nullptr, "exclamation"); + + ItemChanged(item); + } +} + //----------------------------------------------------------------------------- // PrusaDataViewBitmapText //----------------------------------------------------------------------------- -wxIMPLEMENT_DYNAMIC_CLASS(PrusaDataViewBitmapText, wxObject) +wxIMPLEMENT_DYNAMIC_CLASS(DataViewBitmapText, wxObject) -IMPLEMENT_VARIANT_OBJECT(PrusaDataViewBitmapText) +IMPLEMENT_VARIANT_OBJECT(DataViewBitmapText) // --------------------------------------------------------- -// PrusaIconTextRenderer +// BitmapTextRenderer // --------------------------------------------------------- #if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING -PrusaBitmapTextRenderer::PrusaBitmapTextRenderer(wxDataViewCellMode mode /*= wxDATAVIEW_CELL_EDITABLE*/, +BitmapTextRenderer::BitmapTextRenderer(wxDataViewCellMode mode /*= wxDATAVIEW_CELL_EDITABLE*/, int align /*= wxDVR_DEFAULT_ALIGNMENT*/): wxDataViewRenderer(wxT("PrusaDataViewBitmapText"), mode, align) { @@ -1376,25 +1259,25 @@ wxDataViewRenderer(wxT("PrusaDataViewBitmapText"), mode, align) } #endif // ENABLE_NONCUSTOM_DATA_VIEW_RENDERING -bool PrusaBitmapTextRenderer::SetValue(const wxVariant &value) +bool BitmapTextRenderer::SetValue(const wxVariant &value) { m_value << value; return true; } -bool PrusaBitmapTextRenderer::GetValue(wxVariant& WXUNUSED(value)) const +bool BitmapTextRenderer::GetValue(wxVariant& WXUNUSED(value)) const { return false; } #if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING && wxUSE_ACCESSIBILITY -wxString PrusaBitmapTextRenderer::GetAccessibleDescription() const +wxString BitmapTextRenderer::GetAccessibleDescription() const { return m_value.GetText(); } #endif // wxUSE_ACCESSIBILITY && ENABLE_NONCUSTOM_DATA_VIEW_RENDERING -bool PrusaBitmapTextRenderer::Render(wxRect rect, wxDC *dc, int state) +bool BitmapTextRenderer::Render(wxRect rect, wxDC *dc, int state) { int xoffset = 0; @@ -1410,7 +1293,7 @@ bool PrusaBitmapTextRenderer::Render(wxRect rect, wxDC *dc, int state) return true; } -wxSize PrusaBitmapTextRenderer::GetSize() const +wxSize BitmapTextRenderer::GetSize() const { if (!m_value.GetText().empty()) { @@ -1424,15 +1307,15 @@ wxSize PrusaBitmapTextRenderer::GetSize() const } -wxWindow* PrusaBitmapTextRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelRect, const wxVariant& value) +wxWindow* BitmapTextRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelRect, const wxVariant& value) { wxDataViewCtrl* const dv_ctrl = GetOwner()->GetOwner(); - PrusaObjectDataViewModel* const model = dynamic_cast<PrusaObjectDataViewModel*>(dv_ctrl->GetModel()); + ObjectDataViewModel* const model = dynamic_cast<ObjectDataViewModel*>(dv_ctrl->GetModel()); if ( !(model->GetItemType(dv_ctrl->GetSelection()) & (itVolume | itObject)) ) return nullptr; - PrusaDataViewBitmapText data; + DataViewBitmapText data; data << value; m_was_unusable_symbol = false; @@ -1452,7 +1335,7 @@ wxWindow* PrusaBitmapTextRenderer::CreateEditorCtrl(wxWindow* parent, wxRect lab return text_editor; } -bool PrusaBitmapTextRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) +bool BitmapTextRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) { wxTextCtrl* text_editor = wxDynamicCast(ctrl, wxTextCtrl); if (!text_editor || text_editor->GetValue().IsEmpty()) @@ -1471,7 +1354,7 @@ bool PrusaBitmapTextRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& wxVariant valueOld; GetView()->GetModel()->GetValue(valueOld, m_item, 0); - PrusaDataViewBitmapText bmpText; + DataViewBitmapText bmpText; bmpText << valueOld; // But replace the text with the value entered by user. @@ -1482,19 +1365,19 @@ bool PrusaBitmapTextRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& } // ---------------------------------------------------------------------------- -// PrusaDoubleSlider +// DoubleSlider // ---------------------------------------------------------------------------- -PrusaDoubleSlider::PrusaDoubleSlider(wxWindow *parent, - wxWindowID id, - int lowerValue, - int higherValue, - int minValue, - int maxValue, - const wxPoint& pos, - const wxSize& size, - long style, - const wxValidator& val, - const wxString& name) : +DoubleSlider::DoubleSlider( wxWindow *parent, + wxWindowID id, + int lowerValue, + int higherValue, + int minValue, + int maxValue, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& val, + const wxString& name) : wxControl(parent, id, pos, size, wxWANTS_CHARS | wxBORDER_NONE), m_lower_value(lowerValue), m_higher_value (higherValue), m_min_value(minValue), m_max_value(maxValue), @@ -1506,39 +1389,39 @@ PrusaDoubleSlider::PrusaDoubleSlider(wxWindow *parent, if (!is_osx) SetDoubleBuffered(true);// SetDoubleBuffered exists on Win and Linux/GTK, but is missing on OSX - m_bmp_thumb_higher = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap(this, "right_half_circle.png") : create_scaled_bitmap(this, "up_half_circle.png", 16, true)); - m_bmp_thumb_lower = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap(this, "left_half_circle.png" ) : create_scaled_bitmap(this, "down_half_circle.png", 16, true)); - m_thumb_size = m_bmp_thumb_lower.GetSize(); + m_bmp_thumb_higher = (style == wxSL_HORIZONTAL ? ScalableBitmap(this, "right_half_circle.png") : ScalableBitmap(this, "up_half_circle.png", 16, true)); + m_bmp_thumb_lower = (style == wxSL_HORIZONTAL ? ScalableBitmap(this, "left_half_circle.png" ) : ScalableBitmap(this, "down_half_circle.png", 16, true)); + m_thumb_size = m_bmp_thumb_lower.bmp().GetSize(); - m_bmp_add_tick_on = create_scaled_bitmap(this, "colorchange_add_on.png"); - m_bmp_add_tick_off = create_scaled_bitmap(this, "colorchange_add_off.png"); - m_bmp_del_tick_on = create_scaled_bitmap(this, "colorchange_delete_on.png"); - m_bmp_del_tick_off = create_scaled_bitmap(this, "colorchange_delete_off.png"); - m_tick_icon_dim = m_bmp_add_tick_on.GetSize().x; + m_bmp_add_tick_on = ScalableBitmap(this, "colorchange_add_on.png"); + m_bmp_add_tick_off = ScalableBitmap(this, "colorchange_add_off.png"); + m_bmp_del_tick_on = ScalableBitmap(this, "colorchange_delete_on.png"); + m_bmp_del_tick_off = ScalableBitmap(this, "colorchange_delete_off.png"); + m_tick_icon_dim = m_bmp_add_tick_on.bmp().GetSize().x; - m_bmp_one_layer_lock_on = create_scaled_bitmap(this, "one_layer_lock_on.png"); - m_bmp_one_layer_lock_off = create_scaled_bitmap(this, "one_layer_lock_off.png"); - m_bmp_one_layer_unlock_on = create_scaled_bitmap(this, "one_layer_unlock_on.png"); - m_bmp_one_layer_unlock_off = create_scaled_bitmap(this, "one_layer_unlock_off.png"); - m_lock_icon_dim = m_bmp_one_layer_lock_on.GetSize().x; + m_bmp_one_layer_lock_on = ScalableBitmap(this, "one_layer_lock_on.png"); + m_bmp_one_layer_lock_off = ScalableBitmap(this, "one_layer_lock_off.png"); + m_bmp_one_layer_unlock_on = ScalableBitmap(this, "one_layer_unlock_on.png"); + m_bmp_one_layer_unlock_off = ScalableBitmap(this, "one_layer_unlock_off.png"); + m_lock_icon_dim = m_bmp_one_layer_lock_on.bmp().GetSize().x; m_selection = ssUndef; // slider events - Bind(wxEVT_PAINT, &PrusaDoubleSlider::OnPaint, this); - Bind(wxEVT_LEFT_DOWN, &PrusaDoubleSlider::OnLeftDown, this); - Bind(wxEVT_MOTION, &PrusaDoubleSlider::OnMotion, this); - Bind(wxEVT_LEFT_UP, &PrusaDoubleSlider::OnLeftUp, this); - Bind(wxEVT_MOUSEWHEEL, &PrusaDoubleSlider::OnWheel, this); - Bind(wxEVT_ENTER_WINDOW,&PrusaDoubleSlider::OnEnterWin, this); - Bind(wxEVT_LEAVE_WINDOW,&PrusaDoubleSlider::OnLeaveWin, this); - Bind(wxEVT_KEY_DOWN, &PrusaDoubleSlider::OnKeyDown, this); - Bind(wxEVT_KEY_UP, &PrusaDoubleSlider::OnKeyUp, this); - Bind(wxEVT_RIGHT_DOWN, &PrusaDoubleSlider::OnRightDown,this); - Bind(wxEVT_RIGHT_UP, &PrusaDoubleSlider::OnRightUp, this); + Bind(wxEVT_PAINT, &DoubleSlider::OnPaint, this); + Bind(wxEVT_LEFT_DOWN, &DoubleSlider::OnLeftDown, this); + Bind(wxEVT_MOTION, &DoubleSlider::OnMotion, this); + Bind(wxEVT_LEFT_UP, &DoubleSlider::OnLeftUp, this); + Bind(wxEVT_MOUSEWHEEL, &DoubleSlider::OnWheel, this); + Bind(wxEVT_ENTER_WINDOW,&DoubleSlider::OnEnterWin, this); + Bind(wxEVT_LEAVE_WINDOW,&DoubleSlider::OnLeaveWin, this); + Bind(wxEVT_KEY_DOWN, &DoubleSlider::OnKeyDown, this); + Bind(wxEVT_KEY_UP, &DoubleSlider::OnKeyUp, this); + Bind(wxEVT_RIGHT_DOWN, &DoubleSlider::OnRightDown,this); + Bind(wxEVT_RIGHT_UP, &DoubleSlider::OnRightUp, this); // control's view variables - SLIDER_MARGIN = 4 + Slic3r::GUI::wxGetApp().em_unit();//(style == wxSL_HORIZONTAL ? m_bmp_thumb_higher.GetWidth() : m_bmp_thumb_higher.GetHeight()); + SLIDER_MARGIN = 4 + Slic3r::GUI::wxGetApp().em_unit(); DARK_ORANGE_PEN = wxPen(wxColour(253, 84, 2)); ORANGE_PEN = wxPen(wxColour(253, 126, 66)); @@ -1548,32 +1431,65 @@ PrusaDoubleSlider::PrusaDoubleSlider(wxWindow *parent, GREY_PEN = wxPen(wxColour(164, 164, 164)); LIGHT_GREY_PEN = wxPen(wxColour(204, 204, 204)); - line_pens = { &DARK_GREY_PEN, &GREY_PEN, &LIGHT_GREY_PEN }; - segm_pens = { &DARK_ORANGE_PEN, &ORANGE_PEN, &LIGHT_ORANGE_PEN }; + m_line_pens = { &DARK_GREY_PEN, &GREY_PEN, &LIGHT_GREY_PEN }; + m_segm_pens = { &DARK_ORANGE_PEN, &ORANGE_PEN, &LIGHT_ORANGE_PEN }; const wxFont& font = GetFont(); m_font = is_osx ? font.Smaller().Smaller() : font.Smaller(); } -int PrusaDoubleSlider::GetActiveValue() const +void DoubleSlider::msw_rescale() +{ + const wxFont& font = Slic3r::GUI::wxGetApp().normal_font(); + m_font = is_osx ? font.Smaller().Smaller() : font.Smaller(); + + m_bmp_thumb_higher.msw_rescale(); + m_bmp_thumb_lower .msw_rescale(); + m_thumb_size = m_bmp_thumb_lower.bmp().GetSize(); + + m_bmp_add_tick_on .msw_rescale(); + m_bmp_add_tick_off.msw_rescale(); + m_bmp_del_tick_on .msw_rescale(); + m_bmp_del_tick_off.msw_rescale(); + m_tick_icon_dim = m_bmp_add_tick_on.bmp().GetSize().x; + + m_bmp_one_layer_lock_on .msw_rescale(); + m_bmp_one_layer_lock_off .msw_rescale(); + m_bmp_one_layer_unlock_on .msw_rescale(); + m_bmp_one_layer_unlock_off.msw_rescale(); + m_lock_icon_dim = m_bmp_one_layer_lock_on.bmp().GetSize().x; + + SLIDER_MARGIN = 4 + Slic3r::GUI::wxGetApp().em_unit(); + + SetMinSize(get_min_size()); + GetParent()->Layout(); +} + +int DoubleSlider::GetActiveValue() const { return m_selection == ssLower ? m_lower_value : m_selection == ssHigher ? m_higher_value : -1; } -wxSize PrusaDoubleSlider::DoGetBestSize() const +wxSize DoubleSlider::get_min_size() const +{ + const int min_side = is_horizontal() ? + (is_osx ? 8 : 6) * Slic3r::GUI::wxGetApp().em_unit() : + /*(is_osx ? 10 : 8)*/10 * Slic3r::GUI::wxGetApp().em_unit(); + + return wxSize(min_side, min_side); +} + +wxSize DoubleSlider::DoGetBestSize() const { const wxSize size = wxControl::DoGetBestSize(); if (size.x > 1 && size.y > 1) return size; - const int new_size = is_horizontal() ? - (is_osx ? 8 : 6) * Slic3r::GUI::wxGetApp().em_unit() : - (is_osx ? 10 : 8) * Slic3r::GUI::wxGetApp().em_unit(); - return wxSize(new_size, new_size); + return get_min_size(); } -void PrusaDoubleSlider::SetLowerValue(const int lower_val) +void DoubleSlider::SetLowerValue(const int lower_val) { m_selection = ssLower; m_lower_value = lower_val; @@ -1586,7 +1502,7 @@ void PrusaDoubleSlider::SetLowerValue(const int lower_val) ProcessWindowEvent(e); } -void PrusaDoubleSlider::SetHigherValue(const int higher_val) +void DoubleSlider::SetHigherValue(const int higher_val) { m_selection = ssHigher; m_higher_value = higher_val; @@ -1599,7 +1515,7 @@ void PrusaDoubleSlider::SetHigherValue(const int higher_val) ProcessWindowEvent(e); } -void PrusaDoubleSlider::SetSelectionSpan(const int lower_val, const int higher_val) +void DoubleSlider::SetSelectionSpan(const int lower_val, const int higher_val) { m_lower_value = std::max(lower_val, m_min_value); m_higher_value = std::max(std::min(higher_val, m_max_value), m_lower_value); @@ -1614,14 +1530,14 @@ void PrusaDoubleSlider::SetSelectionSpan(const int lower_val, const int higher_v ProcessWindowEvent(e); } -void PrusaDoubleSlider::SetMaxValue(const int max_value) +void DoubleSlider::SetMaxValue(const int max_value) { m_max_value = max_value; Refresh(); Update(); } -void PrusaDoubleSlider::draw_scroll_line(wxDC& dc, const int lower_pos, const int higher_pos) +void DoubleSlider::draw_scroll_line(wxDC& dc, const int lower_pos, const int higher_pos) { int width; int height; @@ -1637,11 +1553,11 @@ void PrusaDoubleSlider::draw_scroll_line(wxDC& dc, const int lower_pos, const in wxCoord segm_end_x = is_horizontal() ? higher_pos : width*0.5 - 1; wxCoord segm_end_y = is_horizontal() ? height*0.5 - 1 : higher_pos-1; - for (int id = 0; id < line_pens.size(); id++) + for (int id = 0; id < m_line_pens.size(); id++) { - dc.SetPen(*line_pens[id]); + dc.SetPen(*m_line_pens[id]); dc.DrawLine(line_beg_x, line_beg_y, line_end_x, line_end_y); - dc.SetPen(*segm_pens[id]); + dc.SetPen(*m_segm_pens[id]); dc.DrawLine(segm_beg_x, segm_beg_y, segm_end_x, segm_end_y); if (is_horizontal()) line_beg_y = line_end_y = segm_beg_y = segm_end_y += 1; @@ -1650,7 +1566,7 @@ void PrusaDoubleSlider::draw_scroll_line(wxDC& dc, const int lower_pos, const in } } -double PrusaDoubleSlider::get_scroll_step() +double DoubleSlider::get_scroll_step() { const wxSize sz = get_size(); const int& slider_len = m_style == wxSL_HORIZONTAL ? sz.x : sz.y; @@ -1658,27 +1574,27 @@ double PrusaDoubleSlider::get_scroll_step() } // get position on the slider line from entered value -wxCoord PrusaDoubleSlider::get_position_from_value(const int value) +wxCoord DoubleSlider::get_position_from_value(const int value) { const double step = get_scroll_step(); const int val = is_horizontal() ? value : m_max_value - value; return wxCoord(SLIDER_MARGIN + int(val*step + 0.5)); } -wxSize PrusaDoubleSlider::get_size() +wxSize DoubleSlider::get_size() { int w, h; get_size(&w, &h); return wxSize(w, h); } -void PrusaDoubleSlider::get_size(int *w, int *h) +void DoubleSlider::get_size(int *w, int *h) { GetSize(w, h); is_horizontal() ? *w -= m_lock_icon_dim : *h -= m_lock_icon_dim; } -double PrusaDoubleSlider::get_double_value(const SelectedSlider& selection) +double DoubleSlider::get_double_value(const SelectedSlider& selection) { if (m_values.empty() || m_lower_value<0) return 0.0; @@ -1689,7 +1605,7 @@ double PrusaDoubleSlider::get_double_value(const SelectedSlider& selection) return m_values[selection == ssLower ? m_lower_value : m_higher_value].second; } -std::vector<double> PrusaDoubleSlider::GetTicksValues() const +std::vector<double> DoubleSlider::GetTicksValues() const { std::vector<double> values; @@ -1703,7 +1619,7 @@ std::vector<double> PrusaDoubleSlider::GetTicksValues() const return values; } -void PrusaDoubleSlider::SetTicksValues(const std::vector<double>& heights) +void DoubleSlider::SetTicksValues(const std::vector<double>& heights) { if (m_values.empty()) return; @@ -1725,7 +1641,7 @@ void PrusaDoubleSlider::SetTicksValues(const std::vector<double>& heights) wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED)); } -void PrusaDoubleSlider::get_lower_and_higher_position(int& lower_pos, int& higher_pos) +void DoubleSlider::get_lower_and_higher_position(int& lower_pos, int& higher_pos) { const double step = get_scroll_step(); if (is_horizontal()) { @@ -1738,7 +1654,7 @@ void PrusaDoubleSlider::get_lower_and_higher_position(int& lower_pos, int& highe } } -void PrusaDoubleSlider::draw_focus_rect() +void DoubleSlider::draw_focus_rect() { if (!m_is_focused) return; @@ -1750,7 +1666,7 @@ void PrusaDoubleSlider::draw_focus_rect() dc.DrawRectangle(1, 1, sz.x - 2, sz.y - 2); } -void PrusaDoubleSlider::render() +void DoubleSlider::render() { SetBackgroundColour(GetParent()->GetBackgroundColour()); draw_focus_rect(); @@ -1783,12 +1699,13 @@ void PrusaDoubleSlider::render() draw_one_layer_icon(dc); } -void PrusaDoubleSlider::draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_end) +void DoubleSlider::draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_end) { const int tick = m_selection == ssLower ? m_lower_value : m_higher_value; - wxBitmap* icon = m_is_action_icon_focesed ? &m_bmp_add_tick_off : &m_bmp_add_tick_on; + + wxBitmap& icon = m_is_action_icon_focesed ? m_bmp_add_tick_off.bmp() : m_bmp_add_tick_on.bmp(); if (m_ticks.find(tick) != m_ticks.end()) - icon = m_is_action_icon_focesed ? &m_bmp_del_tick_off : &m_bmp_del_tick_on; + icon = m_is_action_icon_focesed ? m_bmp_del_tick_off.bmp() : m_bmp_del_tick_on.bmp(); wxCoord x_draw, y_draw; is_horizontal() ? x_draw = pt_beg.x - 0.5*m_tick_icon_dim : y_draw = pt_beg.y - 0.5*m_tick_icon_dim; @@ -1797,13 +1714,13 @@ void PrusaDoubleSlider::draw_action_icon(wxDC& dc, const wxPoint pt_beg, const w else is_horizontal() ? y_draw = pt_beg.y - m_tick_icon_dim-2 : x_draw = pt_end.x + 3; - dc.DrawBitmap(*icon, x_draw, y_draw); + dc.DrawBitmap(icon, x_draw, y_draw); //update rect of the tick action icon m_rect_tick_action = wxRect(x_draw, y_draw, m_tick_icon_dim, m_tick_icon_dim); } -void PrusaDoubleSlider::draw_info_line_with_icon(wxDC& dc, const wxPoint& pos, const SelectedSlider selection) +void DoubleSlider::draw_info_line_with_icon(wxDC& dc, const wxPoint& pos, const SelectedSlider selection) { if (m_selection == selection) { //draw info line @@ -1818,7 +1735,7 @@ void PrusaDoubleSlider::draw_info_line_with_icon(wxDC& dc, const wxPoint& pos, c } } -wxString PrusaDoubleSlider::get_label(const SelectedSlider& selection) const +wxString DoubleSlider::get_label(const SelectedSlider& selection) const { const int value = selection == ssLower ? m_lower_value : m_higher_value; @@ -1833,7 +1750,7 @@ wxString PrusaDoubleSlider::get_label(const SelectedSlider& selection) const return wxString::Format("%s\n(%d)", str, m_values.empty() ? value : m_values[value].first); } -void PrusaDoubleSlider::draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const +void DoubleSlider::draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const { if ((m_is_one_layer || m_higher_value==m_lower_value) && selection != m_selection || !selection) return; @@ -1850,7 +1767,7 @@ void PrusaDoubleSlider::draw_thumb_text(wxDC& dc, const wxPoint& pos, const Sele dc.DrawText(label, text_pos); } -void PrusaDoubleSlider::draw_thumb_item(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) +void DoubleSlider::draw_thumb_item(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) { wxCoord x_draw, y_draw; if (selection == ssLower) { @@ -1873,13 +1790,13 @@ void PrusaDoubleSlider::draw_thumb_item(wxDC& dc, const wxPoint& pos, const Sele y_draw = pos.y - m_thumb_size.y; } } - dc.DrawBitmap(selection == ssLower ? m_bmp_thumb_lower : m_bmp_thumb_higher, x_draw, y_draw); + dc.DrawBitmap(selection == ssLower ? m_bmp_thumb_lower.bmp() : m_bmp_thumb_higher.bmp(), x_draw, y_draw); // Update thumb rect update_thumb_rect(x_draw, y_draw, selection); } -void PrusaDoubleSlider::draw_thumb(wxDC& dc, const wxCoord& pos_coord, const SelectedSlider& selection) +void DoubleSlider::draw_thumb(wxDC& dc, const wxCoord& pos_coord, const SelectedSlider& selection) { //calculate thumb position on slider line int width, height; @@ -1896,7 +1813,7 @@ void PrusaDoubleSlider::draw_thumb(wxDC& dc, const wxCoord& pos_coord, const Sel draw_thumb_text(dc, pos, selection); } -void PrusaDoubleSlider::draw_thumbs(wxDC& dc, const wxCoord& lower_pos, const wxCoord& higher_pos) +void DoubleSlider::draw_thumbs(wxDC& dc, const wxCoord& lower_pos, const wxCoord& higher_pos) { //calculate thumb position on slider line int width, height; @@ -1920,7 +1837,7 @@ void PrusaDoubleSlider::draw_thumbs(wxDC& dc, const wxCoord& lower_pos, const wx draw_thumb_text(dc, pos_l, ssLower); } -void PrusaDoubleSlider::draw_ticks(wxDC& dc) +void DoubleSlider::draw_ticks(wxDC& dc) { dc.SetPen(m_is_enabled_tick_manipulation ? DARK_GREY_PEN : LIGHT_GREY_PEN ); int height, width; @@ -1937,7 +1854,7 @@ void PrusaDoubleSlider::draw_ticks(wxDC& dc) } } -void PrusaDoubleSlider::draw_colored_band(wxDC& dc) +void DoubleSlider::draw_colored_band(wxDC& dc) { int height, width; get_size(&width, &height); @@ -1987,11 +1904,11 @@ void PrusaDoubleSlider::draw_colored_band(wxDC& dc) } } -void PrusaDoubleSlider::draw_one_layer_icon(wxDC& dc) +void DoubleSlider::draw_one_layer_icon(wxDC& dc) { - wxBitmap* icon = m_is_one_layer ? - m_is_one_layer_icon_focesed ? &m_bmp_one_layer_lock_off : &m_bmp_one_layer_lock_on : - m_is_one_layer_icon_focesed ? &m_bmp_one_layer_unlock_off : &m_bmp_one_layer_unlock_on; + const wxBitmap& icon = m_is_one_layer ? + m_is_one_layer_icon_focesed ? m_bmp_one_layer_lock_off.bmp() : m_bmp_one_layer_lock_on.bmp() : + m_is_one_layer_icon_focesed ? m_bmp_one_layer_unlock_off.bmp() : m_bmp_one_layer_unlock_on.bmp(); int width, height; get_size(&width, &height); @@ -2000,13 +1917,13 @@ void PrusaDoubleSlider::draw_one_layer_icon(wxDC& dc) is_horizontal() ? x_draw = width-2 : x_draw = 0.5*width - 0.5*m_lock_icon_dim; is_horizontal() ? y_draw = 0.5*height - 0.5*m_lock_icon_dim : y_draw = height-2; - dc.DrawBitmap(*icon, x_draw, y_draw); + dc.DrawBitmap(icon, x_draw, y_draw); //update rect of the lock/unlock icon m_rect_one_layer_icon = wxRect(x_draw, y_draw, m_lock_icon_dim, m_lock_icon_dim); } -void PrusaDoubleSlider::update_thumb_rect(const wxCoord& begin_x, const wxCoord& begin_y, const SelectedSlider& selection) +void DoubleSlider::update_thumb_rect(const wxCoord& begin_x, const wxCoord& begin_y, const SelectedSlider& selection) { const wxRect& rect = wxRect(begin_x, begin_y, m_thumb_size.x, m_thumb_size.y); if (selection == ssLower) @@ -2015,7 +1932,7 @@ void PrusaDoubleSlider::update_thumb_rect(const wxCoord& begin_x, const wxCoord& m_rect_higher_thumb = rect; } -int PrusaDoubleSlider::get_value_from_position(const wxCoord x, const wxCoord y) +int DoubleSlider::get_value_from_position(const wxCoord x, const wxCoord y) { const int height = get_size().y; const double step = get_scroll_step(); @@ -2026,13 +1943,13 @@ int PrusaDoubleSlider::get_value_from_position(const wxCoord x, const wxCoord y) return int(m_min_value + double(height - SLIDER_MARGIN - y) / step + 0.5); } -void PrusaDoubleSlider::detect_selected_slider(const wxPoint& pt) +void DoubleSlider::detect_selected_slider(const wxPoint& pt) { m_selection = is_point_in_rect(pt, m_rect_lower_thumb) ? ssLower : is_point_in_rect(pt, m_rect_higher_thumb) ? ssHigher : ssUndef; } -bool PrusaDoubleSlider::is_point_in_rect(const wxPoint& pt, const wxRect& rect) +bool DoubleSlider::is_point_in_rect(const wxPoint& pt, const wxRect& rect) { if (rect.GetLeft() <= pt.x && pt.x <= rect.GetRight() && rect.GetTop() <= pt.y && pt.y <= rect.GetBottom()) @@ -2040,7 +1957,7 @@ bool PrusaDoubleSlider::is_point_in_rect(const wxPoint& pt, const wxRect& rect) return false; } -int PrusaDoubleSlider::is_point_near_tick(const wxPoint& pt) +int DoubleSlider::is_point_near_tick(const wxPoint& pt) { for (auto tick : m_ticks) { const wxCoord pos = get_position_from_value(tick); @@ -2057,7 +1974,7 @@ int PrusaDoubleSlider::is_point_near_tick(const wxPoint& pt) return -1; } -void PrusaDoubleSlider::ChangeOneLayerLock() +void DoubleSlider::ChangeOneLayerLock() { m_is_one_layer = !m_is_one_layer; m_selection == ssLower ? correct_lower_value() : correct_higher_value(); @@ -2071,7 +1988,7 @@ void PrusaDoubleSlider::ChangeOneLayerLock() ProcessWindowEvent(e); } -void PrusaDoubleSlider::OnLeftDown(wxMouseEvent& event) +void DoubleSlider::OnLeftDown(wxMouseEvent& event) { this->CaptureMouse(); wxClientDC dc(this); @@ -2116,7 +2033,7 @@ void PrusaDoubleSlider::OnLeftDown(wxMouseEvent& event) event.Skip(); } -void PrusaDoubleSlider::correct_lower_value() +void DoubleSlider::correct_lower_value() { if (m_lower_value < m_min_value) m_lower_value = m_min_value; @@ -2127,7 +2044,7 @@ void PrusaDoubleSlider::correct_lower_value() m_higher_value = m_lower_value; } -void PrusaDoubleSlider::correct_higher_value() +void DoubleSlider::correct_higher_value() { if (m_higher_value > m_max_value) m_higher_value = m_max_value; @@ -2138,7 +2055,7 @@ void PrusaDoubleSlider::correct_higher_value() m_lower_value = m_higher_value; } -void PrusaDoubleSlider::OnMotion(wxMouseEvent& event) +void DoubleSlider::OnMotion(wxMouseEvent& event) { bool action = false; @@ -2172,7 +2089,7 @@ void PrusaDoubleSlider::OnMotion(wxMouseEvent& event) } } -void PrusaDoubleSlider::OnLeftUp(wxMouseEvent& event) +void DoubleSlider::OnLeftUp(wxMouseEvent& event) { if (!HasCapture()) return; @@ -2187,7 +2104,7 @@ void PrusaDoubleSlider::OnLeftUp(wxMouseEvent& event) ProcessWindowEvent(e); } -void PrusaDoubleSlider::enter_window(wxMouseEvent& event, const bool enter) +void DoubleSlider::enter_window(wxMouseEvent& event, const bool enter) { m_is_focused = enter; Refresh(); @@ -2198,7 +2115,7 @@ void PrusaDoubleSlider::enter_window(wxMouseEvent& event, const bool enter) // "condition" have to be true for: // - value increase (if wxSL_VERTICAL) // - value decrease (if wxSL_HORIZONTAL) -void PrusaDoubleSlider::move_current_thumb(const bool condition) +void DoubleSlider::move_current_thumb(const bool condition) { // m_is_one_layer = wxGetKeyState(WXK_CONTROL); int delta = condition ? -1 : 1; @@ -2221,7 +2138,7 @@ void PrusaDoubleSlider::move_current_thumb(const bool condition) ProcessWindowEvent(e); } -void PrusaDoubleSlider::action_tick(const TicksAction action) +void DoubleSlider::action_tick(const TicksAction action) { if (m_selection == ssUndef) return; @@ -2245,7 +2162,7 @@ void PrusaDoubleSlider::action_tick(const TicksAction action) Update(); } -void PrusaDoubleSlider::OnWheel(wxMouseEvent& event) +void DoubleSlider::OnWheel(wxMouseEvent& event) { // Set nearest to the mouse thumb as a selected, if there is not selected thumb if (m_selection == ssUndef) @@ -2265,7 +2182,7 @@ void PrusaDoubleSlider::OnWheel(wxMouseEvent& event) move_current_thumb(event.GetWheelRotation() > 0); } -void PrusaDoubleSlider::OnKeyDown(wxKeyEvent &event) +void DoubleSlider::OnKeyDown(wxKeyEvent &event) { const int key = event.GetKeyCode(); if (key == '+' || key == WXK_NUMPAD_ADD) @@ -2291,7 +2208,7 @@ void PrusaDoubleSlider::OnKeyDown(wxKeyEvent &event) } } -void PrusaDoubleSlider::OnKeyUp(wxKeyEvent &event) +void DoubleSlider::OnKeyUp(wxKeyEvent &event) { if (event.GetKeyCode() == WXK_CONTROL) m_is_one_layer = false; @@ -2300,7 +2217,7 @@ void PrusaDoubleSlider::OnKeyUp(wxKeyEvent &event) event.Skip(); } -void PrusaDoubleSlider::OnRightDown(wxMouseEvent& event) +void DoubleSlider::OnRightDown(wxMouseEvent& event) { this->CaptureMouse(); const wxClientDC dc(this); @@ -2320,7 +2237,7 @@ void PrusaDoubleSlider::OnRightDown(wxMouseEvent& event) event.Skip(); } -void PrusaDoubleSlider::OnRightUp(wxMouseEvent& event) +void DoubleSlider::OnRightUp(wxMouseEvent& event) { if (!HasCapture()) return; @@ -2334,34 +2251,33 @@ void PrusaDoubleSlider::OnRightUp(wxMouseEvent& event) // ---------------------------------------------------------------------------- -// PrusaLockButton +// LockButton // ---------------------------------------------------------------------------- -PrusaLockButton::PrusaLockButton( wxWindow *parent, - wxWindowID id, - const wxPoint& pos /*= wxDefaultPosition*/, - const wxSize& size /*= wxDefaultSize*/): - wxButton(parent, id, wxEmptyString, pos, size, wxBU_EXACTFIT | wxNO_BORDER) +LockButton::LockButton( wxWindow *parent, + wxWindowID id, + const wxPoint& pos /*= wxDefaultPosition*/, + const wxSize& size /*= wxDefaultSize*/): + wxButton(parent, id, wxEmptyString, pos, size, wxBU_EXACTFIT | wxNO_BORDER) { - m_bmp_lock_on = create_scaled_bitmap(this, "one_layer_lock_on.png"); - m_bmp_lock_off = create_scaled_bitmap(this, "one_layer_lock_off.png"); - m_bmp_unlock_on = create_scaled_bitmap(this, "one_layer_unlock_on.png"); - m_bmp_unlock_off = create_scaled_bitmap(this, "one_layer_unlock_off.png"); - + m_bmp_lock_on = ScalableBitmap(this, "one_layer_lock_on.png"); + m_bmp_lock_off = ScalableBitmap(this, "one_layer_lock_off.png"); + m_bmp_unlock_on = ScalableBitmap(this, "one_layer_unlock_on.png"); + m_bmp_unlock_off = ScalableBitmap(this, "one_layer_unlock_off.png"); #ifdef __WXMSW__ SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); #endif // __WXMSW__ - SetBitmap(m_bmp_unlock_on); - SetBitmapDisabled(m_bmp_lock_on); + SetBitmap(m_bmp_unlock_on.bmp()); + SetBitmapDisabled(m_bmp_lock_on.bmp()); //button events - Bind(wxEVT_BUTTON, &PrusaLockButton::OnButton, this); - Bind(wxEVT_ENTER_WINDOW, &PrusaLockButton::OnEnterBtn, this); - Bind(wxEVT_LEAVE_WINDOW, &PrusaLockButton::OnLeaveBtn, this); + Bind(wxEVT_BUTTON, &LockButton::OnButton, this); + Bind(wxEVT_ENTER_WINDOW, &LockButton::OnEnterBtn, this); + Bind(wxEVT_LEAVE_WINDOW, &LockButton::OnLeaveBtn, this); } -void PrusaLockButton::OnButton(wxCommandEvent& event) +void LockButton::OnButton(wxCommandEvent& event) { m_is_pushed = !m_is_pushed; enter_button(true); @@ -2369,18 +2285,26 @@ void PrusaLockButton::OnButton(wxCommandEvent& event) event.Skip(); } -void PrusaLockButton::SetLock(bool lock) +void LockButton::SetLock(bool lock) { m_is_pushed = lock; enter_button(true); } -void PrusaLockButton::enter_button(const bool enter) +void LockButton::msw_rescale() { - wxBitmap* icon = m_is_pushed ? - enter ? &m_bmp_lock_off : &m_bmp_lock_on : - enter ? &m_bmp_unlock_off : &m_bmp_unlock_on; - SetBitmap(*icon); + m_bmp_lock_on .msw_rescale(); + m_bmp_lock_off .msw_rescale(); + m_bmp_unlock_on .msw_rescale(); + m_bmp_unlock_off.msw_rescale(); +} + +void LockButton::enter_button(const bool enter) +{ + const wxBitmap& icon = m_is_pushed ? + enter ? m_bmp_lock_off.bmp() : m_bmp_lock_on.bmp() : + enter ? m_bmp_unlock_off.bmp() : m_bmp_unlock_on.bmp(); + SetBitmap(icon); Refresh(); Update(); @@ -2389,35 +2313,28 @@ void PrusaLockButton::enter_button(const bool enter) // ---------------------------------------------------------------------------- -// PrusaModeButton +// ModeButton // ---------------------------------------------------------------------------- -PrusaModeButton::PrusaModeButton( wxWindow *parent, - wxWindowID id, - const wxString& mode/* = wxEmptyString*/, - const wxBitmap& bmp_on/* = wxNullBitmap*/, - const wxSize& size/* = wxDefaultSize*/, - const wxPoint& pos/* = wxDefaultPosition*/) : - wxButton(parent, id, mode, pos, size, /*wxBU_EXACTFIT | */wxNO_BORDER), - m_bmp_on(bmp_on) +ModeButton::ModeButton( wxWindow * parent, + wxWindowID id, + const std::string& icon_name /* = ""*/, + const wxString& mode /* = wxEmptyString*/, + const wxSize& size /* = wxDefaultSize*/, + const wxPoint& pos /* = wxDefaultPosition*/) : +// wxButton(parent, id, mode, pos, wxDefaultSize/*size*/, wxBU_EXACTFIT | wxNO_BORDER), + ScalableButton(parent, id, icon_name, mode, size, pos) { -#ifdef __WXMSW__ - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -#endif // __WXMSW__ - m_bmp_off = create_scaled_bitmap(this, "mode_off_sq.png"); - m_tt_focused = wxString::Format(_(L("Switch to the %s mode")), mode); m_tt_selected = wxString::Format(_(L("Current mode is %s")), mode); - SetBitmap(m_bmp_on); - //button events - Bind(wxEVT_BUTTON, &PrusaModeButton::OnButton, this); - Bind(wxEVT_ENTER_WINDOW, &PrusaModeButton::OnEnterBtn, this); - Bind(wxEVT_LEAVE_WINDOW, &PrusaModeButton::OnLeaveBtn, this); + Bind(wxEVT_BUTTON, &ModeButton::OnButton, this); + Bind(wxEVT_ENTER_WINDOW, &ModeButton::OnEnterBtn, this); + Bind(wxEVT_LEAVE_WINDOW, &ModeButton::OnLeaveBtn, this); } -void PrusaModeButton::OnButton(wxCommandEvent& event) +void ModeButton::OnButton(wxCommandEvent& event) { m_is_selected = true; focus_button(m_is_selected); @@ -2425,18 +2342,18 @@ void PrusaModeButton::OnButton(wxCommandEvent& event) event.Skip(); } -void PrusaModeButton::SetState(const bool state) +void ModeButton::SetState(const bool state) { m_is_selected = state; focus_button(m_is_selected); SetToolTip(state ? m_tt_selected : m_tt_focused); } -void PrusaModeButton::focus_button(const bool focus) +void ModeButton::focus_button(const bool focus) { -// const wxBitmap& bmp = focus ? m_bmp_on : m_bmp_off; -// SetBitmap(bmp); - const wxFont& new_font = focus ? Slic3r::GUI::wxGetApp().bold_font() : Slic3r::GUI::wxGetApp().small_font(); + wxFont font = GetFont(); + const wxFont& new_font = focus ? font.Bold() : font.GetBaseFont(); + SetFont(new_font); Refresh(); @@ -2445,35 +2362,35 @@ void PrusaModeButton::focus_button(const bool focus) // ---------------------------------------------------------------------------- -// PrusaModeSizer +// ModeSizer // ---------------------------------------------------------------------------- -PrusaModeSizer::PrusaModeSizer(wxWindow *parent, int hgap/* = 10*/) : +ModeSizer::ModeSizer(wxWindow *parent, int hgap/* = 10*/) : wxFlexGridSizer(3, 0, hgap) { SetFlexibleDirection(wxHORIZONTAL); - std::vector<std::pair<wxString, wxBitmap>> buttons = { - {_(L("Simple")), create_scaled_bitmap(parent, "mode_simple_sq.png")}, - {_(L("Advanced")), create_scaled_bitmap(parent, "mode_middle_sq.png")}, - {_(L("Expert")), create_scaled_bitmap(parent, "mode_expert_sq.png")} + std::vector < std::pair < wxString, std::string >> buttons = { + {_(L("Simple")), "mode_simple_sq.png"}, + {_(L("Advanced")), "mode_middle_sq.png"}, + {_(L("Expert")), "mode_expert_sq.png"} }; - mode_btns.reserve(3); + m_mode_btns.reserve(3); for (const auto& button : buttons) { - int x, y; - parent->GetTextExtent(button.first, &x, &y, nullptr, nullptr, &Slic3r::GUI::wxGetApp().bold_font()); - const wxSize size = wxSize(x + button.second.GetWidth() + Slic3r::GUI::wxGetApp().em_unit(), - y + Slic3r::GUI::wxGetApp().em_unit()); - mode_btns.push_back(new PrusaModeButton(parent, wxID_ANY, button.first, button.second, size)); +// int x, y; +// parent->GetTextExtent(button.first, &x, &y, nullptr, nullptr, &Slic3r::GUI::wxGetApp().bold_font()); +// const wxSize size = wxSize(x + button.second.GetWidth() + Slic3r::GUI::wxGetApp().em_unit(), +// y + Slic3r::GUI::wxGetApp().em_unit()); + m_mode_btns.push_back(new ModeButton(parent, wxID_ANY, button.second, button.first/*, size*/)); } - for (auto btn : mode_btns) + for (auto btn : m_mode_btns) { btn->Bind(wxEVT_BUTTON, [btn, this](wxCommandEvent &event) { event.Skip(); int mode_id = 0; - for (auto cur_btn : mode_btns) { + for (auto cur_btn : m_mode_btns) { if (cur_btn == btn) break; else @@ -2487,18 +2404,24 @@ PrusaModeSizer::PrusaModeSizer(wxWindow *parent, int hgap/* = 10*/) : } -void PrusaModeSizer::SetMode(const int mode) +void ModeSizer::SetMode(const int mode) { - for (int m = 0; m < mode_btns.size(); m++) - mode_btns[m]->SetState(m == mode); + for (int m = 0; m < m_mode_btns.size(); m++) + m_mode_btns[m]->SetState(m == mode); } +void ModeSizer::msw_rescale() +{ + for (int m = 0; m < m_mode_btns.size(); m++) + m_mode_btns[m]->msw_rescale(); +} + // ---------------------------------------------------------------------------- -// PrusaMenu +// MenuWithSeparators // ---------------------------------------------------------------------------- -void PrusaMenu::DestroySeparators() +void MenuWithSeparators::DestroySeparators() { if (m_separator_frst) { Destroy(m_separator_frst); @@ -2511,10 +2434,89 @@ void PrusaMenu::DestroySeparators() } } +void MenuWithSeparators::SetFirstSeparator() +{ + m_separator_frst = this->AppendSeparator(); +} -// ************************************** EXPERIMENTS *************************************** +void MenuWithSeparators::SetSecondSeparator() +{ + m_separator_scnd = this->AppendSeparator(); +} + +// ---------------------------------------------------------------------------- +// PrusaBitmap +// ---------------------------------------------------------------------------- +ScalableBitmap::ScalableBitmap( wxWindow *parent, + const std::string& icon_name/* = ""*/, + const int px_cnt/* = 16*/, + const bool is_horizontal/* = false*/): + m_parent(parent), m_icon_name(icon_name), + m_px_cnt(px_cnt), m_is_horizontal(is_horizontal) +{ + m_bmp = create_scaled_bitmap(parent, icon_name, px_cnt, is_horizontal); +} + + +void ScalableBitmap::msw_rescale() +{ + m_bmp = create_scaled_bitmap(m_parent, m_icon_name, m_px_cnt, m_is_horizontal); +} + +// ---------------------------------------------------------------------------- +// PrusaButton +// ---------------------------------------------------------------------------- + +ScalableButton::ScalableButton( wxWindow * parent, + wxWindowID id, + const std::string& icon_name /*= ""*/, + const wxString& label /* = wxEmptyString*/, + const wxSize& size /* = wxDefaultSize*/, + const wxPoint& pos /* = wxDefaultPosition*/, + long style /*= wxBU_EXACTFIT | wxNO_BORDER*/) : + m_current_icon_name(icon_name), + m_parent(parent) +{ + Create(parent, id, label, pos, size, style); +#ifdef __WXMSW__ + if (style & wxNO_BORDER) + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif // __WXMSW__ + + SetBitmap(create_scaled_bitmap(parent, icon_name)); +} + + +ScalableButton::ScalableButton( wxWindow * parent, + wxWindowID id, + const ScalableBitmap& bitmap, + const wxString& label /*= wxEmptyString*/, + long style /*= wxBU_EXACTFIT | wxNO_BORDER*/) : + m_current_icon_name(bitmap.name()), + m_parent(parent) +{ + Create(parent, id, label, wxDefaultPosition, wxDefaultSize, style); +#ifdef __WXMSW__ + if (style & wxNO_BORDER) + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif // __WXMSW__ + + SetBitmap(bitmap.bmp()); +} + +void ScalableButton::SetBitmap_(const ScalableBitmap& bmp) +{ + SetBitmap(bmp.bmp()); + m_current_icon_name = bmp.name(); +} + +void ScalableButton::msw_rescale() +{ + const wxBitmap bmp = create_scaled_bitmap(m_parent, m_current_icon_name); + + SetBitmap(bmp); +} -// ***************************************************************************** diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index b935448d9..589317f2b 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -31,7 +31,12 @@ wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxStrin wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description, std::function<void(wxCommandEvent& event)> cb, wxEvtHandler* event_handler); -wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name, const int px_cnt=16, const bool is_horizontal = false); +class wxDialog; +void edit_tooltip(wxString& tooltip); +void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<int>& btn_ids); +int em_unit(wxWindow* win); + +wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name, const int px_cnt = 16, const bool is_horizontal = false); class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup { @@ -94,91 +99,20 @@ public: }; - -// *** PrusaCollapsiblePane *** // ---------------------------------------------------------------------------- -class PrusaCollapsiblePane : public wxCollapsiblePane -{ -public: - PrusaCollapsiblePane() {} - PrusaCollapsiblePane(wxWindow *parent, - wxWindowID winid, - const wxString& label, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxCP_DEFAULT_STYLE, - const wxValidator& val = wxDefaultValidator, - const wxString& name = wxCollapsiblePaneNameStr) - { - Create(parent, winid, label, pos, size, style, val, name); - } - ~PrusaCollapsiblePane() {} - - void OnStateChange(const wxSize& sz); //override/hide of OnStateChange from wxCollapsiblePane - virtual bool Show(bool show = true) override { - wxCollapsiblePane::Show(show); - OnStateChange(GetBestSize()); - return true; - } -}; - - -// *** PrusaCollapsiblePaneMSW *** used only #ifdef __WXMSW__ +// DataViewBitmapText: helper class used by PrusaBitmapTextRenderer // ---------------------------------------------------------------------------- -#ifdef __WXMSW__ -class PrusaCollapsiblePaneMSW : public PrusaCollapsiblePane//wxCollapsiblePane -{ - wxButton* m_pDisclosureTriangleButton = nullptr; - wxBitmap m_bmp_close; - wxBitmap m_bmp_open; - wxString m_strLabel; -public: - PrusaCollapsiblePaneMSW() {} - PrusaCollapsiblePaneMSW( wxWindow *parent, - wxWindowID winid, - const wxString& label, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxCP_DEFAULT_STYLE, - const wxValidator& val = wxDefaultValidator, - const wxString& name = wxCollapsiblePaneNameStr) - { - Create(parent, winid, label, pos, size, style, val, name); - } - ~PrusaCollapsiblePaneMSW() {} - - bool Create(wxWindow *parent, - wxWindowID id, - const wxString& label, - const wxPoint& pos, - const wxSize& size, - long style, - const wxValidator& val, - const wxString& name); - - void UpdateBtnBmp(); - void SetLabel(const wxString &label) override; - bool Layout() override; - void Collapse(bool collapse) override; -}; -#endif //__WXMSW__ - -// ***************************************************************************** - -// ---------------------------------------------------------------------------- -// PrusaDataViewBitmapText: helper class used by PrusaBitmapTextRenderer -// ---------------------------------------------------------------------------- - -class PrusaDataViewBitmapText : public wxObject +class DataViewBitmapText : public wxObject { public: - PrusaDataViewBitmapText(const wxString &text = wxEmptyString, - const wxBitmap& bmp = wxNullBitmap) : - m_text(text), m_bmp(bmp) + DataViewBitmapText( const wxString &text = wxEmptyString, + const wxBitmap& bmp = wxNullBitmap) : + m_text(text), + m_bmp(bmp) { } - PrusaDataViewBitmapText(const PrusaDataViewBitmapText &other) + DataViewBitmapText(const DataViewBitmapText &other) : wxObject(), m_text(other.m_text), m_bmp(other.m_bmp) @@ -186,18 +120,18 @@ public: void SetText(const wxString &text) { m_text = text; } wxString GetText() const { return m_text; } - void SetBitmap(const wxBitmap &bmp) { m_bmp = bmp; } + void SetBitmap(const wxBitmap &bmp) { m_bmp = bmp; } const wxBitmap &GetBitmap() const { return m_bmp; } - bool IsSameAs(const PrusaDataViewBitmapText& other) const { + bool IsSameAs(const DataViewBitmapText& other) const { return m_text == other.m_text && m_bmp.IsSameAs(other.m_bmp); } - bool operator==(const PrusaDataViewBitmapText& other) const { + bool operator==(const DataViewBitmapText& other) const { return IsSameAs(other); } - bool operator!=(const PrusaDataViewBitmapText& other) const { + bool operator!=(const DataViewBitmapText& other) const { return !IsSameAs(other); } @@ -205,13 +139,13 @@ private: wxString m_text; wxBitmap m_bmp; - wxDECLARE_DYNAMIC_CLASS(PrusaDataViewBitmapText); + wxDECLARE_DYNAMIC_CLASS(DataViewBitmapText); }; -DECLARE_VARIANT_OBJECT(PrusaDataViewBitmapText) +DECLARE_VARIANT_OBJECT(DataViewBitmapText) // ---------------------------------------------------------------------------- -// PrusaObjectDataViewModelNode: a node inside PrusaObjectDataViewModel +// ObjectDataViewModelNode: a node inside PrusaObjectDataViewModel // ---------------------------------------------------------------------------- enum ItemType { @@ -223,56 +157,73 @@ enum ItemType { itSettings = 16 }; -class PrusaObjectDataViewModelNode; -WX_DEFINE_ARRAY_PTR(PrusaObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray); +class ObjectDataViewModelNode; +WX_DEFINE_ARRAY_PTR(ObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray); -class PrusaObjectDataViewModelNode +class ObjectDataViewModelNode { - PrusaObjectDataViewModelNode* m_parent; + ObjectDataViewModelNode* m_parent; MyObjectTreeModelNodePtrArray m_children; wxBitmap m_empty_bmp; size_t m_volumes_cnt = 0; std::vector< std::string > m_opt_categories; + + wxString m_name; + wxBitmap& m_bmp = m_empty_bmp; + ItemType m_type; + int m_idx = -1; + bool m_container = false; + wxString m_extruder = "default"; + wxBitmap m_action_icon; + + std::string m_action_icon_name = ""; + Slic3r::ModelVolumeType m_volume_type; + public: - PrusaObjectDataViewModelNode(const wxString &name, - const wxString& extruder) { - m_parent = NULL; - m_name = name; - m_type = itObject; + ObjectDataViewModelNode(const wxString &name, + const wxString& extruder): + m_parent(NULL), + m_name(name), + m_type(itObject), + m_extruder(extruder) + { #ifdef __WXGTK__ // it's necessary on GTK because of control have to know if this item will be container // in another case you couldn't to add subitem for this item // it will be produce "segmentation fault" m_container = true; #endif //__WXGTK__ - m_extruder = extruder; - set_object_action_icon(); + + set_action_icon(); } - PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent, - const wxString& sub_obj_name, - const wxBitmap& bmp, - const wxString& extruder, - const int idx = -1 ) { - m_parent = parent; - m_name = sub_obj_name; - m_bmp = bmp; - m_type = itVolume; - m_idx = idx; - m_extruder = extruder; + ObjectDataViewModelNode(ObjectDataViewModelNode* parent, + const wxString& sub_obj_name, + const wxBitmap& bmp, + const wxString& extruder, + const int idx = -1 ) : + m_parent (parent), + m_name (sub_obj_name), + m_type (itVolume), + m_idx (idx), + m_extruder (extruder) + { + m_bmp = bmp; #ifdef __WXGTK__ // it's necessary on GTK because of control have to know if this item will be container // in another case you couldn't to add subitem for this item // it will be produce "segmentation fault" m_container = true; #endif //__WXGTK__ - set_part_action_icon(); + + set_action_icon(); } - PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent, const ItemType type) : - m_parent(parent), - m_type(type), - m_extruder(wxEmptyString) + ObjectDataViewModelNode(ObjectDataViewModelNode* parent, + const ItemType type) : + m_parent(parent), + m_type(type), + m_extruder(wxEmptyString) { if (type == itSettings) { m_name = "Settings to modified"; @@ -286,35 +237,28 @@ public: else if (type == itInstance) { m_idx = parent->GetChildCount(); m_name = wxString::Format("Instance_%d", m_idx+1); - set_part_action_icon(); + + set_action_icon(); } } - ~PrusaObjectDataViewModelNode() + ~ObjectDataViewModelNode() { // free all our children nodes size_t count = m_children.GetCount(); for (size_t i = 0; i < count; i++) { - PrusaObjectDataViewModelNode *child = m_children[i]; + ObjectDataViewModelNode *child = m_children[i]; delete child; } } - - wxString m_name; - wxBitmap& m_bmp = m_empty_bmp; - ItemType m_type; - int m_idx = -1; - bool m_container = false; - wxString m_extruder = "default"; - wxBitmap m_action_icon; bool IsContainer() const { return m_container; } - PrusaObjectDataViewModelNode* GetParent() + ObjectDataViewModelNode* GetParent() { return m_parent; } @@ -322,17 +266,17 @@ public: { return m_children; } - PrusaObjectDataViewModelNode* GetNthChild(unsigned int n) + ObjectDataViewModelNode* GetNthChild(unsigned int n) { return m_children.Item(n); } - void Insert(PrusaObjectDataViewModelNode* child, unsigned int n) + void Insert(ObjectDataViewModelNode* child, unsigned int n) { if (!m_container) m_container = true; m_children.Insert(child, n); } - void Append(PrusaObjectDataViewModelNode* child) + void Append(ObjectDataViewModelNode* child) { if (!m_container) m_container = true; @@ -362,7 +306,7 @@ public: switch (col) { case 0:{ - PrusaDataViewBitmapText data; + DataViewBitmapText data; data << variant; m_bmp = data.GetBitmap(); m_name = data.GetText(); @@ -400,7 +344,7 @@ public: } // use this function only for childrens - void AssignAllVal(PrusaObjectDataViewModelNode& from_node) + void AssignAllVal(ObjectDataViewModelNode& from_node) { // ! Don't overwrite other values because of equality of this values for all children -- m_name = from_node.m_name; @@ -416,8 +360,8 @@ public: scnd_id < 0 || scnd_id >= GetChildCount()) return false; - PrusaObjectDataViewModelNode new_scnd = *GetNthChild(frst_id); - PrusaObjectDataViewModelNode new_frst = *GetNthChild(scnd_id); + ObjectDataViewModelNode new_scnd = *GetNthChild(frst_id); + ObjectDataViewModelNode new_frst = *GetNthChild(scnd_id); new_scnd.m_idx = m_children.Item(scnd_id)->m_idx; new_frst.m_idx = m_children.Item(frst_id)->m_idx; @@ -428,37 +372,40 @@ public: } // Set action icons for node - void set_object_action_icon(); - void set_part_action_icon(); - bool update_settings_digest(const std::vector<std::string>& categories); + void set_action_icon(); + + void update_settings_digest_bitmaps(); + bool update_settings_digest(const std::vector<std::string>& categories); + int volume_type() const { return int(m_volume_type); } + void msw_rescale(); private: - friend class PrusaObjectDataViewModel; + friend class ObjectDataViewModel; }; // ---------------------------------------------------------------------------- -// PrusaObjectDataViewModel +// ObjectDataViewModel // ---------------------------------------------------------------------------- // custom message the model sends to associated control to notify a last volume deleted from the object: wxDECLARE_EVENT(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, wxCommandEvent); -class PrusaObjectDataViewModel :public wxDataViewModel +class ObjectDataViewModel :public wxDataViewModel { - std::vector<PrusaObjectDataViewModelNode*> m_objects; + std::vector<ObjectDataViewModelNode*> m_objects; std::vector<wxBitmap*> m_volume_bmps; wxDataViewCtrl* m_ctrl{ nullptr }; public: - PrusaObjectDataViewModel(); - ~PrusaObjectDataViewModel(); + ObjectDataViewModel(); + ~ObjectDataViewModel(); wxDataViewItem Add(const wxString &name, const int extruder); - wxDataViewItem AddVolumeChild(const wxDataViewItem &parent_item, - const wxString &name, - const Slic3r::ModelVolumeType volume_type, - const int extruder = 0, - const bool create_frst_child = true); + wxDataViewItem AddVolumeChild( const wxDataViewItem &parent_item, + const wxString &name, + const Slic3r::ModelVolumeType volume_type, + const int extruder = 0, + const bool create_frst_child = true); wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); wxDataViewItem Delete(const wxDataViewItem &item); @@ -470,76 +417,82 @@ public: wxDataViewItem GetItemById(int obj_idx); wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx); wxDataViewItem GetItemByInstanceId(int obj_idx, int inst_idx); - int GetIdByItem(const wxDataViewItem& item) const; - int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const; - int GetObjectIdByItem(const wxDataViewItem& item) const; - int GetVolumeIdByItem(const wxDataViewItem& item) const; - int GetInstanceIdByItem(const wxDataViewItem& item) const; + int GetIdByItem(const wxDataViewItem& item) const; + int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const; + int GetObjectIdByItem(const wxDataViewItem& item) const; + int GetVolumeIdByItem(const wxDataViewItem& item) const; + int GetInstanceIdByItem(const wxDataViewItem& item) const; void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx); - int GetRowByItem(const wxDataViewItem& item) const; + int GetRowByItem(const wxDataViewItem& item) const; bool IsEmpty() { return m_objects.empty(); } // helper method for wxLog - wxString GetName(const wxDataViewItem &item) const; - wxBitmap& GetBitmap(const wxDataViewItem &item) const; + wxString GetName(const wxDataViewItem &item) const; + wxBitmap& GetBitmap(const wxDataViewItem &item) const; // helper methods to change the model - virtual unsigned int GetColumnCount() const override { return 3;} - virtual wxString GetColumnType(unsigned int col) const override{ return wxT("string"); } + virtual unsigned int GetColumnCount() const override { return 3;} + virtual wxString GetColumnType(unsigned int col) const override{ return wxT("string"); } - virtual void GetValue(wxVariant &variant, - const wxDataViewItem &item, unsigned int col) const override; - virtual bool SetValue(const wxVariant &variant, - const wxDataViewItem &item, unsigned int col) override; - bool SetValue(const wxVariant &variant, const int item_idx, unsigned int col); + virtual void GetValue( wxVariant &variant, + const wxDataViewItem &item, + unsigned int col) const override; + virtual bool SetValue( const wxVariant &variant, + const wxDataViewItem &item, + unsigned int col) override; + bool SetValue( const wxVariant &variant, + const int item_idx, + unsigned int col); -// wxDataViewItem MoveChildUp(const wxDataViewItem &item); -// wxDataViewItem MoveChildDown(const wxDataViewItem &item); // For parent move child from cur_volume_id place to new_volume_id // Remaining items will moved up/down accordingly - wxDataViewItem ReorganizeChildren(int cur_volume_id, - int new_volume_id, - const wxDataViewItem &parent); + wxDataViewItem ReorganizeChildren( const int cur_volume_id, + const int new_volume_id, + const wxDataViewItem &parent); - virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override; + virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override; - virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override; + virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override; // get object item - wxDataViewItem GetTopParent(const wxDataViewItem &item) const; - virtual bool IsContainer(const wxDataViewItem &item) const override; - virtual unsigned int GetChildren(const wxDataViewItem &parent, - wxDataViewItemArray &array) const override; + wxDataViewItem GetTopParent(const wxDataViewItem &item) const; + virtual bool IsContainer(const wxDataViewItem &item) const override; + virtual unsigned int GetChildren(const wxDataViewItem &parent, + wxDataViewItemArray &array) const override; void GetAllChildren(const wxDataViewItem &parent,wxDataViewItemArray &array) const; // Is the container just a header or an item with all columns // In our case it is an item with all columns - virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; } + virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; } - ItemType GetItemType(const wxDataViewItem &item) const ; - wxDataViewItem GetItemByType(const wxDataViewItem &parent_item, ItemType type) const; - wxDataViewItem GetSettingsItem(const wxDataViewItem &item) const; - wxDataViewItem GetInstanceRootItem(const wxDataViewItem &item) const; + ItemType GetItemType(const wxDataViewItem &item) const ; + wxDataViewItem GetItemByType( const wxDataViewItem &parent_item, + ItemType type) const; + wxDataViewItem GetSettingsItem(const wxDataViewItem &item) const; + wxDataViewItem GetInstanceRootItem(const wxDataViewItem &item) const; bool IsSettingsItem(const wxDataViewItem &item) const; - void UpdateSettingsDigest(const wxDataViewItem &item, const std::vector<std::string>& categories); + void UpdateSettingsDigest( const wxDataViewItem &item, + const std::vector<std::string>& categories); void SetVolumeBitmaps(const std::vector<wxBitmap*>& volume_bmps) { m_volume_bmps = volume_bmps; } void SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type); void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; } + // Rescale bitmaps for existing Items + void Rescale(); }; // ---------------------------------------------------------------------------- -// PrusaBitmapTextRenderer +// BitmapTextRenderer // ---------------------------------------------------------------------------- #if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING -class PrusaBitmapTextRenderer : public wxDataViewRenderer +class BitmapTextRenderer : public wxDataViewRenderer #else -class PrusaBitmapTextRenderer : public wxDataViewCustomRenderer +class BitmapTextRenderer : public wxDataViewCustomRenderer #endif //ENABLE_NONCUSTOM_DATA_VIEW_RENDERING { public: - PrusaBitmapTextRenderer(wxDataViewCellMode mode = + BitmapTextRenderer(wxDataViewCellMode mode = #ifdef __WXOSX__ wxDATAVIEW_CELL_INERT #else @@ -550,7 +503,7 @@ public: #if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING ); #else - ) : wxDataViewCustomRenderer(wxT("PrusaDataViewBitmapText"), mode, align) {} + ) : wxDataViewCustomRenderer(wxT("DataViewBitmapText"), mode, align) {} #endif //ENABLE_NONCUSTOM_DATA_VIEW_RENDERING bool SetValue(const wxVariant &value); @@ -578,7 +531,7 @@ public: bool WasCanceled() const { return m_was_unusable_symbol; } private: - PrusaDataViewBitmapText m_value; + DataViewBitmapText m_value; bool m_was_unusable_symbol {false}; }; @@ -676,7 +629,37 @@ private: // ---------------------------------------------------------------------------- -// PrusaDoubleSlider +// ScalableBitmap +// ---------------------------------------------------------------------------- + +class ScalableBitmap +{ +public: + ScalableBitmap() {}; + ScalableBitmap( wxWindow *parent, + const std::string& icon_name = "", + const int px_cnt = 16, + const bool is_horizontal = false); + + ~ScalableBitmap() {} + + void msw_rescale(); + + const wxBitmap& bmp() const { return m_bmp; } + wxBitmap& bmp() { return m_bmp; } + const std::string& name() const{ return m_icon_name; } + +private: + wxWindow* m_parent{ nullptr }; + wxBitmap m_bmp = wxBitmap(); + std::string m_icon_name = ""; + int m_px_cnt {16}; + bool m_is_horizontal {false}; +}; + + +// ---------------------------------------------------------------------------- +// DoubleSlider // ---------------------------------------------------------------------------- // custom message the slider sends to its parent to notify a tick-change: @@ -693,10 +676,10 @@ enum TicksAction{ taDel }; -class PrusaDoubleSlider : public wxControl +class DoubleSlider : public wxControl { public: - PrusaDoubleSlider( + DoubleSlider( wxWindow *parent, wxWindowID id, int lowerValue, @@ -708,7 +691,9 @@ public: long style = wxSL_VERTICAL, const wxValidator& val = wxDefaultValidator, const wxString& name = wxEmptyString); - ~PrusaDoubleSlider() {} + ~DoubleSlider() {} + + void msw_rescale(); int GetMinValue() const { return m_min_value; } int GetMaxValue() const { return m_max_value; } @@ -717,6 +702,7 @@ public: int GetLowerValue() const { return m_lower_value; } int GetHigherValue() const { return m_higher_value; } int GetActiveValue() const; + wxSize get_min_size() const ; double GetLowerValueD() { return get_double_value(ssLower); } double GetHigherValueD() { return get_double_value(ssHigher); } wxSize DoGetBestSize() const override; @@ -801,16 +787,16 @@ private: int m_max_value; int m_lower_value; int m_higher_value; - wxBitmap m_bmp_thumb_higher; - wxBitmap m_bmp_thumb_lower; - wxBitmap m_bmp_add_tick_on; - wxBitmap m_bmp_add_tick_off; - wxBitmap m_bmp_del_tick_on; - wxBitmap m_bmp_del_tick_off; - wxBitmap m_bmp_one_layer_lock_on; - wxBitmap m_bmp_one_layer_lock_off; - wxBitmap m_bmp_one_layer_unlock_on; - wxBitmap m_bmp_one_layer_unlock_off; + ScalableBitmap m_bmp_thumb_higher; + ScalableBitmap m_bmp_thumb_lower; + ScalableBitmap m_bmp_add_tick_on; + ScalableBitmap m_bmp_add_tick_off; + ScalableBitmap m_bmp_del_tick_on; + ScalableBitmap m_bmp_del_tick_off; + ScalableBitmap m_bmp_one_layer_lock_on; + ScalableBitmap m_bmp_one_layer_lock_off; + ScalableBitmap m_bmp_one_layer_unlock_on; + ScalableBitmap m_bmp_one_layer_unlock_off; SelectedSlider m_selection; bool m_is_left_down = false; bool m_is_right_down = false; @@ -841,26 +827,26 @@ private: wxPen GREY_PEN; wxPen LIGHT_GREY_PEN; - std::vector<wxPen*> line_pens; - std::vector<wxPen*> segm_pens; + std::vector<wxPen*> m_line_pens; + std::vector<wxPen*> m_segm_pens; std::set<int> m_ticks; std::vector<std::pair<int,double>> m_values; }; // ---------------------------------------------------------------------------- -// PrusaLockButton +// LockButton // ---------------------------------------------------------------------------- -class PrusaLockButton : public wxButton +class LockButton : public wxButton { public: - PrusaLockButton( + LockButton( wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize); - ~PrusaLockButton() {} + ~LockButton() {} void OnButton(wxCommandEvent& event); void OnEnterBtn(wxMouseEvent& event) { enter_button(true); event.Skip(); } @@ -869,34 +855,72 @@ public: bool IsLocked() const { return m_is_pushed; } void SetLock(bool lock); + void msw_rescale(); + protected: void enter_button(const bool enter); private: bool m_is_pushed = false; - wxBitmap m_bmp_lock_on; - wxBitmap m_bmp_lock_off; - wxBitmap m_bmp_unlock_on; - wxBitmap m_bmp_unlock_off; + ScalableBitmap m_bmp_lock_on; + ScalableBitmap m_bmp_lock_off; + ScalableBitmap m_bmp_unlock_on; + ScalableBitmap m_bmp_unlock_off; }; // ---------------------------------------------------------------------------- -// PrusaModeButton +// ScalableButton // ---------------------------------------------------------------------------- -class PrusaModeButton : public wxButton +class ScalableButton : public wxButton { public: - PrusaModeButton( - wxWindow *parent, - wxWindowID id, - const wxString& mode = wxEmptyString, - const wxBitmap& bmp_on = wxNullBitmap, - const wxSize& size = wxDefaultSize, - const wxPoint& pos = wxDefaultPosition); - ~PrusaModeButton() {} + ScalableButton(){} + ScalableButton( + wxWindow * parent, + wxWindowID id, + const std::string& icon_name = "", + const wxString& label = wxEmptyString, + const wxSize& size = wxDefaultSize, + const wxPoint& pos = wxDefaultPosition, + long style = wxBU_EXACTFIT | wxNO_BORDER); + + ScalableButton( + wxWindow * parent, + wxWindowID id, + const ScalableBitmap& bitmap, + const wxString& label = wxEmptyString, + long style = wxBU_EXACTFIT | wxNO_BORDER); + + ~ScalableButton() {} + + void SetBitmap_(const ScalableBitmap& bmp); + + void msw_rescale(); + +private: + wxWindow* m_parent; + std::string m_current_icon_name = ""; +}; + + +// ---------------------------------------------------------------------------- +// ModeButton +// ---------------------------------------------------------------------------- + +class ModeButton : public ScalableButton +{ +public: + ModeButton( + wxWindow* parent, + wxWindowID id, + const std::string& icon_name = "", + const wxString& mode = wxEmptyString, + const wxSize& size = wxDefaultSize, + const wxPoint& pos = wxDefaultPosition); + ~ModeButton() {} void OnButton(wxCommandEvent& event); void OnEnterBtn(wxMouseEvent& event) { focus_button(true); event.Skip(); } @@ -910,8 +934,6 @@ protected: private: bool m_is_selected = false; - wxBitmap m_bmp_on; - wxBitmap m_bmp_off; wxString m_tt_selected; wxString m_tt_focused; }; @@ -919,47 +941,49 @@ private: // ---------------------------------------------------------------------------- -// PrusaModeSizer +// ModeSizer // ---------------------------------------------------------------------------- -class PrusaModeSizer : public wxFlexGridSizer +class ModeSizer : public wxFlexGridSizer { public: - PrusaModeSizer( wxWindow *parent, int hgap = 10); - ~PrusaModeSizer() {} + ModeSizer( wxWindow *parent, int hgap = 10); + ~ModeSizer() {} void SetMode(const /*ConfigOptionMode*/int mode); + void msw_rescale(); + private: - std::vector<PrusaModeButton*> mode_btns; + std::vector<ModeButton*> m_mode_btns; }; // ---------------------------------------------------------------------------- -// PrusaMenu +// MenuWithSeparators // ---------------------------------------------------------------------------- -class PrusaMenu : public wxMenu +class MenuWithSeparators : public wxMenu { public: - PrusaMenu(const wxString& title, long style = 0) + MenuWithSeparators(const wxString& title, long style = 0) : wxMenu(title, style) {} - PrusaMenu(long style = 0) + MenuWithSeparators(long style = 0) : wxMenu(style) {} - ~PrusaMenu() {} + ~MenuWithSeparators() {} void DestroySeparators(); + void SetFirstSeparator(); + void SetSecondSeparator(); +private: wxMenuItem* m_separator_frst { nullptr }; // use like separator before settings item wxMenuItem* m_separator_scnd { nullptr }; // use like separator between settings items }; -// ******************************* EXPERIMENTS ********************************************** -// ****************************************************************************************** - #endif // slic3r_GUI_wxExtensions_hpp_ |