From fd071421cb25ce62b5c77c73ed1fa8b35cff5d1f Mon Sep 17 00:00:00 2001 From: Oleksandra Yushchenko Date: Fri, 18 Jun 2021 19:46:04 +0200 Subject: [PATCH] DarkMode for MSW (#6632) * MSW specific: Dark Mode: First implementation * Use menu instead of NoteBook * Implemented MessageDialog + Fixed DarkMode for all dialogs and ColorPicker * MSW DarkMode: Added missed updates for the switching between modes * MSW DarkMode: Updated all existed context menus after switching of the mode + Added markers for the menu item witch is related to the selected tab * Used wxFrame instead of wxDialog for SettingsDialog (this change allow us to use menu bar in SettingsDialog) + fix for #6548 - Prusa Slicer 2.3.1 not activating non-modal settings window if settings window is minimized * Implemented "Always use Dark mode colors" preference option * Fixes for non_MSW build * Next fixes for non-MSW builds * Preferences: Fixed selection of the Settings Layout for non-MSW platforms + Updated DarkMode for colorpickers * Windows DarkMode next fixes * MSWDarkMode: Suppress to use system color to the PrusaSlicer Select "Preferences -> Use Dark color mode (experimental)" to allow dark mode for the application * Fixed MSW build * MSWDarkMode: Upadteed color mode for ExtruderSequenceDialog and for dialogs related to the DoubleSlider * Implemented Auto recreation of the PrusaSlicer when color mode is changed. * Preferences: Added option "Set settings tabs as menu items (experimental)" --- resources/icons/white/compare.svg | 30 +++ resources/icons/white/equal.svg | 15 ++ src/libslic3r/AppConfig.cpp | 6 + src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/2DBed.cpp | 4 + src/slic3r/GUI/AboutDialog.cpp | 17 +- src/slic3r/GUI/BedShapeDialog.cpp | 25 +- src/slic3r/GUI/BitmapComboBox.cpp | 266 +++++++++++++++++++ src/slic3r/GUI/BitmapComboBox.hpp | 62 +++++ src/slic3r/GUI/ButtonsDescription.cpp | 8 +- src/slic3r/GUI/ConfigManipulation.cpp | 28 +- src/slic3r/GUI/ConfigSnapshotDialog.cpp | 11 +- src/slic3r/GUI/ConfigWizard.cpp | 86 +++++- src/slic3r/GUI/ConfigWizard.hpp | 1 + src/slic3r/GUI/DoubleSlider.cpp | 27 +- src/slic3r/GUI/ExtraRenderers.cpp | 10 + src/slic3r/GUI/ExtruderSequenceDialog.cpp | 28 +- src/slic3r/GUI/Field.cpp | 59 +++- src/slic3r/GUI/Field.hpp | 4 +- src/slic3r/GUI/FirmwareDialog.cpp | 8 +- src/slic3r/GUI/GUI.cpp | 8 +- src/slic3r/GUI/GUI_App.cpp | 174 +++++++++++- src/slic3r/GUI/GUI_App.hpp | 28 +- src/slic3r/GUI/GUI_Factories.cpp | 81 +++++- src/slic3r/GUI/GUI_Factories.hpp | 3 +- src/slic3r/GUI/GUI_ObjectLayers.cpp | 33 ++- src/slic3r/GUI/GUI_ObjectList.cpp | 15 +- src/slic3r/GUI/GUI_ObjectList.hpp | 3 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 41 ++- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 9 + src/slic3r/GUI/GUI_ObjectSettings.cpp | 8 + src/slic3r/GUI/GUI_ObjectSettings.hpp | 1 + src/slic3r/GUI/GUI_Preview.cpp | 33 ++- src/slic3r/GUI/GUI_Preview.hpp | 8 +- src/slic3r/GUI/GUI_Utils.cpp | 32 +++ src/slic3r/GUI/GUI_Utils.hpp | 27 ++ src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 7 +- src/slic3r/GUI/KBShortcutsDialog.cpp | 18 +- src/slic3r/GUI/MainFrame.cpp | 195 ++++++++++++-- src/slic3r/GUI/MainFrame.hpp | 20 +- src/slic3r/GUI/MsgDialog.cpp | 149 ++++++----- src/slic3r/GUI/MsgDialog.hpp | 25 +- src/slic3r/GUI/OG_CustomCtrl.cpp | 19 +- src/slic3r/GUI/ObjectDataViewModel.cpp | 2 +- src/slic3r/GUI/OptionsGroup.cpp | 34 +++ src/slic3r/GUI/OptionsGroup.hpp | 3 +- src/slic3r/GUI/PhysicalPrinterDialog.cpp | 19 +- src/slic3r/GUI/Plater.cpp | 125 +++++++-- src/slic3r/GUI/Preferences.cpp | 157 +++++++++-- src/slic3r/GUI/Preferences.hpp | 10 +- src/slic3r/GUI/PresetComboBoxes.cpp | 92 ++----- src/slic3r/GUI/PresetComboBoxes.hpp | 21 +- src/slic3r/GUI/PrintHostDialogs.cpp | 6 +- src/slic3r/GUI/ProgressStatusBar.cpp | 8 + src/slic3r/GUI/ProgressStatusBar.hpp | 2 + src/slic3r/GUI/RammingChart.cpp | 16 +- src/slic3r/GUI/Search.cpp | 19 +- src/slic3r/GUI/SysInfoDialog.cpp | 7 +- src/slic3r/GUI/Tab.cpp | 69 +++-- src/slic3r/GUI/Tab.hpp | 30 +-- src/slic3r/GUI/UnsavedChangesDialog.cpp | 38 ++- src/slic3r/GUI/UpdateDialogs.cpp | 6 + src/slic3r/GUI/WipeTowerDialog.cpp | 73 ++++- src/slic3r/GUI/wxExtensions.cpp | 63 +++-- src/slic3r/GUI/wxExtensions.hpp | 13 +- src/slic3r/Utils/FixModelByWin10.cpp | 7 +- 66 files changed, 2011 insertions(+), 443 deletions(-) create mode 100644 resources/icons/white/compare.svg create mode 100644 resources/icons/white/equal.svg create mode 100644 src/slic3r/GUI/BitmapComboBox.cpp create mode 100644 src/slic3r/GUI/BitmapComboBox.hpp diff --git a/resources/icons/white/compare.svg b/resources/icons/white/compare.svg new file mode 100644 index 000000000..7eafebfde --- /dev/null +++ b/resources/icons/white/compare.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + diff --git a/resources/icons/white/equal.svg b/resources/icons/white/equal.svg new file mode 100644 index 000000000..febbb4c5f --- /dev/null +++ b/resources/icons/white/equal.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 869c3e67f..81e4db2ba 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -75,6 +75,12 @@ void AppConfig::set_defaults() set("associate_3mf", "0"); if (get("associate_stl").empty()) set("associate_stl", "0"); + + if (get("dark_color_mode").empty()) + set("dark_color_mode", "0"); + + if (get("tabs_as_menu").empty()) + set("tabs_as_menu", "0"); #endif // _WIN32 // remove old 'use_legacy_opengl' parameter from this config, if present diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 44bc178d0..f6739b0d8 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -91,6 +91,8 @@ set(SLIC3R_GUI_SOURCES GUI/Plater.hpp GUI/PresetComboBoxes.hpp GUI/PresetComboBoxes.cpp + GUI/BitmapComboBox.hpp + GUI/BitmapComboBox.cpp GUI/SavePresetDialog.hpp GUI/SavePresetDialog.cpp GUI/PhysicalPrinterDialog.hpp diff --git a/src/slic3r/GUI/2DBed.cpp b/src/slic3r/GUI/2DBed.cpp index ea6720356..c4eec0b03 100644 --- a/src/slic3r/GUI/2DBed.cpp +++ b/src/slic3r/GUI/2DBed.cpp @@ -33,7 +33,11 @@ void Bed_2D::repaint(const std::vector& shape) // On MacOS the background is erased, on Windows the background is not erased // and on Linux / GTK the background is erased to gray color. // Fill DC with the background on Windows & Linux / GTK. +#ifdef _WIN32 + auto color = wxGetApp().get_highlight_default_clr(); +#else auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT); //GetSystemColour +#endif dc.SetPen(*new wxPen(color, 1, wxPENSTYLE_SOLID)); dc.SetBrush(*new wxBrush(color, wxBRUSHSTYLE_SOLID)); auto rect = GetUpdateRegion().GetBox(); diff --git a/src/slic3r/GUI/AboutDialog.cpp b/src/slic3r/GUI/AboutDialog.cpp index c760b6ad1..5039b9de4 100644 --- a/src/slic3r/GUI/AboutDialog.cpp +++ b/src/slic3r/GUI/AboutDialog.cpp @@ -46,7 +46,11 @@ CopyrightsDialog::CopyrightsDialog() wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { this->SetFont(wxGetApp().normal_font()); +#ifdef _WIN32 + wxGetApp().UpdateDarkUI(this); +#else this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif auto sizer = new wxBoxSizer(wxVERTICAL); @@ -68,6 +72,7 @@ CopyrightsDialog::CopyrightsDialog() m_html->Bind(wxEVT_HTML_LINK_CLICKED, &CopyrightsDialog::onLinkClicked, this); wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCLOSE); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CLOSE, this))); this->SetEscapeId(wxID_CLOSE); this->Bind(wxEVT_BUTTON, &CopyrightsDialog::onCloseDialog, this, wxID_CLOSE); @@ -124,9 +129,9 @@ void CopyrightsDialog::fill_entries() wxString CopyrightsDialog::get_html_text() { - wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + wxColour bgr_clr = wxGetApp().get_window_default_clr();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - const auto text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + const auto text_clr = wxGetApp().get_label_clr_default();// wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); const auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); const auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); @@ -206,7 +211,7 @@ AboutDialog::AboutDialog() { SetFont(wxGetApp().normal_font()); - wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + wxColour bgr_clr = wxGetApp().get_window_default_clr();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); SetBackgroundColour(bgr_clr); wxBoxSizer* hsizer = new wxBoxSizer(wxHORIZONTAL); @@ -250,7 +255,7 @@ AboutDialog::AboutDialog() { m_html->SetMinSize(wxSize(-1, 16 * wxGetApp().em_unit())); wxFont font = get_default_font(this); - const auto text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + const auto text_clr = wxGetApp().get_label_clr_default();//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()); @@ -292,6 +297,7 @@ AboutDialog::AboutDialog() wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCLOSE); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CLOSE, this))); m_copy_rights_btn_id = NewControlId(); auto copy_rights_btn = new wxButton(this, m_copy_rights_btn_id, _L("Portions copyright")+dots); @@ -302,6 +308,9 @@ AboutDialog::AboutDialog() auto copy_version_btn = new wxButton(this, m_copy_version_btn_id, _L("Copy Version Info")); buttons->Insert(1, copy_version_btn, 0, wxLEFT, 5); copy_version_btn->Bind(wxEVT_BUTTON, &AboutDialog::onCopyToClipboard, this); + + wxGetApp().UpdateDarkUI(copy_rights_btn); + wxGetApp().UpdateDarkUI(copy_version_btn); this->SetEscapeId(wxID_CLOSE); this->Bind(wxEVT_BUTTON, &AboutDialog::onCloseDialog, this, wxID_CLOSE); diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 0a10f4753..7284bb51b 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -177,6 +177,8 @@ void BedShape::apply_optgroup_values(ConfigOptionsGroupShp optgroup) void BedShapeDialog::build_dialog(const ConfigOptionPoints& default_pt, const ConfigOptionString& custom_texture, const ConfigOptionString& custom_model) { SetFont(wxGetApp().normal_font()); +// wxGetApp().UpdateDarkUI(this); + m_panel = new BedShapePanel(this); m_panel->build_panel(default_pt, custom_texture, custom_model); @@ -184,6 +186,9 @@ void BedShapeDialog::build_dialog(const ConfigOptionPoints& default_pt, const Co main_sizer->Add(m_panel, 1, wxEXPAND); main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_OK, this)), true); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CANCEL, this)), true); + SetSizer(main_sizer); SetMinSize(GetSize()); main_sizer->SetSizeHints(this); @@ -214,15 +219,19 @@ const std::string BedShapePanel::EMPTY_STRING = ""; void BedShapePanel::build_panel(const ConfigOptionPoints& default_pt, const ConfigOptionString& custom_texture, const ConfigOptionString& custom_model) { + wxGetApp().UpdateDarkUI(this); m_shape = default_pt.values; m_custom_texture = custom_texture.value.empty() ? NONE : custom_texture.value; m_custom_model = custom_model.value.empty() ? NONE : custom_model.value; auto sbsizer = new wxStaticBoxSizer(wxVERTICAL, this, _(L("Shape"))); sbsizer->GetStaticBox()->SetFont(wxGetApp().bold_font()); + wxGetApp().UpdateDarkUI(sbsizer->GetStaticBox()); // shape options m_shape_options_book = new wxChoicebook(this, wxID_ANY, wxDefaultPosition, wxSize(25*wxGetApp().em_unit(), -1), wxCHB_TOP); + wxGetApp().UpdateDarkUI(m_shape_options_book->GetChoiceCtrl()); + sbsizer->Add(m_shape_options_book); auto optgroup = init_shape_options_page(BedShape::get_name(BedShape::Type::Rectangular)); @@ -240,6 +249,7 @@ void BedShapePanel::build_panel(const ConfigOptionPoints& default_pt, const Conf line.full_width = 1; line.widget = [this](wxWindow* parent) { wxButton* shape_btn = new wxButton(parent, wxID_ANY, _L("Load shape from STL...")); + wxGetApp().UpdateDarkUI(shape_btn, true); wxSizer* shape_sizer = new wxBoxSizer(wxHORIZONTAL); shape_sizer->Add(shape_btn, 1, wxEXPAND); @@ -311,6 +321,7 @@ void BedShapePanel::activate_options_page(ConfigOptionsGroupShp options_group) wxPanel* BedShapePanel::init_texture_panel() { wxPanel* panel = new wxPanel(this); + wxGetApp().UpdateDarkUI(panel, true); ConfigOptionsGroupShp optgroup = std::make_shared(panel, _(L("Texture"))); optgroup->label_width = 10; @@ -322,21 +333,24 @@ wxPanel* BedShapePanel::init_texture_panel() line.full_width = 1; line.widget = [this](wxWindow* parent) { wxButton* load_btn = new wxButton(parent, wxID_ANY, _(L("Load..."))); + wxGetApp().UpdateDarkUI(load_btn, true); wxSizer* load_sizer = new wxBoxSizer(wxHORIZONTAL); load_sizer->Add(load_btn, 1, wxEXPAND); wxStaticText* filename_lbl = new wxStaticText(parent, wxID_ANY, _(NONE)); + wxSizer* filename_sizer = new wxBoxSizer(wxHORIZONTAL); filename_sizer->Add(filename_lbl, 1, wxEXPAND); wxButton* remove_btn = new wxButton(parent, wxID_ANY, _(L("Remove"))); + wxGetApp().UpdateDarkUI(remove_btn, true); wxSizer* remove_sizer = new wxBoxSizer(wxHORIZONTAL); remove_sizer->Add(remove_btn, 1, wxEXPAND); wxSizer* sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(filename_sizer, 1, wxEXPAND); sizer->Add(load_sizer, 1, wxEXPAND); - sizer->Add(remove_sizer, 1, wxEXPAND); + sizer->Add(remove_sizer, 1, wxEXPAND | wxTOP, 2); load_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) { @@ -356,7 +370,7 @@ wxPanel* BedShapePanel::init_texture_panel() if (lbl != nullptr) { bool exists = (m_custom_texture == NONE) || boost::filesystem::exists(m_custom_texture); - lbl->SetForegroundColour(exists ? wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) : wxColor(*wxRED)); + lbl->SetForegroundColour(exists ? /*wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)*/wxGetApp().get_label_clr_default() : wxColor(*wxRED)); wxString tooltip_text = ""; if (m_custom_texture != NONE) @@ -391,6 +405,7 @@ wxPanel* BedShapePanel::init_texture_panel() wxPanel* BedShapePanel::init_model_panel() { wxPanel* panel = new wxPanel(this); + wxGetApp().UpdateDarkUI(panel, true); ConfigOptionsGroupShp optgroup = std::make_shared(panel, _(L("Model"))); optgroup->label_width = 10; @@ -402,6 +417,7 @@ wxPanel* BedShapePanel::init_model_panel() line.full_width = 1; line.widget = [this](wxWindow* parent) { wxButton* load_btn = new wxButton(parent, wxID_ANY, _(L("Load..."))); + wxGetApp().UpdateDarkUI(load_btn, true); wxSizer* load_sizer = new wxBoxSizer(wxHORIZONTAL); load_sizer->Add(load_btn, 1, wxEXPAND); @@ -410,13 +426,14 @@ wxPanel* BedShapePanel::init_model_panel() filename_sizer->Add(filename_lbl, 1, wxEXPAND); wxButton* remove_btn = new wxButton(parent, wxID_ANY, _(L("Remove"))); + wxGetApp().UpdateDarkUI(remove_btn, true); wxSizer* remove_sizer = new wxBoxSizer(wxHORIZONTAL); remove_sizer->Add(remove_btn, 1, wxEXPAND); wxSizer* sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(filename_sizer, 1, wxEXPAND); sizer->Add(load_sizer, 1, wxEXPAND); - sizer->Add(remove_sizer, 1, wxEXPAND); + sizer->Add(remove_sizer, 1, wxEXPAND | wxTOP, 2); load_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) { @@ -436,7 +453,7 @@ wxPanel* BedShapePanel::init_model_panel() if (lbl != nullptr) { bool exists = (m_custom_model == NONE) || boost::filesystem::exists(m_custom_model); - lbl->SetForegroundColour(exists ? wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) : wxColor(*wxRED)); + lbl->SetForegroundColour(exists ? /*wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)*/wxGetApp().get_label_clr_default() : wxColor(*wxRED)); wxString tooltip_text = ""; if (m_custom_model != NONE) diff --git a/src/slic3r/GUI/BitmapComboBox.cpp b/src/slic3r/GUI/BitmapComboBox.cpp new file mode 100644 index 000000000..f27c1b671 --- /dev/null +++ b/src/slic3r/GUI/BitmapComboBox.cpp @@ -0,0 +1,266 @@ +#include "BitmapComboBox.hpp" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#ifdef _MSW_DARK_MODE +#include +#endif //_MSW_DARK_MODE +#endif + +#include "libslic3r/libslic3r.h" +#include "libslic3r/PrintConfig.hpp" +#include "libslic3r/PresetBundle.hpp" + +#include "GUI.hpp" +#include "GUI_App.hpp" +#include "Plater.hpp" +#include "MainFrame.hpp" +#include "format.hpp" + +// A workaround for a set of issues related to text fitting into gtk widgets: +// See e.g.: https://github.com/prusa3d/PrusaSlicer/issues/4584 +#if defined(__WXGTK20__) || defined(__WXGTK3__) + #include + #include + #include +#endif + +using Slic3r::GUI::format_wxstr; + +#define BORDER_W 10 + +// --------------------------------- +// *** BitmapComboBox *** +// --------------------------------- + +namespace Slic3r { +namespace GUI { + +/* For PresetComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina + * (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean + * "please scale this to such and such" but rather + * "the wxImage is already sized for backing scale such and such". ) + * Unfortunately, the constructor changes the size of wxBitmap too. + * Thus We need to use unscaled size value for bitmaps that we use + * to avoid scaled size of control items. + * For this purpose control drawing methods and + * control size calculation methods (virtual) are overridden. + **/ + +BitmapComboBox::BitmapComboBox(wxWindow* parent, + wxWindowID id/* = wxID_ANY*/, + const wxString& value/* = wxEmptyString*/, + const wxPoint& pos/* = wxDefaultPosition*/, + const wxSize& size/* = wxDefaultSize*/, + int n/* = 0*/, + const wxString choices[]/* = NULL*/, + long style/* = 0*/) : + wxBitmapComboBox(parent, id, value, pos, size, n, choices, style) +{ + SetFont(Slic3r::GUI::wxGetApp().normal_font()); +#ifdef _WIN32 + // Workaround for ignoring CBN_EDITCHANGE events, which are processed after the content of the combo box changes, so that + // the index of the item inside CBN_EDITCHANGE may no more be valid. + EnableTextChangedEvents(false); + wxGetApp().UpdateDarkUI(this); + if (!HasFlag(wxCB_READONLY)) + wxTextEntry::SetMargins(0,0); +#endif /* _WIN32 */ +} + +BitmapComboBox::~BitmapComboBox() +{ +} + +#ifdef __APPLE__ +bool BitmapComboBox::OnAddBitmap(const wxBitmap& bitmap) +{ + if (bitmap.IsOk()) + { + // we should use scaled! size values of bitmap + int width = (int)bitmap.GetScaledWidth(); + int height = (int)bitmap.GetScaledHeight(); + + if (m_usedImgSize.x < 0) + { + // If size not yet determined, get it from this image. + m_usedImgSize.x = width; + m_usedImgSize.y = height; + + // Adjust control size to vertically fit the bitmap + wxWindow* ctrl = GetControl(); + ctrl->InvalidateBestSize(); + wxSize newSz = ctrl->GetBestSize(); + wxSize sz = ctrl->GetSize(); + if (newSz.y > sz.y) + ctrl->SetSize(sz.x, newSz.y); + else + DetermineIndent(); + } + + wxCHECK_MSG(width == m_usedImgSize.x && height == m_usedImgSize.y, + false, + "you can only add images of same size"); + + return true; + } + + return false; +} + +void BitmapComboBox::OnDrawItem(wxDC& dc, + const wxRect& rect, + int item, + int flags) const +{ + const wxBitmap& bmp = *(static_cast(m_bitmaps[item])); + if (bmp.IsOk()) + { + // we should use scaled! size values of bitmap + wxCoord w = bmp.GetScaledWidth(); + wxCoord h = bmp.GetScaledHeight(); + + const int imgSpacingLeft = 4; + + // Draw the image centered + dc.DrawBitmap(bmp, + rect.x + (m_usedImgSize.x - w) / 2 + imgSpacingLeft, + rect.y + (rect.height - h) / 2, + true); + } + + wxString text = GetString(item); + if (!text.empty()) + dc.DrawText(text, + rect.x + m_imgAreaWidth + 1, + rect.y + (rect.height - dc.GetCharHeight()) / 2); +} +#endif + + +#ifdef _WIN32 + +int BitmapComboBox::Append(const wxString& item) +{ + // Workaround for a correct rendering of the control without Bitmap (under MSW): + //1. We should create small Bitmap to fill Bitmaps RefData, + // ! in this case wxBitmap.IsOK() return true. + //2. But then set width to 0 value for no using of bitmap left and right spacing + //3. Set this empty bitmap to the at list one item and BitmapCombobox will be recreated correct + + wxBitmap bitmap(1, this->GetFont().GetPixelSize().y + 2); + bitmap.SetWidth(0); + + OnAddBitmap(bitmap); + const int n = wxComboBox::Append(item); + if (n != wxNOT_FOUND) + DoSetItemBitmap(n, bitmap); + return n; +} + +enum OwnerDrawnComboBoxPaintingFlags +{ + ODCB_PAINTING_DISABLED = 0x0004, +}; + +bool BitmapComboBox::MSWOnDraw(WXDRAWITEMSTRUCT* item) +{ + LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT)item; + int pos = lpDrawItem->itemID; + + // Draw default for item -1, which means 'focus rect only' + if (pos == -1) + return false; + + int flags = 0; + if (lpDrawItem->itemState & ODS_COMBOBOXEDIT) + flags |= wxODCB_PAINTING_CONTROL; + if (lpDrawItem->itemState & ODS_SELECTED) + flags |= wxODCB_PAINTING_SELECTED; + if (lpDrawItem->itemState & ODS_DISABLED) + flags |= ODCB_PAINTING_DISABLED; + + wxPaintDCEx dc(this, lpDrawItem->hDC); + wxRect rect = wxRectFromRECT(lpDrawItem->rcItem); + + DrawBackground_(dc, rect, pos, flags); + + wxString text; + + if (flags & wxODCB_PAINTING_CONTROL) + { + // Don't draw anything in the editable selection field. + //if (!HasFlag(wxCB_READONLY)) + // return true; + + pos = GetSelection(); + // Skip drawing if there is nothing selected. + if (pos < 0) + return true; + + text = GetValue(); + } + else + { + text = GetString(pos); + } + + wxBitmapComboBoxBase::DrawItem(dc, rect, pos, text, flags); + + return true; +} + +void BitmapComboBox::DrawBackground_(wxDC& dc, const wxRect& rect, int WXUNUSED(item), int flags) const +{ + if (flags & wxODCB_PAINTING_SELECTED) + { + const int vSizeDec = 0; // Vertical size reduction of selection rectangle edges + + dc.SetTextForeground(wxGetApp().get_label_highlight_clr()); + + wxColour selCol = wxGetApp().get_highlight_default_clr(); + dc.SetPen(selCol); + dc.SetBrush(selCol); + dc.DrawRectangle(rect.x, + rect.y + vSizeDec, + rect.width, + rect.height - (vSizeDec * 2)); + } + else + { + dc.SetTextForeground(flags & ODCB_PAINTING_DISABLED ? wxColour(108,108,108) : wxGetApp().get_label_clr_default()); + + wxColour selCol = flags & ODCB_PAINTING_DISABLED ? +#ifdef _MSW_DAEK_MODE + wxRGBToColour(NppDarkMode::InvertLightnessSofter(NppDarkMode::GetBackgroundColor())) : +#else + wxGetApp().get_highlight_default_clr() : +#endif + wxGetApp().get_window_default_clr(); + dc.SetPen(selCol); + dc.SetBrush(selCol); + dc.DrawRectangle(rect); + } +} +#endif + +}} + diff --git a/src/slic3r/GUI/BitmapComboBox.hpp b/src/slic3r/GUI/BitmapComboBox.hpp new file mode 100644 index 000000000..c46edfd50 --- /dev/null +++ b/src/slic3r/GUI/BitmapComboBox.hpp @@ -0,0 +1,62 @@ +#ifndef slic3r_BitmapComboBox_hpp_ +#define slic3r_BitmapComboBox_hpp_ + +#include +#include + +#include "GUI_Utils.hpp" + +// --------------------------------- +// *** BitmapComboBox *** +// --------------------------------- +namespace Slic3r { +namespace GUI { + +// BitmapComboBox used to presets list on Sidebar and Tabs +class BitmapComboBox : public wxBitmapComboBox +{ +public: +BitmapComboBox(wxWindow* parent, + wxWindowID id = wxID_ANY, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + int n = 0, + const wxString choices[] = NULL, + long style = 0); +~BitmapComboBox(); + +#ifdef _WIN32 + int Append(const wxString& item); +#endif + int Append(const wxString& item, const wxBitmap& bitmap) + { + return wxBitmapComboBox::Append(item, bitmap); + } + +protected: + +#ifdef __APPLE__ +/* For PresetComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina + * (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean + * "please scale this to such and such" but rather + * "the wxImage is already sized for backing scale such and such". ) + * Unfortunately, the constructor changes the size of wxBitmap too. + * Thus We need to use unscaled size value for bitmaps that we use + * to avoid scaled size of control items. + * For this purpose control drawing methods and + * control size calculation methods (virtual) are overridden. + **/ +bool OnAddBitmap(const wxBitmap& bitmap) override; +void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override; +#endif + +#ifdef _WIN32 +bool MSWOnDraw(WXDRAWITEMSTRUCT* item) override; +void DrawBackground_(wxDC& dc, const wxRect& rect, int WXUNUSED(item), int flags) const; +#endif + +}; + + }} +#endif diff --git a/src/slic3r/GUI/ButtonsDescription.cpp b/src/slic3r/GUI/ButtonsDescription.cpp index 0610199f5..78a9d2df5 100644 --- a/src/slic3r/GUI/ButtonsDescription.cpp +++ b/src/slic3r/GUI/ButtonsDescription.cpp @@ -16,6 +16,8 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, const std::vectorSetForegroundColour(wxGetApp().get_label_clr_sys()); auto sys_colour = new wxColourPickerCtrl(this, wxID_ANY, wxGetApp().get_label_clr_sys()); + wxGetApp().UpdateDarkUI(sys_colour->GetPickerCtrl(), true); sys_colour->Bind(wxEVT_COLOURPICKER_CHANGED, ([sys_colour, sys_label](wxCommandEvent e) { sys_label->SetForegroundColour(sys_colour->GetColour()); @@ -53,6 +56,7 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, const std::vectorSetForegroundColour(wxGetApp().get_label_clr_modified()); auto mod_colour = new wxColourPickerCtrl(this, wxID_ANY, wxGetApp().get_label_clr_modified()); + wxGetApp().UpdateDarkUI(mod_colour->GetPickerCtrl(), true); mod_colour->Bind(wxEVT_COLOURPICKER_CHANGED, ([mod_colour, mod_label](wxCommandEvent e) { mod_label->SetForegroundColour(mod_colour->GetColour()); @@ -67,7 +71,9 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, const std::vectorAdd(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); wxButton* btn = static_cast(FindWindowById(wxID_OK, this)); - btn->Bind(wxEVT_BUTTON, [sys_colour, mod_colour, this](wxCommandEvent&) { + wxGetApp().UpdateDarkUI(btn); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CANCEL, this))); + btn->Bind(wxEVT_BUTTON, [sys_colour, mod_colour, this](wxCommandEvent&) { wxGetApp().set_label_clr_sys(sys_colour->GetColour()); wxGetApp().set_label_clr_modified(mod_colour->GetColour()); EndModal(wxID_OK); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index c5633b8fa..5596bb633 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -5,6 +5,7 @@ #include "format.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/PresetBundle.hpp" +#include "MsgDialog.hpp" #include @@ -46,7 +47,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con if (config->opt_float("layer_height") < EPSILON) { const wxString msg_text = _(L("Layer height is not valid.\n\nThe layer height will be reset to 0.01.")); - wxMessageDialog dialog(nullptr, msg_text, _(L("Layer height")), wxICON_WARNING | wxOK); + //wxMessageDialog dialog(nullptr, msg_text, _(L("Layer height")), wxICON_WARNING | wxOK); + MessageDialog dialog(nullptr, msg_text, _(L("Layer height")), wxICON_WARNING | wxOK); DynamicPrintConfig new_conf = *config; is_msg_dlg_already_exist = true; dialog.ShowModal(); @@ -58,7 +60,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con if (config->option("first_layer_height")->value < EPSILON) { const wxString msg_text = _(L("First layer height is not valid.\n\nThe first layer height will be reset to 0.01.")); - wxMessageDialog dialog(nullptr, msg_text, _(L("First layer height")), wxICON_WARNING | wxOK); + //wxMessageDialog dialog(nullptr, msg_text, _(L("First layer height")), wxICON_WARNING | wxOK); + MessageDialog dialog(nullptr, msg_text, _(L("First layer height")), wxICON_WARNING | wxOK); DynamicPrintConfig new_conf = *config; is_msg_dlg_already_exist = true; dialog.ShowModal(); @@ -87,7 +90,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con "- Detect thin walls disabled")); if (is_global_config) msg_text += "\n\n" + _(L("Shall I adjust those settings in order to enable Spiral Vase?")); - wxMessageDialog dialog(nullptr, msg_text, _(L("Spiral Vase")), + //wxMessageDialog dialog(nullptr, msg_text, _(L("Spiral Vase")), + MessageDialog dialog(nullptr, msg_text, _(L("Spiral Vase")), wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); DynamicPrintConfig new_conf = *config; auto answer = dialog.ShowModal(); @@ -122,7 +126,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con "(both support_material_extruder and support_material_interface_extruder need to be set to 0).")); if (is_global_config) msg_text += "\n\n" + _(L("Shall I adjust those settings in order to enable the Wipe Tower?")); - wxMessageDialog dialog (nullptr, msg_text, _(L("Wipe Tower")), + //wxMessageDialog dialog (nullptr, msg_text, _(L("Wipe Tower")), + MessageDialog dialog (nullptr, msg_text, _(L("Wipe Tower")), wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); DynamicPrintConfig new_conf = *config; auto answer = dialog.ShowModal(); @@ -142,7 +147,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con "need to be synchronized with the object layers.")); if (is_global_config) msg_text += "\n\n" + _(L("Shall I synchronize support layers in order to enable the Wipe Tower?")); - wxMessageDialog dialog(nullptr, msg_text, _(L("Wipe Tower")), + //wxMessageDialog dialog(nullptr, msg_text, _(L("Wipe Tower")), + MessageDialog dialog(nullptr, msg_text, _(L("Wipe Tower")), wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); DynamicPrintConfig new_conf = *config; auto answer = dialog.ShowModal(); @@ -165,7 +171,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con "- Detect bridging perimeters")); if (is_global_config) msg_text += "\n\n" + _(L("Shall I adjust those settings for supports?")); - wxMessageDialog dialog(nullptr, msg_text, _(L("Support Generator")), + //wxMessageDialog dialog(nullptr, msg_text, _(L("Support Generator")), + MessageDialog dialog(nullptr, msg_text, _(L("Support Generator")), wxICON_WARNING | (is_global_config ? wxYES | wxNO | wxCANCEL : wxOK)); DynamicPrintConfig new_conf = *config; auto answer = dialog.ShowModal(); @@ -204,7 +211,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con _(fill_pattern_def->enum_labels[it_pattern - fill_pattern_def->enum_values.begin()])); if (is_global_config) msg_text += "\n\n" + _L("Shall I switch to rectilinear fill pattern?"); - wxMessageDialog dialog(nullptr, msg_text, _L("Infill"), + //wxMessageDialog dialog(nullptr, msg_text, _L("Infill"), + MessageDialog dialog(nullptr, msg_text, _L("Infill"), wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK) ); DynamicPrintConfig new_conf = *config; auto answer = dialog.ShowModal(); @@ -333,7 +341,8 @@ void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, con if (head_penetration > head_width) { wxString msg_text = _(L("Head penetration should not be greater than the head width.")); - wxMessageDialog dialog(nullptr, msg_text, _(L("Invalid Head penetration")), wxICON_WARNING | wxOK); + //wxMessageDialog dialog(nullptr, msg_text, _(L("Invalid Head penetration")), wxICON_WARNING | wxOK); + MessageDialog dialog(nullptr, msg_text, _(L("Invalid Head penetration")), wxICON_WARNING | wxOK); DynamicPrintConfig new_conf = *config; if (dialog.ShowModal() == wxID_OK) { new_conf.set_key_value("support_head_penetration", new ConfigOptionFloat(head_width)); @@ -346,7 +355,8 @@ void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, con if (pinhead_d > pillar_d) { wxString msg_text = _(L("Pinhead diameter should be smaller than the pillar diameter.")); - wxMessageDialog dialog(nullptr, msg_text, _(L("Invalid pinhead diameter")), wxICON_WARNING | wxOK); + //wxMessageDialog dialog(nullptr, msg_text, _(L("Invalid pinhead diameter")), wxICON_WARNING | wxOK); + MessageDialog dialog(nullptr, msg_text, _(L("Invalid pinhead diameter")), wxICON_WARNING | wxOK); DynamicPrintConfig new_conf = *config; if (dialog.ShowModal() == wxID_OK) { diff --git a/src/slic3r/GUI/ConfigSnapshotDialog.cpp b/src/slic3r/GUI/ConfigSnapshotDialog.cpp index 6a02e6753..7d2029e22 100644 --- a/src/slic3r/GUI/ConfigSnapshotDialog.cpp +++ b/src/slic3r/GUI/ConfigSnapshotDialog.cpp @@ -42,7 +42,7 @@ static wxString generate_html_row(const Config::Snapshot &snapshot, bool row_eve wxString text = ""; text += ""; @@ -104,8 +104,8 @@ static wxString generate_html_page(const Config::SnapshotDB &snapshot_db, const bool dark_mode = wxGetApp().dark_mode(); wxString text = "" - "" - ""; + "" + ""; text += ""; for (size_t i_row = 0; i_row < snapshot_db.snapshots().size(); ++ i_row) { const Config::Snapshot &snapshot = snapshot_db.snapshots()[snapshot_db.snapshots().size() - i_row - 1]; @@ -125,7 +125,11 @@ ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX) { this->SetFont(wxGetApp().normal_font()); +#ifdef _WIN32 + wxGetApp().UpdateDarkUI(this); +#else this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL); this->SetSizer(vsizer); @@ -152,6 +156,7 @@ ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db } wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCLOSE); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CLOSE, this))); this->SetEscapeId(wxID_CLOSE); this->Bind(wxEVT_BUTTON, &ConfigSnapshotDialog::onCloseDialog, this, wxID_CLOSE); vsizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3); diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index f7d16d843..bc66532a0 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ #include "slic3r/Config/Snapshot.hpp" #include "slic3r/Utils/PresetUpdater.hpp" #include "format.hpp" +#include "MsgDialog.hpp" #if defined(__linux__) && defined(__WXGTK3__) #define wxLinux_gtk3 true @@ -177,6 +179,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt , vendor_id(vendor.id) , width(0) { + wxGetApp().UpdateDarkUI(this); const auto &models = vendor.models; auto *sizer = new wxBoxSizer(wxVERTICAL); @@ -235,6 +238,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt bitmaps.push_back(bitmap_widget); auto *variants_panel = new wxPanel(this); + wxGetApp().UpdateDarkUI(variants_panel); auto *variants_sizer = new wxBoxSizer(wxVERTICAL); variants_panel->SetSizer(variants_sizer); const auto model_id = model.id; @@ -323,6 +327,10 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt title_sizer->Add(sel_all, 0, wxRIGHT, BTN_SPACING); title_sizer->Add(sel_none); + wxGetApp().UpdateDarkUI(sel_all_std); + wxGetApp().UpdateDarkUI(sel_all); + wxGetApp().UpdateDarkUI(sel_none); + // fill button indexes used later for buttons rescaling if (is_variants) m_button_indexes = { sel_all_std->GetId(), sel_all->GetId(), sel_none->GetId() }; @@ -412,6 +420,8 @@ ConfigWizardPage::ConfigWizardPage(ConfigWizard *parent, wxString title, wxStrin , shortname(std::move(shortname)) , indent(indent) { + wxGetApp().UpdateDarkUI(this); + auto *sizer = new wxBoxSizer(wxVERTICAL); auto *text = new wxStaticText(this, wxID_ANY, std::move(title), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); @@ -637,6 +647,11 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin btn_sizer->Add(sel_all, 0, wxRIGHT, em / 2); btn_sizer->Add(sel_none); + wxGetApp().UpdateDarkUI(list_printer); + wxGetApp().UpdateDarkUI(list_type); + wxGetApp().UpdateDarkUI(list_vendor); + wxGetApp().UpdateDarkUI(sel_all); + wxGetApp().UpdateDarkUI(sel_none); grid->Add(new wxBoxSizer(wxHORIZONTAL)); grid->Add(new wxBoxSizer(wxHORIZONTAL)); @@ -717,12 +732,16 @@ void PageMaterials::set_compatible_printers_html_window(const std::vectorGetParent()->GetBackgroundColour(); +#else +#if defined(_WIN32) + wxGetApp().get_window_default_clr(); #else wxSystemSettings::GetColour(wxSYS_COLOUR_MENU); +#endif #endif const auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); - const auto text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + const auto text_clr = wxGetApp().get_label_clr_default();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); const auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); wxString first_line = _L("Filaments marked with * are not compatible with some installed printers."); wxString text; @@ -1003,6 +1022,7 @@ void PageMaterials::update_lists(int sel_type, int sel_vendor, int last_selected sel_vendor_prev = sel_vendor; } + wxGetApp().UpdateDarkUI(list_profile); } void PageMaterials::sort_list_data(StringList* list, bool add_All_item, bool material_type_ordering) @@ -1150,6 +1170,8 @@ PageCustom::PageCustom(ConfigWizard *parent) tc_profile_name = new wxTextCtrl(this, wxID_ANY, default_profile_name); auto *label = new wxStaticText(this, wxID_ANY, _L("Custom profile name:")); + wxGetApp().UpdateDarkUI(tc_profile_name); + tc_profile_name->Enable(false); tc_profile_name->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent &evt) { if (tc_profile_name->GetValue().IsEmpty()) { @@ -1338,6 +1360,7 @@ PageFirmware::PageFirmware(ConfigWizard *parent) } gcode_picker = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices); + wxGetApp().UpdateDarkUI(gcode_picker); const auto &enum_values = gcode_opt.enum_values; auto needle = enum_values.cend(); if (gcode_opt.default_value) { @@ -1406,10 +1429,26 @@ static void focus_event(wxFocusEvent& e, wxTextCtrl* ctrl, double def_value) ctrl->SetValue(double_to_string(val)); } +class DiamTextCtrl : public wxTextCtrl +{ +public: + DiamTextCtrl(wxWindow* parent) + { +#ifdef _WIN32 + long style = wxBORDER_SIMPLE; +#else + long style = 0; +#endif + Create(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(Field::def_width_thinner() * wxGetApp().em_unit(), wxDefaultCoord), style); + wxGetApp().UpdateDarkUI(this); + } + ~DiamTextCtrl() {} +}; + PageDiameters::PageDiameters(ConfigWizard *parent) : ConfigWizardPage(parent, _L("Filament and Nozzle Diameters"), _L("Print Diameters"), 1) - , diam_nozzle(new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(Field::def_width_thinner() * wxGetApp().em_unit(), wxDefaultCoord))) - , diam_filam (new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(Field::def_width_thinner() * wxGetApp().em_unit(), wxDefaultCoord))) + , diam_nozzle(new DiamTextCtrl(this)) + , diam_filam (new DiamTextCtrl(this)) { auto *default_nozzle = print_config_def.get("nozzle_diameter")->get_default_value(); wxString value = double_to_string(default_nozzle != nullptr && default_nozzle->size() > 0 ? default_nozzle->get_at(0) : 0.5); @@ -1477,10 +1516,29 @@ void PageDiameters::apply_custom_config(DynamicPrintConfig &config) set_extrusion_width("solid_infill_extrusion_width", 0.45); } +class SpinCtrlDouble: public wxSpinCtrlDouble +{ +public: + SpinCtrlDouble(wxWindow* parent) + { +#ifdef _WIN32 + long style = wxSP_ARROW_KEYS | wxBORDER_SIMPLE; +#else + long style = wxSP_ARROW_KEYS; +#endif + Create(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, style); +#ifdef _WIN32 + wxGetApp().UpdateDarkUI(this->GetText()); +#endif + this->Refresh(); + } + ~SpinCtrlDouble() {} +}; + PageTemperatures::PageTemperatures(ConfigWizard *parent) : ConfigWizardPage(parent, _L("Nozzle and Bed Temperatures"), _L("Temperatures"), 1) - , spin_extr(new wxSpinCtrlDouble(this, wxID_ANY)) - , spin_bed(new wxSpinCtrlDouble(this, wxID_ANY)) + , spin_extr(new SpinCtrlDouble(this)) + , spin_bed (new SpinCtrlDouble(this)) { spin_extr->SetIncrement(5.0); const auto &def_extr = *print_config_def.get("temperature"); @@ -1703,6 +1761,7 @@ void ConfigWizardIndex::on_paint(wxPaintEvent & evt) x += + bullet_w + em_w/2; const auto text_size = dc.GetTextExtent(item.label); + dc.SetTextForeground(wxGetApp().get_label_clr_default()); dc.DrawText(item.label, x, y + yoff_text); y += yinc; @@ -2341,7 +2400,8 @@ bool ConfigWizard::priv::check_and_install_missing_materials(Technology technolo const auto ask_and_select_default_materials = [this](const wxString &message, const std::set &printer_models, Technology technology) { - wxMessageDialog msg(q, message, _L("Notice"), wxYES_NO); + //wxMessageDialog msg(q, message, _L("Notice"), wxYES_NO); + MessageDialog msg(q, message, _L("Notice"), wxYES_NO); if (msg.ShowModal() == wxID_YES) select_default_materials_for_printer_models(technology, printer_models); }; @@ -2628,6 +2688,12 @@ ConfigWizard::ConfigWizard(wxWindow *parent) p->btnsizer->Add(p->btn_finish, 0, wxLEFT, BTN_SPACING); p->btnsizer->Add(p->btn_cancel, 0, wxLEFT, BTN_SPACING); + wxGetApp().UpdateDarkUI(p->btn_sel_all); + wxGetApp().UpdateDarkUI(p->btn_prev); + wxGetApp().UpdateDarkUI(p->btn_next); + wxGetApp().UpdateDarkUI(p->btn_finish); + wxGetApp().UpdateDarkUI(p->btn_cancel); + const auto prusa_it = p->bundles.find("PrusaResearch"); wxCHECK_RET(prusa_it != p->bundles.cend(), "Vendor PrusaResearch not found"); const VendorProfile *vendor_prusa = prusa_it->second.vendor_profile; @@ -2798,5 +2864,11 @@ void ConfigWizard::on_dpi_changed(const wxRect &suggested_rect) Refresh(); } +void ConfigWizard::on_sys_color_changed() +{ + wxGetApp().UpdateDlgDarkUI(this); + Refresh(); +} + } } diff --git a/src/slic3r/GUI/ConfigWizard.hpp b/src/slic3r/GUI/ConfigWizard.hpp index 86245836b..88d2e2d7c 100644 --- a/src/slic3r/GUI/ConfigWizard.hpp +++ b/src/slic3r/GUI/ConfigWizard.hpp @@ -47,6 +47,7 @@ public: static const wxString& name(const bool from_menu = false); protected: void on_dpi_changed(const wxRect &suggested_rect) override ; + void on_sys_color_changed() override; private: struct priv; diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 481eee6d4..d610d9672 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -165,6 +165,8 @@ void Control::msw_rescale() void Control::sys_color_changed() { + GUI::wxGetApp().UpdateDarkUI(GetParent()); + m_bmp_add_tick_on .msw_rescale(); m_bmp_add_tick_off.msw_rescale(); m_bmp_del_tick_on .msw_rescale(); @@ -494,7 +496,7 @@ void Control::draw_focus_rect() void Control::render() { #ifdef _WIN32 - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + GUI::wxGetApp().UpdateDarkUI(this); #else SetBackgroundColour(GetParent()->GetBackgroundColour()); #endif // _WIN32 @@ -990,11 +992,7 @@ void Control::draw_colored_band(wxDC& dc) // don't color a band for MultiExtruder mode if (m_ticks.empty() || m_mode == MultiExtruder) { -#ifdef _WIN32 - draw_band(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW), main_band); -#else draw_band(dc, GetParent()->GetBackgroundColour(), main_band); -#endif // _WIN32 return; } @@ -1593,12 +1591,9 @@ void Control::append_change_extruder_menu_item(wxMenu* menu, bool switch_current (switch_current_code ? _L("Switch code to Change extruder") : _L("Change extruder") ) : _L("Change extruder (N/A)"); - wxMenuItem* change_extruder_menu_item = menu->AppendSubMenu(change_extruder_menu, change_extruder_menu_name, _L("Use another extruder")); - change_extruder_menu_item->SetBitmap(create_scaled_bitmap(active_extruders[1] > 0 ? "edit_uni" : "change_extruder")); - - GUI::wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this, change_extruder_menu_item](wxUpdateUIEvent& evt) { - enable_menu_item(evt, [this]() {return m_mode == MultiAsSingle; }, change_extruder_menu_item, this); }, - change_extruder_menu_item->GetId()); + append_submenu(menu, change_extruder_menu, wxID_ANY, change_extruder_menu_name, _L("Use another extruder"), + active_extruders[1] > 0 ? "edit_uni" : "change_extruder", + [this]() {return m_mode == MultiAsSingle; }, GUI::wxGetApp().plater()); } } @@ -1626,7 +1621,7 @@ void Control::append_add_color_change_menu_item(wxMenu* menu, bool switch_curren format_wxstr(_L("Switch code to Color change (%1%) for:"), gcode(ColorChange)) : format_wxstr(_L("Add color change (%1%) for:"), gcode(ColorChange)); wxMenuItem* add_color_change_menu_item = menu->AppendSubMenu(add_color_change_menu, menu_name, ""); - add_color_change_menu_item->SetBitmap(create_scaled_bitmap("colorchange_add_m")); + add_color_change_menu_item->SetBitmap(create_menu_bitmap("colorchange_add_m")); } } @@ -2143,6 +2138,8 @@ static std::string get_new_color(const std::string& color) * */ static void upgrade_text_entry_dialog(wxTextEntryDialog* dlg, double min = -1.0, double max = -1.0) { + GUI::wxGetApp().UpdateDlgDarkUI(dlg); + // detect TextCtrl and OK button wxTextCtrl* textctrl {nullptr}; wxWindowList& dlg_items = dlg->GetChildren(); @@ -2487,7 +2484,8 @@ bool Control::check_ticks_changed_event(Type type) _L("Your current changes will delete all saved color changes.") + "\n\n\t" + _L("Are you sure you want to continue?"); - wxMessageDialog msg(this, message, _L("Notice"), wxYES_NO); + //wxMessageDialog msg(this, message, _L("Notice"), wxYES_NO); + GUI::MessageDialog msg(this, message, _L("Notice"), wxYES_NO); if (msg.ShowModal() == wxID_YES) { m_ticks.erase_all_ticks_with_code(ColorChange); post_ticks_changed_event(ColorChange); @@ -2507,7 +2505,8 @@ bool Control::check_ticks_changed_event(Type type) _L("Your current changes will delete all saved extruder (tool) changes.") + "\n\n\t" + _L("Are you sure you want to continue?") ) ; - wxMessageDialog msg(this, message, _L("Notice"), wxYES_NO | (m_mode == SingleExtruder ? wxCANCEL : 0)); + //wxMessageDialog msg(this, message, _L("Notice"), wxYES_NO | (m_mode == SingleExtruder ? wxCANCEL : 0)); + GUI::MessageDialog msg(this, message, _L("Notice"), wxYES_NO | (m_mode == SingleExtruder ? wxCANCEL : 0)); const int answer = msg.ShowModal(); if (answer == wxID_YES) { m_ticks.erase_all_ticks_with_code(ToolChange); diff --git a/src/slic3r/GUI/ExtraRenderers.cpp b/src/slic3r/GUI/ExtraRenderers.cpp index 59188c037..9d6a19169 100644 --- a/src/slic3r/GUI/ExtraRenderers.cpp +++ b/src/slic3r/GUI/ExtraRenderers.cpp @@ -139,7 +139,12 @@ bool BitmapTextRenderer::Render(wxRect rect, wxDC *dc, int state) } else #endif // SUPPORTS_MARKUP && wxHAS_GENERIC_DATAVIEWCTRL +#ifdef _WIN32 + // workaround for Windows DarkMode : Don't respect to the state & wxDATAVIEW_CELL_SELECTED to avoid update of the text color + RenderText(m_value.GetText(), xoffset, rect, dc, state & wxDATAVIEW_CELL_SELECTED ? 0 :state); +#else RenderText(m_value.GetText(), xoffset, rect, dc, state); +#endif return true; } @@ -258,7 +263,12 @@ bool BitmapChoiceRenderer::Render(wxRect rect, wxDC* dc, int state) rect.height= icon.GetHeight(); } +#ifdef _WIN32 + // workaround for Windows DarkMode : Don't respect to the state & wxDATAVIEW_CELL_SELECTED to avoid update of the text color + RenderText(m_value.GetText(), xoffset, rect, dc, state & wxDATAVIEW_CELL_SELECTED ? 0 : state); +#else RenderText(m_value.GetText(), xoffset, rect, dc, state); +#endif return true; } diff --git a/src/slic3r/GUI/ExtruderSequenceDialog.cpp b/src/slic3r/GUI/ExtruderSequenceDialog.cpp index 4a0600e53..21c037c4e 100644 --- a/src/slic3r/GUI/ExtruderSequenceDialog.cpp +++ b/src/slic3r/GUI/ExtruderSequenceDialog.cpp @@ -16,6 +16,7 @@ #include "I18N.hpp" #include "OptionsGroup.hpp" #include "MainFrame.hpp" +#include "BitmapComboBox.hpp" namespace Slic3r { @@ -26,7 +27,11 @@ ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequ wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), m_sequence(sequence) { +#ifdef _WIN32 + wxGetApp().UpdateDarkUI(this); +#else SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif SetDoubleBuffered(true); SetFont(wxGetApp().normal_font()); @@ -39,13 +44,14 @@ ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequ auto option_sizer = new wxBoxSizer(wxVERTICAL); auto intervals_box = new wxStaticBox(this, wxID_ANY, _(L("Set extruder change for every"))+ ": "); + wxGetApp().UpdateDarkUI(intervals_box); auto intervals_box_sizer = new wxStaticBoxSizer(intervals_box, wxVERTICAL); m_intervals_grid_sizer = new wxFlexGridSizer(3, 5, em); auto editor_sz = wxSize(4*em, wxDefaultCoord); - auto ID_RADIO_BUTTON = wxWindow::NewControlId(1); + auto ID_RADIO_BUTTON = wxID_ANY;// wxWindow::NewControlId(1); wxRadioButton* rb_by_layers = new wxRadioButton(this, ID_RADIO_BUTTON, "", wxDefaultPosition, wxDefaultSize, wxRB_GROUP); rb_by_layers->Bind(wxEVT_RADIOBUTTON, [this](wxCommandEvent& event) { m_sequence.is_mm_intervals = false; }); @@ -54,7 +60,12 @@ ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequ wxStaticText* st_by_layers = new wxStaticText(this, wxID_ANY, _(L("layers"))); m_interval_by_layers = new wxTextCtrl(this, wxID_ANY, wxString::Format("%d", m_sequence.interval_by_layers), - wxDefaultPosition, editor_sz); + wxDefaultPosition, editor_sz +#ifdef _WIN32 + , wxBORDER_SIMPLE +#endif + ); + wxGetApp().UpdateDarkUI(m_interval_by_layers); m_interval_by_layers->Bind(wxEVT_TEXT, [this, rb_by_layers](wxEvent&) { wxString str = m_interval_by_layers->GetValue(); @@ -89,7 +100,12 @@ ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequ wxStaticText* st_by_mm = new wxStaticText(this, wxID_ANY, _(L("mm"))); m_interval_by_mm = new wxTextCtrl(this, wxID_ANY, double_to_string(sequence.interval_by_mm), - wxDefaultPosition, editor_sz, wxTE_PROCESS_ENTER); + wxDefaultPosition, editor_sz, wxTE_PROCESS_ENTER +#ifdef _WIN32 + | wxBORDER_SIMPLE +#endif + ); + wxGetApp().UpdateDarkUI(m_interval_by_mm); double min_layer_height = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_float("layer_height"); auto change_value = [this, min_layer_height]() @@ -159,6 +175,8 @@ ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequ m_color_repetition->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& e) {m_sequence.color_repetition = e.IsChecked(); }); auto extruders_box = new wxStaticBox(this, wxID_ANY, _(L("Set extruder(tool) sequence"))+ ": "); + wxGetApp().UpdateDarkUI(extruders_box); + auto extruders_box_sizer = new wxStaticBoxSizer(extruders_box, wxVERTICAL); m_extruders_grid_sizer = new wxFlexGridSizer(3, 5, em); @@ -173,6 +191,8 @@ ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequ main_sizer->Add(option_sizer, 0, wxEXPAND | wxALL, em); wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_OK, this))); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CANCEL, this))); main_sizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, em); SetSizer(main_sizer); @@ -195,7 +215,7 @@ void ExtruderSequenceDialog::apply_extruder_sequence() for (size_t extruder=0; extruder < m_sequence.extruders.size(); ++extruder) { - wxBitmapComboBox* extruder_selector = nullptr; + BitmapComboBox* extruder_selector = nullptr; apply_extruder_selector(&extruder_selector, this, "", wxDefaultPosition, wxSize(15*wxGetApp().em_unit(), -1)); extruder_selector->SetSelection(m_sequence.extruders[extruder]); diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 293daacbc..532e44e70 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -13,10 +13,12 @@ #include #include #include +#include #include #include #include "OG_CustomCtrl.hpp" #include "MsgDialog.hpp" +#include "BitmapComboBox.hpp" #ifdef __WXOSX__ #define wxOSX true @@ -411,6 +413,10 @@ void Field::msw_rescale() void Field::sys_color_changed() { +#ifdef _WIN32 + if (wxWindow* win = this->getWindow()) + wxGetApp().UpdateDarkUI(win); +#endif } template @@ -472,13 +478,17 @@ void TextCtrl::BUILD() { break; } - const long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER/*0*/; + long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER; +#ifdef _WIN32 + style |= wxBORDER_SIMPLE; +#endif auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, style); if (parent_is_custom_ctrl && m_opt.height < 0) opt_height = (double)temp->GetSize().GetHeight()/m_em_unit; temp->SetFont(m_opt.is_code ? Slic3r::GUI::wxGetApp().code_font(): Slic3r::GUI::wxGetApp().normal_font()); + wxGetApp().UpdateDarkUI(temp); if (! m_opt.multiline && !wxOSX) // Only disable background refresh for single line input fields, as they are completely painted over by the edit control. @@ -796,7 +806,12 @@ void SpinCtrl::BUILD() { const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647; auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, - 0|wxTE_PROCESS_ENTER, min_val, max_val, default_value); + wxTE_PROCESS_ENTER | wxSP_ARROW_KEYS +#ifdef _WIN32 + | wxBORDER_SIMPLE +#endif + , min_val, max_val, default_value); + #ifdef __WXGTK3__ wxSize best_sz = temp->GetBestSize(); if (best_sz.x > size.x) @@ -804,6 +819,7 @@ void SpinCtrl::BUILD() { #endif //__WXGTK3__ temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT); + wxGetApp().UpdateDarkUI(temp); if (m_opt.height < 0 && parent_is_custom_ctrl) opt_height = (double)temp->GetSize().GetHeight() / m_em_unit; @@ -904,7 +920,11 @@ void SpinCtrl::msw_rescale() static_assert(wxMAJOR_VERSION >= 3, "Use of wxBitmapComboBox on Settings Tabs requires wxWidgets 3.0 and newer"); using choice_ctrl = wxBitmapComboBox; #else +#ifdef _WIN32 +using choice_ctrl = BitmapComboBox; +#else using choice_ctrl = wxComboBox; +#endif #endif // __WXOSX__ void Choice::BUILD() { @@ -1299,6 +1319,8 @@ void ColourPicker::BUILD() temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT); + wxGetApp().UpdateDarkUI(temp->GetPickerCtrl()); + // // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); @@ -1372,6 +1394,15 @@ void ColourPicker::msw_rescale() set_undef_value(field); } +void ColourPicker::sys_color_changed() +{ +#ifdef _WIN32 + if (wxWindow* win = this->getWindow()) + if (wxColourPickerCtrl* picker = dynamic_cast(win)) + wxGetApp().UpdateDarkUI(picker->GetPickerCtrl(), true); +#endif +} + void PointCtrl::BUILD() { auto temp = new wxBoxSizer(wxHORIZONTAL); @@ -1384,8 +1415,12 @@ void PointCtrl::BUILD() val = default_pt(1); wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None); - x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size, wxTE_PROCESS_ENTER); - y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size, wxTE_PROCESS_ENTER); + long style = wxTE_PROCESS_ENTER; +#ifdef _WIN32 + style |= wxBORDER_SIMPLE; +#endif + x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size, style); + y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size, style); if (parent_is_custom_ctrl && m_opt.height < 0) opt_height = (double)x_textctrl->GetSize().GetHeight() / m_em_unit; @@ -1401,6 +1436,11 @@ void PointCtrl::BUILD() static_text_y->SetFont(Slic3r::GUI::wxGetApp().normal_font()); static_text_y->SetBackgroundStyle(wxBG_STYLE_PAINT); + wxGetApp().UpdateDarkUI(x_textctrl); + wxGetApp().UpdateDarkUI(y_textctrl); + wxGetApp().UpdateDarkUI(static_text_x, false, true); + wxGetApp().UpdateDarkUI(static_text_y, false, true); + temp->Add(static_text_x, 0, wxALIGN_CENTER_VERTICAL, 0); temp->Add(x_textctrl); temp->Add(static_text_y, 0, wxALIGN_CENTER_VERTICAL, 0); @@ -1436,6 +1476,15 @@ void PointCtrl::msw_rescale() } } +void PointCtrl::sys_color_changed() +{ +#ifdef _WIN32 + for (wxSizerItem* item: sizer->GetChildren()) + if (item->IsWindow()) + wxGetApp().UpdateDarkUI(item->GetWindow()); +#endif +} + bool PointCtrl::value_was_changed(wxTextCtrl* win) { if (m_value.empty()) @@ -1519,6 +1568,8 @@ void StaticText::BUILD() temp->SetBackgroundStyle(wxBG_STYLE_PAINT); temp->SetFont(wxGetApp().bold_font()); + wxGetApp().UpdateDarkUI(temp); + // // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 1b3503241..0693091ad 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -177,7 +177,7 @@ public: } virtual void msw_rescale(); - void sys_color_changed(); + virtual void sys_color_changed(); bool get_enter_pressed() const { return bEnterPressed; } void set_enter_pressed(bool pressed) { bEnterPressed = pressed; } @@ -394,6 +394,7 @@ public: void set_value(const boost::any& value, bool change_event = false) override; boost::any& get_value() override; void msw_rescale() override; + void sys_color_changed() override; void enable() override { dynamic_cast(window)->Enable(); } void disable() override{ dynamic_cast(window)->Disable(); } @@ -420,6 +421,7 @@ public: boost::any& get_value() override; void msw_rescale() override; + void sys_color_changed() override; void enable() override { x_textctrl->Enable(); diff --git a/src/slic3r/GUI/FirmwareDialog.cpp b/src/slic3r/GUI/FirmwareDialog.cpp index 15f055132..c46dc49bc 100644 --- a/src/slic3r/GUI/FirmwareDialog.cpp +++ b/src/slic3r/GUI/FirmwareDialog.cpp @@ -747,7 +747,8 @@ void FirmwareDialog::priv::on_avrdude(const wxCommandEvent &evt) void FirmwareDialog::priv::on_async_dialog(const wxCommandEvent &evt) { - wxMessageDialog dlg(this->q, evt.GetString(), wxMessageBoxCaptionStr, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); + //wxMessageDialog dlg(this->q, evt.GetString(), wxMessageBoxCaptionStr, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); + GUI::MessageDialog dlg(this->q, evt.GetString(), wxMessageBoxCaptionStr, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); { std::lock_guard lock(mutex); modal_response = dlg.ShowModal(); @@ -863,6 +864,8 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) : bsizer->Add(p->btn_flash); vsizer->Add(bsizer, 0, wxEXPAND); + GUI::wxGetApp().UpdateDlgDarkUI(this); + auto *topsizer = new wxBoxSizer(wxVERTICAL); topsizer->Add(panel, 1, wxEXPAND | wxALL, DIALOG_MARGIN); SetMinSize(wxSize(p->min_width, p->min_height)); @@ -903,7 +906,8 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) : p->btn_flash->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { if (this->p->avrdude) { // Flashing is in progress, ask the user if they're really sure about canceling it - wxMessageDialog dlg(this, + //wxMessageDialog dlg(this, + GUI::MessageDialog dlg(this, _(L("Are you sure you want to cancel firmware flashing?\nThis could leave your printer in an unusable state!")), _(L("Confirmation")), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index c6cb05fac..2831092da 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -225,7 +225,8 @@ void show_error_id(int id, const std::string& message) void show_info(wxWindow* parent, const wxString& message, const wxString& title) { - wxMessageDialog msg_wingow(parent, message, wxString(SLIC3R_APP_NAME " - ") + (title.empty() ? _L("Notice") : title), wxOK | wxICON_INFORMATION); + //wxMessageDialog msg_wingow(parent, message, wxString(SLIC3R_APP_NAME " - ") + (title.empty() ? _L("Notice") : title), wxOK | wxICON_INFORMATION); + MessageDialog msg_wingow(parent, message, wxString(SLIC3R_APP_NAME " - ") + (title.empty() ? _L("Notice") : title), wxOK | wxICON_INFORMATION); msg_wingow.ShowModal(); } @@ -237,7 +238,8 @@ void show_info(wxWindow* parent, const char* message, const char* title) void warning_catcher(wxWindow* parent, const wxString& message) { - wxMessageDialog msg(parent, message, _L("Warning"), wxOK | wxICON_WARNING); + //wxMessageDialog msg(parent, message, _L("Warning"), wxOK | wxICON_WARNING); + MessageDialog msg(parent, message, _L("Warning"), wxOK | wxICON_WARNING); msg.ShowModal(); } @@ -245,6 +247,7 @@ void create_combochecklist(wxComboCtrl* comboCtrl, const std::string& text, cons { if (comboCtrl == nullptr) return; + wxGetApp().UpdateDarkUI(comboCtrl); wxCheckListBoxComboPopup* popup = new wxCheckListBoxComboPopup; if (popup != nullptr) { @@ -279,6 +282,7 @@ void create_combochecklist(wxComboCtrl* comboCtrl, const std::string& text, cons } comboCtrl->SetMinClientSize(wxSize(max_width, -1)); + wxGetApp().UpdateDarkUI(popup); } } diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 052a782a7..1dd9423f8 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -76,7 +76,10 @@ #ifdef __WXMSW__ #include #include -#endif // __WXMSW__ +#ifdef _MSW_DARK_MODE +#include +#endif // _MSW_DARK_MODE +#endif #if ENABLE_THUMBNAIL_GENERATOR_DEBUG #include @@ -816,6 +819,10 @@ bool GUI_App::on_init_inner() wxInitAllImageHandlers(); +#ifdef _MSW_DARK_MODE + if (app_config->get("dark_color_mode") == "1") + NppDarkMode::InitDarkMode(); +#endif SplashScreen* scrn = nullptr; if (app_config->get("show_splash_screen") == "1") { // make a bitmap with dark grey banner on the left side @@ -1015,14 +1022,16 @@ bool GUI_App::dark_mode() // proper dark mode was first introduced. return wxPlatformInfo::Get().CheckOSVersion(10, 14) && mac_dark_mode(); #else - const unsigned luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - return luma < 128; + return wxGetApp().app_config->get("dark_color_mode") == "1" ? true : check_dark_mode(); + //const unsigned luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + //return luma < 128; #endif } void GUI_App::init_label_colours() { - if (dark_mode()) { + bool is_dark_mode = dark_mode(); + if (is_dark_mode) { m_color_label_modified = wxColour(253, 111, 40); m_color_label_sys = wxColour(115, 220, 103); } @@ -1030,7 +1039,15 @@ void GUI_App::init_label_colours() m_color_label_modified = wxColour(252, 77, 1); m_color_label_sys = wxColour(26, 132, 57); } +#ifdef _WIN32 + m_color_label_default = is_dark_mode ? wxColour(250, 250, 250): wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + m_color_highlight_label_default = is_dark_mode ? wxColour(230, 230, 230): wxSystemSettings::GetColour(/*wxSYS_COLOUR_HIGHLIGHTTEXT*/wxSYS_COLOUR_WINDOWTEXT); + m_color_highlight_default = is_dark_mode ? wxColour(78, 78, 78) : wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT); + m_color_hovered_btn_label = is_dark_mode ? wxColour(253, 111, 40) : wxColour(252, 77, 1); +#else m_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); +#endif + m_color_window_default = is_dark_mode ? wxColour(43, 43, 43) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); } void GUI_App::update_label_colours_from_appconfig() @@ -1054,6 +1071,103 @@ void GUI_App::update_label_colours() tab->update_label_colours(); } +void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool just_font/* = false*/) +{ +#ifdef _WIN32 + if (wxButton* btn = dynamic_cast(window)) { + if (!(btn->GetWindowStyle() & wxNO_BORDER)) { + btn->SetWindowStyle(btn->GetWindowStyle() | wxNO_BORDER); + highlited = true; + } + // hovering for buttons + { + auto focus_button = [this, btn](const bool focus) { + btn->SetForegroundColour(focus ? m_color_hovered_btn_label : m_color_label_default); + btn->Refresh(); + btn->Update(); + }; + + btn->Bind(wxEVT_ENTER_WINDOW, [focus_button](wxMouseEvent& event) { focus_button(true); event.Skip(); }); + btn->Bind(wxEVT_LEAVE_WINDOW, [focus_button](wxMouseEvent& event) { focus_button(false); event.Skip(); }); + } + } + else if (dark_mode()) { + if (wxTextCtrl* text = dynamic_cast(window)) { + if (text->GetBorder() != wxBORDER_SIMPLE) + text->SetWindowStyle(text->GetWindowStyle() | wxBORDER_SIMPLE); + } + else if (wxCheckListBox* list = dynamic_cast(window)) { + list->SetWindowStyle(list->GetWindowStyle() | wxBORDER_SIMPLE); + list->SetBackgroundColour(highlited ? m_color_highlight_default : m_color_window_default); + for (size_t i = 0; i < list->GetCount(); i++) + if (wxOwnerDrawn* item = list->GetItem(i)) { + item->SetBackgroundColour(highlited ? m_color_highlight_default : m_color_window_default); + item->SetTextColour(m_color_label_default); + } + return; + } + else if (dynamic_cast(window)) + window->SetWindowStyle(window->GetWindowStyle() | wxBORDER_SIMPLE); + } + + if (!just_font) + window->SetBackgroundColour(highlited ? m_color_highlight_default : m_color_window_default); + window->SetForegroundColour(m_color_label_default); +#endif +} + +// recursive function for scaling fonts for all controls in Window +#ifdef _WIN32 +static void update_dark_children_ui(wxWindow* window) +{ + bool highlight_btn = dynamic_cast(window) != nullptr; + wxGetApp().UpdateDarkUI(window, highlight_btn); + + auto children = window->GetChildren(); + for (auto child : children) { + update_dark_children_ui(child); + } +} +#endif + +void GUI_App::UpdateDlgDarkUI(wxDialog* dlg) +{ +#ifdef _WIN32 + update_dark_children_ui(dlg); +#endif +} +void GUI_App::UpdateDVCDarkUI(wxDataViewCtrl* dvc, bool highlited/* = false*/) +{ +#ifdef _WIN32 + if (!dark_mode()) + return; + UpdateDarkUI(dvc, highlited); + wxItemAttr attr(dark_mode() ? m_color_highlight_default : m_color_label_default, + m_color_window_default, + m_normal_font); + dvc->SetHeaderAttr(attr); + if (dvc->HasFlag(wxDV_ROW_LINES)) + dvc->SetAlternateRowColour(m_color_highlight_default); + if (dvc->GetBorder() != wxBORDER_SIMPLE) + dvc->SetWindowStyle(dvc->GetWindowStyle() | wxBORDER_SIMPLE); +#endif +} + +void GUI_App::UpdateAllStaticTextDarkUI(wxWindow* parent) +{ +#ifdef _WIN32 + if (!dark_mode()) + return; + wxGetApp().UpdateDarkUI(parent); + + auto children = parent->GetChildren(); + for (auto child : children) { + if (dynamic_cast(child)) + child->SetForegroundColour(m_color_label_default); + } +#endif +} + void GUI_App::init_fonts() { m_small_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); @@ -1169,7 +1283,8 @@ void GUI_App::check_printer_presets() _L("By default new Printer devices will be named as \"Printer N\" during its creation.\n" "Note: This name can be changed later from the physical printers settings"); - wxMessageDialog(nullptr, msg_text, _L("Information"), wxOK | wxICON_INFORMATION).ShowModal(); + //wxMessageDialog(nullptr, msg_text, _L("Information"), wxOK | wxICON_INFORMATION).ShowModal(); + MessageDialog(nullptr, msg_text, _L("Information"), wxOK | wxICON_INFORMATION).ShowModal(); preset_bundle->physical_printers.load_printers_from_presets(preset_bundle->printers); } @@ -1258,6 +1373,16 @@ void GUI_App::update_ui_from_settings() { update_label_colours(); mainframe->update_ui_from_settings(); + +#if 0 //#ifdef _WIN32 // #ysDarkMSW - Use to force dark colors for SystemLightMode + if (m_force_sys_colors_update) { + m_force_sys_colors_update = false; + mainframe->force_sys_color_changed(); + mainframe->diff_dialog.force_sys_color_changed(); + if (m_wizard) + m_wizard->force_sys_color_changed(); + } +#endif } void GUI_App::persist_window_geometry(wxTopLevelWindow *window, bool default_maximized) @@ -1395,6 +1520,22 @@ static const wxLanguageInfo* linux_get_existing_locale_language(const wxLanguage } #endif +static int GetSingleChoiceIndex(const wxString& message, + const wxString& caption, + const wxArrayString& choices, + int initialSelection) +{ +#ifdef _WIN32 + wxSingleChoiceDialog dialog(nullptr, message, caption, choices); + wxGetApp().UpdateDlgDarkUI(&dialog); + + dialog.SetSelection(initialSelection); + return dialog.ShowModal() == wxID_OK ? dialog.GetSelection() : -1; +#else + return wxGetSingleChoiceIndex(message, caption, choices, initialSelection); +#endif +} + // select language from the list of installed languages bool GUI_App::select_language() { @@ -1438,7 +1579,7 @@ bool GUI_App::select_language() // This is the language to highlight in the choice dialog initially. init_selection_default = init_selection; - const long index = wxGetSingleChoiceIndex(_L("Select the language"), _L("Language"), names, init_selection_default); + const long index = GetSingleChoiceIndex(_L("Select the language"), _L("Language"), names, init_selection_default); // Try to load a new language. if (index != -1 && (init_selection == -1 || init_selection != index)) { const wxLanguageInfo *new_language_info = language_infos[index]; @@ -1700,6 +1841,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) if (check_unsaved_changes()) { #endif // ENABLE_PROJECT_DIRTY_STATE wxTextEntryDialog dlg(nullptr, _L("Taking configuration snapshot"), _L("Snapshot name")); + UpdateDlgDarkUI(&dlg); // set current normal font for dialog children, // because of just dlg.SetFont(normal_font()) has no result; @@ -1753,6 +1895,17 @@ void GUI_App::add_config_menu(wxMenuBar *menu) if (dlg.seq_top_layer_only_changed()) #endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER this->plater_->refresh_print(); + + if (dlg.recreate_GUI()) { +#ifdef _MSW_DARK_MODE + if (dlg.color_mode_changed()) { + NppDarkMode::SetDarkMode(app_config->get("dark_color_mode") == "1"); + init_label_colours(); + } +#endif + recreate_GUI(_L("Restart application") + dots); + return; + } #ifdef _WIN32 if (is_editor()) { if (app_config->get("associate_3mf") == "1") @@ -1785,7 +1938,8 @@ void GUI_App::add_config_menu(wxMenuBar *menu) // so we put it into an inner scope wxString title = is_editor() ? wxString(SLIC3R_APP_NAME) : wxString(GCODEVIEWER_APP_NAME); title += " - " + _L("Language selection"); - wxMessageDialog dialog(nullptr, + //wxMessageDialog dialog(nullptr, + MessageDialog dialog(nullptr, _L("Switching the language will trigger application restart.\n" "You will lose content of the plater.") + "\n\n" + _L("Do you want to proceed?"), @@ -1918,7 +2072,8 @@ bool GUI_App::check_print_host_queue() } wxString message; message += _(L("The uploads are still ongoing")) + ":\n\n" + job_string +"\n" + _(L("Stop them and continue anyway?")); - wxMessageDialog dialog(mainframe, + //wxMessageDialog dialog(mainframe, + MessageDialog dialog(mainframe, message, wxString(SLIC3R_APP_NAME) + " - " + _(L("Ongoing uploads")), wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT); @@ -2058,8 +2213,7 @@ Model& GUI_App::model() { return plater_->model(); } - -wxNotebook* GUI_App::tab_panel() const +wxBookCtrlBase* GUI_App::tab_panel() const { return mainframe->m_tabpanel; } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 5027dc1ff..e326b0772 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -20,7 +20,8 @@ class wxMenuItem; class wxMenuBar; class wxTopLevelWindow; -class wxNotebook; +class wxDataViewCtrl; +class wxBookCtrlBase; struct wxLanguageInfo; namespace Slic3r { @@ -118,6 +119,13 @@ private: wxColour m_color_label_modified; wxColour m_color_label_sys; wxColour m_color_label_default; + wxColour m_color_window_default; +#ifdef _WIN32 + wxColour m_color_highlight_label_default; + wxColour m_color_hovered_btn_label; + wxColour m_color_highlight_default; + //bool m_force_sys_colors_update { false }; // #ysDarkMSW - Use to force dark colors for SystemLightMode +#endif wxFont m_small_font; wxFont m_bold_font; @@ -170,6 +178,14 @@ public: void init_label_colours(); void update_label_colours_from_appconfig(); void update_label_colours(); + // update color mode for window + void UpdateDarkUI(wxWindow *window, bool highlited = false, bool just_font = false); + // update color mode for whole dialog including all children + void UpdateDlgDarkUI(wxDialog* dlg); + // update color mode for DataViewControl + void UpdateDVCDarkUI(wxDataViewCtrl* dvc, bool highlited = false); + // update color mode for panel including all static texts controls + void UpdateAllStaticTextDarkUI(wxWindow* parent); void init_fonts(); void update_fonts(const MainFrame *main_frame = nullptr); void set_label_clr_modified(const wxColour& clr); @@ -178,6 +194,14 @@ public: const wxColour& get_label_clr_modified(){ return m_color_label_modified; } const wxColour& get_label_clr_sys() { return m_color_label_sys; } const wxColour& get_label_clr_default() { return m_color_label_default; } + const wxColour& get_window_default_clr(){ return m_color_window_default; } + + +#ifdef _WIN32 + const wxColour& get_label_highlight_clr() { return m_color_highlight_label_default; } + const wxColour& get_highlight_default_clr() { return m_color_highlight_default; } +// void force_sys_colors_update() { m_force_sys_colors_update = true; } // #ysDarkMSW - Use to force dark colors for SystemLightMode +#endif const wxFont& small_font() { return m_small_font; } const wxFont& bold_font() { return m_bold_font; } @@ -256,7 +280,7 @@ public: PresetUpdater* get_preset_updater() { return preset_updater; } - wxNotebook* tab_panel() const ; + wxBookCtrlBase* tab_panel() const ; int extruders_cnt() const; int extruders_edited_cnt() const; diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index b434d6767..aeb2ab7e0 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -138,11 +138,11 @@ std::map SettingsFactory::CATEGORY_ICON = { L("Hollowing") , "hollowing" } }; -wxBitmap SettingsFactory::get_category_bitmap(const std::string& category_name) +wxBitmap SettingsFactory::get_category_bitmap(const std::string& category_name, bool menu_bmp /*= true*/) { if (CATEGORY_ICON.find(category_name) == CATEGORY_ICON.end()) return wxNullBitmap; - return create_scaled_bitmap(CATEGORY_ICON.at(category_name)); + return menu_bmp ? create_menu_bitmap(CATEGORY_ICON.at(category_name)) : create_scaled_bitmap(CATEGORY_ICON.at(category_name)); } @@ -206,6 +206,34 @@ static void get_full_settings_hierarchy(FullSettingsHierarchy& settings_menu, co } } +static int GetSelectedChoices( wxArrayInt& selections, + const wxString& message, + const wxString& caption, + const wxArrayString& choices) +{ +#ifdef _WIN32 + wxMultiChoiceDialog dialog(nullptr, message, caption, choices); + wxGetApp().UpdateDlgDarkUI(&dialog); + + // call this even if selections array is empty and this then (correctly) + // deselects the first item which is selected by default + dialog.SetSelections(selections); + + if (dialog.ShowModal() != wxID_OK) + { + // NB: intentionally do not clear the selections array here, the caller + // might want to preserve its original contents if the dialog was + // cancelled + return -1; + } + + selections = dialog.GetSelections(); + return static_cast(selections.GetCount()); +#else + return wxGetSelectedChoices(selections, message, caption, choices); +#endif +} + static wxMenu* create_settings_popupmenu(wxMenu* parent_menu, const bool is_object_settings, wxDataViewItem item/*, ModelConfig& config*/) { wxMenu* menu = new wxMenu; @@ -236,7 +264,7 @@ static wxMenu* create_settings_popupmenu(wxMenu* parent_menu, const bool is_obje } if (!category_options.empty() && - wxGetSelectedChoices(selections, _L("Select showing settings"), category_name, names) != -1) { + GetSelectedChoices(selections, _L("Select showing settings"), category_name, names) != -1) { for (auto sel : selections) category_options[sel].second = true; } @@ -374,7 +402,7 @@ std::vector MenuFactory::get_volume_bitmaps() std::vector volume_bmps; volume_bmps.reserve(ADD_VOLUME_MENU_ITEMS.size()); for (auto item : ADD_VOLUME_MENU_ITEMS) - volume_bmps.push_back(create_scaled_bitmap(item.second)); + volume_bmps.push_back(create_menu_bitmap(item.second)); return volume_bmps; } @@ -542,7 +570,7 @@ wxMenuItem* MenuFactory::append_menu_item_settings(wxMenu* menu_) // Add full settings list auto menu_item = new wxMenuItem(menu, wxID_ANY, menu_name); - menu_item->SetBitmap(create_scaled_bitmap("cog")); + menu_item->SetBitmap(create_menu_bitmap("cog")); menu_item->SetSubMenu(create_settings_popupmenu(menu, is_object_settings, item)); return menu->Append(menu_item); @@ -702,7 +730,10 @@ void MenuFactory::append_menu_item_change_extruder(wxMenu* menu) } - menu->AppendSubMenu(extruder_selection_menu, name); + append_submenu(menu, extruder_selection_menu, wxID_ANY, name, _L("Use another extruder"), + "edit_uni"/* : "change_extruder"*/, []() {return true; }, GUI::wxGetApp().plater()); + +// menu->AppendSubMenu(extruder_selection_menu, name); } void MenuFactory::append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu) @@ -1046,5 +1077,43 @@ void MenuFactory::msw_rescale() msw_rescale_menu(dynamic_cast(menu)); } +#ifdef _WIN32 +// For this class is used code from stackoverflow: +// https://stackoverflow.com/questions/257288/is-it-possible-to-write-a-template-to-check-for-a-functions-existence +// Using this code we can to inspect of an existence of IsWheelInverted() function in class T +template +class menu_has_update_def_colors +{ + typedef char one; + struct two { char x[2]; }; + + template static one test(decltype(&C::UpdateDefColors)); + template static two test(...); + +public: + static constexpr bool value = sizeof(test(0)) == sizeof(char); +}; + +template +static void update_menu_item_def_colors(T* item) +{ + if constexpr (menu_has_update_def_colors::value) { + item->UpdateDefColors(); + } +} +#endif + +void MenuFactory::sys_color_changed() +{ + for (MenuWithSeparators* menu : { &m_object_menu, &m_sla_object_menu, &m_part_menu, &m_default_menu }) { + msw_rescale_menu(dynamic_cast(menu));// msw_rescale_menu updates just icons, so use it +#ifdef _WIN32 + // but under MSW we have to update item's bachground color + for (wxMenuItem* item : menu->GetMenuItems()) + update_menu_item_def_colors(item); +#endif + } +} + } //namespace GUI } //namespace Slic3r diff --git a/src/slic3r/GUI/GUI_Factories.hpp b/src/slic3r/GUI/GUI_Factories.hpp index 7da554de3..2c3e03521 100644 --- a/src/slic3r/GUI/GUI_Factories.hpp +++ b/src/slic3r/GUI/GUI_Factories.hpp @@ -25,7 +25,7 @@ struct SettingsFactory typedef std::map> Bundle; static std::map CATEGORY_ICON; - static wxBitmap get_category_bitmap(const std::string& category_name); + static wxBitmap get_category_bitmap(const std::string& category_name, bool menu_bmp = true); static Bundle get_bundle(const DynamicPrintConfig* config, bool is_object_settings); static std::vector get_options(bool is_part); }; @@ -42,6 +42,7 @@ public: void init(wxWindow* parent); void update_object_menu(); void msw_rescale(); + void sys_color_changed(); wxMenu* default_menu(); wxMenu* object_menu(); diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 7c13c20d6..c243d88ca 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -27,7 +27,7 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : // Legend for object layers for (const std::string col : { L("Start at height"), L("Stop at height"), L("Layer height") }) { - auto temp = new wxStaticText(m_parent, wxID_ANY, _(col), wxDefaultPosition, /*size*/wxDefaultSize, wxST_ELLIPSIZE_MIDDLE); + auto temp = new wxStaticText(m_parent, wxID_ANY, _(col), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_MIDDLE); temp->SetBackgroundStyle(wxBG_STYLE_PAINT); temp->SetFont(wxGetApp().bold_font()); @@ -276,15 +276,12 @@ void ObjectLayers::sys_color_changed() m_bmp_delete.msw_rescale(); m_bmp_add.msw_rescale(); - m_grid_sizer->SetHGap(wxGetApp().em_unit()); - // rescale edit-boxes const int cells_cnt = m_grid_sizer->GetCols() * m_grid_sizer->GetEffectiveRowsCount(); for (int i = 0; i < cells_cnt; ++i) { const wxSizerItem* item = m_grid_sizer->GetItem(i); if (item->IsSizer()) {// case when we have editor with buttons - const std::vector btns = {2, 3}; // del_btn, add_btn - for (auto btn : btns) { + for (size_t btn : {2, 3}) { // del_btn, add_btn wxSizerItem* b_item = item->GetSizer()->GetItem(btn); if (b_item->IsWindow()) { auto button = dynamic_cast(b_item->GetWindow()); @@ -294,7 +291,24 @@ void ObjectLayers::sys_color_changed() } } } - m_grid_sizer->Layout(); + +#ifdef _WIN32 + m_og->sys_color_changed(); + for (int i = 0; i < cells_cnt; ++i) { + const wxSizerItem* item = m_grid_sizer->GetItem(i); + if (item->IsWindow()) { + if (LayerRangeEditor* editor = dynamic_cast(item->GetWindow())) + wxGetApp().UpdateDarkUI(editor); + } + else if (item->IsSizer()) {// case when we have editor with buttons + if (wxSizerItem* e_item = item->GetSizer()->GetItem(size_t(0)); e_item->IsWindow()) { + if (LayerRangeEditor* editor = dynamic_cast(e_item->GetWindow())) + wxGetApp().UpdateDarkUI(editor); + } + } + } +#endif + } void ObjectLayers::reset_selection() @@ -313,9 +327,14 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent, m_type(type), m_set_focus_data(set_focus_data_fn), wxTextCtrl(parent->m_parent, wxID_ANY, value, wxDefaultPosition, - wxSize(8 * em_unit(parent->m_parent), wxDefaultCoord), wxTE_PROCESS_ENTER) + wxSize(8 * em_unit(parent->m_parent), wxDefaultCoord), wxTE_PROCESS_ENTER +#ifdef _WIN32 + | wxBORDER_SIMPLE +#endif + ) { this->SetFont(wxGetApp().normal_font()); + wxGetApp().UpdateDarkUI(this); // Reset m_enter_pressed flag to _false_, when value is editing this->Bind(wxEVT_TEXT, [this](wxEvent&) { m_enter_pressed = false; }, this->GetId()); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index bd0e4923b..443ef7815 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -7,6 +7,7 @@ #include "GUI_App.hpp" #include "I18N.hpp" #include "Plater.hpp" +#include "BitmapComboBox.hpp" #if ENABLE_PROJECT_DIRTY_STATE #include "MainFrame.hpp" #endif // ENABLE_PROJECT_DIRTY_STATE @@ -21,6 +22,7 @@ #include #include +#include #include #include "slic3r/Utils/FixModelByWin10.hpp" @@ -65,8 +67,14 @@ static void take_snapshot(const wxString& snapshot_name) } ObjectList::ObjectList(wxWindow* parent) : - wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE) + wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, +#ifdef _WIN32 + wxBORDER_SIMPLE | +#endif + wxDV_MULTIPLE) { + wxGetApp().UpdateDVCDarkUI(this, true); + // create control create_objects_ctrl(); @@ -3789,10 +3797,9 @@ void ObjectList::msw_rescale() void ObjectList::sys_color_changed() { - // update existing items with bitmaps - m_objects_model->Rescale(); + wxGetApp().UpdateDVCDarkUI(this, true); - Layout(); + msw_rescale(); } void ObjectList::ItemValueChanged(wxDataViewEvent &event) diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 43d61d5c7..36b399e51 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -39,6 +39,7 @@ typedef std::map t_layer_config_ranges; namespace GUI { wxDECLARE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent); +class BitmapComboBox; struct ItemForDelete { @@ -144,7 +145,7 @@ private: ModelConfig *m_config {nullptr}; std::vector *m_objects{ nullptr }; - wxBitmapComboBox *m_extruder_editor { nullptr }; + BitmapComboBox *m_extruder_editor { nullptr }; std::vector m_bmp_vector; diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 701a6daa9..f12adc9d1 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -1,6 +1,7 @@ #include "GUI_ObjectManipulation.hpp" #include "GUI_ObjectList.hpp" #include "I18N.hpp" +#include "BitmapComboBox.hpp" #include "GLCanvas3D.hpp" #include "OptionsGroup.hpp" @@ -12,6 +13,7 @@ #include "Selection.hpp" #include "Plater.hpp" #include "MainFrame.hpp" +#include "MsgDialog.hpp" #include #include "slic3r/Utils/FixModelByWin10.hpp" @@ -64,7 +66,7 @@ static choice_ctrl* create_word_local_combo(wxWindow *parent) temp->SetTextCtrlStyle(wxTE_READONLY); temp->Create(parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr); #else - temp = new choice_ctrl(parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxCB_READONLY); + temp = new choice_ctrl(parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxCB_READONLY | wxBORDER_SIMPLE); #endif //__WXOSX__ temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -198,7 +200,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : auto add_label = [this, height](wxStaticText** label, const std::string& name, wxSizer* reciver = nullptr) { *label = new wxStaticText(m_parent, wxID_ANY, _(name) + ":"); - set_font_and_background_style(m_move_Label, wxGetApp().normal_font()); + set_font_and_background_style(*label, wxGetApp().normal_font()); wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); sizer->SetMinSize(wxSize(-1, height)); @@ -513,7 +515,14 @@ void ObjectManipulation::update_ui_from_settings() int axis_id = 0; for (ManipulationEditor* editor : m_editors) { // editor->SetForegroundColour(m_use_colors ? wxColour(axes_color_text[axis_id]) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); +#ifdef _WIN32 + if (m_use_colors) + editor->SetBackgroundColour(wxColour(axes_color_back[axis_id])); + else + wxGetApp().UpdateDarkUI(editor); +#else editor->SetBackgroundColour(m_use_colors ? wxColour(axes_color_back[axis_id]) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif /* _WIN32 */ if (++axis_id == 3) axis_id = 0; } @@ -949,7 +958,8 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value) // Is the angle close to a multiple of 90 degrees? if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) { // Cannot apply scaling in the world coordinate system. - wxMessageDialog dlg(GUI::wxGetApp().mainframe, + //wxMessageDialog dlg(GUI::wxGetApp().mainframe, + MessageDialog dlg(GUI::wxGetApp().mainframe, _L("The currently manipulated object is tilted (rotation angles are not multiples of 90°).\n" "Non-uniform scaling of tilted objects is only possible in the World coordinate system,\n" "once the rotation is embedded into the object coordinates.") + "\n" + @@ -1015,6 +1025,14 @@ void ObjectManipulation::msw_rescale() void ObjectManipulation::sys_color_changed() { +#ifdef _WIN32 + get_og()->sys_color_changed(); + wxGetApp().UpdateDarkUI(m_word_local_combo); + wxGetApp().UpdateDarkUI(m_check_inch); + + for (ManipulationEditor* editor : m_editors) + editor->sys_color_changed(this); +#endif // btn...->msw_rescale() updates icon on button, so use it m_mirror_bitmap_on.msw_rescale(); m_mirror_bitmap_off.msw_rescale(); @@ -1026,8 +1044,6 @@ void ObjectManipulation::sys_color_changed() for (int id = 0; id < 3; ++id) m_mirror_buttons[id].first->msw_rescale(); - - get_og()->sys_color_changed(); } static const char axes[] = { 'x', 'y', 'z' }; @@ -1035,7 +1051,11 @@ ManipulationEditor::ManipulationEditor(ObjectManipulation* parent, const std::string& opt_key, int axis) : wxTextCtrl(parent->parent(), wxID_ANY, wxEmptyString, wxDefaultPosition, - wxSize((wxOSX ? 5 : 6)*int(wxGetApp().em_unit()), wxDefaultCoord), wxTE_PROCESS_ENTER), + wxSize((wxOSX ? 5 : 6)*int(wxGetApp().em_unit()), wxDefaultCoord), wxTE_PROCESS_ENTER +#ifdef _WIN32 + | wxBORDER_SIMPLE +#endif + ), m_opt_key(opt_key), m_axis(axis) { @@ -1044,8 +1064,9 @@ ManipulationEditor::ManipulationEditor(ObjectManipulation* parent, this->OSXDisableAllSmartSubstitutions(); #endif // __WXOSX__ if (parent->use_colors()) { -// this->SetForegroundColour(wxColour(axes_color_text[axis])); this->SetBackgroundColour(wxColour(axes_color_back[axis])); + } else { + wxGetApp().UpdateDarkUI(this); } // A name used to call handle_sidebar_focus_event() @@ -1094,6 +1115,12 @@ void ManipulationEditor::msw_rescale() SetMinSize(wxSize(5 * em, wxDefaultCoord)); } +void ManipulationEditor::sys_color_changed(ObjectManipulation* parent) +{ + if (!parent->use_colors()) + wxGetApp().UpdateDarkUI(this); +} + double ManipulationEditor::get_value() { wxString str = GetValue(); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index bcc0d4123..92ba01775 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -20,11 +20,19 @@ class wxCheckBox; namespace Slic3r { namespace GUI { +#ifdef _WIN32 +class BitmapComboBox; +#endif + #ifdef __WXOSX__ static_assert(wxMAJOR_VERSION >= 3, "Use of wxBitmapComboBox on Manipulation panel requires wxWidgets 3.0 and newer"); using choice_ctrl = wxBitmapComboBox; +#else +#ifdef _WIN32 + using choice_ctrl = BitmapComboBox; #else using choice_ctrl = wxComboBox; +#endif #endif // __WXOSX__ class Selection; @@ -44,6 +52,7 @@ public: ~ManipulationEditor() {} void msw_rescale(); + void sys_color_changed(ObjectManipulation* parent); void set_value(const wxString& new_value); void kill_focus(ObjectManipulation *parent); diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index e6689b43c..9409ce6c4 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -281,5 +281,13 @@ void ObjectSettings::msw_rescale() group->msw_rescale(); } +void ObjectSettings::sys_color_changed() +{ + m_og->sys_color_changed(); + + for (auto group : m_og_settings) + group->sys_color_changed(); +} + } //namespace GUI } //namespace Slic3r diff --git a/src/slic3r/GUI/GUI_ObjectSettings.hpp b/src/slic3r/GUI/GUI_ObjectSettings.hpp index 91cfe1dda..e5a6937f1 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.hpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.hpp @@ -57,6 +57,7 @@ public: void update_config_values(ModelConfig *config); void UpdateAndShow(const bool show) override; void msw_rescale(); + void sys_color_changed(); }; }} diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index c5124cd63..4a95eaedb 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -14,6 +14,7 @@ #include "Plater.hpp" #include "MainFrame.hpp" +#include #include #include #include @@ -28,6 +29,10 @@ #include "libslic3r/SLAPrint.hpp" #include "NotificationManager.hpp" +#ifdef _WIN32 +#include "BitmapComboBox.hpp" +#endif + namespace Slic3r { namespace GUI { @@ -186,7 +191,7 @@ bool Preview::init(wxWindow* parent, Model* model) // to match the background of the sliders #ifdef _WIN32 - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + wxGetApp().UpdateDarkUI(this); #else SetBackgroundColour(GetParent()->GetBackgroundColour()); #endif // _WIN32 @@ -206,9 +211,13 @@ bool Preview::init(wxWindow* parent, Model* model) m_layers_slider_sizer = create_layers_slider_sizer(); - m_bottom_toolbar_panel = new wxPanel(this); + wxGetApp().UpdateDarkUI(m_bottom_toolbar_panel = new wxPanel(this)); m_label_view_type = new wxStaticText(m_bottom_toolbar_panel, wxID_ANY, _L("View")); +#ifdef _WIN32 + wxGetApp().UpdateDarkUI(m_choice_view_type = new BitmapComboBox(m_bottom_toolbar_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY)); +#else m_choice_view_type = new wxComboBox(m_bottom_toolbar_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY); +#endif m_choice_view_type->Append(_L("Feature type")); m_choice_view_type->Append(_L("Height")); m_choice_view_type->Append(_L("Width")); @@ -222,8 +231,13 @@ bool Preview::init(wxWindow* parent, Model* model) m_label_show = new wxStaticText(m_bottom_toolbar_panel, wxID_ANY, _L("Show")); +#ifdef _WIN32 + long combo_style = wxCB_READONLY | wxBORDER_SIMPLE; //set border allows use default color instead of theme color wich is allways light under MSW +#else + long combo_style = wxCB_READONLY; +#endif m_combochecklist_features = new wxComboCtrl(); - m_combochecklist_features->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Feature types"), wxDefaultPosition, wxDefaultSize, wxCB_READONLY); + m_combochecklist_features->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Feature types"), wxDefaultPosition, wxDefaultSize, combo_style); std::string feature_items = GUI::into_u8( _L("Unknown") + "|1|" + _L("Perimeter") + "|1|" + @@ -244,7 +258,7 @@ bool Preview::init(wxWindow* parent, Model* model) Slic3r::GUI::create_combochecklist(m_combochecklist_features, GUI::into_u8(_L("Feature types")), feature_items); m_combochecklist_options = new wxComboCtrl(); - m_combochecklist_options->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Options"), wxDefaultPosition, wxDefaultSize, wxCB_READONLY); + m_combochecklist_options->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Options"), wxDefaultPosition, wxDefaultSize, combo_style); std::string options_items = GUI::into_u8( get_option_type_string(OptionType::Travel) + "|0|" + get_option_type_string(OptionType::Wipe) + "|0|" + @@ -401,6 +415,17 @@ void Preview::msw_rescale() void Preview::sys_color_changed() { +#ifdef _WIN32 + wxWindowUpdateLocker noUpdates(this); + + wxGetApp().UpdateAllStaticTextDarkUI(m_bottom_toolbar_panel); + wxGetApp().UpdateDarkUI(m_choice_view_type); + wxGetApp().UpdateDarkUI(m_combochecklist_features); + wxGetApp().UpdateDarkUI(static_cast(m_combochecklist_features->GetPopupControl())); + wxGetApp().UpdateDarkUI(m_combochecklist_options); + wxGetApp().UpdateDarkUI(static_cast(m_combochecklist_options->GetPopupControl())); +#endif + if (m_layers_slider != nullptr) m_layers_slider->sys_color_changed(); } diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index d49e6e7ac..7b1fcad19 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -15,7 +15,6 @@ class wxBoxSizer; class wxStaticText; class wxComboBox; class wxComboCtrl; -class wxBitmapComboBox; class wxCheckBox; namespace Slic3r { @@ -36,6 +35,9 @@ class GLToolbar; class Bed3D; struct Camera; class Plater; +#ifdef _WIN32 +class BitmapComboBox; +#endif class View3D : public wxPanel { @@ -82,7 +84,11 @@ class Preview : public wxPanel wxBoxSizer* m_layers_slider_sizer { nullptr }; wxPanel* m_bottom_toolbar_panel { nullptr }; wxStaticText* m_label_view_type { nullptr }; +#ifdef _WIN32 + BitmapComboBox* m_choice_view_type { nullptr }; +#else wxComboBox* m_choice_view_type { nullptr }; +#endif wxStaticText* m_label_show { nullptr }; wxComboCtrl* m_combochecklist_features { nullptr }; size_t m_combochecklist_features_pos { 0 }; diff --git a/src/slic3r/GUI/GUI_Utils.cpp b/src/slic3r/GUI/GUI_Utils.cpp index adb9633ea..df1161843 100644 --- a/src/slic3r/GUI/GUI_Utils.cpp +++ b/src/slic3r/GUI/GUI_Utils.cpp @@ -6,6 +6,8 @@ #ifdef _WIN32 #include +#include "GUI_App.hpp" +#include "libslic3r/AppConfig.hpp" #endif #include @@ -14,6 +16,7 @@ #include #include #include +#include #include "libslic3r/Config.hpp" @@ -149,6 +152,35 @@ wxFont get_default_font_for_dpi(const wxWindow *window, int dpi) return wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); } +bool check_dark_mode() { +#if 0 //#ifdef _WIN32 // #ysDarkMSW - Allow it when we deside to support the sustem colors for application + wxRegKey rk(wxRegKey::HKCU, + "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"); + if (rk.Exists() && rk.HasValue("AppsUseLightTheme")) { + long value = -1; + rk.QueryValue("AppsUseLightTheme", &value); + return value <= 0; + } +#endif +#if wxCHECK_VERSION(3,1,3) + return wxSystemSettings::GetAppearance().IsDark(); +#else + const unsigned luma = wxGetApp().get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + return luma < 128; +#endif +} + + +#ifdef _WIN32 +void update_dark_ui(wxWindow* window) +{ + bool is_dark = wxGetApp().app_config->get("dark_color_mode") == "1" ? true : check_dark_mode(); + window->SetBackgroundColour(is_dark ? wxColour(43, 43, 43) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + window->SetForegroundColour(is_dark ? wxColour(250, 250, 250) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); +} +#endif + + CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { diff --git a/src/slic3r/GUI/GUI_Utils.hpp b/src/slic3r/GUI/GUI_Utils.hpp index 4f02c6c23..66e0ae2aa 100644 --- a/src/slic3r/GUI/GUI_Utils.hpp +++ b/src/slic3r/GUI/GUI_Utils.hpp @@ -55,6 +55,11 @@ int get_dpi_for_window(const wxWindow *window); wxFont get_default_font_for_dpi(const wxWindow* window, int dpi); inline wxFont get_default_font(const wxWindow* window) { return get_default_font_for_dpi(window, get_dpi_for_window(window)); } +bool check_dark_mode(); +#ifdef _WIN32 +void update_dark_ui(wxWindow* window); +#endif + #if !wxVERSION_EQUAL_OR_GREATER_THAN(3,1,3) struct DpiChangedEvent : public wxEvent { int dpi; @@ -92,6 +97,9 @@ public: this->SetFont(m_normal_font); #endif this->CenterOnParent(); +#ifdef _WIN32 + update_dark_ui(this); +#endif // Linux specific issue : get_dpi_for_window(this) still doesn't responce to the Display's scale in new wxWidgets(3.1.3). // So, calculate the m_em_unit value from the font size, as before @@ -167,6 +175,14 @@ public: const wxFont& normal_font() const { return m_normal_font; } void enable_force_rescale() { m_force_rescale = true; } +#if 0 //#ifdef _WIN32 // #ysDarkMSW - Use to force dark colors for SystemLightMode + void force_sys_color_changed() + { + update_dark_ui(this); + on_sys_color_changed(); + } +#endif + protected: virtual void on_dpi_changed(const wxRect &suggested_rect) = 0; virtual void on_sys_color_changed() {}; @@ -243,6 +259,17 @@ private: m_prev_scale_factor = m_scale_factor; } +#if 0 //#ifdef _WIN32 // #ysDarkMSW - Allow it when we deside to support the sustem colors for application + bool HandleSettingChange(WXWPARAM wParam, WXLPARAM lParam) override + { + update_dark_ui(this); + on_sys_color_changed(); + + // let the system handle it + return false; + } +#endif + }; typedef DPIAware DPIFrame; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 10da6b85c..ad33cdb85 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -17,6 +17,7 @@ #include "slic3r/GUI/GUI_ObjectList.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/NotificationManager.hpp" +#include "slic3r/GUI/MsgDialog.hpp" #include "libslic3r/PresetBundle.hpp" #include "libslic3r/SLAPrint.hpp" @@ -920,7 +921,8 @@ void GLGizmoSlaSupports::on_set_state() wxGetApp().CallAfter([this]() { // Following is called through CallAfter, because otherwise there was a problem // on OSX with the wxMessageDialog being shown several times when clicked into. - wxMessageDialog dlg(GUI::wxGetApp().mainframe, _L("Do you want to save your manually " + //wxMessageDialog dlg(GUI::wxGetApp().mainframe, _L("Do you want to save your manually " + MessageDialog dlg(GUI::wxGetApp().mainframe, _L("Do you want to save your manually " "edited support points?") + "\n",_L("Save changes?"), wxICON_QUESTION | wxYES | wxNO); if (dlg.ShowModal() == wxID_YES) editing_mode_apply_changes(); @@ -1139,7 +1141,8 @@ void GLGizmoSlaSupports::get_data_from_backend() void GLGizmoSlaSupports::auto_generate() { - wxMessageDialog dlg(GUI::wxGetApp().plater(), + //wxMessageDialog dlg(GUI::wxGetApp().plater(), + MessageDialog dlg(GUI::wxGetApp().plater(), _L("Autogeneration will erase all manually edited points.") + "\n\n" + _L("Are you sure you want to do it?") + "\n", _L("Warning"), wxICON_WARNING | wxYES | wxNO); diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index e72975629..2c7822a9e 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -9,6 +9,7 @@ #include "wxExtensions.hpp" #include "MainFrame.hpp" #include +#include namespace Slic3r { namespace GUI { @@ -17,7 +18,7 @@ KBShortcutsDialog::KBShortcutsDialog() : DPIDialog(static_cast(wxGetApp().mainframe), wxID_ANY, wxString(wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME) + " - " + _L("Keyboard Shortcuts"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +// SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); // fonts const wxFont& font = wxGetApp().normal_font(); @@ -28,7 +29,18 @@ KBShortcutsDialog::KBShortcutsDialog() main_sizer->Add(create_header(this, bold_font), 0, wxEXPAND | wxALL, 10); +#ifdef _MSW_DARK_MODE + wxBookCtrlBase* book; + if (wxGetApp().dark_mode()) { + book = new wxListbook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP); + wxGetApp().UpdateDarkUI(book); + wxGetApp().UpdateDarkUI(dynamic_cast(book)->GetListView()); + } + else + book = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP); +#else wxNotebook* book = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP); +#endif main_sizer->Add(book, 1, wxEXPAND | wxALL, 10); fill_shortcuts(); @@ -39,6 +51,7 @@ KBShortcutsDialog::KBShortcutsDialog() } wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_OK, this))); this->SetEscapeId(wxID_OK); main_sizer->Add(buttons, 0, wxEXPAND | wxALL, 5); @@ -248,6 +261,7 @@ void KBShortcutsDialog::fill_shortcuts() wxPanel* KBShortcutsDialog::create_header(wxWindow* parent, const wxFont& bold_font) { wxPanel* panel = new wxPanel(parent); + wxGetApp().UpdateDarkUI(panel); wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); wxFont header_font = bold_font; @@ -278,6 +292,7 @@ wxPanel* KBShortcutsDialog::create_header(wxWindow* parent, const wxFont& bold_f wxPanel* KBShortcutsDialog::create_page(wxWindow* parent, const ShortcutsItem& shortcuts, const wxFont& font, const wxFont& bold_font) { wxPanel* main_page = new wxPanel(parent); + wxGetApp().UpdateDarkUI(main_page); wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); if (!shortcuts.first.second.empty()) { @@ -294,6 +309,7 @@ wxPanel* KBShortcutsDialog::create_page(wxWindow* parent, const ShortcutsItem& s int columns_count = 1 + static_cast(shortcuts.second.size()) / max_items_per_column; wxScrolledWindow* scrollable_panel = new wxScrolledWindow(main_page); + wxGetApp().UpdateDarkUI(scrollable_panel); scrollable_panel->SetScrollbars(20, 20, 50, 50); scrollable_panel->SetInitialSize(wxSize(850, 450)); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index ba3221b83..4832b80b9 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include #include @@ -38,6 +40,7 @@ #include "GUI_App.hpp" #include "UnsavedChangesDialog.hpp" +#include "MsgDialog.hpp" #ifdef _WIN32 #include @@ -265,6 +268,84 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S } } +#ifdef _MSW_DARK_MODE +static wxString pref() { return " [ "; } +static wxString suff() { return " ] "; } +static void append_tab_menu_items_to_menubar(wxMenuBar* bar, PrinterTechnology pt, bool is_mainframe_menu) +{ + if (is_mainframe_menu) + bar->Append(new wxMenu(), pref() + _L("Plater") + suff()); + for (const wxString& title : { is_mainframe_menu ? _L("Print Settings") : pref() + _L("Print Settings") + suff(), + pt == ptSLA ? _L("Material Settings") : _L("Filament Settings"), + _L("Printer Settings") }) + bar->Append(new wxMenu(), title); +} + +// update markers for selected/unselected menu items +static void update_marker_for_tabs_menu(wxMenuBar* bar, const wxString& title, bool is_mainframe_menu) +{ + if (!bar) + return; + size_t items_cnt = bar->GetMenuCount(); + for (size_t id = items_cnt - (is_mainframe_menu ? 4 : 3); id < items_cnt; id++) { + wxString label = bar->GetMenuLabel(id); + if (label.First(pref()) == 0) { + if (label == pref() + title + suff()) + return; + label.Remove(size_t(0), pref().Len()); + label.RemoveLast(suff().Len()); + bar->SetMenuLabel(id, label); + break; + } + } + if (int id = bar->FindMenu(title); id != wxNOT_FOUND) + bar->SetMenuLabel(id, pref() + title + suff()); +} + +static void add_tabs_as_menu(wxMenuBar* bar, MainFrame* main_frame, wxWindow* bar_parent) +{ + PrinterTechnology pt = main_frame->plater() ? main_frame->plater()->printer_technology() : ptFFF; + + bool is_mainframe_menu = bar_parent == main_frame; + if (!is_mainframe_menu) + append_tab_menu_items_to_menubar(bar, pt, is_mainframe_menu); + + bar_parent->Bind(wxEVT_MENU_OPEN, [main_frame, bar, is_mainframe_menu](wxMenuEvent& event) { + wxMenu* const menu = event.GetMenu(); + if (!menu || menu->GetMenuItemCount() > 0) + return; + + // update tab selection + + const wxString& title = menu->GetTitle(); + if (title == _L("Plater")) + main_frame->select_tab(size_t(0)); + else if (title == _L("Print Settings")) + main_frame->select_tab(wxGetApp().get_tab(main_frame->plater()->printer_technology() == ptFFF ? Preset::TYPE_PRINT : Preset::TYPE_SLA_PRINT)); + else if (title == _L("Filament Settings")) + main_frame->select_tab(wxGetApp().get_tab(Preset::TYPE_FILAMENT)); + else if (title == _L("Material Settings")) + main_frame->select_tab(wxGetApp().get_tab(Preset::TYPE_SLA_MATERIAL)); + else if (title == _L("Printer Settings")) + main_frame->select_tab(wxGetApp().get_tab(Preset::TYPE_PRINTER)); + + // update markers for selected/unselected menu items + update_marker_for_tabs_menu(bar, title, is_mainframe_menu); + }); +} + +void MainFrame::show_tabs_menu(bool show) +{ + if (show) + append_tab_menu_items_to_menubar(m_menubar, plater() ? plater()->printer_technology() : ptFFF, true); + else + while (m_menubar->GetMenuCount() >= 8) { + if (wxMenu* menu = m_menubar->Remove(7)) + delete menu; + } +} +#endif // _MSW_DARK_MODE + void MainFrame::update_layout() { auto restore_to_creation = [this]() { @@ -305,7 +386,7 @@ void MainFrame::update_layout() ESettingsLayout layout = wxGetApp().is_gcode_viewer() ? ESettingsLayout::GCodeViewer : (wxGetApp().app_config->get("old_settings_layout_mode") == "1" ? ESettingsLayout::Old : - wxGetApp().app_config->get("new_settings_layout_mode") == "1" ? ESettingsLayout::New : + wxGetApp().app_config->get("new_settings_layout_mode") == "1" ? ( wxGetApp().dark_mode() || wxGetApp().app_config->get("tabs_as_menu") == "1" ? ESettingsLayout::Old : ESettingsLayout::New) : wxGetApp().app_config->get("dlg_settings_layout_mode") == "1" ? ESettingsLayout::Dlg : ESettingsLayout::Old); if (m_layout == layout) @@ -330,6 +411,7 @@ void MainFrame::update_layout() layout == ESettingsLayout::Dlg ? State::toDlg : State::noUpdate; #endif //__WXMSW__ + ESettingsLayout old_layout = m_layout; m_layout = layout; // From the very beginning the Print settings should be selected @@ -349,6 +431,14 @@ void MainFrame::update_layout() m_main_sizer->Add(m_tabpanel, 1, wxEXPAND); m_plater->Show(); m_tabpanel->Show(); + // update Tabs + if (old_layout == ESettingsLayout::Dlg) + if (int sel = m_tabpanel->GetSelection(); sel != wxNOT_FOUND) + m_tabpanel->SetSelection(sel+1);// call SetSelection to correct layout after switching from Dlg to Old mode +#ifdef _MSW_DARK_MODE + if (wxGetApp().dark_mode() || wxGetApp().app_config->get("tabs_as_menu") == "1") + show_tabs_menu(true); +#endif break; } case ESettingsLayout::New: @@ -368,6 +458,11 @@ void MainFrame::update_layout() m_settings_dialog.GetSizer()->Add(m_tabpanel, 1, wxEXPAND); m_tabpanel->Show(); m_plater->Show(); + +#ifdef _MSW_DARK_MODE + if (wxGetApp().dark_mode() || wxGetApp().app_config->get("tabs_as_menu") == "1") + show_tabs_menu(false); +#endif break; } case ESettingsLayout::GCodeViewer: @@ -539,21 +634,31 @@ void MainFrame::init_tabpanel() { // wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on Windows 10 // with multiple high resolution displays connected. +#ifdef _MSW_DARK_MODE + if (wxGetApp().dark_mode() || wxGetApp().app_config->get("tabs_as_menu") == "1") { + m_tabpanel = new wxSimplebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME); + wxGetApp().UpdateDarkUI(m_tabpanel); + } + else + m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME); +#else m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME); +#endif + #ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font()); -#endif -#if wxCHECK_VERSION(3,1,3) - if (wxSystemSettings::GetAppearance().IsDark()) - m_tabpanel->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); #endif m_tabpanel->Hide(); m_settings_dialog.set_tabpanel(m_tabpanel); +#ifdef __WXMSW__ + m_tabpanel->Bind(/*wxEVT_LISTBOOK_PAGE_CHANGED*/wxEVT_BOOKCTRL_PAGE_CHANGED, [this](wxBookCtrlEvent& e) { +#else m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [this](wxBookCtrlEvent& e) { +#endif #if ENABLE_VALIDATE_CUSTOM_GCODE if (int old_selection = e.GetOldSelection(); - old_selection != wxNOT_FOUND && old_selection < static_cast(m_tabpanel->GetPageCount())) { + old_selection != wxNOT_FOUND && old_selection < m_tabpanel->GetPageCount()) { Tab* old_tab = dynamic_cast(m_tabpanel->GetPage(old_selection)); if (old_tab) old_tab->validate_custom_gcodes(); @@ -896,7 +1001,8 @@ void MainFrame::on_sys_color_changed() // update label colors in respect to the system mode wxGetApp().init_label_colours(); #ifdef __WXMSW__ - m_tabpanel->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + wxGetApp().UpdateDarkUI(m_tabpanel); + m_statusbar->update_dark_ui(); #endif // update Plater @@ -910,6 +1016,8 @@ void MainFrame::on_sys_color_changed() wxMenuBar* menu_bar = this->GetMenuBar(); for (size_t id = 0; id < menu_bar->GetMenuCount(); id++) msw_rescale_menu(menu_bar->GetMenu(id)); + + this->Refresh(); } #ifdef _MSC_VER @@ -1012,7 +1120,8 @@ void MainFrame::init_menubar_as_editor() m_plater->load_project(filename); else { - wxMessageDialog msg(this, _L("The selected project is no longer available.\nDo you want to remove it from the recent projects list?"), _L("Error"), wxYES_NO | wxYES_DEFAULT); + //wxMessageDialog msg(this, _L("The selected project is no longer available.\nDo you want to remove it from the recent projects list?"), _L("Error"), wxYES_NO | wxYES_DEFAULT); + MessageDialog msg(this, _L("The selected project is no longer available.\nDo you want to remove it from the recent projects list?"), _L("Error"), wxYES_NO | wxYES_DEFAULT); if (msg.ShowModal() == wxID_YES) { m_recent_projects.RemoveFileFromHistory(file_id); @@ -1305,8 +1414,21 @@ void MainFrame::init_menubar_as_editor() // Add additional menus from C++ wxGetApp().add_config_menu(m_menubar); m_menubar->Append(helpMenu, _L("&Help")); + +#ifdef _MSW_DARK_MODE + if (wxGetApp().dark_mode() || wxGetApp().app_config->get("tabs_as_menu") == "1") { + // Add separator + m_menubar->Append(new wxMenu(), " "); + add_tabs_as_menu(m_menubar, this, this); + } +#endif SetMenuBar(m_menubar); +#ifdef _MSW_DARK_MODE + if (wxGetApp().dark_mode() || wxGetApp().app_config->get("tabs_as_menu") == "1") + m_menubar->EnableTop(6, false); +#endif + #ifdef __APPLE__ // This fixes a bug on Mac OS where the quit command doesn't emit window close events // wx bug: https://trac.wxwidgets.org/ticket/18328 @@ -1391,9 +1513,9 @@ void MainFrame::update_menubar() m_changeable_menu_items[miSend] ->SetItemLabel((is_fff ? _L("S&end G-code") : _L("S&end to print")) + dots + "\tCtrl+Shift+G"); m_changeable_menu_items[miMaterialTab] ->SetItemLabel((is_fff ? _L("&Filament Settings Tab") : _L("Mate&rial Settings Tab")) + "\tCtrl+3"); - m_changeable_menu_items[miMaterialTab] ->SetBitmap(create_scaled_bitmap(is_fff ? "spool" : "resin")); + m_changeable_menu_items[miMaterialTab] ->SetBitmap(create_menu_bitmap(is_fff ? "spool" : "resin")); - m_changeable_menu_items[miPrinterTab] ->SetBitmap(create_scaled_bitmap(is_fff ? "printer" : "sla_printer")); + m_changeable_menu_items[miPrinterTab] ->SetBitmap(create_menu_bitmap(is_fff ? "printer" : "sla_printer")); } // To perform the "Quck Slice", "Quick Slice and Save As", "Repeat last Quick Slice" and "Slice to SVG". @@ -1424,13 +1546,15 @@ void MainFrame::quick_slice(const int qs) } else { if (m_qs_last_input_file.IsEmpty()) { - wxMessageDialog dlg(this, _L("No previously sliced file."), + //wxMessageDialog dlg(this, _L("No previously sliced file."), + MessageDialog dlg(this, _L("No previously sliced file."), _L("Error"), wxICON_ERROR | wxOK); dlg.ShowModal(); return; } if (std::ifstream(m_qs_last_input_file.ToUTF8().data())) { - wxMessageDialog dlg(this, _L("Previously sliced file (")+m_qs_last_input_file+_L(") not found."), + //wxMessageDialog dlg(this, _L("Previously sliced file (")+m_qs_last_input_file+_L(") not found."), + MessageDialog dlg(this, _L("Previously sliced file (")+m_qs_last_input_file+_L(") not found."), _L("File Not Found"), wxICON_ERROR | wxOK); dlg.ShowModal(); return; @@ -1514,7 +1638,8 @@ void MainFrame::quick_slice(const int qs) auto message = format(_L("%1% was successfully sliced."), input_file_basename); // wxTheApp->notify(message); - wxMessageDialog(this, message, _L("Slicing Done!"), wxOK | wxICON_INFORMATION).ShowModal(); + //wxMessageDialog(this, message, _L("Slicing Done!"), wxOK | wxICON_INFORMATION).ShowModal(); + MessageDialog(this, message, _L("Slicing Done!"), wxOK | wxICON_INFORMATION).ShowModal(); // }; // Slic3r::GUI::catch_error(this, []() { if (m_progress_dialog) m_progress_dialog->Destroy(); }); } @@ -1743,6 +1868,16 @@ void MainFrame::select_tab(size_t tab/* = size_t(-1)*/) if (m_tabpanel->GetSelection() != (int)new_selection) m_tabpanel->SetSelection(new_selection); +#ifdef _MSW_DARK_MODE + if (wxGetApp().dark_mode() || wxGetApp().app_config->get("tabs_as_menu") == "1") { + if (Tab* cur_tab = dynamic_cast(m_tabpanel->GetPage(new_selection))) + update_marker_for_tabs_menu((m_layout == ESettingsLayout::Old ? m_menubar : m_settings_dialog.menubar()), cur_tab->title(), m_layout == ESettingsLayout::Old); + else if (tab == 0 && m_layout == ESettingsLayout::Old) + m_plater->get_current_canvas3D()->render(); + } +#endif + if (tab == 0 && m_layout == ESettingsLayout::Old) + m_plater->canvas3D()->render(); else if (was_hidden) { Tab* cur_tab = dynamic_cast(m_tabpanel->GetPage(new_selection)); if (cur_tab) @@ -1781,6 +1916,8 @@ void MainFrame::select_tab(size_t tab/* = size_t(-1)*/) m_settings_dialog.Show(); } #endif + if (m_settings_dialog.IsIconized()) + m_settings_dialog.Iconize(false); } else if (m_layout == ESettingsLayout::New) { m_main_sizer->Show(m_plater, tab == 0); @@ -1884,6 +2021,21 @@ void MainFrame::add_to_recent_projects(const wxString& filename) } } +void MainFrame::technology_changed() +{ + // upadte DiffDlg + diff_dialog.update_presets(); + + // update menu titles + PrinterTechnology pt = plater()->printer_technology(); + if (int id = m_menubar->FindMenu(pt == ptFFF ? _L("Material Settings") : _L("Filament Settings")); id != wxNOT_FOUND) + m_menubar->SetMenuLabel(id , pt == ptSLA ? _L("Material Settings") : _L("Filament Settings")); + + //if (wxGetApp().tab_panel()->GetSelection() != wxGetApp().tab_panel()->GetPageCount() - 1) + // wxGetApp().tab_panel()->SetSelection(wxGetApp().tab_panel()->GetPageCount() - 1); + +} + // // Called after the Preferences dialog is closed and the program settings are saved. // Update the UI based on the current preferences. @@ -1920,8 +2072,9 @@ std::string MainFrame::get_dir_name(const wxString &full_name) const // ---------------------------------------------------------------------------- SettingsDialog::SettingsDialog(MainFrame* mainframe) -: DPIDialog(mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings"), wxDefaultPosition, wxDefaultSize, - wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX, "settings_dialog"), +:DPIFrame(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "settings_dialog"), +//: DPIDialog(mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings"), wxDefaultPosition, wxDefaultSize, +// wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX, "settings_dialog"), m_main_frame(mainframe) { if (wxGetApp().is_gcode_viewer()) @@ -1978,6 +2131,18 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe) } }); + //just hide the Frame on closing + this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& evt) { this->Hide(); }); + +#ifdef _MSW_DARK_MODE + if (wxGetApp().dark_mode() || wxGetApp().app_config->get("tabs_as_menu") == "1") { + // menubar + m_menubar = new wxMenuBar(); + add_tabs_as_menu(m_menubar, mainframe, this); + this->SetMenuBar(m_menubar); + } +#endif + // initialize layout auto sizer = new wxBoxSizer(wxVERTICAL); sizer->SetSizeHints(this); diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 55fde8a53..40fff23da 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -19,6 +19,7 @@ #include "UnsavedChangesDialog.hpp" class wxNotebook; +class wxBookCtrlBase; class wxProgressDialog; namespace Slic3r { @@ -52,14 +53,16 @@ struct PresetTab { // SettingsDialog // ---------------------------------------------------------------------------- -class SettingsDialog : public DPIDialog +class SettingsDialog : public DPIFrame//DPIDialog { - wxNotebook* m_tabpanel { nullptr }; - MainFrame* m_main_frame { nullptr }; + wxBookCtrlBase* m_tabpanel { nullptr }; + MainFrame* m_main_frame { nullptr }; + wxMenuBar* m_menubar{ nullptr }; public: SettingsDialog(MainFrame* mainframe); ~SettingsDialog() = default; - void set_tabpanel(wxNotebook* tabpanel) { m_tabpanel = tabpanel; } + void set_tabpanel(wxBookCtrlBase* tabpanel) { m_tabpanel = tabpanel; } + wxMenuBar* menubar() { return m_menubar; } protected: void on_dpi_changed(const wxRect& suggested_rect) override; @@ -80,8 +83,6 @@ class MainFrame : public DPIFrame wxMenuItem* m_menu_item_reslice_now { nullptr }; wxSizer* m_main_sizer{ nullptr }; - - size_t m_last_selected_tab; std::string get_base_name(const wxString &full_name, const char *extension = nullptr) const; @@ -161,7 +162,9 @@ public: void init_menubar_as_editor(); void init_menubar_as_gcodeviewer(); void update_menubar(); - +#ifdef _WIN32 + void show_tabs_menu(bool show); +#endif void update_ui_from_settings(); bool is_loaded() const { return m_loaded; } bool is_last_input_file() const { return !m_qs_last_input_file.IsEmpty(); } @@ -194,11 +197,12 @@ public: #endif // ENABLE_PROJECT_DIRTY_STATE void add_to_recent_projects(const wxString& filename); + void technology_changed(); PrintHostQueueDialog* printhost_queue_dlg() { return m_printhost_queue_dlg; } Plater* m_plater { nullptr }; - wxNotebook* m_tabpanel { nullptr }; + wxBookCtrlBase* m_tabpanel { nullptr }; SettingsDialog m_settings_dialog; DiffPresetDialog diff_dialog; wxWindow* m_plater_page{ nullptr }; diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index de4c7e00f..0c52d8b58 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -64,6 +64,59 @@ MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &he SetSizerAndFit(topsizer); } +void MsgDialog::add_btn(wxWindowID btn_id, bool set_focus /*= false*/) +{ + wxButton* btn = new wxButton(this, btn_id); + if (set_focus) + btn->SetFocus(); + btn_sizer->Add(btn, 0, wxRIGHT, HORIZ_SPACING); + btn->Bind(wxEVT_BUTTON, [this, btn_id](wxCommandEvent&) { this->EndModal(btn_id); }); +}; + +// Text shown as HTML, so that mouse selection and Ctrl-V to copy will work. +static void add_msg_content(wxWindow* parent, wxBoxSizer* content_sizer, wxString msg, bool monospaced_font = false) +{ + wxHtmlWindow* html = new wxHtmlWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO); + + // count lines in the message + int msg_lines = 0; + if (!monospaced_font) { + int line_len = 55;// count of symbols in one line + int start_line = 0; + for (auto i = msg.begin(); i != msg.end(); ++i) { + if (*i == '\n') { + int cur_line_len = i - msg.begin() - start_line; + start_line = i - msg.begin(); + if (cur_line_len == 0 || line_len > cur_line_len) + msg_lines++; + else + msg_lines += std::lround((double)(cur_line_len) / line_len); + } + } + msg_lines++; + } + + html->SetMinSize(wxSize(40 * wxGetApp().em_unit(), monospaced_font ? 30 * wxGetApp().em_unit() : 2 * msg_lines * wxGetApp().em_unit())); + wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + wxFont monospace = wxGetApp().code_font(); + wxColour text_clr = wxGetApp().get_label_clr_default(); + wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + 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 font_size = font.GetPointSize(); + int size[] = { font_size, font_size, font_size, font_size, font_size, font_size, font_size }; + html->SetFonts(font.GetFaceName(), monospace.GetFaceName(), size); + html->SetBorders(2); + std::string msg_escaped = xml_escape(msg.ToUTF8().data()); + boost::replace_all(msg_escaped, "\r\n", "
"); + boost::replace_all(msg_escaped, "\n", "
"); + if (monospaced_font) + // Code formatting will be preserved. This is useful for reporting errors from the placeholder parser. + msg_escaped = std::string("
") + msg_escaped + "
"; + html->SetPage("" + wxString::FromUTF8(msg_escaped.data()) + ""); + content_sizer->Add(html, 1, wxEXPAND | wxBOTTOM, 30); +} + // ErrorDialog ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg, bool monospaced_font) @@ -72,36 +125,13 @@ ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg, bool monospaced_ wxID_NONE) , msg(msg) { - // Text shown as HTML, so that mouse selection and Ctrl-V to copy will work. - wxHtmlWindow* html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO); - { - html->SetMinSize(wxSize(40 * wxGetApp().em_unit(), monospaced_font ? 30 * wxGetApp().em_unit() : -1)); - wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); - wxFont monospace = wxGetApp().code_font(); - wxColour text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); - wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - 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 font_size = font.GetPointSize()-1; - int size[] = {font_size, font_size, font_size, font_size, font_size, font_size, font_size}; - html->SetFonts(font.GetFaceName(), monospace.GetFaceName(), size); - html->SetBorders(2); - std::string msg_escaped = xml_escape(msg.ToUTF8().data()); - boost::replace_all(msg_escaped, "\r\n", "
"); - boost::replace_all(msg_escaped, "\n", "
"); - if (monospaced_font) - // Code formatting will be preserved. This is useful for reporting errors from the placeholder parser. - msg_escaped = std::string("
") + msg_escaped + "
"; - html->SetPage("" + wxString::FromUTF8(msg_escaped.data()) + ""); - content_sizer->Add(html, 1, wxEXPAND); - } - - auto *btn_ok = new wxButton(this, wxID_OK); - btn_ok->SetFocus(); - btn_sizer->Add(btn_ok, 0, wxRIGHT, HORIZ_SPACING); + add_msg_content(this, content_sizer, msg, monospaced_font); + add_btn(wxID_OK, true); // Use a small bitmap with monospaced font, as the error text will not be wrapped. - logo->SetBitmap(create_scaled_bitmap("PrusaSlicer_192px_grayscale.png", this, monospaced_font ? 48 : 192)); + logo->SetBitmap(create_scaled_bitmap("PrusaSlicer_192px_grayscale.png", this, monospaced_font ? 48 : /*1*/92)); + + wxGetApp().UpdateDlgDarkUI(this); SetMaxSize(wxSize(-1, CONTENT_MAX_HEIGHT*wxGetApp().em_unit())); Fit(); @@ -115,45 +145,40 @@ WarningDialog::WarningDialog(wxWindow *parent, long style/* = wxOK*/) : MsgDialog(parent, caption.IsEmpty() ? wxString::Format(_L("%s warning"), SLIC3R_APP_NAME) : caption, wxString::Format(_L("%s has a warning")+":", SLIC3R_APP_NAME), wxID_NONE) - , msg(message) { - // Text shown as HTML, so that mouse selection and Ctrl-V to copy will work. - wxHtmlWindow* html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO); - { - html->SetMinSize(wxSize(40 * wxGetApp().em_unit(), 10 * wxGetApp().em_unit())); - wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); - wxFont monospace = wxGetApp().code_font(); - wxColour text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); - wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - 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 font_size = font.GetPointSize(); - int size[] = {font_size, font_size, font_size, font_size, font_size, font_size, font_size}; - html->SetFonts(font.GetFaceName(), monospace.GetFaceName(), size); - html->SetBorders(2); - std::string msg_escaped = xml_escape(msg.ToUTF8().data()); - boost::replace_all(msg_escaped, "\r\n", "
"); - boost::replace_all(msg_escaped, "\n", "
"); - html->SetPage("" + wxString::FromUTF8(msg_escaped.data()) + ""); - content_sizer->Add(html, 1, wxEXPAND|wxBOTTOM, BORDER); - } + add_msg_content(this, content_sizer, message); - auto add_btn = [this](wxWindowID btn_id) { - auto* btn = new wxButton(this, btn_id); - btn_sizer->Add(btn, 0, wxRIGHT, HORIZ_SPACING); - btn->Bind(wxEVT_BUTTON, [this, btn_id](wxCommandEvent&) { this->EndModal(btn_id); }); - }; + if (style & wxOK) add_btn(wxID_OK, true); + if (style & wxYES) add_btn(wxID_YES); + if (style & wxNO) add_btn(wxID_NO); - if (style & wxOK) - add_btn(wxID_OK); - if (style & wxYES) - add_btn(wxID_YES); - if (style & wxNO) - add_btn(wxID_NO); + logo->SetBitmap(create_scaled_bitmap("PrusaSlicer_192px_grayscale.png", this, 90)); - logo->SetBitmap(create_scaled_bitmap("PrusaSlicer_192px_grayscale.png", this, 150)); + wxGetApp().UpdateDlgDarkUI(this); + Fit(); +} - SetMaxSize(wxSize(-1, CONTENT_MAX_HEIGHT*wxGetApp().em_unit())); + +// MessageDialog + +MessageDialog::MessageDialog(wxWindow* parent, + const wxString& message, + const wxString& caption/* = wxEmptyString*/, + long style/* = wxOK*/) + : MsgDialog(parent, caption.IsEmpty() ? wxString::Format(_L("%s info"), SLIC3R_APP_NAME) : caption, wxEmptyString, wxID_NONE) +{ + add_msg_content(this, content_sizer, message); + + if (style & wxOK) add_btn(wxID_OK, true); + if (style & wxYES) add_btn(wxID_YES); + if (style & wxNO) add_btn(wxID_NO); + if (style & wxCANCEL) add_btn(wxID_CANCEL); + + logo->SetBitmap(create_scaled_bitmap(style & wxICON_WARNING ? "exclamation" : + style & wxICON_INFORMATION ? "info.png" : + style & wxICON_QUESTION ? "question" : "PrusaSlicer_192px_grayscale.png", this, 90)); + + wxGetApp().UpdateDlgDarkUI(this); Fit(); } diff --git a/src/slic3r/GUI/MsgDialog.hpp b/src/slic3r/GUI/MsgDialog.hpp index 20d7f8dd5..8c49107d9 100644 --- a/src/slic3r/GUI/MsgDialog.hpp +++ b/src/slic3r/GUI/MsgDialog.hpp @@ -31,7 +31,7 @@ struct MsgDialog : wxDialog protected: enum { - CONTENT_WIDTH = 50, + CONTENT_WIDTH = 70,//50, CONTENT_MAX_HEIGHT = 60, BORDER = 30, VERT_SPACING = 15, @@ -41,6 +41,8 @@ protected: // button_id is an id of a button that can be added by default, use wxID_NONE to disable MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id = wxID_OK, wxBitmap bitmap = wxNullBitmap); + void add_btn(wxWindowID btn_id, bool set_focus = false); + wxFont boldfont; wxBoxSizer *content_sizer; wxBoxSizer *btn_sizer; @@ -66,12 +68,10 @@ private: }; -// Generic error dialog, used for displaying exceptions +// Generic warning dialog, used for displaying exceptions class WarningDialog : public MsgDialog { public: - // If monospaced_font is true, the error message is displayed using html
tags, - // so that the code formatting will be preserved. This is useful for reporting errors from the placeholder parser. WarningDialog( wxWindow *parent, const wxString& message, const wxString& caption = wxEmptyString, @@ -81,9 +81,22 @@ public: WarningDialog &operator=(WarningDialog&&) = delete; WarningDialog &operator=(const WarningDialog&) = delete; virtual ~WarningDialog() = default; +}; -private: - wxString msg; + +// Generic message dialog, used intead of wxMessageDialog +class MessageDialog : public MsgDialog +{ +public: + MessageDialog( wxWindow *parent, + const wxString& message, + const wxString& caption = wxEmptyString, + long style = wxOK); + MessageDialog(MessageDialog&&) = delete; + MessageDialog(const MessageDialog&) = delete; + MessageDialog &operator=(MessageDialog&&) = delete; + MessageDialog &operator=(const MessageDialog&) = delete; + virtual ~MessageDialog() = default; }; diff --git a/src/slic3r/GUI/OG_CustomCtrl.cpp b/src/slic3r/GUI/OG_CustomCtrl.cpp index aba3404e7..f01a1e962 100644 --- a/src/slic3r/GUI/OG_CustomCtrl.cpp +++ b/src/slic3r/GUI/OG_CustomCtrl.cpp @@ -2,6 +2,7 @@ #include "OptionsGroup.hpp" #include "Plater.hpp" #include "GUI_App.hpp" +#include "MsgDialog.hpp" #include "libslic3r/AppConfig.hpp" #include @@ -353,6 +354,8 @@ void OG_CustomCtrl::correct_widgets_position(wxSizer* widget, const Line& line, wxPoint pos = line_pos; wxSize sz = child->GetWindow()->GetSize(); pos.y += std::max(0, int(0.5 * (line_height - sz.y))); + if (line.extra_widget_sizer && widget == line.extra_widget_sizer) + pos.x += m_h_gap; child->GetWindow()->SetPosition(pos); line_pos.x += sz.x + m_h_gap; } @@ -631,7 +634,12 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_text(wxDC& dc, wxPoint pos, const wxStr #else dc.SetFont(old_font.Bold().Underlined()); #endif - dc.SetTextForeground(color ? *color : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); + dc.SetTextForeground(color ? *color : +#ifdef _WIN32 + wxGetApp().get_label_clr_default()); +#else + wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); +#endif /* _WIN32 */ dc.DrawText(out_text, pos); dc.SetTextForeground(old_clr); dc.SetFont(old_font); @@ -703,7 +711,6 @@ bool OG_CustomCtrl::CtrlLine::launch_browser() const RememberChoiceDialog::RememberChoiceDialog(wxWindow* parent, const wxString& msg_text, const wxString& caption) : wxDialog(parent, wxID_ANY, caption, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxICON_INFORMATION) { - this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); this->SetEscapeId(wxID_CLOSE); wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL); @@ -720,7 +727,8 @@ RememberChoiceDialog::RememberChoiceDialog(wxWindow* parent, const wxString& msg _L("You will not be asked about it again on label hovering.") + "\n\n" + format_wxstr(_L("Visit \"Preferences\" and check \"%1%\"\nto changes your choice."), preferences_item); - wxMessageDialog dialog(nullptr, msg, _L("PrusaSlicer: Don't ask me again"), wxOK | wxCANCEL | wxICON_INFORMATION); + //wxMessageDialog dialog(nullptr, msg, _L("PrusaSlicer: Don't ask me again"), wxOK | wxCANCEL | wxICON_INFORMATION); + MessageDialog dialog(nullptr, msg, _L("PrusaSlicer: Don't ask me again"), wxOK | wxCANCEL | wxICON_INFORMATION); if (dialog.ShowModal() == wxID_CANCEL) m_remember_choice->SetValue(false); }); @@ -737,6 +745,11 @@ RememberChoiceDialog::RememberChoiceDialog(wxWindow* parent, const wxString& msg topSizer->Add(m_remember_choice, 0, wxEXPAND | wxALL, 10); topSizer->Add(btns, 0, wxEXPAND | wxALL, 10); +#ifdef _WIN32 + wxGetApp().UpdateDlgDarkUI(this); +#else + this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif this->SetSizer(topSizer); topSizer->SetSizeHints(this); diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index 482de650d..0e0e39a2b 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -171,7 +171,7 @@ void ObjectDataViewModelNode::update_settings_digest_bitmaps() if (bmp == nullptr) { std::vector bmps; for (auto& category : m_opt_categories) - bmps.emplace_back(SettingsFactory::get_category_bitmap(category)); + bmps.emplace_back(SettingsFactory::get_category_bitmap(category, false)); bmp = m_bitmap_cache->insert(scaled_bitmap_name, bmps); } diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index f70d678d2..7ebe71ef8 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -411,6 +411,7 @@ bool OptionsGroup::activate(std::function throw_if_canceled) stb = new wxStaticBox(m_parent, wxID_ANY, _(title)); if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); stb->SetFont(wxOSX ? wxGetApp().normal_font() : wxGetApp().bold_font()); + wxGetApp().UpdateDarkUI(stb); } else stb = nullptr; @@ -738,6 +739,39 @@ void ConfigOptionsGroup::msw_rescale() void ConfigOptionsGroup::sys_color_changed() { +#ifdef _WIN32 + if (staticbox && stb) { + wxGetApp().UpdateAllStaticTextDarkUI(stb); + // update bitmaps for extra column items (like "delete" buttons on settings panel) + for (auto extra_col : m_extra_column_item_ptrs) + wxGetApp().UpdateDarkUI(extra_col); + } + + auto update = [](wxSizer* sizer) { + for (wxSizerItem* item : sizer->GetChildren()) + if (item->IsWindow()) { + wxWindow* win = item->GetWindow(); + // check if window is ScalableButton + if (ScalableButton* sc_btn = dynamic_cast(win)) { + sc_btn->msw_rescale(); + return; + } + wxGetApp().UpdateDarkUI(win, dynamic_cast(win) != nullptr); + } + }; + + // scale widgets and extra widgets if any exists + for (const Line& line : m_lines) { + if (line.widget_sizer) + update(line.widget_sizer); + if (line.extra_widget_sizer) + update(line.extra_widget_sizer); + } + + if (custom_ctrl) + wxGetApp().UpdateDarkUI(custom_ctrl); +#endif + // update undo buttons : rescale bitmaps for (const auto& field : m_fields) field.second->sys_color_changed(); diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 96fe94e0f..10cea5dda 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -87,7 +87,8 @@ using t_optionfield_map = std::map; using t_opt_map = std::map< std::string, std::pair >; class OptionsGroup { - wxStaticBox* stb; +protected: + wxStaticBox* stb {nullptr}; public: const bool staticbox {true}; const wxString title; diff --git a/src/slic3r/GUI/PhysicalPrinterDialog.cpp b/src/slic3r/GUI/PhysicalPrinterDialog.cpp index 8b16575ba..bb0191b4d 100644 --- a/src/slic3r/GUI/PhysicalPrinterDialog.cpp +++ b/src/slic3r/GUI/PhysicalPrinterDialog.cpp @@ -31,6 +31,7 @@ #include "RemovableDriveManager.hpp" #include "BitmapCache.hpp" #include "BonjourDialog.hpp" +#include "MsgDialog.hpp" namespace Slic3r { namespace GUI { @@ -156,8 +157,9 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_ m_printer("", wxGetApp().preset_bundle->physical_printers.default_config()) { SetFont(wxGetApp().normal_font()); +#ifndef _WIN32 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - +#endif m_default_name = _L("Type here the name of your printer device"); bool new_printer = true; @@ -171,12 +173,13 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_ wxStaticText* label_top = new wxStaticText(this, wxID_ANY, _L("Descriptive name for the printer") + ":"); - m_add_preset_btn = new ScalableButton(this, wxID_ANY, "add_copies", "", wxDefaultSize, wxDefaultPosition, /*wxBU_LEFT | */wxBU_EXACTFIT); + m_add_preset_btn = new ScalableButton(this, wxID_ANY, "add_copies", "", wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT); m_add_preset_btn->SetFont(wxGetApp().normal_font()); m_add_preset_btn->SetToolTip(_L("Add preset for this printer device")); m_add_preset_btn->Bind(wxEVT_BUTTON, &PhysicalPrinterDialog::AddPreset, this); m_printer_name = new wxTextCtrl(this, wxID_ANY, printer_name, wxDefaultPosition, wxDefaultSize); + wxGetApp().UpdateDarkUI(m_printer_name); m_printer_name->Bind(wxEVT_TEXT, [this](wxEvent&) { this->update_full_printer_names(); }); PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers; @@ -207,8 +210,11 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_ wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL); wxButton* btnOK = static_cast(this->FindWindowById(wxID_OK, this)); + wxGetApp().UpdateDarkUI(btnOK); btnOK->Bind(wxEVT_BUTTON, &PhysicalPrinterDialog::OnOK, this); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CANCEL, this))); + wxBoxSizer* nameSizer = new wxBoxSizer(wxHORIZONTAL); nameSizer->Add(m_printer_name, 1, wxEXPAND); nameSizer->Add(m_add_preset_btn, 0, wxEXPAND | wxLEFT, BORDER_W); @@ -554,7 +560,8 @@ void PhysicalPrinterDialog::OnOK(wxEvent& event) { wxString msg_text = from_u8((boost::format(_u8L("Printer with name \"%1%\" already exists.")) % existing->name/*printer_name*/).str()); msg_text += "\n" + _L("Replace?"); - wxMessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxYES | wxNO); + //wxMessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxYES | wxNO); + MessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxYES | wxNO); if (dialog.ShowModal() == wxID_NO) return; @@ -583,7 +590,8 @@ void PhysicalPrinterDialog::OnOK(wxEvent& event) "The above preset for printer \"%2%\" will be used just once.", "Following printer presets are duplicated:%1%" "The above presets for printer \"%2%\" will be used just once.", repeat_cnt), repeatable_presets, printer_name); - wxMessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxOK | wxCANCEL); + //wxMessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxOK | wxCANCEL); + MessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxOK | wxCANCEL); if (dialog.ShowModal() == wxID_CANCEL) return; } @@ -628,7 +636,8 @@ void PhysicalPrinterDialog::DeletePreset(PresetForPrinter* preset_for_printer) { if (m_presets.size() == 1) { wxString msg_text = _L("It's not possible to delete the last related preset for the printer."); - wxMessageDialog dialog(nullptr, msg_text, _L("Information"), wxICON_INFORMATION | wxOK); + //wxMessageDialog dialog(nullptr, msg_text, _L("Information"), wxICON_INFORMATION | wxOK); + MessageDialog dialog(nullptr, msg_text, _L("Information"), wxICON_INFORMATION | wxOK); dialog.ShowModal(); return; } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 3fc12457a..13e866965 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -81,6 +81,7 @@ #include "InstanceCheck.hpp" #include "NotificationManager.hpp" #include "PresetComboBoxes.hpp" +#include "MsgDialog.hpp" #if ENABLE_PROJECT_DIRTY_STATE #include "ProjectDirtyStateManager.hpp" #endif // ENABLE_PROJECT_DIRTY_STATE @@ -149,6 +150,7 @@ ObjectInfo::ObjectInfo(wxWindow *parent) : wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _L("Info")), wxVERTICAL) { GetStaticBox()->SetFont(wxGetApp().bold_font()); + wxGetApp().UpdateDarkUI(GetStaticBox()); auto *grid_sizer = new wxFlexGridSizer(4, 5, 15); grid_sizer->SetFlexibleDirection(wxHORIZONTAL); @@ -224,6 +226,7 @@ SlicedInfo::SlicedInfo(wxWindow *parent) : wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _L("Sliced Info")), wxVERTICAL) { GetStaticBox()->SetFont(wxGetApp().bold_font()); + wxGetApp().UpdateDarkUI(GetStaticBox()); auto *grid_sizer = new wxFlexGridSizer(2, 5, 15); grid_sizer->SetFlexibleDirection(wxVERTICAL); @@ -283,6 +286,7 @@ public: void Show(const bool is_fff) override; void msw_rescale(); + void sys_color_changed(); }; void FreqChangedParams::msw_rescale() @@ -294,6 +298,17 @@ void FreqChangedParams::msw_rescale() btn->msw_rescale(); } +void FreqChangedParams::sys_color_changed() +{ + m_og->sys_color_changed(); + m_og_sla->sys_color_changed(); + + for (auto btn: m_empty_buttons) + btn->msw_rescale(); + + wxGetApp().UpdateDarkUI(m_wiping_dialog_button, true); +} + FreqChangedParams::FreqChangedParams(wxWindow* parent) : OG_Settings(parent, false) { @@ -411,6 +426,8 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : auto wiping_dialog_btn = [this](wxWindow* parent) { m_wiping_dialog_button = new wxButton(parent, wxID_ANY, _L("Purging volumes") + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); m_wiping_dialog_button->SetFont(wxGetApp().normal_font()); + wxGetApp().UpdateDarkUI(m_wiping_dialog_button, true); + auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(m_wiping_dialog_button, 0, wxALIGN_CENTER_VERTICAL); m_wiping_dialog_button->Bind(wxEVT_BUTTON, ([parent](wxCommandEvent& e) @@ -640,7 +657,12 @@ Sidebar::Sidebar(Plater *parent) SetFont(wxGetApp().normal_font()); #ifndef __APPLE__ +#ifdef _WIN32 + wxGetApp().UpdateDarkUI(this); + wxGetApp().UpdateDarkUI(p->scrolled); +#else SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif #endif // Sizer in the scrolled area @@ -648,7 +670,7 @@ Sidebar::Sidebar(Plater *parent) p->scrolled->SetSizer(scrolled_sizer); // Sizer with buttons for mode changing - p->mode_sizer = new ModeSizer(p->scrolled); + p->mode_sizer = new ModeSizer(p->scrolled, int(0.5 * wxGetApp().em_unit())); // The preset chooser p->sizer_presets = new wxFlexGridSizer(10, 1, 1, 2); @@ -660,6 +682,7 @@ Sidebar::Sidebar(Plater *parent) p->scrolled->SetDoubleBuffered(true); p->presets_panel = new wxPanel(p->scrolled, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + wxGetApp().UpdateDarkUI(p->presets_panel); p->presets_panel->SetSizer(p->sizer_presets); is_msw = true; @@ -763,11 +786,16 @@ Sidebar::Sidebar(Plater *parent) // regular buttons "Slice now" and "Export G-code" // const int scaled_height = p->btn_eject_device->GetBitmapHeight() + 4; +#ifdef _WIN32 + const int scaled_height = p->btn_export_gcode_removable->GetBitmapHeight(); +#else const int scaled_height = p->btn_export_gcode_removable->GetBitmapHeight() + 4; +#endif auto init_btn = [this](wxButton **btn, wxString label, const int button_height) { *btn = new wxButton(this, wxID_ANY, label, wxDefaultPosition, wxSize(-1, button_height), wxBU_EXACTFIT); (*btn)->SetFont(wxGetApp().bold_font()); + wxGetApp().UpdateDarkUI((*btn), true); }; init_btn(&p->btn_export_gcode, _L("Export G-code") + dots , scaled_height); @@ -779,8 +807,8 @@ Sidebar::Sidebar(Plater *parent) auto* complect_btns_sizer = new wxBoxSizer(wxHORIZONTAL); complect_btns_sizer->Add(p->btn_export_gcode, 1, wxEXPAND); - complect_btns_sizer->Add(p->btn_send_gcode); - complect_btns_sizer->Add(p->btn_export_gcode_removable); + complect_btns_sizer->Add(p->btn_send_gcode, 0, wxLEFT, margin_5); + complect_btns_sizer->Add(p->btn_export_gcode_removable, 0, wxLEFT, margin_5); // complect_btns_sizer->Add(p->btn_eject_device); @@ -958,7 +986,11 @@ void Sidebar::msw_rescale() p->btn_send_gcode->msw_rescale(); // p->btn_eject_device->msw_rescale(); p->btn_export_gcode_removable->msw_rescale(); - const int scaled_height = p->btn_export_gcode_removable->GetBitmap().GetHeight() + 4; +#ifdef _WIN32 + const int scaled_height = p->btn_export_gcode_removable->GetBitmapHeight(); +#else + const int scaled_height = p->btn_export_gcode_removable->GetBitmapHeight() + 4; +#endif p->btn_export_gcode->SetMinSize(wxSize(-1, scaled_height)); p->btn_reslice ->SetMinSize(wxSize(-1, scaled_height)); @@ -967,19 +999,29 @@ void Sidebar::msw_rescale() void Sidebar::sys_color_changed() { -#ifdef __WXMSW__ - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#ifdef _WIN32 + wxWindowUpdateLocker noUpdates(this); + + for (wxWindow* win : std::vector{ this, p->sliced_info->GetStaticBox(), p->object_info->GetStaticBox(), p->btn_reslice, p->btn_export_gcode }) + wxGetApp().UpdateDarkUI(win); + for (wxWindow* win : std::vector{ p->scrolled, p->presets_panel }) + wxGetApp().UpdateAllStaticTextDarkUI(win); + for (wxWindow* btn : std::vector{ p->btn_reslice, p->btn_export_gcode }) + wxGetApp().UpdateDarkUI(btn, true); + + p->mode_sizer->msw_rescale(); + p->frequently_changed_parameters->sys_color_changed(); + p->object_settings->sys_color_changed(); #endif for (PlaterPresetComboBox* combo : std::vector{ p->combo_print, p->combo_sla_print, p->combo_sla_material, p->combo_printer }) - combo->msw_rescale(); + combo->sys_color_changed(); for (PlaterPresetComboBox* combo : p->combos_filament) - combo->msw_rescale(); + combo->sys_color_changed(); - p->object_list->msw_rescale(); p->object_list->sys_color_changed(); p->object_manipulation->sys_color_changed(); p->object_layers->sys_color_changed(); @@ -1531,7 +1573,8 @@ struct Plater::priv if (dirty_state.is_dirty()) { MainFrame* mainframe = wxGetApp().mainframe; if (mainframe->can_save_as()) { - wxMessageDialog dlg(mainframe, _L("Do you want to save the changes to the current project ?"), wxString(SLIC3R_APP_NAME), wxYES_NO | wxCANCEL); + //wxMessageDialog dlg(mainframe, _L("Do you want to save the changes to the current project ?"), wxString(SLIC3R_APP_NAME), wxYES_NO | wxCANCEL); + MessageDialog dlg(mainframe, _L("Do you want to save the changes to the current project ?"), wxString(SLIC3R_APP_NAME), wxYES_NO | wxCANCEL); int res = dlg.ShowModal(); if (res == wxID_YES) mainframe->save_project_as(wxGetApp().plater()->get_project_filename()); @@ -2311,7 +2354,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ // Convert even if the object is big. convert_from_imperial_units(model, false); else if (model.looks_like_saved_in_meters()) { - wxMessageDialog msg_dlg(q, format_wxstr(_L_PLURAL( + //wxMessageDialog msg_dlg(q, format_wxstr(_L_PLURAL( + MessageDialog msg_dlg(q, format_wxstr(_L_PLURAL( "The object in file %s looks like saved in meters.\n" "Should I consider it as a saved in meters and convert it?", "Some objects in file %s look like saved in meters.\n" @@ -2322,7 +2366,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ model.convert_from_meters(true); } else if (model.looks_like_imperial_units()) { - wxMessageDialog msg_dlg(q, format_wxstr(_L_PLURAL( + //wxMessageDialog msg_dlg(q, format_wxstr(_L_PLURAL( + MessageDialog msg_dlg(q, format_wxstr(_L_PLURAL( "The object in file %s looks like saved in inches.\n" "Should I consider it as a saved in inches and convert it?", "Some objects in file %s look like saved in inches.\n" @@ -2334,7 +2379,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ } if (model.looks_like_multipart_object()) { - wxMessageDialog msg_dlg(q, _L( + //wxMessageDialog msg_dlg(q, _L( + MessageDialog msg_dlg(q, _L( "This file contains several objects positioned at multiple heights.\n" "Instead of considering them as multiple objects, should I consider\n" "this file as a single object having multiple parts?") + "\n", @@ -2345,7 +2391,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ } } else if ((wxGetApp().get_mode() == comSimple) && (type_3mf || type_any_amf) && model_has_advanced_features(model)) { - wxMessageDialog msg_dlg(q, _L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?")+"\n", + //wxMessageDialog msg_dlg(q, _L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?")+"\n", + MessageDialog msg_dlg(q, _L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?")+"\n", _L("Detected advanced data"), wxICON_WARNING | wxYES | wxNO); if (msg_dlg.ShowModal() == wxID_YES) { Slic3r::GUI::wxGetApp().save_mode(comAdvanced); @@ -2397,7 +2444,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ } if (new_model != nullptr && new_model->objects.size() > 1) { - wxMessageDialog msg_dlg(q, _L( + //wxMessageDialog msg_dlg(q, _L( + MessageDialog msg_dlg(q, _L( "Multiple objects were loaded for a multi-material printer.\n" "Instead of considering them as multiple objects, should I consider\n" "these files to represent a single object having multiple parts?") + "\n", @@ -3154,7 +3202,7 @@ void Plater::priv::replace_with_stl() fs::path out_path = dialog.GetPath().ToUTF8().data(); if (out_path.empty()) { - wxMessageDialog dlg(q, _L("File for the replace wasn't selected"), _L("Error during replace"), wxOK | wxOK_DEFAULT | wxICON_WARNING); + MessageDialog dlg(q, _L("File for the replace wasn't selected"), _L("Error during replace"), wxOK | wxOK_DEFAULT | wxICON_WARNING); dlg.ShowModal(); return; } @@ -3179,7 +3227,7 @@ void Plater::priv::replace_with_stl() } if (new_model.objects.size() > 1 || new_model.objects[0]->volumes.size() > 1) { - wxMessageDialog dlg(q, _L("Unable to replace with more than one volume"), _L("Error during replace"), wxOK | wxOK_DEFAULT | wxICON_WARNING); + MessageDialog dlg(q, _L("Unable to replace with more than one volume"), _L("Error during replace"), wxOK | wxOK_DEFAULT | wxICON_WARNING); dlg.ShowModal(); return; } @@ -3318,7 +3366,8 @@ void Plater::priv::reload_from_disk() } else { wxString message = _L("It is not allowed to change the file to reload") + " (" + from_u8(search.filename().string()) + ").\n" + _L("Do you want to retry") + " ?"; - wxMessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION); + //wxMessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION); + MessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION); if (dlg.ShowModal() != wxID_YES) return; } @@ -3432,7 +3481,8 @@ void Plater::priv::reload_from_disk() for (const wxString& s : fail_list) { message += s + "\n"; } - wxMessageDialog dlg(q, message, _L("Error during reload"), wxOK | wxOK_DEFAULT | wxICON_WARNING); + //wxMessageDialog dlg(q, message, _L("Error during reload"), wxOK | wxOK_DEFAULT | wxICON_WARNING); + MessageDialog dlg(q, message, _L("Error during reload"), wxOK | wxOK_DEFAULT | wxICON_WARNING); dlg.ShowModal(); } @@ -3808,7 +3858,8 @@ bool Plater::priv::warnings_dialog() text += it.first.message; } //text += "\n\nDo you still wish to export?"; - wxMessageDialog msg_wingow(this->q, from_u8(text), wxString(SLIC3R_APP_NAME " ") + _L("generated warnings"), wxOK); + //wxMessageDialog msg_wingow(this->q, from_u8(text), wxString(SLIC3R_APP_NAME " ") + _L("generated warnings"), wxOK); + MessageDialog msg_wingow(this->q, from_u8(text), wxString(SLIC3R_APP_NAME " ") + _L("generated warnings"), wxOK); const auto res = msg_wingow.ShowModal(); return res == wxID_OK; @@ -4841,7 +4892,8 @@ void Plater::load_gcode(const wxString& filename) p->preview->get_canvas3d()->zoom_to_gcode(); if (p->preview->get_canvas3d()->get_gcode_layers_zs().empty()) { - wxMessageDialog(this, _L("The selected file") + ":\n" + filename + "\n" + _L("does not contain valid gcode."), + //wxMessageDialog(this, _L("The selected file") + ":\n" + filename + "\n" + _L("does not contain valid gcode."), + MessageDialog(this, _L("The selected file") + ":\n" + filename + "\n" + _L("does not contain valid gcode."), wxString(GCODEVIEWER_APP_NAME) + " - " + _L("Error while loading .gcode file"), wxCLOSE | wxICON_WARNING | wxCENTRE).ShowModal(); set_project_filename(wxEmptyString); } @@ -4953,7 +5005,8 @@ bool Plater::load_files(const wxArrayString& filenames) } if (paths.size() > 1) { - wxMessageDialog(static_cast(this), _L("You can open only one .gcode file at a time."), + //wxMessageDialog(static_cast(this), _L("You can open only one .gcode file at a time."), + MessageDialog(static_cast(this), _L("You can open only one .gcode file at a time."), wxString(SLIC3R_APP_NAME) + " - " + _L("Drag and drop G-code file"), wxCLOSE | wxICON_WARNING | wxCENTRE).ShowModal(); return false; } @@ -5083,7 +5136,8 @@ void Plater::reset() { p->reset(); } void Plater::reset_with_confirm() { if (p->model.objects.empty() || - wxMessageDialog(static_cast(this), _L("All objects will be removed, continue?"), wxString(SLIC3R_APP_NAME) + " - " + _L("Delete all"), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES) + //wxMessageDialog(static_cast(this), _L("All objects will be removed, continue?"), wxString(SLIC3R_APP_NAME) + " - " + _L("Delete all"), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES) + MessageDialog(static_cast(this), _L("All objects will be removed, continue?"), wxString(SLIC3R_APP_NAME) + " - " + _L("Delete all"), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES) reset(); } @@ -5156,6 +5210,26 @@ void Plater::decrease_instances(size_t num) this->p->schedule_background_process(); } +static long GetNumberFromUser( const wxString& msg, + const wxString& prompt, + const wxString& title, + long value, + long min, + long max, + wxWindow* parent) +{ +#ifdef _WIN32 + wxNumberEntryDialog dialog(parent, msg, prompt, title, value, min, max, wxDefaultPosition); + wxGetApp().UpdateDlgDarkUI(&dialog); + if (dialog.ShowModal() == wxID_OK) + return dialog.GetValue(); + + return -1; +#else + return wxGetNumberFromUser(msg, prompt, title, value, min, max, parent); +#endif +} + void Plater::set_number_of_copies(/*size_t num*/) { int obj_idx = p->get_selected_object_idx(); @@ -5164,7 +5238,7 @@ void Plater::set_number_of_copies(/*size_t num*/) ModelObject* model_object = p->model.objects[obj_idx]; - const int num = wxGetNumberFromUser( " ", _L("Enter the number of copies:"), + const int num = GetNumberFromUser( " ", _L("Enter the number of copies:"), _L("Copies of the selected object"), model_object->instances.size(), 0, 1000, this ); if (num < 0) return; @@ -6292,8 +6366,7 @@ void Plater::sys_color_changed() p->preview->sys_color_changed(); p->sidebar->sys_color_changed(); - // msw_rescale_menu updates just icons, so use it - p->menus.msw_rescale(); + p->menus.sys_color_changed(); Layout(); GetParent()->Layout(); diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index e884db13a..6626ce9a5 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -2,9 +2,11 @@ #include "OptionsGroup.hpp" #include "GUI_App.hpp" #include "Plater.hpp" +#include "MsgDialog.hpp" #include "I18N.hpp" #include "libslic3r/AppConfig.hpp" #include +#include namespace Slic3r { namespace GUI { @@ -19,7 +21,7 @@ PreferencesDialog::PreferencesDialog(wxWindow* parent) : build(); } -static std::shared_ptrcreate_options_tab(const wxString& title, wxNotebook* tabs) +static std::shared_ptrcreate_options_tab(const wxString& title, wxBookCtrlBase* tabs) { wxPanel* tab = new wxPanel(tabs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); tabs->AddPage(tab, title); @@ -44,15 +46,30 @@ static void activate_options_tab(std::shared_ptr optgroup) void PreferencesDialog::build() { +#ifdef _WIN32 + wxGetApp().UpdateDarkUI(this); +#else SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif const wxFont& font = wxGetApp().normal_font(); SetFont(font); auto app_config = get_app_config(); - wxNotebook* tabs = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME); -#ifdef __WXMSW__ - tabs->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#ifdef _MSW_DARK_MODE + wxBookCtrlBase* tabs; + if (wxGetApp().dark_mode()) { + tabs = new wxListbook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME | wxNO_BORDER); + wxGetApp().UpdateDarkUI(tabs); + wxGetApp().UpdateDarkUI(dynamic_cast(tabs)->GetListView()); + } + else { + tabs = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME | wxNB_DEFAULT); + tabs->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + } +#else + wxNotebook* tabs = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL |wxNB_NOPAGETHEME | wxNB_DEFAULT ); + tabs->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); #endif // Add "General" tab @@ -320,6 +337,24 @@ void PreferencesDialog::build() option = Option(def, "order_volumes"); m_optgroup_gui->append_single_option_line(option); +#ifdef _MSW_DARK_MODE + def.label = L("Use Dark color mode (experimental)"); + def.type = coBool; + def.tooltip = L("If enabled, UI will use Dark mode colors. " + "If disabled, old UI will be used."); + def.set_default_value(new ConfigOptionBool{ app_config->get("dark_color_mode") == "1" }); + option = Option(def, "dark_color_mode"); + m_optgroup_gui->append_single_option_line(option); +#endif + + def.label = L("Set settings tabs as menu items (experimental)"); + def.type = coBool; + def.tooltip = L("If enabled, Settings Tabs will be placed as menu items. " + "If disabled, old UI will be used."); + def.set_default_value(new ConfigOptionBool{ app_config->get("tabs_as_menu") == "1" }); + option = Option(def, "tabs_as_menu"); + m_optgroup_gui->append_single_option_line(option); + def.label = L("Use custom size for toolbar icons"); def.type = coBool; def.tooltip = L("If enabled, you can change size of toolbar icons manually."); @@ -363,6 +398,10 @@ void PreferencesDialog::build() auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL); wxButton* btn = static_cast(FindWindowById(wxID_OK, this)); btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { accept(); }); + + wxGetApp().UpdateDarkUI(btn); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CANCEL, this))); + sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM | wxTOP, 10); SetSizer(sizer); @@ -372,8 +411,43 @@ void PreferencesDialog::build() void PreferencesDialog::accept() { - if (m_values.find("no_defaults") != m_values.end()) - warning_catcher(this, wxString::Format(_L("You need to restart %s to make the changes effective."), SLIC3R_APP_NAME)); +// if (m_values.find("no_defaults") != m_values.end() +// warning_catcher(this, wxString::Format(_L("You need to restart %s to make the changes effective."), SLIC3R_APP_NAME)); + + std::vector options_to_recreate_GUI = { "no_defaults", "tabs_as_menu" +#ifdef _MSW_DARK_MODE + ,"dark_color_mode" +#endif + }; + + for (const std::string& option : options_to_recreate_GUI) { + if (m_values.find(option) != m_values.end()) { + wxString title = wxGetApp().is_editor() ? wxString(SLIC3R_APP_NAME) : wxString(GCODEVIEWER_APP_NAME); + title += " - " + _L("Changes for the critical options"); + MessageDialog dialog(nullptr, + _L("Changing fo some options will trigger application restart.\n" + "You will lose content of the plater.") + "\n\n" + + _L("Do you want to proceed?"), + title, + wxICON_QUESTION | wxYES | wxNO); + if (dialog.ShowModal() == wxID_YES) { + m_recreate_GUI = true; +#ifdef _MSW_DARK_MODE + m_color_mode_changed = m_values.find("dark_color_mode") != m_values.end(); +#endif + } + else { + for (const std::string& option : options_to_recreate_GUI) + m_values.erase(option); + } + break; + } + } + + if (m_values.empty()) { + EndModal(wxID_CANCEL); + return; + } auto app_config = get_app_config(); @@ -405,6 +479,11 @@ void PreferencesDialog::accept() m_values.erase(it); // we shouldn't change value, if some of those parameters was selected, and then deselected } +#if 0 //#ifdef _WIN32 // #ysDarkMSW - Allow it when we deside to support the sustem colors for application + if (m_values.find("always_dark_color_mode") != m_values.end()) + wxGetApp().force_sys_colors_update(); +#endif + for (std::map::iterator it = m_values.begin(); it != m_values.end(); ++it) app_config->set(it->first, it->second); @@ -453,6 +532,7 @@ void PreferencesDialog::create_icon_size_slider() m_icon_size_sizer = new wxBoxSizer(wxHORIZONTAL); wxWindow* parent = m_optgroup_gui->parent(); + wxGetApp().UpdateDarkUI(parent); if (isOSX) // For correct rendering of the slider and value label under OSX @@ -505,31 +585,59 @@ void PreferencesDialog::create_icon_size_slider() void PreferencesDialog::create_settings_mode_widget() { - wxString choices[] = { _L("Old regular layout with the tab bar"), - _L("New layout, access via settings button in the top menu"), - _L("Settings in non-modal window") }; + bool dark_mode = wxGetApp().dark_mode(); + std::vector choices = { _L("Old regular layout with the tab bar"), + _L("New layout, access via settings button in the top menu"), + _L("Settings in non-modal window") }; auto app_config = get_app_config(); - int selection = app_config->get("old_settings_layout_mode") == "1" ? 0 : - app_config->get("new_settings_layout_mode") == "1" ? 1 : - app_config->get("dlg_settings_layout_mode") == "1" ? 2 : 0; + int selection = app_config->get("old_settings_layout_mode") == "1" ? 0 : + app_config->get("new_settings_layout_mode") == "1" ? 1 : + app_config->get("dlg_settings_layout_mode") == "1" ? 2 : 0; + +#ifdef _MSW_DARK_MODE + if (dark_mode) { + choices = { _L("Old regular layout with the tab bar"), + _L("Settings in non-modal window") }; + selection = app_config->get("dlg_settings_layout_mode") == "1" ? 1 : 0; + } +#endif wxWindow* parent = m_optgroup_gui->parent(); + wxGetApp().UpdateDarkUI(parent); - m_layout_mode_box = new wxRadioBox(parent, wxID_ANY, _L("Layout Options"), wxDefaultPosition, wxDefaultSize, - WXSIZEOF(choices), choices, 3, wxRA_SPECIFY_ROWS); - m_layout_mode_box->SetFont(wxGetApp().normal_font()); - m_layout_mode_box->SetSelection(selection); + wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _L("Layout Options")); + wxGetApp().UpdateDarkUI(stb); + if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); + stb->SetFont(wxGetApp().normal_font()); - m_layout_mode_box->Bind(wxEVT_RADIOBOX, [this](wxCommandEvent& e) { - int selection = e.GetSelection(); - m_values["old_settings_layout_mode"] = boost::any_cast(selection == 0) ? "1" : "0"; - m_values["new_settings_layout_mode"] = boost::any_cast(selection == 1) ? "1" : "0"; - m_values["dlg_settings_layout_mode"] = boost::any_cast(selection == 2) ? "1" : "0"; - }); + wxSizer* stb_sizer = new wxStaticBoxSizer(stb, wxVERTICAL); + + int id = 0; + for (const wxString& label : choices) { + wxRadioButton* btn = new wxRadioButton(parent, wxID_ANY, label, wxDefaultPosition, wxDefaultSize, id==0 ? wxRB_GROUP : 0); + stb_sizer->Add(btn); + btn->SetValue(id == selection); + + int dlg_id = 2; +#ifdef _MSW_DARK_MODE + if (dark_mode) + dlg_id = 1; +#endif + + btn->Bind(wxEVT_RADIOBUTTON, [this, id, dlg_id, dark_mode](wxCommandEvent& ) { + m_values["old_settings_layout_mode"] = (id == 0) ? "1" : "0"; +#ifdef _MSW_DARK_MODE + if (!dark_mode) + m_values["new_settings_layout_mode"] = (id == 1) ? "1" : "0"; +#endif + m_values["dlg_settings_layout_mode"] = (id == dlg_id) ? "1" : "0"; + }); + id++; + } auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(m_layout_mode_box, 1, wxALIGN_CENTER_VERTICAL); + sizer->Add(/*m_layout_mode_box*/stb_sizer, 1, wxALIGN_CENTER_VERTICAL); m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit()); } @@ -538,6 +646,7 @@ void PreferencesDialog::create_settings_text_color_widget() wxWindow* parent = m_optgroup_gui->parent(); wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _L("Text color Settings")); + wxGetApp().UpdateDarkUI(stb); if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); wxSizer* sizer = new wxStaticBoxSizer(stb, wxVERTICAL); @@ -547,6 +656,7 @@ void PreferencesDialog::create_settings_text_color_widget() auto sys_label = new wxStaticText(parent, wxID_ANY, _L("Value is the same as the system value")); sys_label->SetForegroundColour(wxGetApp().get_label_clr_sys()); m_sys_colour = new wxColourPickerCtrl(parent, wxID_ANY, wxGetApp().get_label_clr_sys()); + wxGetApp().UpdateDarkUI(m_sys_colour->GetPickerCtrl(), true); m_sys_colour->Bind(wxEVT_COLOURPICKER_CHANGED, [this, sys_label](wxCommandEvent&) { sys_label->SetForegroundColour(m_sys_colour->GetColour()); sys_label->Refresh(); @@ -558,6 +668,7 @@ void PreferencesDialog::create_settings_text_color_widget() auto mod_label = new wxStaticText(parent, wxID_ANY, _L("Value was changed and is not equal to the system value or the last saved preset")); mod_label->SetForegroundColour(wxGetApp().get_label_clr_modified()); m_mod_colour = new wxColourPickerCtrl(parent, wxID_ANY, wxGetApp().get_label_clr_modified()); + wxGetApp().UpdateDarkUI(m_mod_colour->GetPickerCtrl(), true); m_mod_colour->Bind(wxEVT_COLOURPICKER_CHANGED, [this, mod_label](wxCommandEvent&) { mod_label->SetForegroundColour(m_mod_colour->GetColour()); mod_label->Refresh(); diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index 68e75662a..2ad3858ad 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -34,7 +34,10 @@ class PreferencesDialog : public DPIDialog #if ENABLE_GCODE_LINES_ID_IN_H_SLIDER bool m_seq_top_gcode_indices_changed{ false }; #endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER - + bool m_recreate_GUI{false}; +#ifdef _MSW_DARK_MODE + bool m_color_mode_changed {false}; +#endif public: explicit PreferencesDialog(wxWindow* parent); ~PreferencesDialog() = default; @@ -44,7 +47,10 @@ public: #if ENABLE_GCODE_LINES_ID_IN_H_SLIDER bool seq_seq_top_gcode_indices_changed() const { return m_seq_top_gcode_indices_changed; } #endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER - + bool recreate_GUI() const { return m_recreate_GUI; } +#ifdef _MSW_DARK_MODE + bool color_mode_changed() const { return m_color_mode_changed; } +#endif void build(); void accept(); diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index 7630c44bb..aab8c2829 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -13,6 +13,13 @@ #include #include #include +#include +#include + +#ifdef _WIN32 +#include +#include +#endif #include "libslic3r/libslic3r.h" #include "libslic3r/PrintConfig.hpp" @@ -31,6 +38,7 @@ #include "BitmapCache.hpp" #include "PhysicalPrinterDialog.hpp" #include "SavePresetDialog.hpp" +#include "MsgDialog.hpp" // A workaround for a set of issues related to text fitting into gtk widgets: // See e.g.: https://github.com/prusa3d/PrusaSlicer/issues/4584 @@ -63,19 +71,12 @@ namespace GUI { **/ PresetComboBox::PresetComboBox(wxWindow* parent, Preset::Type preset_type, const wxSize& size, PresetBundle* preset_bundle/* = nullptr*/) : - wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, size, 0, nullptr, wxCB_READONLY), + BitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, size, 0, nullptr, wxCB_READONLY), m_type(preset_type), m_last_selected(wxNOT_FOUND), m_em_unit(em_unit(this)), m_preset_bundle(preset_bundle ? preset_bundle : wxGetApp().preset_bundle) { - SetFont(wxGetApp().normal_font()); -#ifdef _WIN32 - // Workaround for ignoring CBN_EDITCHANGE events, which are processed after the content of the combo box changes, so that - // the index of the item inside CBN_EDITCHANGE may no more be valid. - EnableTextChangedEvents(false); -#endif /* _WIN32 */ - switch (m_type) { case Preset::TYPE_PRINT: { @@ -335,7 +336,8 @@ bool PresetComboBox::del_physical_printer(const wxString& note_string/* = wxEmpt msg += note_string + "\n"; msg += format_wxstr(_L("Are you sure you want to delete \"%1%\" printer?"), printer_name); - if (wxMessageDialog(this, msg, _L("Delete Physical Printer"), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal() != wxID_YES) + //if (wxMessageDialog(this, msg, _L("Delete Physical Printer"), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal() != wxID_YES) + if (MessageDialog(this, msg, _L("Delete Physical Printer"), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal() != wxID_YES) return false; m_preset_bundle->physical_printers.delete_selected_printer(); @@ -383,6 +385,12 @@ void PresetComboBox::msw_rescale() update(); } +void PresetComboBox::sys_color_changed() +{ + wxGetApp().UpdateDarkUI(this); + msw_rescale(); +} + void PresetComboBox::fill_width_height() { // To avoid asserts, each added bitmap to wxBitmapCombobox should be the same size, so @@ -532,72 +540,6 @@ bool PresetComboBox::selection_is_changed_according_to_physical_printers() return true; } -#ifdef __APPLE__ -bool PresetComboBox::OnAddBitmap(const wxBitmap& bitmap) -{ - if (bitmap.IsOk()) - { - // we should use scaled! size values of bitmap - int width = (int)bitmap.GetScaledWidth(); - int height = (int)bitmap.GetScaledHeight(); - - if (m_usedImgSize.x < 0) - { - // If size not yet determined, get it from this image. - m_usedImgSize.x = width; - m_usedImgSize.y = height; - - // Adjust control size to vertically fit the bitmap - wxWindow* ctrl = GetControl(); - ctrl->InvalidateBestSize(); - wxSize newSz = ctrl->GetBestSize(); - wxSize sz = ctrl->GetSize(); - if (newSz.y > sz.y) - ctrl->SetSize(sz.x, newSz.y); - else - DetermineIndent(); - } - - wxCHECK_MSG(width == m_usedImgSize.x && height == m_usedImgSize.y, - false, - "you can only add images of same size"); - - return true; - } - - return false; -} - -void PresetComboBox::OnDrawItem(wxDC& dc, - const wxRect& rect, - int item, - int flags) const -{ - const wxBitmap& bmp = *(static_cast(m_bitmaps[item])); - if (bmp.IsOk()) - { - // we should use scaled! size values of bitmap - wxCoord w = bmp.GetScaledWidth(); - wxCoord h = bmp.GetScaledHeight(); - - const int imgSpacingLeft = 4; - - // Draw the image centered - dc.DrawBitmap(bmp, - rect.x + (m_usedImgSize.x - w) / 2 + imgSpacingLeft, - rect.y + (rect.height - h) / 2, - true); - } - - wxString text = GetString(item); - if (!text.empty()) - dc.DrawText(text, - rect.x + m_imgAreaWidth + 1, - rect.y + (rect.height - dc.GetCharHeight()) / 2); -} -#endif - - // --------------------------------- // *** PlaterPresetComboBox *** // --------------------------------- diff --git a/src/slic3r/GUI/PresetComboBoxes.hpp b/src/slic3r/GUI/PresetComboBoxes.hpp index efcbec370..6e974676d 100644 --- a/src/slic3r/GUI/PresetComboBoxes.hpp +++ b/src/slic3r/GUI/PresetComboBoxes.hpp @@ -1,11 +1,12 @@ #ifndef slic3r_PresetComboBoxes_hpp_ #define slic3r_PresetComboBoxes_hpp_ -#include +//#include #include #include "libslic3r/Preset.hpp" #include "wxExtensions.hpp" +#include "BitmapComboBox.hpp" #include "GUI_Utils.hpp" class wxString; @@ -28,7 +29,7 @@ class BitmapCache; // --------------------------------- // BitmapComboBox used to presets list on Sidebar and Tabs -class PresetComboBox : public wxBitmapComboBox +class PresetComboBox : public BitmapComboBox { bool m_show_all { false }; public: @@ -71,6 +72,7 @@ public: void show_all(bool show_all); virtual void update(); virtual void msw_rescale(); + virtual void sys_color_changed(); virtual void OnSelect(wxCommandEvent& evt); protected: @@ -126,21 +128,6 @@ protected: wxBitmap* get_bmp( std::string bitmap_key, const std::string& main_icon_name, const std::string& next_icon_name, bool is_enabled = true, bool is_compatible = true, bool is_system = false); -#ifdef __APPLE__ - /* For PresetComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina - * (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean - * "please scale this to such and such" but rather - * "the wxImage is already sized for backing scale such and such". ) - * Unfortunately, the constructor changes the size of wxBitmap too. - * Thus We need to use unscaled size value for bitmaps that we use - * to avoid scaled size of control items. - * For this purpose control drawing methods and - * control size calculation methods (virtual) are overridden. - **/ - bool OnAddBitmap(const wxBitmap& bitmap) override; - void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override; -#endif - private: void fill_width_height(); }; diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp index 935746a64..9b07157fd 100644 --- a/src/slic3r/GUI/PrintHostDialogs.cpp +++ b/src/slic3r/GUI/PrintHostDialogs.cpp @@ -92,7 +92,8 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, bool can_start_pr // .gcode suffix control if (!path.Lower().EndsWith(suffix.Lower())) { - wxMessageDialog msg_wingow(this, wxString::Format(_L("Upload filename doesn't end with \"%s\". Do you wish to continue?"), suffix), wxString(SLIC3R_APP_NAME), wxYES | wxNO); + //wxMessageDialog msg_wingow(this, wxString::Format(_L("Upload filename doesn't end with \"%s\". Do you wish to continue?"), suffix), wxString(SLIC3R_APP_NAME), wxYES | wxNO); + MessageDialog msg_wingow(this, wxString::Format(_L("Upload filename doesn't end with \"%s\". Do you wish to continue?"), suffix), wxString(SLIC3R_APP_NAME), wxYES | wxNO); if (msg_wingow.ShowModal() == wxID_NO) return; } @@ -238,6 +239,9 @@ PrintHostQueueDialog::PrintHostQueueDialog(wxWindow *parent) topsizer->Add(btnsizer, 0, wxEXPAND); SetSizer(topsizer); + wxGetApp().UpdateDlgDarkUI(this); + wxGetApp().UpdateDVCDarkUI(job_list); + std::vector size; SetSize(load_user_data(UDT_SIZE, size) ? wxSize(size[0] * em, size[1] * em) : wxSize(HEIGHT * em, WIDTH * em)); diff --git a/src/slic3r/GUI/ProgressStatusBar.cpp b/src/slic3r/GUI/ProgressStatusBar.cpp index 1ec2b8193..10c391161 100644 --- a/src/slic3r/GUI/ProgressStatusBar.cpp +++ b/src/slic3r/GUI/ProgressStatusBar.cpp @@ -28,6 +28,7 @@ ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id) wxDefaultSize)} , m_timer{new wxTimer(self)} { + update_dark_ui(); m_prog->Hide(); m_cancelbutton->Hide(); @@ -68,6 +69,13 @@ ProgressStatusBar::~ProgressStatusBar() { if(m_timer && m_timer->IsRunning()) m_timer->Stop(); } +void ProgressStatusBar::update_dark_ui() +{ + GUI::wxGetApp().UpdateDarkUI(self); + GUI::wxGetApp().UpdateDarkUI(m_prog); + GUI::wxGetApp().UpdateDarkUI(m_cancelbutton); +} + int ProgressStatusBar::get_progress() const { return m_prog ? m_prog->GetValue() : 0; diff --git a/src/slic3r/GUI/ProgressStatusBar.hpp b/src/slic3r/GUI/ProgressStatusBar.hpp index 15b10deeb..73c046be6 100644 --- a/src/slic3r/GUI/ProgressStatusBar.hpp +++ b/src/slic3r/GUI/ProgressStatusBar.hpp @@ -61,6 +61,8 @@ public: void show_cancel_button(); void hide_cancel_button(); + void update_dark_ui(); + private: bool m_busy = false; CancelFn m_cancel_cb; diff --git a/src/slic3r/GUI/RammingChart.cpp b/src/slic3r/GUI/RammingChart.cpp index dbd6bfad6..244d83a9b 100644 --- a/src/slic3r/GUI/RammingChart.cpp +++ b/src/slic3r/GUI/RammingChart.cpp @@ -3,6 +3,7 @@ #include "RammingChart.hpp" #include "GUI.hpp" +#include "GUI_App.hpp" #include "I18N.hpp" wxDEFINE_EVENT(EVT_WIPE_TOWER_CHART_CHANGED, wxCommandEvent); @@ -15,8 +16,13 @@ void Chart::draw() { dc.SetPen(GetBackgroundColour()); dc.DrawRectangle(GetClientRect()); // otherwise the background would end up black on windows +#ifdef _WIN32 + dc.SetPen(wxPen(GetForegroundColour())); + dc.SetBrush(wxBrush(Slic3r::GUI::wxGetApp().get_highlight_default_clr())); +#else dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxWHITE_BRUSH); +#endif dc.DrawRectangle(m_rect); if (visible_area.m_width < 0.499) { @@ -31,7 +37,11 @@ void Chart::draw() { dc.SetPen( wxPen( wxColor(std::min(255,color),255-std::max(color-255,0),0), 1 ) ); dc.DrawLine(m_rect.GetLeft()+1+i,(m_line_to_draw)[i],m_rect.GetLeft()+1+i,m_rect.GetBottom()); } +#ifdef _WIN32 + dc.SetPen(wxPen(GetForegroundColour())); +#else dc.SetPen( wxPen( wxColor(0,0,0), 1 ) ); +#endif for (unsigned int i=0;iAssociateModel(search_list_model); @@ -442,6 +447,7 @@ SearchDialog::SearchDialog(OptionsSearcher* searcher) check_english = new wxCheckBox(this, wxID_ANY, _L("Search in English")); wxStdDialogButtonSizer* cancel_btn = this->CreateStdDialogButtonSizer(wxCANCEL); + GUI::wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CANCEL, this))); check_sizer->Add(new wxStaticText(this, wxID_ANY, _L("Use for search") + ":"), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, border); check_sizer->Add(check_category, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, border); @@ -656,6 +662,13 @@ void SearchDialog::on_dpi_changed(const wxRect& suggested_rect) void SearchDialog::on_sys_color_changed() { +#ifdef _WIN32 + GUI::wxGetApp().UpdateAllStaticTextDarkUI(this); + GUI::wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CANCEL, this)), true); + for (wxWindow* win : std::vector {search_line, search_list, check_category, check_english}) + if (win) GUI::wxGetApp().UpdateDarkUI(win); +#endif + // msw_rescale updates just icons, so use it search_list_model->msw_rescale(); diff --git a/src/slic3r/GUI/SysInfoDialog.cpp b/src/slic3r/GUI/SysInfoDialog.cpp index 606bb9f88..4dddf13c1 100644 --- a/src/slic3r/GUI/SysInfoDialog.cpp +++ b/src/slic3r/GUI/SysInfoDialog.cpp @@ -82,7 +82,7 @@ std::string get_mem_info(bool format_as_html) SysInfoDialog::SysInfoDialog() : DPIDialog(static_cast(wxGetApp().mainframe), wxID_ANY, (wxGetApp().is_editor() ? wxString(SLIC3R_APP_NAME) : wxString(GCODEVIEWER_APP_NAME)) + " - " + _L("System Information"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + wxColour bgr_clr = wxGetApp().get_window_default_clr();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); SetBackgroundColour(bgr_clr); SetFont(wxGetApp().normal_font()); @@ -112,7 +112,7 @@ SysInfoDialog::SysInfoDialog() // main_info_text wxFont font = get_default_font(this); - const auto text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + const auto text_clr = wxGetApp().get_label_clr_default();//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()); @@ -169,6 +169,9 @@ SysInfoDialog::SysInfoDialog() this->SetEscapeId(wxID_OK); this->Bind(wxEVT_BUTTON, &SysInfoDialog::onCloseDialog, this, wxID_OK); main_sizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3); + + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_OK, this)), true); + wxGetApp().UpdateDarkUI(m_btn_copy_to_clipboard, true); // this->Bind(wxEVT_LEFT_DOWN, &SysInfoDialog::onCloseDialog, this); // logo->Bind(wxEVT_LEFT_DOWN, &SysInfoDialog::onCloseDialog, this); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 60bd36e7f..b74048fe0 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -43,6 +43,7 @@ #include "PhysicalPrinterDialog.hpp" #include "UnsavedChangesDialog.hpp" #include "SavePresetDialog.hpp" +#include "MsgDialog.hpp" #ifdef WIN32 #include @@ -100,12 +101,14 @@ void Tab::Highlighter::blink() invalidate(); } -Tab::Tab(wxNotebook* parent, const wxString& title, Preset::Type type) : +Tab::Tab(wxBookCtrlBase* parent, const wxString& title, Preset::Type type) : m_parent(parent), m_title(title), m_type(type) { Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL/*, name*/); this->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + wxGetApp().UpdateDarkUI(this); + m_compatible_printers.type = Preset::TYPE_PRINTER; m_compatible_printers.key_list = "compatible_printers"; m_compatible_printers.key_condition = "compatible_printers_condition"; @@ -253,7 +256,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 ModeSizer(panel); + m_mode_sizer = new ModeSizer(panel, int (0.5*em_unit(this))); const float scale_factor = /*wxGetApp().*/em_unit(this)*0.1;// GetContentScaleFactor(); m_hsizer = new wxBoxSizer(wxHORIZONTAL); @@ -305,6 +308,7 @@ void Tab::create_preset_tab() m_treectrl->AssignImageList(m_icons); m_treectrl->AddRoot("root"); m_treectrl->SetIndent(0); + wxGetApp().UpdateDarkUI(m_treectrl); // Delay processing of the following handler until the message queue is flushed. // This helps to process all the cursor key events on Windows in the tree control, @@ -483,11 +487,25 @@ void Tab::OnActivate() // create controls on active page activate_selected_page([](){}); m_hsizer->Layout(); + + // Workaroud for Menu instead of NoteBook +#ifdef _MSW_DARK_MODE + if (wxGetApp().dark_mode()) { + wxSize sz = m_presets_choice->GetSize(); + wxSize ok_sz = wxSize(35 * m_em_unit, m_presets_choice->GetBestSize().y+1); + if (sz != ok_sz) { + m_presets_choice->SetMinSize(ok_sz); + m_presets_choice->SetSize(ok_sz); + GetSizer()->GetItem(size_t(0))->GetSizer()->Layout(); + } + } +#endif // _MSW_DARK_MODE Refresh(); } void Tab::update_label_colours() { + m_default_text_clr = wxGetApp().get_label_clr_default(); if (m_sys_label_clr == wxGetApp().get_label_clr_sys() && m_modified_label_clr == wxGetApp().get_label_clr_modified()) return; m_sys_label_clr = wxGetApp().get_label_clr_sys(); @@ -984,14 +1002,15 @@ void Tab::msw_rescale() void Tab::sys_color_changed() { - update_tab_ui(); - m_presets_choice->msw_rescale(); + m_presets_choice->sys_color_changed(); // update buttons and cached bitmaps for (const auto btn : m_scaled_buttons) btn->msw_rescale(); for (const auto bmp : m_scaled_bitmaps) bmp->msw_rescale(); + if (m_detach_preset_btn) + m_detach_preset_btn->msw_rescale(); // update icons for tree_ctrl for (ScalableBitmap& bmp : m_scaled_icons_list) @@ -1002,15 +1021,20 @@ void Tab::sys_color_changed() for (ScalableBitmap& bmp : m_scaled_icons_list) m_icons->Add(bmp.bmp()); m_treectrl->AssignImageList(m_icons); -#ifdef __WXMSW__ - m_treectrl->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -#endif + // Colors for ui "decoration" update_label_colours(); +#ifdef _WIN32 + wxWindowUpdateLocker noUpdates(this); + m_mode_sizer->msw_rescale(); + wxGetApp().UpdateDarkUI(this); + wxGetApp().UpdateDarkUI(m_treectrl); +#endif + update_changed_tree_ui(); // update options_groups if (m_active_page) - m_active_page->msw_rescale(); + m_active_page->sys_color_changed(); Layout(); } @@ -1271,7 +1295,8 @@ void Tab::build_preset_description_line(ConfigOptionsGroup* optgroup) msg_text += "\n\n"; msg_text += _(L("This action is not revertible.\nDo you want to proceed?")); - wxMessageDialog dialog(parent, msg_text, _(L("Detach preset")), wxICON_WARNING | wxYES_NO | wxCANCEL); + //wxMessageDialog dialog(parent, msg_text, _(L("Detach preset")), wxICON_WARNING | wxYES_NO | wxCANCEL); + MessageDialog dialog(parent, msg_text, _(L("Detach preset")), wxICON_WARNING | wxYES_NO | wxCANCEL); if (dialog.ShowModal() == wxID_YES) save_preset(m_presets->get_edited_preset().is_system ? std::string() : m_presets->get_edited_preset().name, true); }); @@ -1740,7 +1765,8 @@ bool Tab::validate_custom_gcode(const wxString& title, const std::string& gcode) reports += _L("contain reserved keywords.") + "\n"; reports += _L("Please remove them, as they may cause problems in g-code visualization and printing time estimation."); - wxMessageDialog dialog(wxGetApp().mainframe, reports, _L("Found reserved keywords in") + " " + _(title), wxICON_WARNING | wxOK); + //wxMessageDialog dialog(wxGetApp().mainframe, reports, _L("Found reserved keywords in") + " " + _(title), wxICON_WARNING | wxOK); + MessageDialog dialog(wxGetApp().mainframe, reports, _L("Found reserved keywords in") + " " + _(title), wxICON_WARNING | wxOK); dialog.ShowModal(); } return !invalid; @@ -1952,6 +1978,7 @@ void TabFilament::build() create_line_with_widget(optgroup.get(), "filament_ramming_parameters", wxEmptyString, [this](wxWindow* parent) { auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); + wxGetApp().UpdateDarkUI(ramming_dialog_btn); ramming_dialog_btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); ramming_dialog_btn->SetSize(ramming_dialog_btn->GetBestSize()); auto sizer = new wxBoxSizer(wxHORIZONTAL); @@ -2232,7 +2259,8 @@ void TabPrinter::build_fff() const wxString msg_text = _(L("Single Extruder Multi Material is selected, \n" "and all extruders must have the same diameter.\n" "Do you want to change the diameter for all extruders to first extruder nozzle diameter value?")); - wxMessageDialog dialog(parent(), msg_text, _(L("Nozzle diameter")), wxICON_WARNING | wxYES_NO); + //wxMessageDialog dialog(parent(), msg_text, _(L("Nozzle diameter")), wxICON_WARNING | wxYES_NO); + MessageDialog dialog(parent(), msg_text, _(L("Nozzle diameter")), wxICON_WARNING | wxYES_NO); DynamicPrintConfig new_conf = *m_config; if (dialog.ShowModal() == wxID_YES) { @@ -2690,7 +2718,8 @@ void TabPrinter::build_unregular_pages(bool from_initial_build/* = false*/) { const wxString msg_text = _(L("This is a single extruder multimaterial printer, diameters of all extruders " "will be set to the new value. Do you want to proceed?")); - wxMessageDialog dialog(parent(), msg_text, _(L("Nozzle diameter")), wxICON_WARNING | wxYES_NO); + //wxMessageDialog dialog(parent(), msg_text, _(L("Nozzle diameter")), wxICON_WARNING | wxYES_NO); + MessageDialog dialog(parent(), msg_text, _(L("Nozzle diameter")), wxICON_WARNING | wxYES_NO); DynamicPrintConfig new_conf = *m_config; if (dialog.ShowModal() == wxID_YES) { @@ -2921,7 +2950,8 @@ void TabPrinter::toggle_options() toggle_option("retract_before_wipe", wipe, i); if (use_firmware_retraction && wipe) { - wxMessageDialog dialog(parent(), + //wxMessageDialog dialog(parent(), + MessageDialog dialog(parent(), _(L("The Wipe option is not available when using the Firmware Retraction mode.\n" "\nShall I disable it in order to enable Firmware Retraction?")), _(L("Firmware Retraction")), wxICON_WARNING | wxYES | wxNO); @@ -3047,8 +3077,12 @@ void Tab::load_current_preset() Page* tmp_page = m_active_page; m_active_page = nullptr; for (auto tab : wxGetApp().tabs_list) { - if (tab->type() == Preset::TYPE_PRINTER) // Printer tab is shown every time + if (tab->type() == Preset::TYPE_PRINTER) { // Printer tab is shown every time + int cur_selection = wxGetApp().tab_panel()->GetSelection(); + if (cur_selection != 0) + wxGetApp().tab_panel()->SetSelection(wxGetApp().tab_panel()->GetPageCount() - 1); continue; + } if (tab->supports_printer_technology(printer_technology)) { wxGetApp().tab_panel()->InsertPage(wxGetApp().tab_panel()->FindPage(this), tab, tab->title()); @@ -3324,7 +3358,7 @@ void Tab::select_preset(std::string preset_name, bool delete_current /*=false*/, } if (technology_changed) - wxGetApp().mainframe->diff_dialog.update_presets(); + wxGetApp().mainframe->technology_changed(); } // If the current preset is dirty, the user is asked whether the changes may be discarded. @@ -3651,7 +3685,8 @@ void Tab::delete_preset() // TRN Remove/Delete wxString title = from_u8((boost::format(_utf8(L("%1% Preset"))) % action).str()); //action + _(L(" Preset")); if (current_preset.is_default || - wxID_YES != wxMessageDialog(parent(), msg, title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal()) + //wxID_YES != wxMessageDialog(parent(), msg, title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal()) + wxID_YES != MessageDialog(parent(), msg, title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal()) return; // if we just delete preset from the physical printer @@ -3730,6 +3765,7 @@ 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()); + wxGetApp().UpdateDarkUI(deps.checkbox, false, true); deps.btn = new ScalableButton(parent, wxID_ANY, "printer", from_u8((boost::format(" %s %s") % _utf8(L("Set")) % std::string(dots.ToUTF8())).str()), wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true); deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -3768,6 +3804,7 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep } wxMultiChoiceDialog dlg(parent, deps.dialog_title, deps.dialog_label, presets); + wxGetApp().UpdateDlgDarkUI(&dlg); // Collect and set indices of depending_presets marked as compatible. wxArrayInt selections; auto *compatible_printers = dynamic_cast(m_config->option(deps.key_list)); diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 601995ea7..762123e60 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -104,7 +105,7 @@ protected: using PageShp = std::shared_ptr; class Tab: public wxPanel { - wxNotebook* m_parent; + wxBookCtrlBase* m_parent; #ifdef __WXOSX__ wxPanel* m_tmp_panel; int m_size_move = -1; @@ -259,13 +260,11 @@ public: int m_update_cnt = 0; public: -// Tab(wxNotebook* parent, const wxString& title, const char* name); - Tab(wxNotebook* parent, const wxString& title, Preset::Type type); + Tab(wxBookCtrlBase* parent, const wxString& title, Preset::Type type); ~Tab() {} wxWindow* parent() const { return m_parent; } wxString title() const { return m_title; } -// std::string name() const { return m_name; } std::string name() const { return m_presets->name(); } Preset::Type type() const { return m_type; } // The tab is already constructed. @@ -386,9 +385,8 @@ protected: class TabPrint : public Tab { public: - TabPrint(wxNotebook* parent) : -// Tab(parent, _L("Print Settings"), L("print")) {} - Tab(parent, _L("Print Settings"), Slic3r::Preset::TYPE_PRINT) {} + TabPrint(wxBookCtrlBase* parent) : + Tab(parent, _(L("Print Settings")), Slic3r::Preset::TYPE_PRINT) {} ~TabPrint() {} void build() override; @@ -420,9 +418,8 @@ private: std::map m_overrides_options; public: - TabFilament(wxNotebook* parent) : -// Tab(parent, _L("Filament Settings"), L("filament")) {} - Tab(parent, _L("Filament Settings"), Slic3r::Preset::TYPE_FILAMENT) {} + TabFilament(wxBookCtrlBase* parent) : + Tab(parent, _(L("Filament Settings")), Slic3r::Preset::TYPE_FILAMENT) {} ~TabFilament() {} void build() override; @@ -466,8 +463,7 @@ public: PrinterTechnology m_printer_technology = ptFFF; -// TabPrinter(wxNotebook* parent) : Tab(parent, _(L("Printer Settings")), L("printer")) {} - TabPrinter(wxNotebook* parent) : + TabPrinter(wxBookCtrlBase* parent) : Tab(parent, _L("Printer Settings"), Slic3r::Preset::TYPE_PRINTER) {} ~TabPrinter() {} @@ -504,9 +500,8 @@ public: class TabSLAMaterial : public Tab { public: - TabSLAMaterial(wxNotebook* parent) : -// Tab(parent, _L("Material Settings"), L("sla_material")) {} - Tab(parent, _L("Material Settings"), Slic3r::Preset::TYPE_SLA_MATERIAL) {} + TabSLAMaterial(wxBookCtrlBase* parent) : + Tab(parent, _(L("Material Settings")), Slic3r::Preset::TYPE_SLA_MATERIAL) {} ~TabSLAMaterial() {} void build() override; @@ -524,9 +519,8 @@ public: class TabSLAPrint : public Tab { public: - TabSLAPrint(wxNotebook* parent) : -// Tab(parent, _L("Print Settings"), L("sla_print")) {} - Tab(parent, _L("Print Settings"), Slic3r::Preset::TYPE_SLA_PRINT) {} + TabSLAPrint(wxBookCtrlBase* parent) : + Tab(parent, _(L("Print Settings")), Slic3r::Preset::TYPE_SLA_PRINT) {} ~TabSLAPrint() {} ogStaticText* m_support_object_elevation_description_line = nullptr; diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index dc2c56246..9fb8a1e64 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -19,6 +19,7 @@ #include "wxExtensions.hpp" #include "SavePresetDialog.hpp" #include "MainFrame.hpp" +#include "MsgDialog.hpp" //#define FTS_FUZZY_MATCH_IMPLEMENTATION //#include "fts_fuzzy_match.h" @@ -56,7 +57,7 @@ static std::string get_icon_name(Preset::Type type, PrinterTechnology pt) { static std::string def_text_color() { - wxColour def_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + wxColour def_colour = wxGetApp().get_label_clr_default();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), def_colour.Red(), def_colour.Green(), def_colour.Blue()); return clr_str.ToStdString(); } @@ -581,9 +582,15 @@ static std::string get_pure_opt_key(std::string opt_key) // ---------------------------------------------------------------------------- DiffViewCtrl::DiffViewCtrl(wxWindow* parent, wxSize size) - : wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, size, wxBORDER_SIMPLE | wxDV_VARIABLE_LINE_HEIGHT | wxDV_ROW_LINES), + : wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, size, wxDV_VARIABLE_LINE_HEIGHT | wxDV_ROW_LINES +#ifdef _WIN32 + | wxBORDER_SIMPLE +#endif + ), m_em_unit(em_unit(parent)) { + wxGetApp().UpdateDVCDarkUI(this); + model = new DiffModel(parent); this->AssociateModel(model); model->SetAssociatedControl(this); @@ -789,9 +796,6 @@ UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, PresetCollection* void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header) { - wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - SetBackgroundColour(bgr_clr); - #if defined(__WXMSW__) // ys_FIXME! temporary workaround for correct font scaling // Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts, @@ -865,7 +869,8 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_ _L("You will not be asked about the unsaved changes the next time you switch a preset.")) + "\n\n" + format_wxstr(_L("Visit \"Preferences\" and check \"%1%\"\nto be asked about unsaved changes again."), preferences_item); - wxMessageDialog dialog(nullptr, msg, _L("PrusaSlicer: Don't ask me again"), wxOK | wxCANCEL | wxICON_INFORMATION); + //wxMessageDialog dialog(nullptr, msg, _L("PrusaSlicer: Don't ask me again"), wxOK | wxCANCEL | wxICON_INFORMATION); + MessageDialog dialog(nullptr, msg, _L("PrusaSlicer: Don't ask me again"), wxOK | wxCANCEL | wxICON_INFORMATION); if (dialog.ShowModal() == wxID_CANCEL) m_remember_choice->SetValue(false); }); @@ -1279,8 +1284,7 @@ void UnsavedChangesDialog::on_sys_color_changed() FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString& old_value, const wxString& new_value) : wxDialog(nullptr, wxID_ANY, option_name, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - SetBackgroundColour(bgr_clr); + wxGetApp().UpdateDarkUI(this); int border = 10; @@ -1323,7 +1327,8 @@ FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString std::set_difference(new_set.begin(), new_set.end(), old_set.begin(), old_set.end(), std::inserter(new_old_diff_set, new_old_diff_set.begin())); auto add_value = [grid_sizer, border, this](wxString label, const std::set& diff_set, bool is_colored = false) { - wxTextCtrl* text = new wxTextCtrl(this, wxID_ANY, label, wxDefaultPosition, wxSize(400, 400), wxTE_MULTILINE | wxTE_READONLY | wxBORDER_NONE | wxTE_RICH); + wxTextCtrl* text = new wxTextCtrl(this, wxID_ANY, label, wxDefaultPosition, wxSize(400, 400), wxTE_MULTILINE | wxTE_READONLY | wxBORDER_SIMPLE | wxTE_RICH); + wxGetApp().UpdateDarkUI(text); text->SetStyle(0, label.Len(), wxTextAttr(is_colored ? wxColour(orange) : wxNullColour, wxNullColour, this->GetFont())); for (const wxString& str : diff_set) { @@ -1341,6 +1346,7 @@ FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString sizer->Add(grid_sizer, 1, wxEXPAND); wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK); + wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_OK, this)), true); wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL); @@ -1375,9 +1381,6 @@ DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe) : DPIDialog(mainframe, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), m_pr_technology(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology()) { - wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - SetBackgroundColour(bgr_clr); - #if defined(__WXMSW__) // ys_FIXME! temporary workaround for correct font scaling // Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts, @@ -1673,6 +1676,17 @@ void DiffPresetDialog::on_dpi_changed(const wxRect&) void DiffPresetDialog::on_sys_color_changed() { +#ifdef _WIN32 + wxGetApp().UpdateAllStaticTextDarkUI(this); + wxGetApp().UpdateDarkUI(m_show_all_presets); + wxGetApp().UpdateDVCDarkUI(m_tree); +#endif + + for (auto preset_combos : m_preset_combos) { + preset_combos.presets_left->msw_rescale(); + preset_combos.equal_bmp->msw_rescale(); + preset_combos.presets_right->msw_rescale(); + } // msw_rescale updates just icons, so use it m_tree->Rescale(); Refresh(); diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp index 97a3e3880..c3189c4c1 100644 --- a/src/slic3r/GUI/UpdateDialogs.cpp +++ b/src/slic3r/GUI/UpdateDialogs.cpp @@ -137,6 +137,8 @@ MsgUpdateConfig::MsgUpdateConfig(const std::vector &updates) : btn_sizer->Add(btn_ok); btn_ok->SetFocus(); + wxGetApp().UpdateDlgDarkUI(this); + Fit(); } @@ -292,6 +294,8 @@ MsgDataLegacy::MsgDataLegacy() : content_sizer->Add(link); content_sizer->AddSpacer(VERT_SPACING); + wxGetApp().UpdateDlgDarkUI(this); + Fit(); } @@ -316,6 +320,8 @@ MsgNoUpdates::MsgNoUpdates() : logo->SetBitmap(create_scaled_bitmap("PrusaSlicer_192px_grayscale.png", this, 192)); + wxGetApp().UpdateDlgDarkUI(this); + Fit(); } diff --git a/src/slic3r/GUI/WipeTowerDialog.cpp b/src/slic3r/GUI/WipeTowerDialog.cpp index 1c3c831b8..71b87322f 100644 --- a/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/src/slic3r/GUI/WipeTowerDialog.cpp @@ -5,23 +5,32 @@ #include "GUI.hpp" #include "I18N.hpp" #include "GUI_App.hpp" +#include "MsgDialog.hpp" #include int scale(const int val) { return val * Slic3r::GUI::wxGetApp().em_unit(); } -int ITEM_WIDTH() { return scale(6); } +int ITEM_WIDTH() { return scale(6); } + +static void update_ui(wxWindow* window) +{ + Slic3r::GUI::wxGetApp().UpdateDarkUI(window); +} RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) : wxDialog(parent, wxID_ANY, _(L("Ramming customization")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE/* | wxRESIZE_BORDER*/) { + update_ui(this); m_panel_ramming = new RammingPanel(this,parameters); // Not found another way of getting the background colours of RammingDialog, RammingPanel and Chart correct than setting // them all explicitely. Reading the parent colour yielded colour that didn't really match it, no wxSYS_COLOUR_... matched // colour used for the dialog. Same issue (and "solution") here : https://forums.wxwidgets.org/viewtopic.php?f=1&t=39608 // Whoever can fix this, feel free to do so. +#ifndef _WIN32 this-> SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_FRAMEBK)); m_panel_ramming->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_FRAMEBK)); +#endif m_panel_ramming->Show(true); this->Show(); @@ -31,6 +40,9 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) SetSizer(main_sizer); main_sizer->SetSizeHints(this); + update_ui(static_cast(this->FindWindowById(wxID_OK, this))); + update_ui(static_cast(this->FindWindowById(wxID_CANCEL, this))); + this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { @@ -38,20 +50,28 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) EndModal(wxID_OK); },wxID_OK); this->Show(); - wxMessageDialog(this,_(L("Ramming denotes the rapid extrusion just before a tool change in a single-extruder MM printer. Its purpose is to " - "properly shape the end of the unloaded filament so it does not prevent insertion of the new filament and can itself " - "be reinserted later. This phase is important and different materials can require different extrusion speeds to get " - "the good shape. For this reason, the extrusion rates during ramming are adjustable.\n\nThis is an expert-level " - "setting, incorrect adjustment will likely lead to jams, extruder wheel grinding into filament etc.")),_(L("Warning")),wxOK|wxICON_EXCLAMATION).ShowModal(); +// wxMessageDialog dlg(this, _(L("Ramming denotes the rapid extrusion just before a tool change in a single-extruder MM printer. Its purpose is to " + Slic3r::GUI::MessageDialog dlg(this, _(L("Ramming denotes the rapid extrusion just before a tool change in a single-extruder MM printer. Its purpose is to " + "properly shape the end of the unloaded filament so it does not prevent insertion of the new filament and can itself " + "be reinserted later. This phase is important and different materials can require different extrusion speeds to get " + "the good shape. For this reason, the extrusion rates during ramming are adjustable.\n\nThis is an expert-level " + "setting, incorrect adjustment will likely lead to jams, extruder wheel grinding into filament etc.")), _(L("Warning")), wxOK | wxICON_EXCLAMATION);// .ShowModal(); + dlg.ShowModal(); } +#ifdef _WIN32 +#define style wxSP_ARROW_KEYS | wxBORDER_SIMPLE +#else +#define style wxSP_ARROW_KEYS +#endif RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize/*,wxPoint(50,50), wxSize(800,350),wxBORDER_RAISED*/) { + update_ui(this); auto sizer_chart = new wxBoxSizer(wxVERTICAL); auto sizer_param = new wxBoxSizer(wxVERTICAL); @@ -71,13 +91,24 @@ RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters) buttons.push_back(std::make_pair(x, y)); m_chart = new Chart(this, wxRect(scale(1),scale(1),scale(48),scale(36)), buttons, ramming_speed_size, 0.25f, scale(1)); +#ifdef _WIN32 + update_ui(m_chart); +#else m_chart->SetBackgroundColour(parent->GetBackgroundColour()); // see comment in RammingDialog constructor +#endif sizer_chart->Add(m_chart, 0, wxALL, 5); - m_widget_time = new wxSpinCtrlDouble(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),wxSP_ARROW_KEYS,0.,5.0,3.,0.5); - m_widget_volume = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),wxSP_ARROW_KEYS,0,10000,0); - m_widget_ramming_line_width_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),wxSP_ARROW_KEYS,10,200,100); - m_widget_ramming_step_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),wxSP_ARROW_KEYS,10,200,100); + m_widget_time = new wxSpinCtrlDouble(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),style,0.,5.0,3.,0.5); + m_widget_volume = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),style,0,10000,0); + m_widget_ramming_line_width_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),style,10,200,100); + m_widget_ramming_step_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(ITEM_WIDTH(), -1),style,10,200,100); + +#ifdef _WIN32 + update_ui(m_widget_time->GetText()); + update_ui(m_widget_volume); + update_ui(m_widget_ramming_line_width_multiplicator); + update_ui(m_widget_ramming_step_multiplicator); +#endif auto gsizer_param = new wxFlexGridSizer(2, 5, 15); gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Total ramming time")) + " (" + _(L("s")) + "):")), 0, wxALIGN_CENTER_VERTICAL); @@ -141,7 +172,9 @@ std::string RammingPanel::get_parameters() WipingDialog::WipingDialog(wxWindow* parent, const std::vector& matrix, const std::vector& extruders, const std::vector& extruder_colours) : wxDialog(parent, wxID_ANY, _(L("Wipe tower - Purging volume adjustment")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE/* | wxRESIZE_BORDER*/) { + update_ui(this); auto widget_button = new wxButton(this,wxID_ANY,"-",wxPoint(0,0),wxDefaultSize); + update_ui(widget_button); m_panel_wiping = new WipingPanel(this,matrix,extruders, extruder_colours, widget_button); auto main_sizer = new wxBoxSizer(wxVERTICAL); @@ -156,6 +189,9 @@ WipingDialog::WipingDialog(wxWindow* parent, const std::vector& matrix, c SetSizer(main_sizer); main_sizer->SetSizeHints(this); + update_ui(static_cast(this->FindWindowById(wxID_OK, this))); + update_ui(static_cast(this->FindWindowById(wxID_CANCEL, this))); + this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { // if OK button is clicked.. @@ -203,6 +239,9 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con m_page_simple->SetSizer(m_sizer_simple); m_page_advanced->SetSizer(m_sizer_advanced); + update_ui(m_page_simple); + update_ui(m_page_advanced); + auto gridsizer_simple = new wxGridSizer(3, 5, 10); m_gridsizer_advanced = new wxGridSizer(m_number_of_extruders+1, 5, 1); @@ -211,7 +250,13 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con edit_boxes.push_back(std::vector(0)); for (unsigned int j = 0; j < m_number_of_extruders; ++j) { +#ifdef _WIN32 + wxTextCtrl* text = new wxTextCtrl(m_page_advanced, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(ITEM_WIDTH(), -1), wxBORDER_SIMPLE); + update_ui(text); + edit_boxes.back().push_back(text); +#else edit_boxes.back().push_back(new wxTextCtrl(m_page_advanced, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(ITEM_WIDTH(), -1))); +#endif if (i == j) edit_boxes[i][j]->Disable(); else @@ -265,7 +310,8 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con auto add_spin_ctrl = [this](std::vector& vec, float initial) { - wxSpinCtrl* spin_ctrl = new wxSpinCtrl(m_page_simple, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(ITEM_WIDTH(), -1), wxSP_ARROW_KEYS | wxALIGN_RIGHT, 0, 300, (int)initial); + wxSpinCtrl* spin_ctrl = new wxSpinCtrl(m_page_simple, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(ITEM_WIDTH(), -1), style | wxALIGN_RIGHT, 0, 300, (int)initial); + update_ui(spin_ctrl); vec.push_back(spin_ctrl); #ifdef __WXOSX__ @@ -392,8 +438,9 @@ bool WipingPanel::advanced_matches_simple() { // Switches the dialog from simple to advanced mode and vice versa void WipingPanel::toggle_advanced(bool user_action) { if (m_advanced && !advanced_matches_simple() && user_action) { - if (wxMessageDialog(this,wxString(_(L("Switching to simple settings will discard changes done in the advanced mode!\n\nDo you want to proceed?"))), - wxString(_(L("Warning"))),wxYES_NO|wxICON_EXCLAMATION).ShowModal() != wxID_YES) +// if (wxMessageDialog(this,wxString(_(L("Switching to simple settings will discard changes done in the advanced mode!\n\nDo you want to proceed?"))), + if (Slic3r::GUI::MessageDialog(this, _L("Switching to simple settings will discard changes done in the advanced mode!\n\nDo you want to proceed?"), + _L("Warning"),wxYES_NO|wxICON_EXCLAMATION).ShowModal() != wxID_YES) return; } if (user_action) diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index c8b0dfd31..377f50b9b 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -15,6 +15,7 @@ #include "GUI_Utils.hpp" #include "Plater.hpp" #include "../Utils/MacDarkMode.hpp" +#include "BitmapComboBox.hpp" #ifndef __linux__ // msw_menuitem_bitmaps is used for MSW and OSX @@ -26,7 +27,7 @@ void msw_rescale_menu(wxMenu* menu) static void run(wxMenuItem* item) { const auto it = msw_menuitem_bitmaps.find(item->GetId()); if (it != msw_menuitem_bitmaps.end()) { - const wxBitmap& item_icon = create_scaled_bitmap(it->second); + const wxBitmap& item_icon = create_menu_bitmap(it->second); if (item_icon.IsOk()) item->SetBitmap(item_icon); } @@ -96,7 +97,7 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const if (id == wxID_ANY) id = wxNewId(); - const wxBitmap& bmp = !icon.empty() ? create_scaled_bitmap(icon) : wxNullBitmap; // FIXME: pass window ptr + const wxBitmap& bmp = !icon.empty() ? create_menu_bitmap(icon) : wxNullBitmap; // FIXME: pass window ptr //#ifdef __WXMSW__ #ifndef __WXGTK__ if (bmp.IsOk()) @@ -114,7 +115,7 @@ wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxStrin wxMenuItem* item = new wxMenuItem(menu, id, string, description); if (!icon.empty()) { - item->SetBitmap(create_scaled_bitmap(icon)); // FIXME: pass window ptr + item->SetBitmap(create_menu_bitmap(icon)); // FIXME: pass window ptr //#ifdef __WXMSW__ #ifndef __WXGTK__ msw_menuitem_bitmaps[id] = icon; @@ -416,13 +417,19 @@ int mode_icon_px_size() #endif } +wxBitmap create_menu_bitmap(const std::string& bmp_name) +{ + return create_scaled_bitmap(bmp_name, nullptr, 16, false, true); +} + // win is used to get a correct em_unit value // It's important for bitmaps of dialogs. // if win == nullptr, em_unit value of MainFrame will be used wxBitmap create_scaled_bitmap( const std::string& bmp_name_in, wxWindow *win/* = nullptr*/, const int px_cnt/* = 16*/, - const bool grayscale/* = false*/) + const bool grayscale/* = false*/, + const bool menu_bitmap/* = false*/) { static Slic3r::GUI::BitmapCache cache; @@ -432,8 +439,14 @@ wxBitmap create_scaled_bitmap( const std::string& bmp_name_in, std::string bmp_name = bmp_name_in; boost::replace_last(bmp_name, ".png", ""); + bool dark_mode = +#ifdef _WIN32 + menu_bitmap ? Slic3r::GUI::check_dark_mode() : +#endif + Slic3r::GUI::wxGetApp().dark_mode(); + // Try loading an SVG first, then PNG if SVG is not found: - wxBitmap *bmp = cache.load_svg(bmp_name, width, height, grayscale, Slic3r::GUI::wxGetApp().dark_mode()); + wxBitmap *bmp = cache.load_svg(bmp_name, width, height, grayscale, dark_mode); if (bmp == nullptr) { bmp = cache.load_png(bmp_name, width, height, grayscale); } @@ -487,7 +500,7 @@ std::vector get_extruder_color_icons(bool thin_icon/* = false*/) } -void apply_extruder_selector(wxBitmapComboBox** ctrl, +void apply_extruder_selector(Slic3r::GUI::BitmapComboBox** ctrl, wxWindow* parent, const std::string& first_item/* = ""*/, wxPoint pos/* = wxDefaultPosition*/, @@ -496,9 +509,10 @@ void apply_extruder_selector(wxBitmapComboBox** ctrl, { std::vector icons = get_extruder_color_icons(use_thin_icon); - if (!*ctrl) - *ctrl = new wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, pos, size, - 0, nullptr, wxCB_READONLY); + if (!*ctrl) { + *ctrl = new Slic3r::GUI::BitmapComboBox(parent, wxID_ANY, wxEmptyString, pos, size, 0, nullptr, wxCB_READONLY); + Slic3r::GUI::wxGetApp().UpdateDarkUI(*ctrl); + } else { (*ctrl)->SetPosition(pos); @@ -550,9 +564,7 @@ LockButton::LockButton( wxWindow *parent, m_bmp_lock_open = ScalableBitmap(this, "lock_open"); m_bmp_lock_open_f = ScalableBitmap(this, "lock_open_f"); -#ifdef __WXMSW__ - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -#endif // __WXMSW__ + Slic3r::GUI::wxGetApp().UpdateDarkUI(this); SetBitmap(m_bmp_lock_open.bmp()); SetBitmapDisabled(m_bmp_lock_open.bmp()); SetBitmapHover(m_bmp_lock_closed_f.bmp()); @@ -590,9 +602,7 @@ void LockButton::msw_rescale() void LockButton::update_button_bitmaps() { -#ifdef __WXMSW__ - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -#endif + Slic3r::GUI::wxGetApp().UpdateDarkUI(this); SetBitmap(m_is_pushed ? m_bmp_lock_closed.bmp() : m_bmp_lock_open.bmp()); SetBitmapHover(m_is_pushed ? m_bmp_lock_closed_f.bmp() : m_bmp_lock_open_f.bmp()); @@ -662,6 +672,7 @@ void ModeButton::focus_button(const bool focus) Slic3r::GUI::wxGetApp().normal_font(); SetFont(new_font); +#ifndef _WIN32 SetForegroundColour(wxSystemSettings::GetColour(focus ? wxSYS_COLOUR_BTNTEXT : #if defined (__linux__) && defined (__WXGTK3__) wxSYS_COLOUR_GRAYTEXT @@ -671,6 +682,7 @@ void ModeButton::focus_button(const bool focus) wxSYS_COLOUR_BTNSHADOW #endif )); +#endif /* no _WIN32 */ Refresh(); Update(); @@ -820,13 +832,11 @@ ScalableButton::ScalableButton( wxWindow * parent, m_parent(parent), m_current_icon_name(icon_name), m_use_default_disabled_bitmap (use_default_disabled_bitmap), - m_px_cnt(bmp_px_cnt) + m_px_cnt(bmp_px_cnt), + m_has_border(!(style & wxNO_BORDER)) { Create(parent, id, label, pos, size, style); -#ifdef __WXMSW__ - if (style & wxNO_BORDER) - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -#endif // __WXMSW__ + Slic3r::GUI::wxGetApp().UpdateDarkUI(this); SetBitmap(create_scaled_bitmap(icon_name, parent, m_px_cnt)); if (m_use_default_disabled_bitmap) @@ -848,13 +858,11 @@ ScalableButton::ScalableButton( wxWindow * parent, long style /*= wxBU_EXACTFIT | wxNO_BORDER*/) : m_parent(parent), m_current_icon_name(bitmap.name()), - m_px_cnt(bitmap.px_cnt()) + m_px_cnt(bitmap.px_cnt()), + m_has_border(!(style& wxNO_BORDER)) { Create(parent, id, label, wxDefaultPosition, wxDefaultSize, style); -#ifdef __WXMSW__ - if (style & wxNO_BORDER) - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -#endif // __WXMSW__ + Slic3r::GUI::wxGetApp().UpdateDarkUI(this); SetBitmap(bitmap.bmp()); } @@ -888,9 +896,8 @@ void ScalableButton::UseDefaultBitmapDisabled() void ScalableButton::msw_rescale() { -#ifdef __WXMSW__ - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -#endif + Slic3r::GUI::wxGetApp().UpdateDarkUI(this, m_has_border); + SetBitmap(create_scaled_bitmap(m_current_icon_name, m_parent, m_px_cnt)); if (!m_disabled_icon_name.empty()) SetBitmapDisabled(create_scaled_bitmap(m_disabled_icon_name, m_parent, m_px_cnt)); diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 4f5204775..1664a51f3 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -48,11 +48,19 @@ void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector< int em_unit(wxWindow* win); int mode_icon_px_size(); +wxBitmap create_menu_bitmap(const std::string& bmp_name); + wxBitmap create_scaled_bitmap(const std::string& bmp_name, wxWindow *win = nullptr, - const int px_cnt = 16, const bool grayscale = false); + const int px_cnt = 16, const bool grayscale = false, const bool menu_bitmap = false); std::vector get_extruder_color_icons(bool thin_icon = false); -void apply_extruder_selector(wxBitmapComboBox** ctrl, + +namespace Slic3r { +namespace GUI { +class BitmapComboBox; +} +} +void apply_extruder_selector(Slic3r::GUI::BitmapComboBox** ctrl, wxWindow* parent, const std::string& first_item = "", wxPoint pos = wxDefaultPosition, @@ -240,6 +248,7 @@ private: // bitmap dimensions int m_px_cnt{ 16 }; + bool m_has_border {false}; }; diff --git a/src/slic3r/Utils/FixModelByWin10.cpp b/src/slic3r/Utils/FixModelByWin10.cpp index dead35267..92eab9307 100644 --- a/src/slic3r/Utils/FixModelByWin10.cpp +++ b/src/slic3r/Utils/FixModelByWin10.cpp @@ -35,6 +35,7 @@ #include "libslic3r/Format/3mf.hpp" #include "../GUI/GUI.hpp" #include "../GUI/I18N.hpp" +#include "../GUI/MsgDialog.hpp" #include #include @@ -421,10 +422,12 @@ void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx) if (canceled) { // Nothing to show. } else if (success) { - wxMessageDialog dlg(nullptr, _(L("Model repaired successfully")), _(L("Model Repair by the Netfabb service")), wxICON_INFORMATION | wxOK_DEFAULT); + //wxMessageDialog dlg(nullptr, _(L("Model repaired successfully")), _(L("Model Repair by the Netfabb service")), wxICON_INFORMATION | wxOK_DEFAULT); + Slic3r::GUI::MessageDialog dlg(nullptr, _(L("Model repaired successfully")), _(L("Model Repair by the Netfabb service")), wxICON_INFORMATION | wxOK_DEFAULT); dlg.ShowModal(); } else { - wxMessageDialog dlg(nullptr, _(L("Model repair failed:")) + " \n" + _(progress.message), _(L("Model Repair by the Netfabb service")), wxICON_ERROR | wxOK_DEFAULT); + //wxMessageDialog dlg(nullptr, _(L("Model repair failed:")) + " \n" + _(progress.message), _(L("Model Repair by the Netfabb service")), wxICON_ERROR | wxOK_DEFAULT); + Slic3r::GUI::MessageDialog dlg(nullptr, _(L("Model repair failed:")) + " \n" + _(progress.message), _(L("Model Repair by the Netfabb service")), wxICON_ERROR | wxOK_DEFAULT); dlg.ShowModal(); } worker_thread.join();