wxST_NO_AUTORESIZE and invalidating best size

61 views
Skip to first unread message

Vadim Zeitlin

unread,
May 14, 2016, 5:22:54 PM5/14/16
to wx-dev
Hello,

I was recently surprised by a not quite obvious behaviour of wxStaticText
objects with wxST_NO_AUTORESIZE style and am now wondering if we should
change this. The code I have is something like this:

// Status field is initially empty, but put a few newlines into it
// to ensure that it's tall enough to show whatever we display in
// it later and so the control below doesn't jump around when the
// status changes.
m_status = new wxStaticText(this, wxID_ANY, "\n\n\n\n\n",
wxDefaultPosition, wxDefaultSize,
wxST_NO_AUTORESIZE
);

auto sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(m_status, wxSizerFlags().Expand());
sizer->Add(some_other_control, wxSizerFlags(1).Expand());

And the idea is that, at some later time, I can call

m_status->SetLabelText("Connecting to server...\nPlease wait");

and this string just appears in the status area without affecting the
existing controls.

And this actually does work fine. However if I later do

m_status->SetLabelText("1\n2\n3\n4\n5");

the label doesn't fit and only the first two lines are shown, in spite of
allocating enough space for 6 lines to this control initially.

As I said, this surprised me initially because I didn't see why would the
control size decrease in spite of wxST_NO_AUTORESIZE. After some debugging
I realized that this happened because SetLabelText() invalidated the best
size, so it was computed again when needed for the next layout and used the
smaller size sufficient to show the 2 lines of the "Connecting..." message
and not the initial, taller, message. And so the next Layout(), which
actually happened implicitly due to making the notebook page containing
these controls current, used this smaller size. But the last call to
SetLabelText() wasn't followed by Layout() and so the text was truncated.

Now I could, of course, call Layout() manually but this is completely
contrary to the initial purpose of avoiding the controls jumping around
when the status message changes. I really want to keep the status size
fixed instead. This is simple enough to do too by just adding

sizer->SetItemMinSize(m_status, m_status->GetBestSize());

after adding the item to the sizer. Unlike the wxStaticText own best size,
the min item size set at the sizer level won't change and so now things
finally behave as desired.

If nothing else, I hope this message could be helpful to others if anybody
runs into the same problem. But I also wonder if we shouldn't change the
code to avoid invalidating the best size of wxStaticText controls with
wxST_NO_AUTORESIZE style when their label changes. This seems more logical
to me and would, IMHO, result in more intuitive behaviour. And I don't see
what existing code could this break. Am I missing any good reasons to still
invalidate best size even for wxST_NO_AUTORESIZE controls? Or should we
make this change?

What do you think?
VZ

Vadim Zeitlin

unread,
Jul 20, 2016, 3:08:16 PM7/20/16
to wx-...@googlegroups.com
On Sat, 14 May 2016 23:22:36 +0200 I wrote:

[see http://thread.gmane.org/gmane.comp.lib.wxwidgets.devel/167494 for full
context]

Me> But I also wonder if we shouldn't change the
Me> code to avoid invalidating the best size of wxStaticText controls with
Me> wxST_NO_AUTORESIZE style when their label changes. This seems more logical
Me> to me and would, IMHO, result in more intuitive behaviour. And I don't see
Me> what existing code could this break. Am I missing any good reasons to still
Me> invalidate best size even for wxST_NO_AUTORESIZE controls? Or should we
Me> make this change?

I've finally decided to make it as there haven't been any objections but
quickly ran into another question I'm not sure about: currently,
AutoResizeIfNecessary() considers that it's always necessary to resize the
control unless if has wxST_NO_AUTORESIZE set. However the code calling it
(or doing its equivalent in wxGTK and wxOSX) also checks for IsEllipsized()
with the same comment in all ports:

if ( !IsEllipsized() ) // if ellipsize is ON, then we don't want to get resized!
{
AutoResizeIfNecessary();
}

But why is this comment actually correct? IMO it makes sense to want to use
ellipsis if there is not enough space to show the full text, but still use
as much of it as possible. And we already have the perfectly clearly named
(for once!) wxST_NO_AUTORESIZE if you really don't want the control to
resize itself no matter what and nothing prevents you from combining it
with one of wxST_ELLIPSIZE_XXX flags.

So IMO the current behaviour is just wrong and we should change it and
remove "!IsEllipsized()" checks. If there are no objections to this
neither, I will do this, as well as the change proposed above when I next
have a moment for it (hopefully sooner than in 2 months...).

Regards,
VZ
Reply all
Reply to author
Forward
0 new messages