Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Dark Mode issues on Linux(via LAB) #5044

Merged
merged 7 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 27 additions & 11 deletions src/slic3r/GUI/GUI_App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions src/slic3r/GUI/UnsavedChangesDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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 );

Expand Down
132 changes: 131 additions & 1 deletion src/slic3r/GUI/Widgets/StateColor.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "StateColor.hpp"
#include <cmath>

static bool gDarkMode = false;

Expand Down Expand Up @@ -41,7 +42,136 @@ static std::map<wxColour, wxColour> gDarkColors{
//{"#F0F0F0", "#4C4C54"},
};

std::map<wxColour, wxColour> const & StateColor::GetDarkMap()
std::tuple<double, double, double> 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<double, double, double>(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<int>(r_new * 255);
int g_int = static_cast<int>(g_new * 255);
int b_int = static_cast<int>(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<int>(r_new * 255);
int g_int = static_cast<int>(g_new * 255);
int b_int = static_cast<int>(b_new * 255);

return wxColour(r_int, g_int, b_int);
}

std::map<wxColour, wxColour> const & StateColor::GetDarkMap()
{
return gDarkColors;
}
Expand Down
9 changes: 8 additions & 1 deletion src/slic3r/GUI/Widgets/StateColor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class StateColor
{
public:
enum State {
Normal = 0,
Normal = 0,
Enabled = 1,
Checked = 2,
Focused = 4,
Expand All @@ -23,6 +23,13 @@ class StateColor
};

public:
static std::tuple<double, double, double> 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<wxColour, wxColour> const & GetDarkMap();
Expand Down