From 13922a52b65c7db45e4dbd8f81674d9946a812dd Mon Sep 17 00:00:00 2001 From: Tommaso Bianchi Date: Thu, 13 Aug 2026 08:49:18 +0200 Subject: [PATCH] Design status: clear the DoF line on leaving sketch mode, and wrap the HUD chip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two independent leftovers, both in the same status area. snaporca-752: the "N degrees of freedom" line described a sketch's constraint state and stayed on screen after Confirm, Cancel and the Escape downgrade, in Feature mode where it means nothing — visible in every Feature-mode screenshot of the 2026-07-27 sweep. Cleared in set_ui_mode rather than at those three exits, because that is the one place all of them pass through and a fourth exit added later would otherwise reintroduce it. Constrain mode keeps the readout: that is where the number is the whole point. snaporca-8cc: moving the status out of the panel and into the viewport HUD removed the clipping, but not the underlying problem. The chip is a top-level popup that Fit()s to its text, so a long sentence grew past the right edge of the canvas and hung over the window instead of being cut off inside it — the same silent length limit wearing a different hat. The label now wraps to the room actually available (canvas width minus the view-cube inset), which is what makes the earlier promise that "a sentence can be a sentence" true at 1366 as well as at 1920. SetLabel + Wrap + Fit are now one function called from both the text change and the placement. Wrap() rewrites the label it is handed, so it has to follow a fresh SetLabel every time, and the placement path runs on resize — a chip wrapped for the old width either overhangs a narrowed canvas or wastes a widened one. The left inset is one constant now because the wrap width and the anchor have to agree, or the chip wraps to a width it is not then given. snaporca-752, snaporca-8cc. Reviewed and compiled (RC=0), not exercised. --- src/slic3r/GUI/DesignCanvas.cpp | 33 +++++++++++++++++++++++++++++---- src/slic3r/GUI/DesignCanvas.hpp | 1 + src/slic3r/GUI/DesignPanel.cpp | 9 +++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/DesignCanvas.cpp b/src/slic3r/GUI/DesignCanvas.cpp index 2d83ea026e..500dba8ad3 100644 --- a/src/slic3r/GUI/DesignCanvas.cpp +++ b/src/slic3r/GUI/DesignCanvas.cpp @@ -1027,6 +1027,11 @@ void DesignCanvas::set_readout(const std::string& text) m_hud->Raise(); } +// Clear of the view cube and the two round view buttons, which own the bottom-left corner. +// Shared by the placement and by the wrap width, which have to agree or the chip wraps to a +// width it is then not given. +static constexpr int kStatusHudLeftInsetDip = 190; + void DesignCanvas::set_status_text(const wxString& text, const wxColour& colour) { if (!m_status_hud || !m_status_hud_label || !m_canvas_widget) return; @@ -1035,11 +1040,29 @@ void DesignCanvas::set_status_text(const wxString& text, const wxColour& colour) m_status_hud_colour = colour; if (text.IsEmpty()) { m_status_hud->Hide(); return; } m_status_hud_label->SetForegroundColour(colour); - m_status_hud_label->SetLabel(text); - m_status_hud->Fit(); + apply_status_label(); place_status_hud(); } +// SetLabel + Wrap + Fit, in that order and always together. Moving the status out of the panel +// removed the clipping of snaporca-8cc but not the underlying problem: the chip is a top-level +// popup that Fit()s to its text, so a long sentence simply grew past the right edge of the canvas +// and hung over the window. Wrapping to the room actually available is what makes the earlier +// promise — "a sentence can be a sentence" — true at every window width, including the charter's +// 1366 reach. Wrap() rewrites the label it is given, so it must follow a fresh SetLabel every +// time; that is the whole reason this is one function instead of three call sites. +void DesignCanvas::apply_status_label() +{ + if (!m_status_hud || !m_status_hud_label || !m_canvas_widget) return; + m_status_hud_label->SetLabel(m_status_hud_last); + const int avail = m_canvas_widget->GetClientSize().GetWidth() + - m_canvas_widget->FromDIP(kStatusHudLeftInsetDip) + - m_canvas_widget->FromDIP(24); + if (avail > m_canvas_widget->FromDIP(120)) // a uselessly narrow canvas: leave it unwrapped + m_status_hud_label->Wrap(avail); + m_status_hud->Fit(); +} + void DesignCanvas::place_status_hud() { if (!m_status_hud || !m_canvas_widget || m_status_hud_last.IsEmpty()) return; @@ -1048,9 +1071,11 @@ void DesignCanvas::place_status_hud() // then stayed until the next status change moved it. Nothing to anchor to: stay down. if (!m_canvas_widget->IsShownOnScreen()) { m_status_hud->Hide(); return; } const wxSize cs = m_canvas_widget->GetClientSize(); + // Re-wrap first: this also runs on resize, and a chip wrapped for the old width either + // overhangs a narrowed canvas or wastes a widened one. + apply_status_label(); const wxSize hs = m_status_hud->GetSize(); - // Clear of the view cube and the two round view buttons, which own the bottom-left corner. - const int kLeftInset = m_canvas_widget->FromDIP(190); + const int kLeftInset = m_canvas_widget->FromDIP(kStatusHudLeftInsetDip); const wxPoint bl = m_canvas_widget->ClientToScreen( wxPoint(kLeftInset, cs.GetHeight() - hs.GetHeight() - 12)); // No Raise() and no focus juggling: a popup neither takes focus nor falls behind. This was diff --git a/src/slic3r/GUI/DesignCanvas.hpp b/src/slic3r/GUI/DesignCanvas.hpp index d0203f5863..657cddd924 100644 --- a/src/slic3r/GUI/DesignCanvas.hpp +++ b/src/slic3r/GUI/DesignCanvas.hpp @@ -330,6 +330,7 @@ private: wxString m_status_hud_last; wxColour m_status_hud_colour; void place_status_hud(); // re-anchors to the canvas corner (also on resize) + void apply_status_label(); // SetLabel + Wrap to the canvas width + Fit, always together std::function m_on_sketch_commit; std::function&, const std::vector&, diff --git a/src/slic3r/GUI/DesignPanel.cpp b/src/slic3r/GUI/DesignPanel.cpp index 1f60673c07..992c7f8dff 100644 --- a/src/slic3r/GUI/DesignPanel.cpp +++ b/src/slic3r/GUI/DesignPanel.cpp @@ -3918,6 +3918,15 @@ void DesignPanel::set_ui_mode(UiMode m) { m_ui_mode = m; if (m != UiMode::Sketch) m_sketch_on.clear(); // no stale "on the picked face" on the next hint + // The DoF readout describes a SKETCH's constraint state, so it means nothing back in Feature + // mode — where it nonetheless stayed on screen after every Confirm, Cancel and Escape + // (snaporca-752). Cleared here rather than at those three exits because this is the one place + // all of them pass through, and a fourth exit added later would otherwise reintroduce it. + // Constrain mode keeps it: that is where the number is the whole point. + if (m == UiMode::Feature && m_dof_status != nullptr) { + m_dof_status->SetLabel(wxString()); + m_dof_status->Show(false); + } wxSizer* s = m_toolbar->GetSizer(); s->Show(m_tb_feature, m == UiMode::Feature, true); s->Show(m_tb_sketch, m == UiMode::Sketch, true);