Match OrcaSlicer's color theme in the color-mixing UI

This commit is contained in:
SoftFever
2026-08-25 00:47:25 +08:00
parent 1631d3cf01
commit 0fa25acda8
10 changed files with 264 additions and 352 deletions
+15 -14
View File
@@ -26,7 +26,7 @@
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
static const wxColour COLOR_BRAND("#00AE42"); static const wxColour COLOR_BRAND("#009688");
static const wxColour COLOR_BORDER_NORMAL("#EEEEEE"); static const wxColour COLOR_BORDER_NORMAL("#EEEEEE");
static const wxColour COLOR_BG_CARD("#F8F8F8"); static const wxColour COLOR_BG_CARD("#F8F8F8");
static const wxColour COLOR_LABEL_GREY("#ACACAC"); static const wxColour COLOR_LABEL_GREY("#ACACAC");
@@ -394,7 +394,7 @@ wxPanel* ColorDecomposeDialog::create_mode_card(wxWindow* parent, DecomposeMode
auto* title_sizer = new wxBoxSizer(wxHORIZONTAL); auto* title_sizer = new wxBoxSizer(wxHORIZONTAL);
auto* title_label = new wxStaticText(card, wxID_ANY, title); auto* title_label = new wxStaticText(card, wxID_ANY, title);
title_label->SetFont(Label::Body_14); title_label->SetFont(Label::Body_14);
title_label->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#909090"))); title_label->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#6B6A6A")));
match_parent_bg(title_label, StateColor::darkModeColorFor(COLOR_BG_CARD)); match_parent_bg(title_label, StateColor::darkModeColorFor(COLOR_BG_CARD));
title_sizer->Add(title_label, 1, wxALIGN_CENTER_VERTICAL); title_sizer->Add(title_label, 1, wxALIGN_CENTER_VERTICAL);
@@ -523,7 +523,7 @@ wxBoxSizer* ColorDecomposeDialog::create_mode_selection_section()
m_no_card_hint = new wxStaticText(this, wxID_ANY, m_no_card_hint = new wxStaticText(this, wxID_ANY,
_L("At least two filaments of the same material type are required for decomposition")); _L("At least two filaments of the same material type are required for decomposition"));
m_no_card_hint->SetFont(Label::Body_13); m_no_card_hint->SetFont(Label::Body_13);
m_no_card_hint->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#909090"))); m_no_card_hint->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#6B6A6A")));
m_no_card_hint->Wrap(FromDIP(400)); m_no_card_hint->Wrap(FromDIP(400));
m_no_card_hint->Hide(); m_no_card_hint->Hide();
sizer->Add(m_no_card_hint, 0, wxTOP, FromDIP(8)); sizer->Add(m_no_card_hint, 0, wxTOP, FromDIP(8));
@@ -536,7 +536,7 @@ wxBoxSizer* ColorDecomposeDialog::create_mode_selection_section()
wxDefaultPosition, wxSize(FromDIP(16), FromDIP(16))); wxDefaultPosition, wxSize(FromDIP(16), FromDIP(16)));
m_limit_warning_text = new wxStaticText(m_limit_warning_panel, wxID_ANY, wxEmptyString); m_limit_warning_text = new wxStaticText(m_limit_warning_panel, wxID_ANY, wxEmptyString);
m_limit_warning_text->SetFont(Label::Body_13); m_limit_warning_text->SetFont(Label::Body_13);
m_limit_warning_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#D32F2F"))); m_limit_warning_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#D01B1B")));
m_limit_warning_text->Wrap(FromDIP(400)); m_limit_warning_text->Wrap(FromDIP(400));
warning_sizer->Add(warn_bmp, 0, wxALIGN_TOP | wxRIGHT, FromDIP(6)); warning_sizer->Add(warn_bmp, 0, wxALIGN_TOP | wxRIGHT, FromDIP(6));
warning_sizer->Add(m_limit_warning_text, 1, wxEXPAND); warning_sizer->Add(m_limit_warning_text, 1, wxEXPAND);
@@ -553,22 +553,23 @@ wxBoxSizer* ColorDecomposeDialog::create_button_panel()
sizer->AddStretchSpacer(); sizer->AddStretchSpacer();
m_btn_cancel = new Button(this, _L("Cancel")); m_btn_cancel = new Button(this, _L("Cancel"));
m_btn_cancel->SetBackgroundColor(StateColor::darkModeColorFor(*wxWHITE)); m_btn_cancel->SetBackgroundColor(*wxWHITE);
m_btn_cancel->SetBorderColor(StateColor::darkModeColorFor(wxColour("#CECECE"))); m_btn_cancel->SetBorderColor(wxColour("#CECECE"));
m_btn_cancel->SetTextColor(StateColor::darkModeColorFor(wxColour("#262E30"))); m_btn_cancel->SetTextColor(COLOR_TEXT_DARK);
m_btn_cancel->SetMinSize(wxSize(FromDIP(55), FromDIP(24))); m_btn_cancel->SetMinSize(wxSize(FromDIP(55), FromDIP(24)));
m_btn_cancel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { EndModal(wxID_CANCEL); }); m_btn_cancel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { EndModal(wxID_CANCEL); });
m_btn_ok = new Button(this, _L("OK")); m_btn_ok = new Button(this, _L("OK"));
m_btn_ok->SetBackgroundColor(StateColor( m_btn_ok->SetBackgroundColor(StateColor(
std::make_pair(wxColour("#C2C2C2"), (int) StateColor::Disabled), std::make_pair(wxColour("#CECECE"), (int) StateColor::Disabled),
std::make_pair(wxColour("#00AE42"), (int) StateColor::Normal))); std::make_pair(wxColour(0, 137, 123), (int) StateColor::Pressed),
std::make_pair(COLOR_BRAND, (int) StateColor::Normal)));
m_btn_ok->SetBorderColor(StateColor( m_btn_ok->SetBorderColor(StateColor(
std::make_pair(wxColour("#C2C2C2"), (int) StateColor::Disabled), std::make_pair(wxColour("#CECECE"), (int) StateColor::Disabled),
std::make_pair(wxColour("#00AE42"), (int) StateColor::Normal))); std::make_pair(COLOR_BRAND, (int) StateColor::Normal)));
m_btn_ok->SetTextColor(StateColor( // Off-by-one white: plain #FFFFFF is a dark-mode key and would repaint the
std::make_pair(*wxWHITE, (int) StateColor::Disabled), // label as the window background on the accent fill.
std::make_pair(*wxWHITE, (int) StateColor::Normal))); m_btn_ok->SetTextColor(wxColour("#FFFFFE"));
m_btn_ok->SetMinSize(wxSize(FromDIP(55), FromDIP(24))); m_btn_ok->SetMinSize(wxSize(FromDIP(55), FromDIP(24)));
m_btn_ok->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { m_btn_ok->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
EndModal(wxID_OK); EndModal(wxID_OK);
+6
View File
@@ -9751,6 +9751,12 @@ void GLCanvas3D::_render_paint_toolbar() const
const float text_offset_y = 4.0f * em_unit * f_scale; const float text_offset_y = 4.0f * em_unit * f_scale;
for (int i = 0; i < extruder_num; i++) { for (int i = 0; i < extruder_num; i++) {
// A gradient slot's swatch shows its fade instead of the blended colour in `colors`, so the
// labels take their contrast from the colour printed at the middle of the fade they sit on.
if (i < (int) gradient_ramps.size() && !gradient_ramps[i].empty()) {
const wxColour& c = gradient_ramps[i][gradient_ramps[i].size() / 2];
rgba = ColorRGBA(c.Red(), c.Green(), c.Blue(), c.Alpha());
} else
decode_color(colors[i], rgba); decode_color(colors[i], rgba);
float gray = 0.299 * rgba.r_uchar() + 0.587 * rgba.g_uchar() + 0.114 * rgba.b_uchar(); float gray = 0.299 * rgba.r_uchar() + 0.587 * rgba.g_uchar() + 0.114 * rgba.b_uchar();
ImVec4 text_color = gray < 80 ? ImVec4(1.0f, 1.0f, 1.0f, 1.0f) : ImVec4(0, 0, 0, 1.0f); ImVec4 text_color = gray < 80 ? ImVec4(1.0f, 1.0f, 1.0f, 1.0f) : ImVec4(0, 0, 0, 1.0f);
+6 -8
View File
@@ -39,12 +39,13 @@ constexpr int kAxisArrowLen = 10; // length of the axis arrow triangle (DIP
// Light-mode design tokens. Resolved through StateColor::darkModeColorFor() // Light-mode design tokens. Resolved through StateColor::darkModeColorFor()
// at paint time so the editor follows the app theme (#EEEEEE -> #4C4C55, #6B6B6B -> // at paint time so the editor follows the app theme (#EEEEEE -> #4C4C55, #6B6B6B ->
// #818183, #262E30 -> #EFEFF0, *wxWHITE -> #2D2D31). Don't read these directly in paint; // #818183, #262E30 -> #EFEFF0, #ACACAC -> #65656A, *wxWHITE -> #2D2D31). Don't read these
// always go through the resolved locals declared at the top of on_paint(). // directly in paint; always go through the resolved locals declared at the top of on_paint().
const wxColour kGridColor (238, 238, 238); // #EEEEEE grey 300 const wxColour kGridColor (238, 238, 238); // #EEEEEE grey 300
const wxColour kAxisColor (107, 107, 107); // #6B6B6B grey 700 const wxColour kAxisColor (107, 107, 107); // #6B6B6B grey 700
const wxColour kLabelMuted (107, 107, 107); // #6B6B6B grey 700 const wxColour kLabelMuted (107, 107, 107); // #6B6B6B grey 700
const wxColour kLabelStrong ( 38, 46, 48); // #262E30 grey 900 const wxColour kLabelStrong ( 38, 46, 48); // #262E30 grey 900
const wxColour kOutlineColor(172, 172, 172); // #ACACAC dimmed elements
// LAB (DeltaE76) threshold for "curve color is too close to the background": below it the curve // LAB (DeltaE76) threshold for "curve color is too close to the background": below it the curve
// gets a subtle outline so it does not visually vanish, otherwise it is drawn plain. Looser than // gets a subtle outline so it does not visually vanish, otherwise it is drawn plain. Looser than
@@ -321,6 +322,9 @@ void GradientCurveEditor::on_paint(wxPaintEvent& /*evt*/)
const wxColour label_muted = StateColor::darkModeColorFor(kLabelMuted); const wxColour label_muted = StateColor::darkModeColorFor(kLabelMuted);
const wxColour label_strong = StateColor::darkModeColorFor(kLabelStrong); const wxColour label_strong = StateColor::darkModeColorFor(kLabelStrong);
const wxColour point_fill = StateColor::darkModeColorFor(*wxWHITE); const wxColour point_fill = StateColor::darkModeColorFor(*wxWHITE);
// Softer than axis_color: the curve outline only has to lift the curve off the
// background, it must not compete with the structural axis / grid.
const wxColour outline_color = StateColor::darkModeColorFor(kOutlineColor);
wxAutoBufferedPaintDC raw_dc(this); wxAutoBufferedPaintDC raw_dc(this);
raw_dc.SetBackground(wxBrush(bg)); raw_dc.SetBackground(wxBrush(bg));
@@ -462,12 +466,6 @@ void GradientCurveEditor::on_paint(wxPaintEvent& /*evt*/)
// Outline only when the curve color is perceptually close to the background; otherwise // Outline only when the curve color is perceptually close to the background; otherwise
// the plain filament color reads fine and the extra stroke would look heavy. // the plain filament color reads fine and the extra stroke would look heavy.
// Outline tone is intentionally softer than axis_color so it disambiguates the curve
// from the bg without competing with the structural axis/grid: light mode uses a pale
// grey, dark mode uses a slightly-above-bg grey (gDarkColors has no entry for these).
const wxColour outline_color = wxGetApp().dark_mode()
? wxColour(90, 90, 94) // > bg #2B2B2B, < axis #818183
: wxColour(200, 200, 200); // > grid #EEEEEE, < axis #6B6B6B
auto needs_outline = [&](const wxColour& c) { auto needs_outline = [&](const wxColour& c) {
return calc_color_distance(c, bg) < kBgSimilarThreshold; return calc_color_distance(c, bg) < kBgSimilarThreshold;
}; };
+35 -53
View File
@@ -35,6 +35,9 @@ namespace GUI {
static constexpr int MAX_COMPONENTS = 3; static constexpr int MAX_COMPONENTS = 3;
static constexpr int MIN_COMPONENT_RATIO = 10; static constexpr int MIN_COMPONENT_RATIO = 10;
// Section headings and the placeholder text share one muted tone; light key, resolved at each use.
static const wxColour COLOR_LABEL_MUTED("#6B6A6A");
// Lightweight self-painting label used for both dual-color and triple-color // Lightweight self-painting label used for both dual-color and triple-color
// ratio percentage display. Hover shows a rounded-rect background; click // ratio percentage display. Hover shows a rounded-rect background; click
// fires wxEVT_LEFT_DOWN which the owning dialog binds to start_ratio_editor. // fires wxEVT_LEFT_DOWN which the owning dialog binds to start_ratio_editor.
@@ -92,7 +95,7 @@ private:
} }
dc.SetFont(GetFont()); dc.SetFont(GetFont());
dc.SetTextForeground(m_hovered ? wxColour("#00AE42") dc.SetTextForeground(m_hovered ? StateColor::darkModeColorFor(wxColour("#009688"))
: StateColor::darkModeColorFor(wxColour("#262E30"))); : StateColor::darkModeColorFor(wxColour("#262E30")));
wxSize ts = dc.GetTextExtent(m_text); wxSize ts = dc.GetTextExtent(m_text);
int x = (sz.GetWidth() - ts.GetWidth()) / 2; int x = (sz.GetWidth() - ts.GetWidth()) / 2;
@@ -132,12 +135,6 @@ MixedFilamentDialog::MixedFilamentDialog(wxWindow* parent,
m_result.ratios = {50, 50}; m_result.ratios = {50, 50};
build_ui(); build_ui();
wxGetApp().UpdateDlgDarkUI(this); wxGetApp().UpdateDlgDarkUI(this);
wxImage img;
if (img.LoadFile(from_u8(Slic3r::var("mixed_filament_preview_twocolor.png")), wxBITMAP_TYPE_PNG))
m_preview_bmp_two = wxBitmap(img);
if (img.LoadFile(from_u8(Slic3r::var("mixed_filament_preview_threecolor.png")), wxBITMAP_TYPE_PNG))
m_preview_bmp_three = wxBitmap(img);
} }
MixedFilamentDialog::~MixedFilamentDialog() MixedFilamentDialog::~MixedFilamentDialog()
@@ -180,12 +177,6 @@ MixedFilamentDialog::MixedFilamentDialog(wxWindow* parent,
} }
build_ui(); build_ui();
wxGetApp().UpdateDlgDarkUI(this); wxGetApp().UpdateDlgDarkUI(this);
wxImage img;
if (img.LoadFile(from_u8(Slic3r::var("mixed_filament_preview_twocolor.png")), wxBITMAP_TYPE_PNG))
m_preview_bmp_two = wxBitmap(img);
if (img.LoadFile(from_u8(Slic3r::var("mixed_filament_preview_threecolor.png")), wxBITMAP_TYPE_PNG))
m_preview_bmp_three = wxBitmap(img);
} }
void MixedFilamentDialog::on_dpi_changed(const wxRect&) void MixedFilamentDialog::on_dpi_changed(const wxRect&)
@@ -609,13 +600,7 @@ void MixedFilamentDialog::commit_ratio_editor_from_background(wxMouseEvent& e)
void MixedFilamentDialog::build_ui() void MixedFilamentDialog::build_ui()
{ {
const wxColour mc_bg = StateColor::darkModeColorFor(*wxWHITE); SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
const wxColour mc_bg_sub = StateColor::darkModeColorFor(wxColour("#F8F8F8"));
const wxColour mc_border = StateColor::darkModeColorFor(wxColour("#CECECE"));
const wxColour mc_text = StateColor::darkModeColorFor(wxColour("#262E30"));
const wxColour mc_dim_text = StateColor::darkModeColorFor(wxColour("#ACACAC"));
SetBackgroundColour(mc_bg);
Bind(wxEVT_LEFT_DOWN, &MixedFilamentDialog::commit_ratio_editor_from_background, this); Bind(wxEVT_LEFT_DOWN, &MixedFilamentDialog::commit_ratio_editor_from_background, this);
SetSize(FromDIP(439), FromDIP(580)); SetSize(FromDIP(439), FromDIP(580));
@@ -727,7 +712,7 @@ wxBoxSizer* MixedFilamentDialog::create_preview_panel()
sizer->Add(m_preview_canvas, 0, wxALIGN_CENTER); sizer->Add(m_preview_canvas, 0, wxALIGN_CENTER);
auto* label = new wxStaticText(this, wxID_ANY, _L("Effect Preview")); auto* label = new wxStaticText(this, wxID_ANY, _L("Effect Preview"));
label->SetForegroundColour(wxColour("#909090")); label->SetForegroundColour(StateColor::darkModeColorFor(COLOR_LABEL_MUTED));
label->SetFont(::Label::Body_13); label->SetFont(::Label::Body_13);
sizer->Add(label, 0, wxALIGN_CENTER | wxTOP, FromDIP(4)); sizer->Add(label, 0, wxALIGN_CENTER | wxTOP, FromDIP(4));
@@ -803,7 +788,7 @@ wxBoxSizer* MixedFilamentDialog::create_material_selection()
sizer->Add(m_summary_panel, 0, wxEXPAND); sizer->Add(m_summary_panel, 0, wxEXPAND);
auto* sel_label = new wxStaticText(this, wxID_ANY, _L("Select Mixed Materials")); auto* sel_label = new wxStaticText(this, wxID_ANY, _L("Select Mixed Materials"));
sel_label->SetForegroundColour(wxColour("#909090")); sel_label->SetForegroundColour(StateColor::darkModeColorFor(COLOR_LABEL_MUTED));
sel_label->SetFont(::Label::Body_12); sel_label->SetFont(::Label::Body_12);
sizer->Add(sel_label, 0, wxTOP, FromDIP(6)); sizer->Add(sel_label, 0, wxTOP, FromDIP(6));
@@ -821,7 +806,10 @@ wxBoxSizer* MixedFilamentDialog::create_material_selection()
m_btn_add_material = new Button(this, _L("+ Add Material")); m_btn_add_material = new Button(this, _L("+ Add Material"));
m_btn_add_material->SetBackgroundColor(wxColour("#F8F8F8")); m_btn_add_material->SetBackgroundColor(wxColour("#F8F8F8"));
m_btn_add_material->SetBorderColor(wxColour("#EEEEEE")); m_btn_add_material->SetBorderColor(wxColour("#EEEEEE"));
m_btn_add_material->SetTextColor(wxColour("#262E30")); // The disabled tone rides on the StateColor so Enable() alone repaints it, the way m_btn_ok does.
m_btn_add_material->SetTextColor(StateColor(
std::make_pair(wxColour("#ACACAC"), (int) StateColor::Disabled),
std::make_pair(wxColour("#262E30"), (int) StateColor::Normal)));
m_btn_add_material->SetMinSize(wxSize(-1, FromDIP(24))); m_btn_add_material->SetMinSize(wxSize(-1, FromDIP(24)));
m_btn_add_material->SetCursor(wxCursor(wxCURSOR_HAND)); m_btn_add_material->SetCursor(wxCursor(wxCURSOR_HAND));
m_btn_add_material->EnableTooltipEvenDisabled(); m_btn_add_material->EnableTooltipEvenDisabled();
@@ -848,7 +836,7 @@ wxBoxSizer* MixedFilamentDialog::create_ratio_slider()
auto* sizer = new wxBoxSizer(wxVERTICAL); auto* sizer = new wxBoxSizer(wxVERTICAL);
auto* ratio_label = new wxStaticText(this, wxID_ANY, _L("Ratio")); auto* ratio_label = new wxStaticText(this, wxID_ANY, _L("Ratio"));
ratio_label->SetForegroundColour(wxColour("#909090")); ratio_label->SetForegroundColour(StateColor::darkModeColorFor(COLOR_LABEL_MUTED));
ratio_label->SetFont(::Label::Body_12); ratio_label->SetFont(::Label::Body_12);
sizer->Add(ratio_label, 0, wxBOTTOM, FromDIP(4)); sizer->Add(ratio_label, 0, wxBOTTOM, FromDIP(4));
@@ -870,7 +858,9 @@ wxBoxSizer* MixedFilamentDialog::create_ratio_slider()
} }
int div_x = (int)(ratio(1) / 100.0 * sz.GetWidth()); int div_x = (int)(ratio(1) / 100.0 * sz.GetWidth());
dc.SetPen(wxPen(StateColor::darkModeColorFor(wxColour(80, 80, 80)), FromDIP(4))); // Fixed in both themes, like the triangle picker's drag handle: the divider is drawn over
// blended filament colour, so it has to keep its contrast against data rather than chrome.
dc.SetPen(wxPen(wxColour(80, 80, 80), FromDIP(4)));
dc.DrawLine(div_x, 0, div_x, sz.GetHeight()); dc.DrawLine(div_x, 0, div_x, sz.GetHeight());
dc.SetPen(wxPen(*wxWHITE, FromDIP(2))); dc.SetPen(wxPen(*wxWHITE, FromDIP(2)));
dc.DrawLine(div_x, 0, div_x, sz.GetHeight()); dc.DrawLine(div_x, 0, div_x, sz.GetHeight());
@@ -1081,7 +1071,7 @@ wxBoxSizer* MixedFilamentDialog::create_triangle_picker()
int top_label_y = std::max(0, (int)(v0.y - ts0.GetHeight() - FromDIP(4))); int top_label_y = std::max(0, (int)(v0.y - ts0.GetHeight() - FromDIP(4)));
dc.SetFont(::Label::Body_12); dc.SetFont(::Label::Body_12);
dc.SetTextForeground(wxColour("#909090")); dc.SetTextForeground(StateColor::darkModeColorFor(COLOR_LABEL_MUTED));
dc.DrawText(_L("Ratio"), FromDIP(2), top_label_y); dc.DrawText(_L("Ratio"), FromDIP(2), top_label_y);
// Position the real RatioLabelPanel children // Position the real RatioLabelPanel children
@@ -1247,7 +1237,7 @@ wxBoxSizer* MixedFilamentDialog::create_recommendation_grid()
auto* rec_line = new wxPanel(this, wxID_ANY); auto* rec_line = new wxPanel(this, wxID_ANY);
rec_line->SetMinSize(wxSize(-1, 1)); rec_line->SetMinSize(wxSize(-1, 1));
rec_line->SetBackgroundColour(StateColor::darkModeColorFor(wxColour("#DFDFDF"))); rec_line->SetBackgroundColour(StateColor::darkModeColorFor(wxColour("#EEEEEE")));
title_sizer->Add(rec_line, 1, wxALIGN_CENTER_VERTICAL); title_sizer->Add(rec_line, 1, wxALIGN_CENTER_VERTICAL);
outer->Add(title_sizer, 0, wxEXPAND | wxBOTTOM, FromDIP(4)); outer->Add(title_sizer, 0, wxEXPAND | wxBOTTOM, FromDIP(4));
@@ -1386,9 +1376,14 @@ wxBoxSizer* MixedFilamentDialog::create_button_panel()
m_btn_cancel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { EndModal(wxID_CANCEL); }); m_btn_cancel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { EndModal(wxID_CANCEL); });
m_btn_ok = new Button(this, _L("OK")); m_btn_ok = new Button(this, _L("OK"));
m_btn_ok->SetBackgroundColor(wxColour("#00AE42")); m_btn_ok->SetBackgroundColor(StateColor(
m_btn_ok->SetBorderColor(wxColour("#00AE42")); std::make_pair(wxColour("#CECECE"), (int) StateColor::Disabled),
m_btn_ok->SetTextColor(*wxWHITE); std::make_pair(wxColour(0, 137, 123), (int) StateColor::Pressed),
std::make_pair(wxColour("#009688"), (int) StateColor::Normal)));
m_btn_ok->SetBorderColor(StateColor(
std::make_pair(wxColour("#CECECE"), (int) StateColor::Disabled),
std::make_pair(wxColour("#009688"), (int) StateColor::Normal)));
m_btn_ok->SetTextColor(wxColour("#FFFFFE"));
m_btn_ok->SetMinSize(wxSize(FromDIP(55), FromDIP(24))); m_btn_ok->SetMinSize(wxSize(FromDIP(55), FromDIP(24)));
m_btn_ok->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { EndModal(wxID_OK); }); m_btn_ok->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { EndModal(wxID_OK); });
@@ -1721,15 +1716,15 @@ void MixedFilamentDialog::paint_warning_panel(wxPaintEvent&)
dc.SetPen(*wxTRANSPARENT_PEN); dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(0, 0, sz.GetWidth(), sz.GetHeight()); dc.DrawRectangle(0, 0, sz.GetWidth(), sz.GetHeight());
dc.SetBrush(wxBrush(wxColour(255, 245, 245))); dc.SetBrush(wxBrush(StateColor::darkModeColorFor(wxColour("#F8F8F8"))));
dc.SetPen(wxPen(wxColour("#E84C4C"), 1)); dc.SetPen(wxPen(StateColor::darkModeColorFor(wxColour("#D01B1B")), 1));
dc.DrawRoundedRectangle(0, 0, sz.GetWidth(), sz.GetHeight(), FromDIP(4)); dc.DrawRoundedRectangle(0, 0, sz.GetWidth(), sz.GetHeight(), FromDIP(4));
int x = FromDIP(10); int x = FromDIP(10);
int cy = sz.GetHeight() / 2; int cy = sz.GetHeight() / 2;
int icon_r = FromDIP(7); int icon_r = FromDIP(7);
dc.SetBrush(wxBrush(wxColour("#E84C4C"))); dc.SetBrush(wxBrush(StateColor::darkModeColorFor(wxColour("#D01B1B"))));
dc.SetPen(*wxTRANSPARENT_PEN); dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawCircle(x + icon_r, cy, icon_r); dc.DrawCircle(x + icon_r, cy, icon_r);
dc.SetFont(::Label::Body_10); dc.SetFont(::Label::Body_10);
@@ -1741,7 +1736,7 @@ void MixedFilamentDialog::paint_warning_panel(wxPaintEvent&)
if (m_type_mismatch_msg.empty()) return; if (m_type_mismatch_msg.empty()) return;
dc.SetFont(::Label::Body_12); dc.SetFont(::Label::Body_12);
dc.SetTextForeground(wxColour("#E84C4C")); dc.SetTextForeground(StateColor::darkModeColorFor(wxColour("#D01B1B")));
wxString msg = m_type_mismatch_msg; wxString msg = m_type_mismatch_msg;
int avail_w = sz.GetWidth() - x - FromDIP(10); int avail_w = sz.GetWidth() - x - FromDIP(10);
wxSize ts = dc.GetTextExtent(msg); wxSize ts = dc.GetTextExtent(msg);
@@ -1812,20 +1807,14 @@ void MixedFilamentDialog::update_ok_button_state()
} }
bool can_confirm = !has_type_mismatch && !has_unselected; bool can_confirm = !has_type_mismatch && !has_unselected;
// Enable() alone repaints the button: its StateColor carries the disabled grey.
m_btn_ok->Enable(can_confirm); m_btn_ok->Enable(can_confirm);
if (has_unselected) { if (has_unselected)
m_btn_ok->SetBackgroundColor(wxColour("#CECECE"));
m_btn_ok->SetBorderColor(wxColour("#CECECE"));
m_btn_ok->SetToolTip(_L("Please select a filament for all components")); m_btn_ok->SetToolTip(_L("Please select a filament for all components"));
} else if (has_type_mismatch) { else if (has_type_mismatch)
m_btn_ok->SetBackgroundColor(wxColour("#CECECE"));
m_btn_ok->SetBorderColor(wxColour("#CECECE"));
m_btn_ok->SetToolTip(_L("Cannot mix different filament types")); m_btn_ok->SetToolTip(_L("Cannot mix different filament types"));
} else { else
m_btn_ok->SetBackgroundColor(wxColour("#00AE42"));
m_btn_ok->SetBorderColor(wxColour("#00AE42"));
m_btn_ok->SetToolTip(wxEmptyString); m_btn_ok->SetToolTip(wxEmptyString);
}
if (m_warning_panel) { if (m_warning_panel) {
m_warning_panel->Show(has_type_mismatch); m_warning_panel->Show(has_type_mismatch);
@@ -1946,15 +1935,8 @@ void MixedFilamentDialog::update_component_count_ui()
if (m_btn_add_material) { if (m_btn_add_material) {
bool can_add = (num_components() < (size_t)MAX_COMPONENTS && m_physical_colors.size() > num_components()); bool can_add = (num_components() < (size_t)MAX_COMPONENTS && m_physical_colors.size() > num_components());
m_btn_add_material->Enable(can_add); m_btn_add_material->Enable(can_add);
if (can_add) { m_btn_add_material->SetToolTip(can_add ? wxString()
m_btn_add_material->SetTextColor(wxColour("#262E30")); : (is_three ? _L("Maximum 3 materials for mixing") : _L("Maximum number of components reached")));
m_btn_add_material->SetBorderColor(wxColour("#EEEEEE"));
m_btn_add_material->SetToolTip(wxEmptyString);
} else {
m_btn_add_material->SetTextColor(wxColour("#CECECE"));
m_btn_add_material->SetBorderColor(wxColour("#EEEEEE"));
m_btn_add_material->SetToolTip(is_three ? _L("Maximum 3 materials for mixing") : _L("Maximum number of components reached"));
}
} }
if (m_btn_remove_material) { if (m_btn_remove_material) {
-4
View File
@@ -158,10 +158,6 @@ private:
wxScrolledWindow* m_recommendation_scroll{nullptr}; wxScrolledWindow* m_recommendation_scroll{nullptr};
wxWrapSizer* m_recommendation_grid{nullptr}; wxWrapSizer* m_recommendation_grid{nullptr};
// Cached preview bitmaps (loaded once at construction)
wxBitmap m_preview_bmp_two;
wxBitmap m_preview_bmp_three;
// Drag state. The ratio bar and the triangle picker capture the mouse // Drag state. The ratio bar and the triangle picker capture the mouse
// independently, so they must not share a flag: a mouse-up on one would // independently, so they must not share a flag: a mouse-up on one would
// otherwise clear the other's flag and skip its ReleaseMouse(). // otherwise clear the other's flag and skip its ReleaseMouse().
+1 -1
View File
@@ -486,7 +486,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title
wxDefaultPosition, wxSize(FromDIP(16), FromDIP(16))); wxDefaultPosition, wxSize(FromDIP(16), FromDIP(16)));
auto *warn_text = new wxStaticText(this, wxID_ANY, auto *warn_text = new wxStaticText(this, wxID_ANY,
_L("The filament list contains mixed filaments. Custom filament sequence will not take effect.")); _L("The filament list contains mixed filaments. Custom filament sequence will not take effect."));
warn_text->SetForegroundColour(wxColour(255, 111, 0)); warn_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#FF6F00")));
warn_text->SetFont(Label::Body_12); warn_text->SetFont(Label::Body_12);
warn_text->Wrap(FromDIP(300)); warn_text->Wrap(FromDIP(300));
+7 -7
View File
@@ -3148,12 +3148,12 @@ Sidebar::Sidebar(Plater *parent)
// 4) Warning bar for mixes whose components were deleted or whose types disagree. // 4) Warning bar for mixes whose components were deleted or whose types disagree.
p->m_panel_mixed_warning = new wxPanel(p->scrolled, wxID_ANY); p->m_panel_mixed_warning = new wxPanel(p->scrolled, wxID_ANY);
p->m_panel_mixed_warning->SetBackgroundColour(wxColour("#FDE8E8")); p->m_panel_mixed_warning->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
{ {
auto* warn_sizer = new wxBoxSizer(wxHORIZONTAL); auto* warn_sizer = new wxBoxSizer(wxHORIZONTAL);
p->m_text_mixed_warning = new wxStaticText(p->m_panel_mixed_warning, wxID_ANY, p->m_text_mixed_warning = new wxStaticText(p->m_panel_mixed_warning, wxID_ANY,
_L("Mixed filament has invalid or mismatched components. Please re-edit affected entries.")); _L("Mixed filament has invalid or mismatched components. Please re-edit affected entries."));
p->m_text_mixed_warning->SetForegroundColour(wxColour("#D32F2F")); p->m_text_mixed_warning->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#D01B1B")));
p->m_text_mixed_warning->SetFont(::Label::Body_12); p->m_text_mixed_warning->SetFont(::Label::Body_12);
p->m_text_mixed_warning->Wrap(FromDIP(360)); p->m_text_mixed_warning->Wrap(FromDIP(360));
warn_sizer->Add(p->m_text_mixed_warning, 1, wxALL, FromDIP(6)); warn_sizer->Add(p->m_text_mixed_warning, 1, wxALL, FromDIP(6));
@@ -3999,12 +3999,12 @@ void Sidebar::update_mixed_filament_list()
physical_colors.push_back(colours_opt->values[i]); physical_colors.push_back(colours_opt->values[i]);
} }
auto make_swatch_panel = [this, mc_text](wxWindow* parent, const wxColour& col, unsigned int num) -> wxPanel* { auto make_swatch_panel = [this](wxWindow* parent, const wxColour& col, unsigned int num) -> wxPanel* {
int swatch_sz = FromDIP(20); int swatch_sz = FromDIP(20);
auto* panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(swatch_sz, swatch_sz)); auto* panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(swatch_sz, swatch_sz));
panel->SetMinSize(wxSize(swatch_sz, swatch_sz)); panel->SetMinSize(wxSize(swatch_sz, swatch_sz));
bool is_dark = wxGetApp().dark_mode(); bool is_dark = wxGetApp().dark_mode();
panel->Bind(wxEVT_PAINT, [panel, col, num, mc_text, is_dark](wxPaintEvent&) { panel->Bind(wxEVT_PAINT, [panel, col, num, is_dark](wxPaintEvent&) {
wxPaintDC dc(panel); wxPaintDC dc(panel);
wxSize sz = panel->GetClientSize(); wxSize sz = panel->GetClientSize();
dc.SetBackground(wxBrush(col)); dc.SetBackground(wxBrush(col));
@@ -4110,7 +4110,7 @@ void Sidebar::update_mixed_filament_list()
wxDefaultPosition, wxSize(swatch_sz, swatch_sz)); wxDefaultPosition, wxSize(swatch_sz, swatch_sz));
grad_panel->SetMinSize(wxSize(swatch_sz, swatch_sz)); grad_panel->SetMinSize(wxSize(swatch_sz, swatch_sz));
grad_panel->SetBackgroundStyle(wxBG_STYLE_PAINT); grad_panel->SetBackgroundStyle(wxBG_STYLE_PAINT);
grad_panel->Bind(wxEVT_PAINT, [grad_panel, gradient_ramp, mix_num, mc_text](wxPaintEvent&) { grad_panel->Bind(wxEVT_PAINT, [grad_panel, gradient_ramp, mix_num](wxPaintEvent&) {
wxBufferedPaintDC dc(grad_panel); wxBufferedPaintDC dc(grad_panel);
wxSize sz = grad_panel->GetClientSize(); wxSize sz = grad_panel->GetClientSize();
fill_gradient_ramp_rect(dc, wxRect(0, 0, sz.GetWidth(), sz.GetHeight()), gradient_ramp); fill_gradient_ramp_rect(dc, wxRect(0, 0, sz.GetWidth(), sz.GetHeight()), gradient_ramp);
@@ -4119,7 +4119,7 @@ void Sidebar::update_mixed_filament_list()
wxSize txt_sz = dc.GetTextExtent(txt); wxSize txt_sz = dc.GetTextExtent(txt);
// The number sits at the swatch's middle, so take its contrast from the // The number sits at the swatch's middle, so take its contrast from the
// colour printed at mid height rather than from either endpoint. // colour printed at mid height rather than from either endpoint.
dc.SetTextForeground(gradient_ramp[gradient_ramp.size() / 2].GetLuminance() > 0.5 ? mc_text : *wxWHITE); dc.SetTextForeground(gradient_ramp[gradient_ramp.size() / 2].GetLuminance() > 0.5 ? wxColour(50, 58, 61) : *wxWHITE);
dc.DrawText(txt, (sz.GetWidth() - txt_sz.GetWidth()) / 2, dc.DrawText(txt, (sz.GetWidth() - txt_sz.GetWidth()) / 2,
(sz.GetHeight() - txt_sz.GetHeight()) / 2); (sz.GetHeight() - txt_sz.GetHeight()) / 2);
}); });
@@ -4251,7 +4251,7 @@ void Sidebar::update_mixed_filament_list()
dc.DrawRectangle(x, y_swatch, cp_swatch_sz, cp_swatch_sz); dc.DrawRectangle(x, y_swatch, cp_swatch_sz, cp_swatch_sz);
wxString dash = wxT("\u2014"); wxString dash = wxT("\u2014");
wxSize dash_sz = dc.GetTextExtent(dash); wxSize dash_sz = dc.GetTextExtent(dash);
dc.SetTextForeground(wxColour("#909090")); dc.SetTextForeground(mc_dim);
dc.DrawText(dash, x + (cp_swatch_sz - dash_sz.GetWidth()) / 2, dc.DrawText(dash, x + (cp_swatch_sz - dash_sz.GetWidth()) / 2,
y_swatch + (cp_swatch_sz - dash_sz.GetHeight()) / 2); y_swatch + (cp_swatch_sz - dash_sz.GetHeight()) / 2);
} }
+174 -247
View File
@@ -43,11 +43,6 @@ static constexpr const char* DEFAULT_VIRTUAL_FILAMENT_NAME = "Bambu PLA Ba
static bool is_dark() { return Slic3r::GUI::wxGetApp().dark_mode(); } static bool is_dark() { return Slic3r::GUI::wxGetApp().dark_mode(); }
static wxColour dark_or(const wxColour& light, const wxColour& dark)
{
return is_dark() ? dark : light;
}
static wxColour texture_import_gray9000() static wxColour texture_import_gray9000()
{ {
return wxColour(38, 46, 48); return wxColour(38, 46, 48);
@@ -58,9 +53,41 @@ static wxColour texture_import_text_colour()
return StateColor::darkModeColorFor(texture_import_gray9000()); return StateColor::darkModeColorFor(texture_import_gray9000());
} }
// StaticLine::SetLineColour stores the raw key and resolves it itself when it paints, so those
// sinks take SEPARATOR_COLOUR_KEY directly; only raw wx sinks need the resolved form below.
static constexpr const char* SEPARATOR_COLOUR_KEY = "#CECECE";
static wxColour texture_import_separator_colour() static wxColour texture_import_separator_colour()
{ {
return StateColor::darkModeColorFor(wxColour("#CECECE")); return StateColor::darkModeColorFor(wxColour(SEPARATOR_COLOUR_KEY));
}
// Orca's confirm palette, applied here rather than through Button::SetStyle because these buttons
// keep custom pill geometry that SetStyle resets. The Disabled entries are load-bearing: without
// one, StateColor::colorForStates falls through to the Normal entry and a disabled button paints
// as a live accent button.
static void apply_accent_button_colours(Button* btn)
{
btn->SetBackgroundColor(StateColor(
std::pair<wxColour, int>(wxColour("#CECECE"), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal)));
btn->SetBorderColor(StateColor(
std::pair<wxColour, int>(wxColour("#CECECE"), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal)));
btn->SetTextColor(StateColor(
std::pair<wxColour, int>(wxColour("#6B6B6A"), StateColor::Disabled),
std::pair<wxColour, int>(wxColour("#FFFFFE"), StateColor::Normal)));
}
// The same button while the parameters behind it are dirty: still clickable, but reading as
// "what you see is not what this button would apply".
static void apply_muted_button_colours(Button* btn)
{
btn->SetBackgroundColor(wxColour("#CECECE"));
btn->SetBorderColor(wxColour("#CECECE"));
btn->SetTextColor(wxColour("#6B6B6A"));
} }
static wxFont texture_import_section_title_font(wxWindow* win) static wxFont texture_import_section_title_font(wxWindow* win)
@@ -162,29 +189,16 @@ static wxString ellipsize_text(wxDC& dc, wxString text, int max_width)
return text + ellipsis; return text + ellipsis;
} }
static int draw_brand_icon_and_strip(wxDC& dc, wxWindow* win, wxString& name, int x, int cy)
{
int icon_sz = win->FromDIP(16);
if (name.StartsWith("Bambu ")) {
name = name.Mid(6);
wxBitmap bmp = create_scaled_bitmap("BambuStudioBlack", win, 16);
if (bmp.IsOk())
dc.DrawBitmap(bmp, x, cy - icon_sz / 2, true);
x += icon_sz + win->FromDIP(4);
}
return x;
}
// ============================================================ // ============================================================
// GreenSlider — thin track + green triangle thumb // AccentSlider — thin track + accent-coloured triangle thumb
// ============================================================ // ============================================================
class GreenSlider : public wxPanel { class AccentSlider : public wxPanel {
public: public:
GreenSlider(wxWindow* parent, int value, int minVal, int maxVal, AccentSlider(wxWindow* parent, int value, int minVal, int maxVal,
const wxPoint& pos = wxDefaultPosition, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize); const wxSize& size = wxDefaultSize);
~GreenSlider() override; ~AccentSlider() override;
int GetValue() const; int GetValue() const;
void SetValue(int val); void SetValue(int val);
bool Enable(bool enable = true) override; bool Enable(bool enable = true) override;
@@ -197,7 +211,7 @@ private:
bool m_dragging = false; bool m_dragging = false;
}; };
GreenSlider::GreenSlider(wxWindow* parent, int value, int minVal, int maxVal, AccentSlider::AccentSlider(wxWindow* parent, int value, int minVal, int maxVal,
const wxPoint& pos, const wxSize& size) const wxPoint& pos, const wxSize& size)
: wxPanel(parent, wxID_ANY, pos, size.IsFullySpecified() ? size : wxSize(-1, parent->FromDIP(24)), : wxPanel(parent, wxID_ANY, pos, size.IsFullySpecified() ? size : wxSize(-1, parent->FromDIP(24)),
wxTAB_TRAVERSAL | wxFULL_REPAINT_ON_RESIZE) wxTAB_TRAVERSAL | wxFULL_REPAINT_ON_RESIZE)
@@ -206,18 +220,18 @@ GreenSlider::GreenSlider(wxWindow* parent, int value, int minVal, int maxVal,
SetBackgroundStyle(wxBG_STYLE_PAINT); SetBackgroundStyle(wxBG_STYLE_PAINT);
SetMinSize(wxSize(-1, FromDIP(24))); SetMinSize(wxSize(-1, FromDIP(24)));
Bind(wxEVT_PAINT, &GreenSlider::OnPaint, this); Bind(wxEVT_PAINT, &AccentSlider::OnPaint, this);
Bind(wxEVT_SIZE, [this](wxSizeEvent& evt) { Bind(wxEVT_SIZE, [this](wxSizeEvent& evt) {
evt.Skip(); evt.Skip();
Refresh(); Refresh();
}); });
Bind(wxEVT_LEFT_DOWN, &GreenSlider::OnMouse, this); Bind(wxEVT_LEFT_DOWN, &AccentSlider::OnMouse, this);
Bind(wxEVT_LEFT_UP, &GreenSlider::OnMouse, this); Bind(wxEVT_LEFT_UP, &AccentSlider::OnMouse, this);
Bind(wxEVT_MOTION, &GreenSlider::OnMouse, this); Bind(wxEVT_MOTION, &AccentSlider::OnMouse, this);
Bind(wxEVT_MOUSE_CAPTURE_LOST, [this](wxMouseCaptureLostEvent&) { m_dragging = false; }); Bind(wxEVT_MOUSE_CAPTURE_LOST, [this](wxMouseCaptureLostEvent&) { m_dragging = false; });
} }
GreenSlider::~GreenSlider() AccentSlider::~AccentSlider()
{ {
// See MixedFilamentDialog::~MixedFilamentDialog: a widget destroyed while it // See MixedFilamentDialog::~MixedFilamentDialog: a widget destroyed while it
// still holds the capture wedges mouse input for the whole application. // still holds the capture wedges mouse input for the whole application.
@@ -225,22 +239,22 @@ GreenSlider::~GreenSlider()
ReleaseMouse(); ReleaseMouse();
} }
int GreenSlider::GetValue() const { return m_value; } int AccentSlider::GetValue() const { return m_value; }
void GreenSlider::SetValue(int val) void AccentSlider::SetValue(int val)
{ {
val = std::clamp(val, m_min, m_max); val = std::clamp(val, m_min, m_max);
if (val != m_value) { m_value = val; Refresh(); } if (val != m_value) { m_value = val; Refresh(); }
} }
bool GreenSlider::Enable(bool enable) bool AccentSlider::Enable(bool enable)
{ {
bool ok = wxPanel::Enable(enable); bool ok = wxPanel::Enable(enable);
Refresh(); Refresh();
return ok; return ok;
} }
int GreenSlider::xFromValue() const int AccentSlider::xFromValue() const
{ {
wxSize sz = GetClientSize(); wxSize sz = GetClientSize();
int margin = FromDIP(6); int margin = FromDIP(6);
@@ -249,7 +263,7 @@ int GreenSlider::xFromValue() const
return margin + (m_value - m_min) * track_w / (m_max - m_min); return margin + (m_value - m_min) * track_w / (m_max - m_min);
} }
int GreenSlider::valueFromX(int x) const int AccentSlider::valueFromX(int x) const
{ {
wxSize sz = GetClientSize(); wxSize sz = GetClientSize();
int margin = FromDIP(6); int margin = FromDIP(6);
@@ -259,7 +273,7 @@ int GreenSlider::valueFromX(int x) const
return std::clamp(val, m_min, m_max); return std::clamp(val, m_min, m_max);
} }
void GreenSlider::OnPaint(wxPaintEvent&) void AccentSlider::OnPaint(wxPaintEvent&)
{ {
wxAutoBufferedPaintDC dc(this); wxAutoBufferedPaintDC dc(this);
wxSize sz = GetClientSize(); wxSize sz = GetClientSize();
@@ -272,17 +286,15 @@ void GreenSlider::OnPaint(wxPaintEvent&)
int ts = FromDIP(8); int ts = FromDIP(8);
int pen_w = FromDIP(2); int pen_w = FromDIP(2);
wxColour greenClr = IsEnabled() ? wxColour(0, 174, 66) wxColour accent_clr = StateColor::darkModeColorFor(IsEnabled() ? wxColour("#009688") : wxColour("#ACACAC"));
: dark_or(wxColour(180, 180, 180), wxColour(90, 90, 96)); wxColour track_clr = StateColor::darkModeColorFor(IsEnabled() ? wxColour("#CECECE") : wxColour("#DFDFDF"));
wxColour grayClr = IsEnabled() ? dark_or(wxColour(200, 200, 200), wxColour(90, 90, 96))
: dark_or(wxColour(220, 220, 220), wxColour(70, 70, 76));
int tx = xFromValue(); int tx = xFromValue();
dc.SetPen(wxPen(greenClr, pen_w)); dc.SetPen(wxPen(accent_clr, pen_w));
dc.DrawLine(margin, track_y, tx, track_y); dc.DrawLine(margin, track_y, tx, track_y);
dc.SetPen(wxPen(grayClr, pen_w)); dc.SetPen(wxPen(track_clr, pen_w));
dc.DrawLine(tx, track_y, sz.x - margin, track_y); dc.DrawLine(tx, track_y, sz.x - margin, track_y);
wxPoint tri[3] = { wxPoint tri[3] = {
@@ -290,12 +302,12 @@ void GreenSlider::OnPaint(wxPaintEvent&)
{tx - ts / 2, track_y + FromDIP(1) + ts}, {tx - ts / 2, track_y + FromDIP(1) + ts},
{tx + ts / 2, track_y + FromDIP(1) + ts} {tx + ts / 2, track_y + FromDIP(1) + ts}
}; };
dc.SetBrush(wxBrush(greenClr)); dc.SetBrush(wxBrush(accent_clr));
dc.SetPen(*wxTRANSPARENT_PEN); dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawPolygon(3, tri); dc.DrawPolygon(3, tri);
} }
void GreenSlider::OnMouse(wxMouseEvent& evt) void AccentSlider::OnMouse(wxMouseEvent& evt)
{ {
if (!IsEnabled()) return; if (!IsEnabled()) return;
@@ -516,7 +528,7 @@ public:
, m_on_close(std::move(on_close)) , m_on_close(std::move(on_close))
, m_display_numbers(std::move(display_numbers)) , m_display_numbers(std::move(display_numbers))
{ {
wxColour pop_bg = dark_or(*wxWHITE, wxColour(0x2D, 0x2D, 0x31)); wxColour pop_bg = StateColor::darkModeColorFor(*wxWHITE);
SetBackgroundColour(pop_bg); SetBackgroundColour(pop_bg);
m_content = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL); m_content = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL);
@@ -528,7 +540,7 @@ public:
const int row_h = FromDIP(32); const int row_h = FromDIP(32);
const int pad = FromDIP(8); const int pad = FromDIP(8);
const int max_visible_rows = 10; const int max_visible_rows = 10;
const wxColour header_clr = dark_or(wxColour(0xAC, 0xAC, 0xAC), wxColour(0x81, 0x81, 0x83)); const wxColour header_clr = StateColor::darkModeColorFor(wxColour("#ACACAC"));
auto add_section_header = [&](const wxString& label) { auto add_section_header = [&](const wxString& label) {
auto* hdr = new wxStaticText(m_content, wxID_ANY, label); auto* hdr = new wxStaticText(m_content, wxID_ANY, label);
@@ -538,7 +550,7 @@ public:
hdr->SetForegroundColour(header_clr); hdr->SetForegroundColour(header_clr);
outer->Add(hdr, 0, wxLEFT | wxRIGHT | wxTOP, pad); outer->Add(hdr, 0, wxLEFT | wxRIGHT | wxTOP, pad);
auto* line = new StaticLine(m_content); auto* line = new StaticLine(m_content);
line->SetLineColour(texture_import_separator_colour()); line->SetLineColour(wxColour(SEPARATOR_COLOUR_KEY));
outer->Add(line, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP | wxBOTTOM, pad); outer->Add(line, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP | wxBOTTOM, pad);
}; };
@@ -577,8 +589,9 @@ public:
add_label->SetFont(af); add_label->SetFont(af);
decompose_label->SetFont(af); decompose_label->SetFont(af);
const bool add_enabled = !m_can_add_filament || m_can_add_filament(); const bool add_enabled = !m_can_add_filament || m_can_add_filament();
add_label->SetForegroundColour(add_enabled ? wxColour(0x00, 0xAE, 0x42) : header_clr); const wxColour action_clr = StateColor::darkModeColorFor(wxColour("#009688"));
decompose_label->SetForegroundColour(add_enabled ? wxColour(0x00, 0xAE, 0x42) : header_clr); add_label->SetForegroundColour(add_enabled ? action_clr : header_clr);
decompose_label->SetForegroundColour(add_enabled ? action_clr : header_clr);
add_label->SetCursor(wxCursor(add_enabled ? wxCURSOR_HAND : wxCURSOR_ARROW)); add_label->SetCursor(wxCursor(add_enabled ? wxCURSOR_HAND : wxCURSOR_ARROW));
decompose_label->SetCursor(wxCursor(add_enabled ? wxCURSOR_HAND : wxCURSOR_ARROW)); decompose_label->SetCursor(wxCursor(add_enabled ? wxCURSOR_HAND : wxCURSOR_ARROW));
if (!add_enabled) if (!add_enabled)
@@ -634,11 +647,11 @@ public:
top_sizer->AddSpacer(FromDIP(4)); top_sizer->AddSpacer(FromDIP(4));
auto* sep_line = new StaticLine(this); auto* sep_line = new StaticLine(this);
sep_line->SetLineColour(texture_import_separator_colour()); sep_line->SetLineColour(wxColour(SEPARATOR_COLOUR_KEY));
top_sizer->Add(sep_line, 0, wxEXPAND | wxLEFT | wxRIGHT, pad); top_sizer->Add(sep_line, 0, wxEXPAND | wxLEFT | wxRIGHT, pad);
top_sizer->Add(decompose_label, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP | wxBOTTOM, pad); top_sizer->Add(decompose_label, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP | wxBOTTOM, pad);
auto* sep_line2 = new StaticLine(this); auto* sep_line2 = new StaticLine(this);
sep_line2->SetLineColour(texture_import_separator_colour()); sep_line2->SetLineColour(wxColour(SEPARATOR_COLOUR_KEY));
top_sizer->Add(sep_line2, 0, wxEXPAND | wxLEFT | wxRIGHT, pad); top_sizer->Add(sep_line2, 0, wxEXPAND | wxLEFT | wxRIGHT, pad);
top_sizer->Add(add_label, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP | wxBOTTOM, pad); top_sizer->Add(add_label, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP | wxBOTTOM, pad);
SetSizerAndFit(top_sizer); SetSizerAndFit(top_sizer);
@@ -676,8 +689,8 @@ private:
wxPanel* create_item_row(size_t idx, int row_h) wxPanel* create_item_row(size_t idx, int row_h)
{ {
wxColour row_bg = dark_or(*wxWHITE, wxColour(0x2D, 0x2D, 0x31)); wxColour row_bg = StateColor::darkModeColorFor(*wxWHITE);
wxColour hover_bg = dark_or(wxColour(245, 245, 245), wxColour(0x3C, 0x3C, 0x42)); wxColour hover_bg = StateColor::darkModeColorFor(wxColour("#F4F4F4"));
wxColour name_fg = texture_import_text_colour(); wxColour name_fg = texture_import_text_colour();
wxPanel* row = new wxPanel(m_content, wxID_ANY, wxDefaultPosition, wxSize(-1, row_h)); wxPanel* row = new wxPanel(m_content, wxID_ANY, wxDefaultPosition, wxSize(-1, row_h));
@@ -731,15 +744,14 @@ private:
dc.DrawText(ns, sq_x + (sq - tsz.x) / 2, sq_y + (sq - tsz.y) / 2); dc.DrawText(ns, sq_x + (sq - tsz.x) / 2, sq_y + (sq - tsz.y) / 2);
} }
// Brand icon + material name // Material name
{ {
wxFont mf = p->GetFont(); wxFont mf = p->GetFont();
mf.SetPointSize(10); mf.SetPointSize(10);
dc.SetFont(mf); dc.SetFont(mf);
dc.SetTextForeground(name_fg); dc.SetTextForeground(name_fg);
wxString display = name_str; int tx = sq_x + sq + gap1;
int tx = draw_brand_icon_and_strip(dc, p, display, sq_x + sq + gap1, sz.y / 2); wxString display = ellipsize_text(dc, name_str, sz.x - tx - p->FromDIP(4));
display = ellipsize_text(dc, display, sz.x - tx - p->FromDIP(4));
wxSize tsz = dc.GetTextExtent(display); wxSize tsz = dc.GetTextExtent(display);
if (!display.empty()) if (!display.empty())
dc.DrawText(display, tx, (sz.y - tsz.y) / 2); dc.DrawText(display, tx, (sz.y - tsz.y) / 2);
@@ -772,10 +784,9 @@ private:
wxPanel* create_mixed_item_row(const TextureFilamentEntry& entry, int row_h) wxPanel* create_mixed_item_row(const TextureFilamentEntry& entry, int row_h)
{ {
wxColour row_bg = dark_or(*wxWHITE, wxColour(0x2D, 0x2D, 0x31)); wxColour row_bg = StateColor::darkModeColorFor(*wxWHITE);
wxColour hover_bg = dark_or(wxColour(245, 245, 245), wxColour(0x3C, 0x3C, 0x42)); wxColour hover_bg = StateColor::darkModeColorFor(wxColour("#F4F4F4"));
wxColour name_fg = texture_import_text_colour(); wxColour name_fg = texture_import_text_colour();
wxColour plus_fg = dark_or(wxColour(38, 46, 48), wxColour(0xE6, 0xE6, 0xE8));
const int idx = entry.dialog_index; const int idx = entry.dialog_index;
wxPanel* row = new wxPanel(m_content, wxID_ANY, wxDefaultPosition, wxSize(-1, row_h)); wxPanel* row = new wxPanel(m_content, wxID_ANY, wxDefaultPosition, wxSize(-1, row_h));
@@ -784,7 +795,7 @@ private:
row->SetCursor(wxCursor(wxCURSOR_HAND)); row->SetCursor(wxCursor(wxCURSOR_HAND));
row->SetToolTip(entry.name.empty() ? wxString::Format("Filament %d", display_number(idx)) : filament_name_to_wx_string(entry.name)); row->SetToolTip(entry.name.empty() ? wxString::Format("Filament %d", display_number(idx)) : filament_name_to_wx_string(entry.name));
row->Bind(wxEVT_PAINT, [this, entry, idx, row_bg, hover_bg, name_fg, plus_fg](wxPaintEvent& e) { row->Bind(wxEVT_PAINT, [this, entry, idx, row_bg, hover_bg, name_fg](wxPaintEvent& e) {
auto* p = static_cast<wxPanel*>(e.GetEventObject()); auto* p = static_cast<wxPanel*>(e.GetEventObject());
wxAutoBufferedPaintDC dc(p); wxAutoBufferedPaintDC dc(p);
wxSize sz = p->GetClientSize(); wxSize sz = p->GetClientSize();
@@ -803,7 +814,7 @@ private:
for (size_t ci = 0; ci < entry.mixed_components.size() && ci < entry.mixed_ratios.size(); ++ci) { for (size_t ci = 0; ci < entry.mixed_components.size() && ci < entry.mixed_ratios.size(); ++ci) {
if (ci > 0) { if (ci > 0) {
dc.SetTextForeground(plus_fg); dc.SetTextForeground(name_fg);
wxString plus = "+"; wxString plus = "+";
wxSize psz = dc.GetTextExtent(plus); wxSize psz = dc.GetTextExtent(plus);
dc.DrawText(plus, x, (sz.y - psz.y) / 2); dc.DrawText(plus, x, (sz.y - psz.y) / 2);
@@ -907,7 +918,7 @@ public:
, m_on_select(std::move(on_select)) , m_on_select(std::move(on_select))
, m_on_close(std::move(on_close)) , m_on_close(std::move(on_close))
{ {
wxColour pop_bg = dark_or(*wxWHITE, wxColour(0x2D, 0x2D, 0x31)); wxColour pop_bg = StateColor::darkModeColorFor(*wxWHITE);
SetBackgroundColour(pop_bg); SetBackgroundColour(pop_bg);
auto* content = new wxPanel(this, wxID_ANY); auto* content = new wxPanel(this, wxID_ANY);
@@ -939,10 +950,10 @@ private:
wxPanel* create_item_row(wxWindow* parent, TextureAutoMixMode mode, int row_h) wxPanel* create_item_row(wxWindow* parent, TextureAutoMixMode mode, int row_h)
{ {
wxColour row_bg = dark_or(*wxWHITE, wxColour(0x2D, 0x2D, 0x31)); wxColour row_bg = StateColor::darkModeColorFor(*wxWHITE);
wxColour hover_bg = dark_or(wxColour(245, 245, 245), wxColour(0x3C, 0x3C, 0x42)); wxColour hover_bg = StateColor::darkModeColorFor(wxColour("#F4F4F4"));
wxColour text_fg = texture_import_text_colour(); wxColour text_fg = texture_import_text_colour();
wxColour green = wxColour(0, 174, 66); wxColour accent = StateColor::darkModeColorFor(wxColour("#009688"));
wxPanel* row = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, row_h), wxPanel* row = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, row_h),
wxTAB_TRAVERSAL | wxFULL_REPAINT_ON_RESIZE); wxTAB_TRAVERSAL | wxFULL_REPAINT_ON_RESIZE);
@@ -951,7 +962,7 @@ private:
row->SetCursor(wxCursor(wxCURSOR_HAND)); row->SetCursor(wxCursor(wxCURSOR_HAND));
const int row_idx = mode == TextureAutoMixMode::CMYW ? 0 : 1; const int row_idx = mode == TextureAutoMixMode::CMYW ? 0 : 1;
row->Bind(wxEVT_PAINT, [this, row_bg, hover_bg, text_fg, green, mode, row_idx](wxPaintEvent& e) { row->Bind(wxEVT_PAINT, [this, row_bg, hover_bg, text_fg, accent, mode, row_idx](wxPaintEvent& e) {
auto* p = static_cast<wxPanel*>(e.GetEventObject()); auto* p = static_cast<wxPanel*>(e.GetEventObject());
wxAutoBufferedPaintDC dc(p); wxAutoBufferedPaintDC dc(p);
wxSize sz = p->GetClientSize(); wxSize sz = p->GetClientSize();
@@ -975,7 +986,7 @@ private:
check_font.SetPointSize(12); check_font.SetPointSize(12);
check_font.MakeBold(); check_font.MakeBold();
dc.SetFont(check_font); dc.SetFont(check_font);
dc.SetTextForeground(green); dc.SetTextForeground(accent);
wxString check = wxString::FromUTF8("✓"); wxString check = wxString::FromUTF8("✓");
wxSize csz = dc.GetTextExtent(check); wxSize csz = dc.GetTextExtent(check);
dc.DrawText(check, sz.x - p->FromDIP(16) - csz.x, (sz.y - csz.y) / 2); dc.DrawText(check, sz.x - p->FromDIP(16) - csz.x, (sz.y - csz.y) / 2);
@@ -1286,13 +1297,13 @@ void TexturePreviewCanvas::upload_reset_icon_textures()
return; return;
if (!m_reset_icon_tex) if (!m_reset_icon_tex)
m_reset_icon_tex = upload_reset_icon_texture("fit_camera"); m_reset_icon_tex = upload_reset_icon_texture("canvas_zoom");
if (!m_reset_icon_hover_tex) if (!m_reset_icon_hover_tex)
m_reset_icon_hover_tex = upload_reset_icon_texture("fit_camera_hover"); m_reset_icon_hover_tex = upload_reset_icon_texture("canvas_zoom_hover");
if (!m_reset_icon_dark_tex) if (!m_reset_icon_dark_tex)
m_reset_icon_dark_tex = upload_reset_icon_texture("fit_camera_dark"); m_reset_icon_dark_tex = upload_reset_icon_texture("canvas_zoom_dark");
if (!m_reset_icon_dark_hover_tex) if (!m_reset_icon_dark_hover_tex)
m_reset_icon_dark_hover_tex = upload_reset_icon_texture("fit_camera_dark_hover"); m_reset_icon_dark_hover_tex = upload_reset_icon_texture("canvas_zoom_dark_hover");
} }
bool TexturePreviewCanvas::handle_reset_overlay_mouse(wxMouseEvent& evt) bool TexturePreviewCanvas::handle_reset_overlay_mouse(wxMouseEvent& evt)
@@ -1475,10 +1486,9 @@ void TexturePreviewCanvas::render()
wxSize viewport_sz = gl_viewport_size(this, sz); wxSize viewport_sz = gl_viewport_size(this, sz);
glViewport(0, 0, viewport_sz.x, viewport_sz.y); glViewport(0, 0, viewport_sz.x, viewport_sz.y);
if (is_dark()) // Same palette key as the preview container, so canvas and frame cannot drift apart.
glClearColor(0.24f, 0.24f, 0.27f, 1.0f); const wxColour clear_clr = StateColor::darkModeColorFor(wxColour("#EEEEEE"));
else glClearColor(clear_clr.Red() / 255.f, clear_clr.Green() / 255.f, clear_clr.Blue() / 255.f, 1.0f);
glClearColor(0.933f, 0.933f, 0.933f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@@ -1886,14 +1896,14 @@ int TextureImportDialog::ShowModal()
void TextureImportDialog::build_ui() void TextureImportDialog::build_ui()
{ {
const wxColour dialog_bg = dark_or(*wxWHITE, wxColour(0x2D, 0x2D, 0x31)); const wxColour dialog_bg = StateColor::darkModeColorFor(*wxWHITE);
SetBackgroundColour(dialog_bg); SetBackgroundColour(dialog_bg);
SetForegroundColour(dark_or(wxColour(50, 58, 61), wxColour(0xEF, 0xEF, 0xF0))); SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3D")));
wxBoxSizer* root_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer* root_sizer = new wxBoxSizer(wxVERTICAL);
auto line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1)); auto line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1));
line_top->SetBackgroundColour(dark_or(wxColour(166, 169, 170), wxColour(80, 80, 86))); line_top->SetBackgroundColour(texture_import_separator_colour());
root_sizer->Add(line_top, 0, wxEXPAND); root_sizer->Add(line_top, 0, wxEXPAND);
wxBoxSizer* main_sizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* main_sizer = new wxBoxSizer(wxHORIZONTAL);
@@ -1936,8 +1946,8 @@ void TextureImportDialog::build_ui()
void TextureImportDialog::build_preview_panel(wxWindow* parent, wxSizer* sizer) void TextureImportDialog::build_preview_panel(wxWindow* parent, wxSizer* sizer)
{ {
wxColour preview_bg = dark_or(wxColour(238, 238, 238), wxColour(0x3E, 0x3E, 0x45)); wxColour preview_bg = StateColor::darkModeColorFor(wxColour("#EEEEEE"));
wxColour preview_bd = dark_or(wxColour(206, 206, 206), wxColour(0x54, 0x54, 0x5B)); wxColour preview_bd = texture_import_separator_colour();
wxPanel* preview_container = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); wxPanel* preview_container = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
preview_container->SetBackgroundColour(preview_bg); preview_container->SetBackgroundColour(preview_bg);
@@ -2044,7 +2054,7 @@ void TextureImportDialog::build_preview_panel(wxWindow* parent, wxSizer* sizer)
void TextureImportDialog::build_params_panel(wxWindow* parent, wxSizer* sizer) void TextureImportDialog::build_params_panel(wxWindow* parent, wxSizer* sizer)
{ {
wxColour label_fg = dark_or(wxColour(50, 58, 61), wxColour(0xEF, 0xEF, 0xF0)); wxColour label_fg = StateColor::darkModeColorFor(wxColour("#323A3D"));
wxBoxSizer* color_header_sizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* color_header_sizer = new wxBoxSizer(wxHORIZONTAL);
wxStaticText* lbl_colors = new wxStaticText(parent, wxID_ANY, _L("Color Count")); wxStaticText* lbl_colors = new wxStaticText(parent, wxID_ANY, _L("Color Count"));
@@ -2063,18 +2073,18 @@ void TextureImportDialog::build_params_panel(wxWindow* parent, wxSizer* sizer)
{ {
StateColor preset_bg( StateColor preset_bg(
std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed | StateColor::Checked), std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed | StateColor::Checked),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered | StateColor::Checked), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered | StateColor::Checked),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Checked), std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Checked),
std::pair<wxColour, int>(dark_or(wxColour(206, 206, 206), wxColour(0x54, 0x54, 0x5B)), StateColor::Pressed), std::pair<wxColour, int>(wxColour("#CECECE"), StateColor::Pressed),
std::pair<wxColour, int>(dark_or(wxColour(238, 238, 238), wxColour(0x4C, 0x4C, 0x55)), StateColor::Hovered), std::pair<wxColour, int>(wxColour("#EEEEEE"), StateColor::Hovered),
std::pair<wxColour, int>(dark_or(wxColour(255, 255, 255), wxColour(0x2D, 0x2D, 0x31)), StateColor::Normal)); std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
StateColor preset_bd( StateColor preset_bd(
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Checked), std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Checked),
std::pair<wxColour, int>(dark_or(wxColour(206, 206, 206), wxColour(0x54, 0x54, 0x5B)), StateColor::Normal)); std::pair<wxColour, int>(wxColour("#CECECE"), StateColor::Normal));
StateColor preset_text( StateColor preset_text(
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Checked), std::pair<wxColour, int>(wxColour("#FFFFFE"), StateColor::Checked),
std::pair<wxColour, int>(dark_or(wxColour(50, 58, 61), wxColour(0xEF, 0xEF, 0xF0)), StateColor::Normal)); std::pair<wxColour, int>(wxColour("#323A3D"), StateColor::Normal));
for (auto* btn : {m_btn_color_4, m_btn_color_8, m_btn_color_16}) { for (auto* btn : {m_btn_color_4, m_btn_color_8, m_btn_color_16}) {
btn->SetCornerRadius(FromDIP(12)); btn->SetCornerRadius(FromDIP(12));
@@ -2093,7 +2103,7 @@ void TextureImportDialog::build_params_panel(wxWindow* parent, wxSizer* sizer)
sizer->Add(color_header_sizer, 0, wxBOTTOM, FromDIP(4)); sizer->Add(color_header_sizer, 0, wxBOTTOM, FromDIP(4));
wxBoxSizer* color_slider_sizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* color_slider_sizer = new wxBoxSizer(wxHORIZONTAL);
m_color_slider = new GreenSlider(parent, m_param_color_count, 1, (int)max_filament_count()); m_color_slider = new AccentSlider(parent, m_param_color_count, 1, (int)max_filament_count());
m_color_spin = new SpinInput(parent, wxString::Format("%d", m_param_color_count), m_color_spin = new SpinInput(parent, wxString::Format("%d", m_param_color_count),
wxEmptyString, wxDefaultPosition, wxEmptyString, wxDefaultPosition,
wxSize(FromDIP(60), FromDIP(28)), wxSize(FromDIP(60), FromDIP(28)),
@@ -2113,7 +2123,7 @@ void TextureImportDialog::build_params_panel(wxWindow* parent, wxSizer* sizer)
sizer->Add(lbl_smooth, 0, wxBOTTOM, FromDIP(4)); sizer->Add(lbl_smooth, 0, wxBOTTOM, FromDIP(4));
wxBoxSizer* smooth_sizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* smooth_sizer = new wxBoxSizer(wxHORIZONTAL);
m_smooth_slider = new GreenSlider(parent, m_param_smooth, 0, 10); m_smooth_slider = new AccentSlider(parent, m_param_smooth, 0, 10);
m_smooth_spin = new SpinInput(parent, wxString::Format("%d", m_param_smooth), m_smooth_spin = new SpinInput(parent, wxString::Format("%d", m_param_smooth),
wxEmptyString, wxDefaultPosition, wxEmptyString, wxDefaultPosition,
wxSize(FromDIP(60), FromDIP(28)), wxSize(FromDIP(60), FromDIP(28)),
@@ -2132,25 +2142,23 @@ void TextureImportDialog::build_params_panel(wxWindow* parent, wxSizer* sizer)
{ {
StateColor btn_bg_white( StateColor btn_bg_white(
std::pair<wxColour, int>(dark_or(wxColour(206, 206, 206), wxColour(0x54, 0x54, 0x5B)), StateColor::Pressed), std::pair<wxColour, int>(wxColour("#CECECE"), StateColor::Pressed),
std::pair<wxColour, int>(dark_or(wxColour(238, 238, 238), wxColour(0x4C, 0x4C, 0x55)), StateColor::Hovered), std::pair<wxColour, int>(wxColour("#EEEEEE"), StateColor::Hovered),
std::pair<wxColour, int>(dark_or(wxColour(255, 255, 255), wxColour(0x2D, 0x2D, 0x31)), StateColor::Normal)); std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
StateColor btn_bd_green( const wxColour btn_bd_accent = wxColour(0, 150, 136);
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal)); const wxColour btn_text_accent = wxColour(0, 150, 136);
StateColor btn_text_green(
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
m_btn_color_auto->SetCornerRadius(FromDIP(12)); m_btn_color_auto->SetCornerRadius(FromDIP(12));
m_btn_color_auto->SetMinSize(wxSize(FromDIP(60), FromDIP(28))); m_btn_color_auto->SetMinSize(wxSize(FromDIP(60), FromDIP(28)));
m_btn_color_auto->SetBackgroundColor(btn_bg_white); m_btn_color_auto->SetBackgroundColor(btn_bg_white);
m_btn_color_auto->SetBorderColor(btn_bd_green); m_btn_color_auto->SetBorderColor(btn_bd_accent);
m_btn_color_auto->SetTextColor(btn_text_green); m_btn_color_auto->SetTextColor(btn_text_accent);
m_btn_apply->SetCornerRadius(FromDIP(12)); m_btn_apply->SetCornerRadius(FromDIP(12));
m_btn_apply->SetMinSize(wxSize(FromDIP(60), FromDIP(28))); m_btn_apply->SetMinSize(wxSize(FromDIP(60), FromDIP(28)));
m_btn_apply->SetBackgroundColor(btn_bg_white); m_btn_apply->SetBackgroundColor(btn_bg_white);
m_btn_apply->SetBorderColor(btn_bd_green); m_btn_apply->SetBorderColor(btn_bd_accent);
m_btn_apply->SetTextColor(btn_text_green); m_btn_apply->SetTextColor(btn_text_accent);
} }
// Defer attaching the Auto/Apply tooltips until the dialog has actually // Defer attaching the Auto/Apply tooltips until the dialog has actually
@@ -2179,19 +2187,19 @@ void TextureImportDialog::build_params_panel(wxWindow* parent, wxSizer* sizer)
m_hint_label = new wxStaticText(parent, wxID_ANY, m_hint_label = new wxStaticText(parent, wxID_ANY,
_L("Reminder: parameters changed, click Apply to take effect")); _L("Reminder: parameters changed, click Apply to take effect"));
m_hint_label->SetForegroundColour(wxColour(0xFF, 0x6F, 0x00)); m_hint_label->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#FF6F00")));
m_hint_label->SetFont(texture_import_section_title_font(parent)); m_hint_label->SetFont(texture_import_section_title_font(parent));
m_hint_label->Hide(); m_hint_label->Hide();
sizer->Add(m_hint_label, 0, wxBOTTOM, FromDIP(4)); sizer->Add(m_hint_label, 0, wxBOTTOM, FromDIP(4));
auto* mapping_separator = new StaticLine(parent); auto* mapping_separator = new StaticLine(parent);
mapping_separator->SetLineColour(texture_import_separator_colour()); mapping_separator->SetLineColour(wxColour(SEPARATOR_COLOUR_KEY));
sizer->Add(mapping_separator, 0, wxEXPAND | wxBOTTOM, FromDIP(8)); sizer->Add(mapping_separator, 0, wxEXPAND | wxBOTTOM, FromDIP(8));
} }
void TextureImportDialog::build_mapping_panel(wxWindow* parent, wxSizer* sizer) void TextureImportDialog::build_mapping_panel(wxWindow* parent, wxSizer* sizer)
{ {
wxColour secondary_fg = dark_or(wxColour(107, 107, 107), wxColour(0x81, 0x81, 0x83)); wxColour secondary_fg = StateColor::darkModeColorFor(wxColour("#6B6B6B"));
wxBoxSizer* header_sizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* header_sizer = new wxBoxSizer(wxHORIZONTAL);
@@ -2206,9 +2214,9 @@ void TextureImportDialog::build_mapping_panel(wxWindow* parent, wxSizer* sizer)
m_btn_mix_reset->SetPaddingSize(wxSize(FromDIP(2), FromDIP(2))); m_btn_mix_reset->SetPaddingSize(wxSize(FromDIP(2), FromDIP(2)));
{ {
StateColor reset_bg( StateColor reset_bg(
std::pair<wxColour, int>(dark_or(wxColour(245, 245, 245), wxColour(0x3C, 0x3C, 0x42)), StateColor::Pressed), std::pair<wxColour, int>(wxColour("#F4F4F4"), StateColor::Pressed),
std::pair<wxColour, int>(dark_or(wxColour(248, 248, 248), wxColour(0x35, 0x35, 0x3A)), StateColor::Hovered), std::pair<wxColour, int>(wxColour("#F8F8F8"), StateColor::Hovered),
std::pair<wxColour, int>(dark_or(*wxWHITE, wxColour(0x2D, 0x2D, 0x31)), StateColor::Normal)); std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
m_btn_mix_reset->SetBackgroundColor(reset_bg); m_btn_mix_reset->SetBackgroundColor(reset_bg);
m_btn_mix_reset->SetBorderColor(StateColor()); m_btn_mix_reset->SetBorderColor(StateColor());
} }
@@ -2232,13 +2240,11 @@ void TextureImportDialog::build_mapping_panel(wxWindow* parent, wxSizer* sizer)
m_btn_auto_mix->SetMinSize(wxSize(FromDIP(178), FromDIP(28))); m_btn_auto_mix->SetMinSize(wxSize(FromDIP(178), FromDIP(28)));
{ {
StateColor btn_bg( StateColor btn_bg(
std::pair<wxColour, int>(dark_or(wxColour(245, 245, 245), wxColour(0x3C, 0x3C, 0x42)), StateColor::Pressed), std::pair<wxColour, int>(wxColour("#F4F4F4"), StateColor::Pressed),
std::pair<wxColour, int>(dark_or(wxColour(248, 248, 248), wxColour(0x35, 0x35, 0x3A)), StateColor::Hovered), std::pair<wxColour, int>(wxColour("#F8F8F8"), StateColor::Hovered),
std::pair<wxColour, int>(dark_or(*wxWHITE, wxColour(0x2D, 0x2D, 0x31)), StateColor::Normal)); std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
StateColor btn_bd( const wxColour btn_bd = wxColour("#CECECE");
std::pair<wxColour, int>(dark_or(wxColour(206, 206, 206), wxColour(0x54, 0x54, 0x5B)), StateColor::Normal)); const wxColour btn_text = texture_import_gray9000();
StateColor btn_text(
std::pair<wxColour, int>(texture_import_text_colour(), StateColor::Normal));
m_btn_auto_mix->SetBackgroundColor(btn_bg); m_btn_auto_mix->SetBackgroundColor(btn_bg);
m_btn_auto_mix->SetBorderColor(btn_bd); m_btn_auto_mix->SetBorderColor(btn_bd);
m_btn_auto_mix->SetTextColor(btn_text); m_btn_auto_mix->SetTextColor(btn_text);
@@ -2269,7 +2275,7 @@ void TextureImportDialog::build_mapping_panel(wxWindow* parent, wxSizer* sizer)
m_mapping_scroll = new wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, m_mapping_scroll = new wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition,
wxSize(-1, FromDIP(300))); wxSize(-1, FromDIP(300)));
m_mapping_scroll->SetScrollRate(0, FromDIP(10)); m_mapping_scroll->SetScrollRate(0, FromDIP(10));
m_mapping_scroll->SetBackgroundColour(dark_or(wxColour(255, 255, 255), wxColour(0x2D, 0x2D, 0x31))); m_mapping_scroll->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
m_mapping_scroll->Bind(wxEVT_MOUSEWHEEL, &TextureImportDialog::dismiss_filament_popup_on_wheel, this); m_mapping_scroll->Bind(wxEVT_MOUSEWHEEL, &TextureImportDialog::dismiss_filament_popup_on_wheel, this);
m_mapping_sizer = new wxBoxSizer(wxVERTICAL); m_mapping_sizer = new wxBoxSizer(wxVERTICAL);
@@ -2284,7 +2290,7 @@ void TextureImportDialog::build_bottom_buttons(wxSizer* sizer)
wxString::Format( wxString::Format(
_L("The project supports up to %d filaments. Extra filaments will be discarded."), _L("The project supports up to %d filaments. Extra filaments will be discarded."),
(int)max_filament_count())); (int)max_filament_count()));
m_drop_warning_label->SetForegroundColour(wxColour(0xFF, 0x6F, 0x00)); m_drop_warning_label->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#FF6F00")));
m_drop_warning_label->SetFont(texture_import_section_title_font(this)); m_drop_warning_label->SetFont(texture_import_section_title_font(this));
m_drop_warning_label->Hide(); m_drop_warning_label->Hide();
sizer->Add(m_drop_warning_label, 0, wxALIGN_LEFT | wxBOTTOM, FromDIP(4)); sizer->Add(m_drop_warning_label, 0, wxALIGN_LEFT | wxBOTTOM, FromDIP(4));
@@ -2297,13 +2303,11 @@ void TextureImportDialog::build_bottom_buttons(wxSizer* sizer)
m_btn_skip->SetMinSize(wxSize(FromDIP(136), FromDIP(40))); m_btn_skip->SetMinSize(wxSize(FromDIP(136), FromDIP(40)));
{ {
StateColor skip_bg( StateColor skip_bg(
std::pair<wxColour, int>(dark_or(wxColour(206, 206, 206), wxColour(0x54, 0x54, 0x5B)), StateColor::Pressed), std::pair<wxColour, int>(wxColour("#CECECE"), StateColor::Pressed),
std::pair<wxColour, int>(dark_or(wxColour(238, 238, 238), wxColour(0x4C, 0x4C, 0x55)), StateColor::Hovered), std::pair<wxColour, int>(wxColour("#EEEEEE"), StateColor::Hovered),
std::pair<wxColour, int>(dark_or(wxColour(255, 255, 255), wxColour(0x2D, 0x2D, 0x31)), StateColor::Normal)); std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
StateColor skip_bd( const wxColour skip_bd = wxColour("#CECECE");
std::pair<wxColour, int>(dark_or(wxColour(206, 206, 206), wxColour(0x54, 0x54, 0x5B)), StateColor::Normal)); const wxColour skip_text = wxColour("#6B6B6A");
StateColor skip_text(
std::pair<wxColour, int>(dark_or(wxColour(107, 107, 107), wxColour(0xB3, 0xB3, 0xB5)), StateColor::Normal));
m_btn_skip->SetBackgroundColor(skip_bg); m_btn_skip->SetBackgroundColor(skip_bg);
m_btn_skip->SetBorderColor(skip_bd); m_btn_skip->SetBorderColor(skip_bd);
m_btn_skip->SetTextColor(skip_text); m_btn_skip->SetTextColor(skip_text);
@@ -2313,19 +2317,7 @@ void TextureImportDialog::build_bottom_buttons(wxSizer* sizer)
m_btn_ok->SetId(wxID_OK); m_btn_ok->SetId(wxID_OK);
m_btn_ok->SetCornerRadius(FromDIP(20)); m_btn_ok->SetCornerRadius(FromDIP(20));
m_btn_ok->SetMinSize(wxSize(FromDIP(156), FromDIP(40))); m_btn_ok->SetMinSize(wxSize(FromDIP(156), FromDIP(40)));
{ apply_accent_button_colours(m_btn_ok);
StateColor ok_bg(
std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor ok_bd(
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor ok_text(
std::pair<wxColour, int>(wxColour("#FFFFFE"), StateColor::Normal));
m_btn_ok->SetBackgroundColor(ok_bg);
m_btn_ok->SetBorderColor(ok_bd);
m_btn_ok->SetTextColor(ok_text);
}
btn_sizer->AddStretchSpacer(); btn_sizer->AddStretchSpacer();
btn_sizer->Add(m_btn_skip, 0, wxRIGHT, FromDIP(16)); btn_sizer->Add(m_btn_skip, 0, wxRIGHT, FromDIP(16));
@@ -2372,36 +2364,10 @@ void TextureImportDialog::update_ui_for_state()
m_preview_canvas->set_computing_overlay(computing); m_preview_canvas->set_computing_overlay(computing);
if (ready && valid && is_params_dirty()) { if (ready && valid)
m_btn_ok->Enable(true); style_confirm_button(is_params_dirty());
StateColor gray_bg( else if (m_hint_label)
std::pair<wxColour, int>(dark_or(wxColour(206, 206, 206), wxColour(0x54, 0x54, 0x5B)), StateColor::Normal)); m_hint_label->Hide();
StateColor gray_bd(
std::pair<wxColour, int>(dark_or(wxColour(206, 206, 206), wxColour(0x54, 0x54, 0x5B)), StateColor::Normal));
StateColor gray_text(
std::pair<wxColour, int>(dark_or(wxColour(107, 107, 107), wxColour(0xB3, 0xB3, 0xB5)), StateColor::Normal));
m_btn_ok->SetBackgroundColor(gray_bg);
m_btn_ok->SetBorderColor(gray_bd);
m_btn_ok->SetTextColor(gray_text);
m_btn_ok->SetToolTip(_L("Reminder: parameters changed, click Apply to take effect"));
if (m_hint_label) m_hint_label->Show();
} else if (ready && valid) {
StateColor ok_bg(
std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor ok_bd(
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor ok_text(
std::pair<wxColour, int>(wxColour("#FFFFFE"), StateColor::Normal));
m_btn_ok->SetBackgroundColor(ok_bg);
m_btn_ok->SetBorderColor(ok_bd);
m_btn_ok->SetTextColor(ok_text);
m_btn_ok->UnsetToolTip();
if (m_hint_label) m_hint_label->Hide();
} else {
if (m_hint_label) m_hint_label->Hide();
}
m_btn_ok->Refresh(); m_btn_ok->Refresh();
Layout(); Layout();
@@ -2687,33 +2653,16 @@ void TextureImportDialog::on_mesh_repair_decision_required(wxCommandEvent&)
_L("Mesh repair"), wxYES_NO | wxICON_WARNING | wxYES_DEFAULT); _L("Mesh repair"), wxYES_NO | wxICON_WARNING | wxYES_DEFAULT);
dlg.SetButtonLabel(wxID_YES, _L("Import without repair")); dlg.SetButtonLabel(wxID_YES, _L("Import without repair"));
dlg.SetButtonLabel(wxID_NO, _L("Repair and import"), true); dlg.SetButtonLabel(wxID_NO, _L("Repair and import"), true);
StateColor primary_bg( // "Repair and import" is the recommended action here, so the accent moves off the default YES
std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), // button onto NO. MsgDialog::add_button already styled both as ButtonType::Choice, so restyling
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered), // with the same type swaps only the palette and leaves the geometry alone.
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor primary_bd(
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor primary_text(
std::pair<wxColour, int>(wxColour("#FFFFFE"), StateColor::Normal));
StateColor secondary_bg(
std::pair<wxColour, int>(wxColour("#CECECE"), StateColor::Pressed),
std::pair<wxColour, int>(wxColour("#EEEEEE"), StateColor::Hovered),
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
StateColor secondary_bd(
std::pair<wxColour, int>(texture_import_gray9000(), StateColor::Normal));
StateColor secondary_text(
std::pair<wxColour, int>(texture_import_gray9000(), StateColor::Normal));
if (auto* yes_btn = dynamic_cast<Button*>(dlg.FindWindow(wxID_YES))) { if (auto* yes_btn = dynamic_cast<Button*>(dlg.FindWindow(wxID_YES))) {
yes_btn->SetStyle(ButtonStyle::Regular, ButtonType::Choice);
yes_btn->SetMinSize(wxSize(FromDIP(180), FromDIP(24))); yes_btn->SetMinSize(wxSize(FromDIP(180), FromDIP(24)));
yes_btn->SetBackgroundColor(secondary_bg);
yes_btn->SetBorderColor(secondary_bd);
yes_btn->SetTextColor(secondary_text);
} }
if (auto* no_btn = dynamic_cast<Button*>(dlg.FindWindow(wxID_NO))) { if (auto* no_btn = dynamic_cast<Button*>(dlg.FindWindow(wxID_NO))) {
no_btn->SetStyle(ButtonStyle::Confirm, ButtonType::Choice);
no_btn->SetMinSize(wxSize(FromDIP(160), FromDIP(24))); no_btn->SetMinSize(wxSize(FromDIP(160), FromDIP(24)));
no_btn->SetBackgroundColor(primary_bg);
no_btn->SetBorderColor(primary_bd);
no_btn->SetTextColor(primary_text);
} }
dlg.Layout(); dlg.Layout();
dlg.Fit(); dlg.Fit();
@@ -3780,12 +3729,12 @@ void TextureImportDialog::rebuild_mapping_rows()
return wxString::Format("Filament %d", display_number(idx)); return wxString::Format("Filament %d", display_number(idx));
}; };
const wxColour dash_clr = dark_or(wxColour(179, 179, 179), wxColour(100, 100, 106)); const wxColour dash_clr = StateColor::darkModeColorFor(wxColour("#ACACAC"));
const wxColour hex_fg = texture_import_text_colour(); const wxColour hex_fg = texture_import_text_colour();
const wxColour card_bg = dark_or(wxColour(235, 235, 235), wxColour(0x3C, 0x3C, 0x42)); const wxColour card_bg = StateColor::darkModeColorFor(wxColour("#E8E8E8"));
const wxColour card_bd = dark_or(wxColour(224, 224, 224), wxColour(0x46, 0x46, 0x4C)); const wxColour card_bd = StateColor::darkModeColorFor(wxColour("#DBDBDB"));
const wxColour name_fg = texture_import_text_colour(); const wxColour name_fg = texture_import_text_colour();
const wxColour chev_clr = dark_or(wxColour(107, 107, 107), wxColour(0xB3, 0xB3, 0xB5)); const wxColour chev_clr = StateColor::darkModeColorFor(wxColour("#6B6B6A"));
m_mapping_rows.resize(m_current_matches.size()); m_mapping_rows.resize(m_current_matches.size());
for (size_t ci = 0; ci < m_current_matches.size(); ++ci) { for (size_t ci = 0; ci < m_current_matches.size(); ++ci) {
@@ -4003,14 +3952,14 @@ void TextureImportDialog::rebuild_mapping_rows()
dc.DrawText(num_str, sq_x + (sq - nsz.x) / 2, sq_y + (sq - nsz.y) / 2); dc.DrawText(num_str, sq_x + (sq - nsz.x) / 2, sq_y + (sq - nsz.y) / 2);
} }
// Brand icon + material name // Material name
{ {
wxFont name_font = p->GetFont(); wxFont name_font = p->GetFont();
name_font.SetPointSize(9); name_font.SetPointSize(9);
dc.SetFont(name_font); dc.SetFont(name_font);
dc.SetTextForeground(name_fg); dc.SetTextForeground(name_fg);
wxString name_str = get_filament_label(fil_idx); wxString name_str = get_filament_label(fil_idx);
int text_x = draw_brand_icon_and_strip(dc, p, name_str, sq_x + sq + p->FromDIP(8), sz.y / 2); int text_x = sq_x + sq + p->FromDIP(8);
int max_text_w = sz.x - text_x - p->FromDIP(24); int max_text_w = sz.x - text_x - p->FromDIP(24);
if (max_text_w > 0) { if (max_text_w > 0) {
name_str = ellipsize_text(dc, name_str, max_text_w); name_str = ellipsize_text(dc, name_str, max_text_w);
@@ -4097,7 +4046,7 @@ void TextureImportDialog::set_smooth_value(int value, bool update_spin)
update_confirm_button_state(); update_confirm_button_state();
} }
void TextureImportDialog::preview_spin_text_value(SpinInput* spin, GreenSlider* slider, int& param, void TextureImportDialog::preview_spin_text_value(SpinInput* spin, AccentSlider* slider, int& param,
int min_value, int max_value, const wxString& text, int min_value, int max_value, const wxString& text,
std::function<void()> on_value_changed) std::function<void()> on_value_changed)
{ {
@@ -4204,30 +4153,22 @@ void TextureImportDialog::highlight_view_button(int view_index)
{ {
Button* btns[] = { m_btn_view_original, m_btn_view_multicolor }; Button* btns[] = { m_btn_view_original, m_btn_view_multicolor };
StateColor active_bg( // The inactive pill lies on m_tab_panel, which is preview_bg (#EEEEEE -> #4C4C55), and has to
std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), // read as raised above that strip in both themes — so its fill steps away from the strip in
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered), // opposite directions. gDarkColors pairs one light tone with one dark tone and cannot express
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal)); // an inversion, so the two are picked here the way filament_swatch_border_colour() does.
StateColor active_bd( const bool dark_pill = is_dark();
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor active_text(
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Normal));
StateColor inactive_bg( StateColor inactive_bg(
std::pair<wxColour, int>(dark_or(wxColour(245, 245, 245), wxColour(0x5C, 0x5C, 0x64)), StateColor::Pressed), std::pair<wxColour, int>(dark_pill ? wxColour(0x5C, 0x5C, 0x64) : wxColour("#F4F4F4"), StateColor::Pressed),
std::pair<wxColour, int>(dark_or(wxColour(255, 255, 255), wxColour(0x66, 0x66, 0x6E)), StateColor::Hovered), std::pair<wxColour, int>(dark_pill ? wxColour(0x66, 0x66, 0x6E) : wxColour("#F8F8F8"), StateColor::Hovered),
std::pair<wxColour, int>(dark_or(wxColour(255, 255, 255), wxColour(0x54, 0x54, 0x5B)), StateColor::Normal)); std::pair<wxColour, int>(dark_pill ? wxColour(0x54, 0x54, 0x5B) : *wxWHITE, StateColor::Normal));
StateColor inactive_bd( const wxColour inactive_bd = dark_pill ? wxColour(0x54, 0x54, 0x5B) : *wxWHITE;
std::pair<wxColour, int>(dark_or(wxColour(255, 255, 255), wxColour(0x54, 0x54, 0x5B)), StateColor::Normal)); const wxColour inactive_text = wxColour("#6B6B6A");
StateColor inactive_text(
std::pair<wxColour, int>(dark_or(wxColour(104, 104, 104), wxColour(0xD0, 0xD0, 0xD2)), StateColor::Normal));
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
if (!btns[i]) continue; if (!btns[i]) continue;
if (i == view_index) { if (i == view_index) {
btns[i]->SetBackgroundColor(active_bg); apply_accent_button_colours(btns[i]);
btns[i]->SetBorderColor(active_bd);
btns[i]->SetTextColor(active_text);
} else { } else {
btns[i]->SetBackgroundColor(inactive_bg); btns[i]->SetBackgroundColor(inactive_bg);
btns[i]->SetBorderColor(inactive_bd); btns[i]->SetBorderColor(inactive_bd);
@@ -4298,42 +4239,28 @@ void TextureImportDialog::update_confirm_button_state()
return; return;
} }
bool dirty = is_params_dirty();
m_btn_ok->Enable(true); m_btn_ok->Enable(true);
style_confirm_button(is_params_dirty());
if (dirty) {
StateColor gray_bg(
std::pair<wxColour, int>(dark_or(wxColour(206, 206, 206), wxColour(0x54, 0x54, 0x5B)), StateColor::Normal));
StateColor gray_bd(
std::pair<wxColour, int>(dark_or(wxColour(206, 206, 206), wxColour(0x54, 0x54, 0x5B)), StateColor::Normal));
StateColor gray_text(
std::pair<wxColour, int>(dark_or(wxColour(107, 107, 107), wxColour(0xB3, 0xB3, 0xB5)), StateColor::Normal));
m_btn_ok->SetBackgroundColor(gray_bg);
m_btn_ok->SetBorderColor(gray_bd);
m_btn_ok->SetTextColor(gray_text);
m_btn_ok->SetToolTip(_L("Reminder: parameters changed, click Apply to take effect"));
if (m_hint_label) m_hint_label->Show();
} else {
StateColor ok_bg(
std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor ok_bd(
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor ok_text(
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Normal));
m_btn_ok->SetBackgroundColor(ok_bg);
m_btn_ok->SetBorderColor(ok_bd);
m_btn_ok->SetTextColor(ok_text);
m_btn_ok->UnsetToolTip();
if (m_hint_label) m_hint_label->Hide();
}
m_btn_ok->Refresh(); m_btn_ok->Refresh();
Layout(); Layout();
} }
// Both state updaters land here: the Confirm button reads as accent only while it would apply
// exactly what the preview shows.
void TextureImportDialog::style_confirm_button(bool dirty)
{
if (dirty) {
apply_muted_button_colours(m_btn_ok);
m_btn_ok->SetToolTip(_L("Reminder: parameters changed, click Apply to take effect"));
} else {
apply_accent_button_colours(m_btn_ok);
m_btn_ok->UnsetToolTip();
}
if (m_hint_label)
m_hint_label->Show(dirty);
}
void TextureImportDialog::on_ok_clicked(wxCommandEvent&) void TextureImportDialog::on_ok_clicked(wxCommandEvent&)
{ {
if (m_state != TextureImportState::Ready || !has_valid_result() || is_params_dirty()) if (m_state != TextureImportState::Ready || !has_valid_result() || is_params_dirty())
+5 -4
View File
@@ -27,7 +27,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
class GreenSlider; class AccentSlider;
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
@@ -299,7 +299,7 @@ private:
void set_color_count_value(int value, bool update_spin); void set_color_count_value(int value, bool update_spin);
void set_smooth_value(int value, bool update_spin); void set_smooth_value(int value, bool update_spin);
void preview_spin_text_value(SpinInput* spin, GreenSlider* slider, int& param, void preview_spin_text_value(SpinInput* spin, AccentSlider* slider, int& param,
int min_value, int max_value, const wxString& text, int min_value, int max_value, const wxString& text,
std::function<void()> on_value_changed = {}); std::function<void()> on_value_changed = {});
void update_color_count_preset_buttons(); void update_color_count_preset_buttons();
@@ -307,6 +307,7 @@ private:
bool has_valid_result() const; bool has_valid_result() const;
bool is_params_dirty() const; bool is_params_dirty() const;
void update_confirm_button_state(); void update_confirm_button_state();
void style_confirm_button(bool dirty);
Slic3r::TexturedMesh m_textured_mesh; Slic3r::TexturedMesh m_textured_mesh;
std::vector<std::string> m_filament_color_strs; // existing + virtual std::vector<std::string> m_filament_color_strs; // existing + virtual
@@ -355,9 +356,9 @@ private:
Button* m_btn_color_8 = nullptr; Button* m_btn_color_8 = nullptr;
Button* m_btn_color_16 = nullptr; Button* m_btn_color_16 = nullptr;
Button* m_btn_color_auto = nullptr; Button* m_btn_color_auto = nullptr;
GreenSlider* m_color_slider = nullptr; AccentSlider* m_color_slider = nullptr;
SpinInput* m_color_spin = nullptr; SpinInput* m_color_spin = nullptr;
GreenSlider* m_smooth_slider = nullptr; AccentSlider* m_smooth_slider = nullptr;
SpinInput* m_smooth_spin = nullptr; SpinInput* m_smooth_spin = nullptr;
Button* m_btn_apply = nullptr; Button* m_btn_apply = nullptr;
+4 -3
View File
@@ -360,8 +360,6 @@ void DropDown::render(wxDC &dc)
for (int i = 0; i < items.size(); ++i) { for (int i = 0; i < items.size(); ++i) {
auto &item = items[i]; auto &item = items[i];
int states2 = states; int states2 = states;
// Dimmed items render greyed out but stay selectable, so they cannot reuse the disabled state.
bool is_dimmed = (item.style & DD_ITEM_STYLE_DIMMED) != 0;
if ((item.style & DD_ITEM_STYLE_DISABLED) != 0) if ((item.style & DD_ITEM_STYLE_DISABLED) != 0)
states2 &= ~StateColor::Enabled; states2 &= ~StateColor::Enabled;
// Skip by group // Skip by group
@@ -429,7 +427,10 @@ void DropDown::render(wxDC &dc)
} }
pt.y += (rcContent.height - textSize.y) / 2; pt.y += (rcContent.height - textSize.y) / 2;
dc.SetFont(GetFont()); dc.SetFont(GetFont());
dc.SetTextForeground(is_dimmed ? wxColour(0xCE, 0xCE, 0xCE) : text_color.colorForStates(states2)); // Dimmed items stay selectable, so they only borrow the disabled text tone rather
// than taking the disabled state itself.
const int text_states = (item.style & DD_ITEM_STYLE_DIMMED) ? (states2 & ~StateColor::Enabled) : states2;
dc.SetTextForeground(text_color.colorForStates(text_states));
dc.DrawText(text, pt); dc.DrawText(text, pt);
if (group.IsEmpty() && !item.group_key.IsEmpty()) { if (group.IsEmpty() && !item.group_key.IsEmpty()) {
auto szBmp = arrow_bitmap.GetBmpSize(); auto szBmp = arrow_bitmap.GetBmpSize();