diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index c5e4ac642a..0c925c1286 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -959,7 +959,7 @@ void GUI_App::post_init() if (app_config->get("stealth_mode") == "false") hms_query = new HMSQuery(); - + m_show_gcode_window = app_config->get_bool("show_gcode_window"); if (m_networking_need_update) { //updating networking @@ -2807,7 +2807,7 @@ void GUI_App::init_label_colours() m_color_label_modified = is_dark_mode ? wxColour("#F1754E") : wxColour("#F1754E"); m_color_label_sys = is_dark_mode ? wxColour("#B2B3B5") : wxColour("#363636"); -#ifdef _WIN32 +#if defined(_WIN32) || defined(__linux__) || defined(__APPLE__) m_color_label_default = is_dark_mode ? wxColour(250, 250, 250) : m_color_label_sys; // 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); @@ -2920,22 +2920,38 @@ void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool ju /*if (m_is_dark_mode != dark_mode() ) m_is_dark_mode = dark_mode();*/ - if (m_is_dark_mode) { - auto original_col = window->GetBackgroundColour(); - auto bg_col = StateColor::darkModeColorFor(original_col); - if (bg_col != original_col) { + auto orig_col = window->GetBackgroundColour(); + auto bg_col = StateColor::darkModeColorFor(orig_col); + // there are cases where the background color of an item is bright, specifically: + // * the background color of a button: #009688 -- 73 + if (bg_col != orig_col) { window->SetBackgroundColour(bg_col); } - original_col = window->GetForegroundColour(); - auto fg_col = StateColor::darkModeColorFor(original_col); + orig_col = window->GetForegroundColour(); + auto fg_col = StateColor::darkModeColorFor(orig_col); + auto fg_l = StateColor::GetLightness(fg_col); - if (fg_col != original_col) { - window->SetForegroundColour(fg_col); + auto color_difference = StateColor::GetColorDifference(bg_col, fg_col); + + // fallback and sanity check with LAB + // color difference of less than 2 or 3 is not normally visible, and even less than 30-40 doesn't stand out + if (color_difference < 10) { + fg_col = StateColor::SetLightness(fg_col, 90); } + // some of the stock colors have a lightness of ~49 + if (fg_l < 45) { + fg_col = StateColor::SetLightness(fg_col, 70); + } + // at this point it shouldn't be possible that fg_col is the same as bg_col, but let's be safe + if (fg_col == bg_col) { + fg_col = StateColor::SetLightness(fg_col, 70); + } + + window->SetForegroundColour(fg_col); } else { auto original_col = window->GetBackgroundColour(); @@ -3891,7 +3907,7 @@ void GUI_App::on_http_error(wxCommandEvent &evt) MessageDialog msg_dlg(nullptr, _L("The version of Orca Slicer is too low and needs to be updated to the latest version before it can be used normally"), "", wxAPPLY | wxOK); if (msg_dlg.ShowModal() == wxOK) { } - + } // request login diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 03f41a85da..221d8db9df 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -1533,7 +1533,6 @@ void UnsavedChangesDialog::update_list() text_left->SetFont(::Label::Head_13); text_left->Wrap(-1); text_left->SetForegroundColour(GREY700); - text_left->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT)); sizer_left_v->Add(text_left, 0, wxLEFT, 37); @@ -1562,7 +1561,6 @@ void UnsavedChangesDialog::update_list() text_left->SetFont(::Label::Body_13); text_left->Wrap(-1); text_left->SetForegroundColour(GREY700); - text_left->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT)); sizer_left_v->Add(text_left, 0, wxLEFT, 51 ); diff --git a/src/slic3r/GUI/Widgets/StateColor.cpp b/src/slic3r/GUI/Widgets/StateColor.cpp index fb038eb24c..2e2b3168d6 100644 --- a/src/slic3r/GUI/Widgets/StateColor.cpp +++ b/src/slic3r/GUI/Widgets/StateColor.cpp @@ -1,4 +1,5 @@ #include "StateColor.hpp" +#include static bool gDarkMode = false; @@ -41,7 +42,136 @@ static std::map gDarkColors{ //{"#F0F0F0", "#4C4C54"}, }; -std::map const & StateColor::GetDarkMap() +std::tuple StateColor::GetLAB(const wxColour& color) { + // Convert color to RGB color space + double r = color.Red() / 255.0; + double g = color.Green() / 255.0; + double b = color.Blue() / 255.0; + + // Convert to XYZ color space + double x = 0.412453*r + 0.357580*g + 0.180423*b; + double y = 0.212671*r + 0.715160*g + 0.072169*b; + double z = 0.019334*r + 0.119193*g + 0.950227*b; + + // Normalize XYZ values + double x_n = x / 0.950456; + double y_n = y / 1.0; + double z_n = z / 1.088754; + + // Convert to LAB color space + double epsilon = 0.008856; + double kappa = 903.3; + double fx = (x_n > epsilon) ? cbrt(x_n) : (kappa*x_n + 16.0) / 116.0; + double fy = (y_n > epsilon) ? cbrt(y_n) : (kappa*y_n + 16.0) / 116.0; + double fz = (z_n > epsilon) ? cbrt(z_n) : (kappa*z_n + 16.0) / 116.0; + + double l = 116.0 * fy - 16.0; + double a = 500.0 * (fx - fy); + double b_lab = 200.0 * (fy - fz); + + return std::tuple(l, a, b_lab); +} + +double StateColor::LAB_Delta_E(const wxColour& color1, const wxColour& color2) { + auto [l1, a1, b1] = GetLAB(color1); + auto [l2, a2, b2] = GetLAB(color2); + return sqrt((l1 - l2) * (l1 - l2) + (a1 - a2) * (a1 - a2) + (b1 - b2) * (b1 - b2)); +} + +double StateColor::GetColorDifference(const wxColour& color1, const wxColour& color2) { + return LAB_Delta_E(color1, color2); +} + +double StateColor::GetLightness(const wxColour& color) { + auto [l, a, b_lab] = GetLAB(color); + return l; +} + +// Function to lighten or darken a wxColour using LAB color space +wxColour StateColor::SetLightness(const wxColour& color, double lightness) { + auto [l, a, b_lab] = GetLAB(color); + + // Clamp lightness value + l = std::max(0.0, std::min(100.0, lightness)); + + // Convert back to XYZ color space + double fy_3 = (l + 16.0) / 116.0; + double fx_3 = a / 500.0 + fy_3; + double fz_3 = fy_3 - b_lab / 200.0; + + double epsilon = 0.008856; + double kappa = 903.3; + double x_3 = (fx_3 > epsilon) ? fx_3 * fx_3 * fx_3 : (116.0 * fx_3 - 16.0) / kappa; + double y_3 = (l > kappa*epsilon) ? fy_3 * fy_3 * fy_3 : l / kappa; + double z_3 = (fz_3 > epsilon) ? fz_3 * fz_3 * fz_3 : (116.0 * fz_3 - 16.0) / kappa; + + // Denormalize XYZ values + double x = x_3 * 0.950456; + double y = y_3 * 1.0; + double z = z_3 * 1.088754; + + // Convert XYZ to RGB + double r_new = 3.240479*x - 1.537150*y - 0.498535*z; + double g_new = -0.969256*x + 1.875992*y + 0.041556*z; + double b_new = 0.055648*x - 0.204043*y + 1.057311*z; + + // Clamp RGB values + r_new = std::max(0.0, std::min(1.0, r_new)); + g_new = std::max(0.0, std::min(1.0, g_new)); + b_new = std::max(0.0, std::min(1.0, b_new)); + + // Convert back to wxColour + int r_int = static_cast(r_new * 255); + int g_int = static_cast(g_new * 255); + int b_int = static_cast(b_new * 255); + + return wxColour(r_int, g_int, b_int); +} + +wxColour StateColor::LightenDarkenColor(const wxColour& color, int amount) { + auto [l, a, b_lab] = GetLAB(color); + + // Modify lightness + l += amount; + + // Clamp lightness value + l = std::max(0.0, std::min(100.0, l)); + + // Convert back to XYZ color space + double fy_3 = (l + 16.0) / 116.0; + double fx_3 = a / 500.0 + fy_3; + double fz_3 = fy_3 - b_lab / 200.0; + + double epsilon = 0.008856; + double kappa = 903.3; + double x_3 = (fx_3 > epsilon) ? fx_3 * fx_3 * fx_3 : (116.0 * fx_3 - 16.0) / kappa; + double y_3 = (l > kappa*epsilon) ? fy_3 * fy_3 * fy_3 : l / kappa; + double z_3 = (fz_3 > epsilon) ? fz_3 * fz_3 * fz_3 : (116.0 * fz_3 - 16.0) / kappa; + + // Denormalize XYZ values + double x = x_3 * 0.950456; + double y = y_3 * 1.0; + double z = z_3 * 1.088754; + + // Convert XYZ to RGB + double r_new = 3.240479*x - 1.537150*y - 0.498535*z; + double g_new = -0.969256*x + 1.875992*y + 0.041556*z; + double b_new = 0.055648*x - 0.204043*y + 1.057311*z; + + // Clamp RGB values + r_new = std::max(0.0, std::min(1.0, r_new)); + g_new = std::max(0.0, std::min(1.0, g_new)); + b_new = std::max(0.0, std::min(1.0, b_new)); + + // Convert back to wxColour + int r_int = static_cast(r_new * 255); + int g_int = static_cast(g_new * 255); + int b_int = static_cast(b_new * 255); + + return wxColour(r_int, g_int, b_int); +} + +std::map const & StateColor::GetDarkMap() { return gDarkColors; } diff --git a/src/slic3r/GUI/Widgets/StateColor.hpp b/src/slic3r/GUI/Widgets/StateColor.hpp index 1f7799faab..3c68c252fb 100644 --- a/src/slic3r/GUI/Widgets/StateColor.hpp +++ b/src/slic3r/GUI/Widgets/StateColor.hpp @@ -9,7 +9,7 @@ class StateColor { public: enum State { - Normal = 0, + Normal = 0, Enabled = 1, Checked = 2, Focused = 4, @@ -23,6 +23,13 @@ public: }; public: + static std::tuple GetLAB(const wxColour& color); + static double GetLightness(const wxColour& color); + static wxColour SetLightness(const wxColour& color, double lightness); + static wxColour LightenDarkenColor(const wxColour& color, int amount); + static double GetColorDifference(const wxColour& c1, const wxColour& c2); + static double LAB_Delta_E(const wxColour& c1, const wxColour& c2); + static void SetDarkMode(bool dark); static std::map const & GetDarkMap();