diff --git a/src/slic3r/GUI/StatusPanel.cpp b/src/slic3r/GUI/StatusPanel.cpp index c5096378cc..4a6c6f241c 100644 --- a/src/slic3r/GUI/StatusPanel.cpp +++ b/src/slic3r/GUI/StatusPanel.cpp @@ -2709,6 +2709,12 @@ void StatusPanel::sync_nozzle_temp_controls(size_t count) const size_t old_size = m_tempCtrl_nozzles.size(); ensure_nozzle_temp_controls(count); + // A generic printer with more than two tools needs to name each control; the L/R badge on + // Bambu's dual-tool layout is handled by TempInput itself and must stay unchanged. + const bool show_tool_ids = count > 2; + for (size_t i = 0; i < m_tempCtrl_nozzles.size(); ++i) + m_tempCtrl_nozzles[i]->SetDisplayIdText(show_tool_ids ? wxString::Format("T%d", int(i) + 1) : wxString()); + bool layout_changed = false; if (m_tempCtrl_nozzle->IsShown()) { m_tempCtrl_nozzle->Hide(); diff --git a/src/slic3r/GUI/Widgets/TempInput.cpp b/src/slic3r/GUI/Widgets/TempInput.cpp index 418f1a5620..d329c9bb04 100644 --- a/src/slic3r/GUI/Widgets/TempInput.cpp +++ b/src/slic3r/GUI/Widgets/TempInput.cpp @@ -8,6 +8,7 @@ #include #include #include "slic3r/GUI/Widgets/StateHandler.hpp" +#include #include #include #include @@ -245,6 +246,37 @@ void TempInput::SetCurrType(TempInputType type) { m_input_type = type; } +wxString TempInput::badge_text() const +{ + if (m_input_type == TEMP_OF_MAIN_NOZZLE_TYPE) + return "R"; + if (m_input_type == TEMP_OF_DEPUTY_NOZZLE_TYPE) + return "L"; + return m_display_id_text; +} + +int TempInput::badge_width(wxDC &dc) const +{ + const wxString text = badge_text(); + if (text.IsEmpty()) + return 0; + // The explicit Tn id sits in the same compact control as the L/R badge, so it uses the smaller + // body font. Keep this formula identical to render() so measurement and painting cannot drift. + dc.SetFont(has_tool_id_badge() ? ::Label::Body_10 : ::Label::Body_12); + const wxSize text_size = dc.GetMultiLineTextExtent(text); + const wxSize icon_size = round_scale_hint_icon.GetBmpSize(); + return std::max(icon_size.x, text_size.x + FromDIP(2)); +} + +void TempInput::SetDisplayIdText(const wxString &text) +{ + if (m_display_id_text == text) + return; + m_display_id_text = text; + messureMiniSize(); + Refresh(); +} + void TempInput::Warning(bool warn, WarningType type) { warning_mode = warn; @@ -392,10 +424,8 @@ void TempInput::DoSetSize(int x, int y, int width, int height, int sizeFlags) // interval left += 9; - if (m_input_type == TEMP_OF_MAIN_NOZZLE_TYPE || m_input_type == TEMP_OF_DEPUTY_NOZZLE_TYPE) { - wxSize szIcon = round_scale_hint_icon.GetBmpSize(); - left += szIcon.x + 3; - } + if (const int badge = badge_width(dc); badge > 0) + left += badge + 3; // label dc.SetFont(::Label::Head_14); @@ -474,34 +504,30 @@ void TempInput::render(wxDC &dc) ScalableBitmap round_icon(this, "round", 16);/*icon diffs in normal and dark mode*/ round_icon.msw_rescale(); - if (round_icon.bmp().IsOk() && m_input_type == TEMP_OF_DEPUTY_NOZZLE_TYPE){ - wxSize szIcon = round_icon.GetBmpSize(); - pt.y = (size.y - szIcon.y) / 2; - dc.DrawBitmap(round_icon.bmp(), pt); + const wxString display_id = badge_text(); + if (round_icon.bmp().IsOk() && !display_id.IsEmpty()) { + const wxSize icon_size = round_icon.GetBmpSize(); + dc.SetFont(has_tool_id_badge() ? ::Label::Body_10 : ::Label::Body_12); + const wxSize text_size = dc.GetMultiLineTextExtent(display_id); + // L/R and single-digit tool ids fit the round icon; a wider id (e.g. T10) gets a pill + // with the same fill and white lettering. + const int badge_width = std::max(icon_size.x, text_size.x + FromDIP(2)); - dc.SetFont(::Label::Body_12); - auto sepSize = dc.GetMultiLineTextExtent(wxString("L")); + pt.y = (size.y - icon_size.y) / 2; + if (badge_width > icon_size.x) { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(wxColour("#262E30"))); + dc.DrawRoundedRectangle(pt.x, pt.y, badge_width, icon_size.y, icon_size.y / 2); + } else { + dc.DrawBitmap(round_icon.bmp(), pt); + } + dc.SetBrush(*wxTRANSPARENT_BRUSH); const wxColour& clr = Slic3r::GUI::wxGetApp().dark_mode() ? StateColor::darkModeColorFor(*wxWHITE) : *wxWHITE; dc.SetTextForeground(clr); dc.SetTextBackground(clr); - dc.DrawText(wxString("L"), pt.x + (szIcon.x - sepSize.x) / 2, (size.y - sepSize.y) / 2); - pt.x += szIcon.x + 3; - } - - if (round_icon.bmp().IsOk() && m_input_type == TEMP_OF_MAIN_NOZZLE_TYPE) { - wxSize szIcon = round_icon.GetBmpSize(); - pt.y = (size.y - szIcon.y) / 2; - dc.DrawBitmap(round_icon.bmp(), pt); - - dc.SetFont(::Label::Body_12); - auto sepSize = dc.GetMultiLineTextExtent(wxString("R")); - - const wxColour& clr = Slic3r::GUI::wxGetApp().dark_mode() ? StateColor::darkModeColorFor(*wxWHITE) : *wxWHITE; - dc.SetTextForeground(clr); - dc.SetTextBackground(clr); - dc.DrawText(wxString("R"), pt.x + (szIcon.x - sepSize.x) / 2, (size.y - sepSize.y) / 2); - pt.x += szIcon.x + 3; + dc.DrawText(display_id, pt.x + (badge_width - text_size.x) / 2, (size.y - text_size.y) / 2); + pt.x += badge_width + 3; } // label @@ -570,11 +596,7 @@ void TempInput::messureMiniSize() // interval width += 9; - if (m_input_type == TEMP_OF_MAIN_NOZZLE_TYPE || m_input_type == TEMP_OF_DEPUTY_NOZZLE_TYPE) { - wxSize szIcon = round_scale_hint_icon.GetBmpSize(); - width += szIcon.x; - } - width += 3; + width += badge_width(dc) + 3; // label dc.SetFont(::Label::Head_14); @@ -630,11 +652,7 @@ void TempInput::messureSize() // interval width += 9; - if (m_input_type == TEMP_OF_MAIN_NOZZLE_TYPE || m_input_type == TEMP_OF_DEPUTY_NOZZLE_TYPE) { - wxSize szIcon = round_scale_hint_icon.GetBmpSize(); - width += szIcon.x; - } - width += 3; + width += badge_width(dc) + 3; // label dc.SetFont(::Label::Head_14); diff --git a/src/slic3r/GUI/Widgets/TempInput.hpp b/src/slic3r/GUI/Widgets/TempInput.hpp index d583e881b5..5b6be4010c 100644 --- a/src/slic3r/GUI/Widgets/TempInput.hpp +++ b/src/slic3r/GUI/Widgets/TempInput.hpp @@ -53,7 +53,16 @@ class TempInput : public wxNavigationEnabled int min_temp = 0; std::unordered_set additional_temps; bool warning_mode = false; - TempInputType m_input_type; + TempInputType m_input_type = TEMP_OF_NORMAL_TYPE; + wxString m_display_id_text; // optional badge (T1, T2, ...) beside the icon + + // Badge shown over the round icon: L/R for Bambu's main/deputy nozzle, or the explicit tool id. + wxString badge_text() const; + bool has_tool_id_badge() const + { + return m_input_type == TEMP_OF_NORMAL_TYPE && !m_display_id_text.IsEmpty(); + } + int badge_width(wxDC &dc) const; int padding_left = 0; static const int TempInputWidth = 200; @@ -123,6 +132,8 @@ public: wxString GetCurrTemp() { return GetLabel(); } int get_max_temp() { return max_temp; } void SetLabel(const wxString &label) override; + // Tool identity shown in the round badge (for printers with more than two toolheads). + void SetDisplayIdText(const wxString &text); void SetTextColor(StateColor const &color);