How to handle word-wrapping static text?

Greetings of the Season to you all!

I have a question about the "right" way to handle word-wrapping static
text within a window. In my application, I have lots of places where
I need to include what amounts to a wx.StaticText control within a
window, and have its position and size controlled by a wx.Sizer. The
string to display can sometimes be short, but other times might
consist of up to, say, a hundred words of text, so the text needs to
word-wrap nicely to fit within the space allocated to it by the sizer
(which, it appears, means that wx.StaticText isn't suitable, as it
doesn't appear to word-wrap correctly when running under MS Windows).
I also can't use an uneditable wx.TextCtrl, because the height of the
control must vary according to how many lines of text it uses.
Ideally, the text should adjust the word-wrapping dynamically if the
user resizes the frame. And, of course, this needs to work on both
the Mac and MS Windows.

I've done some digging through the mailing list archives, and it
appears that this isn't easy to do -- but surely it's something that
people need quite often. I avoided the problem initially by
hard-coding newlines into the text to display, but when I went to port
my application from Windows to the Mac the windows all look ugly
because the text sizes and character widths are all different. It now
looks like I either need a generic solution, or else include separate
versions of each string to display, with newlines embedded in
different places, for each playform. Urgh!

How have others handled this problem? Is there a generic solution to
making sure this works correctly across all platforms? I've had a go
at creating my own "WrappingStaticTextCtrl" class based on
wx.lib.stattext.GenStaticText, but it's a bit of an ugly hack and
doesn't really work all that well. There must be a better way. Any
suggestions?

Thanks,

- Erik.

Greetings of the Season to you all!

I have a question about the "right" way to handle word-wrapping static
text within a window.

<<snip>>

Thanks,

- Erik.

I might be missing something here, but wouldn't HTMLWindow do the job? Needs
a bit of html wrapped around (and maybe inserted in) the text, but that's
simple enough.

- --
  Nigel Rowe
  rho@swiftdsl.com.au

···

On Thu, 23 Dec 2004 05:59, Erik Westra wrote:

Hi Nigel,

I might be missing something here, but wouldn't HTMLWindow do the job? Needs
a bit of html wrapped around (and maybe inserted in) the text, but that's
simple enough.

I've done that in a couple of places, but an HTML window doesn't
satisfy the requirement of taking up exactly the height of its
contents -- it uses a scrolling window and just takes the same size
regardless of the amount of text to be displayed, which works
sometimes (when you have nothing below the text to display, or can
have a fixed-size window), but looks terribly unprofessional in many
cases. Let me give you an example of the type of problem I'm up
against.

In my system, I often get messages returned by some remote part of the
system (possibly from a background thread, possibly even from a
program running on a different computer), and these messages must be
displayed by the GUI. These messages might be as short as "The
operation completed successfully", or they might include a more
detailed description of why an operation failed, which can extend to
maybe five or ten lines of text.

At present, I'm making use of wx.MessageBox to display these messages,
and including embedded newline characters in the text to force the
wx.MessageBox to word-wrap the text so that it looks good. This works
well, in that the wx.MessageBox automatically adjusts its height
according to how many lines of text are in the message to be
dissplayed -- but, as I said earlier, I've now discovered that what
looks good on one platform looks awful on another, and I'd have to
somehow adjust the embedded newlines according to which platform we're
running on.

Of course, I also tried using a wx.lib.dialogs.ScrolledMessageDialog
to achieve this (which is the equivalent of what you've suggested
above), but because the window is a fixed size it looks terribly
unprofessional when a one-line message is shown in a large scrollable
window. It really doesn't do it for me, I'm afraid.

Of course, this example is only one place where I hit up against this
problem. More generally, I've got to create my own windows with
complicated layouts, that really do need to make use of a static text
control of some sort that automatically word-wraps, and then adjusts
its height so that the sizer can place the other controls correctly
around it, allowing for whatever amount of text the control happens to
be showing at the time. If there's some way of making an HTML window
(or a ready-only wx.TextCtrl) do that, then that'll solve the problem
-- but I haven't been able to figure out any way of making these
controls behave in this way.

Thanks for the suggestion, though...

- Erik.

Erik Westra wrote:

How have others handled this problem? Is there a generic solution to
making sure this works correctly across all platforms? I've had a go
at creating my own "WrappingStaticTextCtrl" class based on
wx.lib.stattext.GenStaticText, but it's a bit of an ugly hack and
doesn't really work all that well. There must be a better way. Any
suggestions?

I think that the approach to take will be to break the message string into words (leaving the separating spaces in the words) and then measure the width of each word using dc.GetTextExtent. Then choose some fixed width for the control, or require that a width be passed to the __init__, (but it can resize itself smaller if there is only one or more short lines in the label) and then start adding word widths until you reach that limit. Then reassemble the string with newlines before the words that would have caused the word to cross the limit. Don't forget to account for newlines already in the source string. You could probably derive this class from wx.StaticText so you could take advantage of the builtin DoGetBestSize, etc., just manipulate the label before passing it to the native control.

Make sense?

P.S. This would be nice to have in the lib if you are able to contribute it.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

P.S. This would be nice to have in the lib if you are able to contribute it.

I did actually experiment with doing a derived static HTML text
control that auto-sizes. It is easy to get it to come up the
correct size initially. The biggest problem I then had is that the doc is very unclear about when the various sizing routines are
called.

The most important case to detect is a sizer making you wider or
taller, and then adjusting the other dimension if necessary.

Roger