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)"
This commit is contained in:
Oleksandra Yushchenko 2021-06-18 19:46:04 +02:00 committed by GitHub
parent 65f440c2ba
commit fd071421cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
66 changed files with 2011 additions and 443 deletions

View file

@ -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<wxWindow*>{ this, p->sliced_info->GetStaticBox(), p->object_info->GetStaticBox(), p->btn_reslice, p->btn_export_gcode })
wxGetApp().UpdateDarkUI(win);
for (wxWindow* win : std::vector<wxWindow*>{ p->scrolled, p->presets_panel })
wxGetApp().UpdateAllStaticTextDarkUI(win);
for (wxWindow* btn : std::vector<wxWindow*>{ 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<PlaterPresetComboBox*>{ 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<size_t> Plater::priv::load_files(const std::vector<fs::path>& 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<size_t> Plater::priv::load_files(const std::vector<fs::path>& 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<size_t> Plater::priv::load_files(const std::vector<fs::path>& 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<size_t> Plater::priv::load_files(const std::vector<fs::path>& 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<size_t> Plater::priv::load_files(const std::vector<fs::path>& 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<wxWindow*>(this), _L("You can open only one .gcode file at a time."),
//wxMessageDialog(static_cast<wxWindow*>(this), _L("You can open only one .gcode file at a time."),
MessageDialog(static_cast<wxWindow*>(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<wxWindow*>(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<wxWindow*>(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<wxWindow*>(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();