Fix macOS dark-theme rendering and AMS settings icon clipping (#14846)

Fixes a set of Mac only GUI rendering issues:
1. cropped icon
2. wrong color in dark theme
## Screenshots

<img width="343" height="370" alt="Screenshot 2026-07-19 at 16 16 39"
src="https://github.com/user-attachments/assets/1b89dc01-cd52-43ff-9231-ac31a7e1c18f"
/>
<img width="701" height="700" alt="Screenshot 2026-07-19 at 13 19 02"
src="https://github.com/user-attachments/assets/00fa173f-dea9-4b87-8ac8-ae311dca5c31"
/>
<img width="425" height="324" alt="Screenshot 2026-07-19 at 02 31 14"
src="https://github.com/user-attachments/assets/50740669-d5c0-4309-b0ac-b577a460cc91"
/>
<img width="1121" height="890" alt="Screenshot 2026-07-19 at 02 24 33"
src="https://github.com/user-attachments/assets/9ab380e3-63f6-41a1-9c2c-8d0247bd036f"
/>
This commit is contained in:
SoftFever
2026-07-19 20:27:14 +08:00
committed by GitHub
10 changed files with 82 additions and 26 deletions
@@ -8,6 +8,7 @@
#include "uiDeviceUpdateVersion.h"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/wxExtensions.hpp"
#include "slic3r/GUI/Widgets/Label.hpp" // Orca: explicit Label include
@@ -27,6 +28,7 @@ uiDeviceUpdateVersion::uiDeviceUpdateVersion(wxWindow* parent,
long style /*= wxTAB_TRAVERSAL*/)
: wxPanel(parent, id, pos, size, style)
{
SetBackgroundColour(*wxWHITE);
CreateWidgets();
}
@@ -110,4 +112,6 @@ void uiDeviceUpdateVersion::CreateWidgets()
SetSizer(main_sizer);
Layout();
wxGetApp().UpdateDarkUIWin(this);
}
@@ -257,7 +257,9 @@ void wgtDeviceNozzleRackArea::CreateGui()
wxSizer* content_sizer = new wxBoxSizer(wxVERTICAL);
m_panel_content = new wxPanel(m_simple_book, wxID_ANY);
m_panel_content->SetBackgroundColour(*wxWHITE);
m_panel_refresh = new wxPanel(m_simple_book, wxID_ANY);
m_panel_refresh->SetBackgroundColour(*wxWHITE);
// Create Hotends ans Rack Position Panel
wxSizer* hotends_rack_sizer = new wxBoxSizer(wxHORIZONTAL);
@@ -188,6 +188,7 @@ void wgtDeviceNozzleRackHotendUpdate::CreateGui()
// Icon
wxPanel* imagePanel = new wxPanel(this);
imagePanel->SetBackgroundColour(WGT_DEVICE_NOZZLE_RACK_HOTEND_UPDATE_DEFAULT_BG);
imagePanel->SetMaxSize(WX_DIP_SIZE(46, -1));
imagePanel->SetMinSize(WX_DIP_SIZE(46, -1));
imagePanel->SetSize(wxSize(FromDIP(46), FromDIP(-1)));
@@ -203,6 +204,7 @@ void wgtDeviceNozzleRackHotendUpdate::CreateGui()
// Diameter/type (vertical)
wxPanel* type_panel = new wxPanel(this);
type_panel->SetBackgroundColour(WGT_DEVICE_NOZZLE_RACK_HOTEND_UPDATE_DEFAULT_BG);
auto* main_type_sizer = new wxBoxSizer(wxVERTICAL);
auto* type_sizer_row_1 = new wxBoxSizer(wxHORIZONTAL);
auto* type_sizer_row_2 = new wxBoxSizer(wxHORIZONTAL);
@@ -251,6 +253,7 @@ void wgtDeviceNozzleRackHotendUpdate::CreateGui()
// SN and version (vertical)
wxPanel* info_panel = new wxPanel(this);
info_panel->SetBackgroundColour(WGT_DEVICE_NOZZLE_RACK_HOTEND_UPDATE_DEFAULT_BG);
auto* info_sizer = new wxBoxSizer(wxVERTICAL);
m_sn_label = new Label(info_panel);
m_sn_label->SetFont(Label::Body_12);
@@ -9,6 +9,7 @@
#include "wgtDeviceNozzleRack.h"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/DeviceTab/wgtMsgBox.h"
#include "slic3r/GUI/Widgets/Label.hpp" // Orca: explicit Label include
@@ -28,6 +29,7 @@ wgtDeviceNozzleRackSelect::wgtDeviceNozzleRackSelect(wxWindow *parent) : wxPanel
static wxPanel* s_create_title(wxWindow *parent, const wxString& text)
{
wxPanel *panel = new wxPanel(parent, wxID_ANY);
panel->SetBackgroundColour(*wxWHITE);
auto title = new Label(panel, text);
title->SetFont(::Label::Body_13);
@@ -35,7 +37,7 @@ static wxPanel* s_create_title(wxWindow *parent, const wxString& text)
title->SetForegroundColour(0x909090);
auto split_line = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
split_line->SetBackgroundColour(0xeeeeee);
split_line->SetBackgroundColour(wxColour(0xEE, 0xEE, 0xEE));
split_line->SetMinSize(wxSize(-1, 1));
split_line->SetMaxSize(wxSize(-1, 1));
@@ -104,6 +106,8 @@ void wgtDeviceNozzleRackSelect::CreateGui()
SetSizer(main_sizer);
Layout();
Fit();
wxGetApp().UpdateDarkUIWin(this);
}
static void s_update_nozzle_info(wgtDeviceNozzleRackNozzleItem* item,
+6
View File
@@ -30,6 +30,7 @@ HMSNotifyItem::HMSNotifyItem(const std::string& dev_id, wxWindow *parent, DevHMS
auto main_sizer = new wxBoxSizer(wxVERTICAL);
m_panel_hms = new wxPanel(this, wxID_ANY, wxDefaultPosition, HMS_NOTIFY_ITEM_SIZE, wxTAB_TRAVERSAL);
m_panel_hms->SetBackgroundColour(*wxWHITE);
auto m_panel_sizer = new wxBoxSizer(wxVERTICAL);
auto m_panel_sizer_inner = new wxBoxSizer(wxHORIZONTAL);
@@ -126,6 +127,8 @@ HMSNotifyItem::HMSNotifyItem(const std::string& dev_id, wxWindow *parent, DevHMS
if (!m_url.empty()) wxLaunchDefaultBrowser(m_url);
});
#endif
wxGetApp().UpdateDarkUIWin(this);
}
HMSNotifyItem ::~HMSNotifyItem() {
;
@@ -166,6 +169,7 @@ HMSPanel::HMSPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wx
auto m_main_sizer = new wxBoxSizer(wxVERTICAL);
m_scrolledWindow = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL);
m_scrolledWindow->SetBackgroundColour(*wxWHITE);
m_scrolledWindow->SetScrollRate(5, 5);
m_top_sizer = new wxBoxSizer(wxVERTICAL);
@@ -179,6 +183,8 @@ HMSPanel::HMSPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wx
this->SetSizerAndFit(m_main_sizer);
Layout();
wxGetApp().UpdateDarkUIWin(this);
}
HMSPanel::~HMSPanel() {
+38 -15
View File
@@ -460,6 +460,17 @@ enum class ActionButtonType : int {
abSendGCode
};
// Background for the extruder-group title chip and its edit buttons, matching the StaticGroup
// interior. macOS keeps a lighter #F7F7F7 tint in light mode; dark mode uses the mapped colour.
static wxColour extruder_group_chip_bg()
{
#ifdef __WXOSX__
if (!wxGetApp().dark_mode())
return wxColour("#F7F7F7");
#endif
return StateColor::darkModeColorFor(*wxWHITE);
}
// Interactive title row for the sidebar extruder cards: "<title> ( <count> ) [edit]". The count shows the
// extruder's physical nozzle count on multi-nozzle printers (hidden elsewhere, SetCount(-1)), and the
// trailing button opens the manual nozzle-count editor when enabled (a plain dot otherwise).
@@ -468,11 +479,7 @@ class HoverLabel : public wxPanel
public:
HoverLabel(wxWindow *parent, const wxString &label) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
{
#ifdef __WXOSX__
SetBackgroundColour("#F7F7F7");
#else
SetBackgroundColour(*wxWHITE);
#endif
SetBackgroundColour(extruder_group_chip_bg());
auto sizer = new wxBoxSizer(wxHORIZONTAL);
m_label = new wxStaticText(this, wxID_ANY, label, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
@@ -496,11 +503,7 @@ public:
m_hover_btn = new ScalableButton(this, wxID_ANY, "dot");
m_hover_btn->SetMinSize(wxSize(FromDIP(25), -1));
#ifdef __WXOSX__
m_hover_btn->SetBackgroundColour("#F7F7F7");
#else
m_hover_btn->SetBackgroundColour(*wxWHITE);
#endif
m_hover_btn->SetBackgroundColour(extruder_group_chip_bg());
m_hover_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &evt) {
if (m_enabled && m_hover_on_click)
m_hover_on_click();
@@ -550,6 +553,17 @@ public:
void Rescale() { m_hover_btn->msw_rescale(); }
// Re-apply the chip colours on a live light/dark switch (they are set once at construction).
void sys_color_changed()
{
SetBackgroundColour(extruder_group_chip_bg());
m_label->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#6B6B6B")));
for (wxStaticText *t : {m_brace_left, m_count, m_brace_right})
t->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#262E30")));
m_hover_btn->SetBackgroundColour(extruder_group_chip_bg());
Refresh();
}
private:
// Content changed: the cached best size (ours and, transitively, our ancestors') is stale,
// and the parent must re-lay this row or the sizer keeps allocating the old width.
@@ -625,6 +639,15 @@ struct ExtruderGroup : StaticGroup
for (int i = 0; i < 4; ++i)
ams[i]->msw_rescale();
}
void sys_color_changed()
{
if (hover_label)
hover_label->sys_color_changed();
if (btn_edit)
btn_edit->SetBackgroundColour(extruder_group_chip_bg());
Refresh();
}
};
struct Sidebar::priv
@@ -1275,11 +1298,7 @@ ExtruderGroup::ExtruderGroup(wxWindow * parent, int index, wxString const &title
//label_ams->SetMinSize({FromDIP(70), -1});
if (index >= 0) {
btn_edit = new ScalableButton(this, wxID_ANY, "dot");
#ifdef __WXOSX__
btn_edit->SetBackgroundColour("#F7F7F7");
#else
btn_edit->SetBackgroundColour(*wxWHITE);
#endif
btn_edit->SetBackgroundColour(extruder_group_chip_bg());
btn_edit->Hide();
btn_edit->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this, index](auto &evt) {
PopupWindow *window = new AMSCountPopupWindow(this, index);
@@ -3866,6 +3885,10 @@ void Sidebar::sys_color_changed()
p->image_printer->SetSize(FromDIP(PRINTER_THUMBNAIL_SIZE));
p->image_printer_bed->SetSize(FromDIP(PRINTER_THUMBNAIL_SIZE));
for (ExtruderGroup *ext : {p->left_extruder, p->right_extruder, p->single_extruder})
if (ext)
ext->sys_color_changed();
// call a kill focus event to ensure new colors applied
for (ComboBox* combo : std::vector<ComboBox*>{p->combo_printer, p->combo_nozzle_dia, p->combo_printer_bed}){
wxFocusEvent fakeEvent(wxEVT_KILL_FOCUS);
+17 -10
View File
@@ -559,7 +559,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
sizer_split_options->Add(m_split_options_line, 1, wxALIGN_CENTER, 0);
m_options_other = new wxPanel(m_scroll_area);
m_options_other->SetBackgroundColour(*wxWHITE);
auto option_timelapse = new PrintOption(m_options_other, _L("Timelapse"), wxEmptyString, ops_no_auto, "timelapse");
@@ -3144,7 +3144,7 @@ void SelectMachineDialog::save_option_vals(MachineObject *obj) {
void SelectMachineDialog::Enable_Auto_Refill(bool enable)
{
if (enable) {
m_ams_backup_tip->SetForegroundColour(wxColour("#009688"));
m_ams_backup_tip->SetForegroundColour(StateColor::darkModeColorFor("#009688"));
}
else {
m_ams_backup_tip->SetForegroundColour(wxColour(0x90, 0x90, 0x90));
@@ -3169,19 +3169,21 @@ void SelectMachineDialog::show_timelapse_folder_popup()
return;
}
// build popup with rounded corners + light border
// build popup with rounded corners + themed border
const wxColour popup_bg = wxGetApp().dark_mode() ? wxColour("#333337") : wxColour(0xF0, 0xF0, 0xF0);
const wxColour popup_border = StateColor::darkModeColorFor(wxColour(0xCE, 0xCE, 0xCE));
m_timelapse_storage_popup = new PopupWindow(this, wxBORDER_NONE);
m_timelapse_storage_popup->SetBackgroundColour(wxColour(0xF0, 0xF0, 0xF0));
m_timelapse_storage_popup->Bind(wxEVT_PAINT, [this](wxPaintEvent&) {
m_timelapse_storage_popup->SetBackgroundColour(popup_bg);
m_timelapse_storage_popup->Bind(wxEVT_PAINT, [this, popup_bg, popup_border](wxPaintEvent&) {
wxPaintDC dc(m_timelapse_storage_popup);
auto size = m_timelapse_storage_popup->GetSize();
dc.SetPen(wxPen(wxColour(0xCE, 0xCE, 0xCE)));
dc.SetBrush(wxBrush(wxColour(0xF0, 0xF0, 0xF0)));
dc.SetPen(wxPen(popup_border));
dc.SetBrush(wxBrush(popup_bg));
dc.DrawRoundedRectangle(0, 0, size.x, size.y, FromDIP(8));
});
auto* panel = new wxPanel(m_timelapse_storage_popup, wxID_ANY);
panel->SetBackgroundColour(wxColour(0xF0, 0xF0, 0xF0));
panel->SetBackgroundColour(popup_bg);
// horizontal layout: [ Internal] [External]
auto* sizer = new wxBoxSizer(wxHORIZONTAL);
@@ -3202,7 +3204,8 @@ void SelectMachineDialog::show_timelapse_folder_popup()
if (enabled) radio->Enable(); else radio->Disable();
auto* text = new Label(panel, Label::Body_14, label);
text->SetForegroundColour(enabled ? wxColour(0x5C, 0x5C, 0x5C) : wxColour(0xAC, 0xAC, 0xAC));
text->SetForegroundColour(enabled ? (wxGetApp().dark_mode() ? wxColour("#E5E5E4") : wxColour(0x5C, 0x5C, 0x5C))
: StateColor::darkModeColorFor(wxColour(0xAC, 0xAC, 0xAC)));
if (enabled) {
auto on_select = [this, val](wxMouseEvent&) {
@@ -3376,7 +3379,7 @@ void SelectMachineDialog::show_timelapse_storage_dialog(MachineObject* obj)
create_scaled_bitmap("obj_warning", &dlg, 16), wxDefaultPosition, wxSize(FromDIP(16), FromDIP(16)));
auto* msg_label = new Label(&dlg, body_text);
msg_label->SetFont(Label::Body_14);
msg_label->SetForegroundColour(wxColour(0x33, 0x33, 0x33));
msg_label->SetForegroundColour(wxGetApp().dark_mode() ? wxColour("#EFEFF0") : wxColour(0x33, 0x33, 0x33));
msg_label->Wrap(FromDIP(340));
msg_sizer->Add(warn_bmp, 0, wxALIGN_TOP | wxRIGHT, FromDIP(6));
msg_sizer->Add(msg_label, 1, wxEXPAND);
@@ -3417,6 +3420,7 @@ void SelectMachineDialog::show_timelapse_storage_dialog(MachineObject* obj)
dlg.SetSizer(main_sizer);
dlg.Fit();
dlg.CenterOnParent();
wxGetApp().UpdateDlgDarkUI(&dlg);
// ShowModal returns after the dialog closes; handle the action outside the modal stack.
// wxID_CANCEL is returned when the user clicks X (close button) -> do nothing in that case.
@@ -4077,12 +4081,15 @@ void SelectMachineDialog::on_timer(wxTimerEvent &event)
if (m_ams_backup_tip->IsShown()) {
m_ams_backup_tip->Hide();
img_ams_backup->Hide();
m_scroll_area->Layout();
}
}
else {
if (!m_ams_backup_tip->IsShown()) {
m_ams_backup_tip->Show();
img_ams_backup->Show();
// first show: position them, they were never laid out while hidden
m_scroll_area->Layout();
}
}
+2
View File
@@ -538,6 +538,7 @@ void PrintingTaskPanel::create_panel(wxWindow* parent)
wxBoxSizer *bSizer_task_name = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *bSizer_task_name_hor = new wxBoxSizer(wxHORIZONTAL);
wxPanel* task_name_panel = new wxPanel(parent);
task_name_panel->SetBackgroundColour(*wxWHITE);
m_staticText_subtask_value = new wxStaticText(task_name_panel, wxID_ANY, _L("N/A"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT | wxST_ELLIPSIZE_END);
m_staticText_subtask_value->SetMaxSize(wxSize(FromDIP(600), -1));
@@ -705,6 +706,7 @@ void PrintingTaskPanel::create_panel(wxWindow* parent)
bSizer_text->Add(m_staticText_progress_left, 0, wxALIGN_CENTER_VERTICAL | wxALL, 0);
m_printing_stage_panel = new wxPanel(penel_finish_time);
m_printing_stage_panel->SetBackgroundColour(*wxWHITE);
wxBoxSizer *printingstage_vertical_sizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *printingstage_horizontal_sizer = new wxBoxSizer(wxHORIZONTAL);
+3
View File
@@ -1796,6 +1796,8 @@ bool UpgradePanel::Show(bool show)
const wxString &name /*= wxEmptyString*/)
: wxPanel(parent,id,pos,size,style)
{
SetBackgroundColour(*wxWHITE);
upgrade_green_icon = ScalableBitmap(this, "monitor_upgrade_online", 5);
auto ams_sizer = new wxFlexGridSizer(0, 2, 0, 0);
@@ -1879,6 +1881,7 @@ bool UpgradePanel::Show(bool show)
const wxString& name /*= wxEmptyString*/)
: wxPanel(parent, id, pos, size, style)
{
SetBackgroundColour(*wxWHITE);
upgrade_green_icon = ScalableBitmap(this, "monitor_upgrade_online", 5);
+2
View File
@@ -145,6 +145,8 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons
m_button_ams_setting_press = ScalableBitmap(this, "ams_setting_press", 24);
m_button_ams_setting = new wxStaticBitmap(m_panel_option_left, wxID_ANY, m_button_ams_setting_normal.bmp(), wxDefaultPosition, wxSize(FromDIP(24), FromDIP(24)));
m_button_ams_setting->SetMinSize(wxSize(FromDIP(24), FromDIP(24)));
m_button_ams_setting->SetMaxSize(wxSize(FromDIP(24), FromDIP(24)));
m_sizer_option_left->Add(m_button_auto_refill, 0, wxALIGN_CENTER, 0);
m_sizer_option_left->Add(0, 0, 0, wxLEFT, FromDIP(20));
m_sizer_option_left->Add(m_button_ams_setting, 0, wxALIGN_CENTER, 0);