From 97546a6f0cf941ce94b42a27b23f51e224c8e54e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 22 Jul 2023 22:58:55 +0200 Subject: [PATCH] Really fix wxProcessDialog size when the message length changes Ensure that we only increase the dialog width but never decrease it to prevent the dialog from jumping annoyingly to different size with each label change. The previous attempt to do this in 4101849b4d (Grow wxGenericProgressDialog automatically if needed, 2017-10-27) didn't work because it seemingly didn't take into account the fact that wxStaticText width changes when its label changes and so calling SetLabel() could make it smaller, meaning that the next update would call Fit() again. So fix this by preventing the control from changing its size by using wxST_NO_AUTORESIZE and then only resizing it manually if it really needs more space. See #10624, #23727. --- src/generic/progdlgg.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/generic/progdlgg.cpp b/src/generic/progdlgg.cpp index 0c3ccd380f..fc033224e0 100644 --- a/src/generic/progdlgg.cpp +++ b/src/generic/progdlgg.cpp @@ -179,7 +179,14 @@ bool wxGenericProgressDialog::Create( const wxString& title, // top-level sizerTop wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL); - m_msg = new wxStaticText(this, wxID_ANY, message); + // We use wxST_NO_AUTORESIZE to prevent the label from snapping back to + // smaller size if the message becomes shorter: we need this because we + // always increase its size to fit the longest message and so we assume + // that its current size is always this longest size and not some maybe + // shorter size. + m_msg = new wxStaticText(this, wxID_ANY, message, + wxDefaultPosition, wxDefaultSize, + wxST_NO_AUTORESIZE); sizerTop->Add(m_msg, 0, wxLEFT | wxRIGHT | wxTOP, 2*LAYOUT_MARGIN); int gauge_style = wxGA_HORIZONTAL; @@ -778,12 +785,18 @@ void wxGenericProgressDialog::UpdateMessage(const wxString &newmsg) { if ( !newmsg.empty() && newmsg != m_msg->GetLabel() ) { - const wxSize sizeOld = m_msg->GetSize(); - m_msg->SetLabel(newmsg); - if ( m_msg->GetSize().x > sizeOld.x ) + // When using wxST_NO_AUTORESIZE, best size is not invalidated by + // changing the label, but we do want to compute the best size here + // so do it manually. + m_msg->InvalidateBestSize(); + + const wxSize sizeNeeded = m_msg->GetBestSize(); + if ( sizeNeeded.x > m_msg->GetSize().x ) { + m_msg->SetSize(sizeNeeded); + // Resize the dialog to fit its new, longer contents instead of // just truncating it. Fit();