Dynamic text wrapping in a StaticBox

Hey, I've been trying to get this to work now for a couple of hours
but I'm having no luck.

I want to have a StaticBox which expands to the edges of the panel,
but the height is dynamic and is heigh enough to hold the text
contained inside (which should wrap).

I guess this is a bit tricky as the box calculates its size based of
the contents, but StaticText wont know what height to return in
DoGetBestSize, because it doesn't know the width it's living in
(changing width will change the wrapping points, so changing the
height) - so it's a bit of a catch 22. The box needs to know the
height from the control, and the control needs to know the width from
the box.

One thing I did discover which I found very weird is that if I wrap
the control a bit shorter (or I guess anywhere) it behaves as I want,
except that the wrapping point(s) always break at those points, even
after resizing. The example below should show what I mean - The second
box works as I want when I resize the frame, but the last word is
always on a new line. Weirdly If I set the wrapping point as the same
width of the control then it doesn't wrap at all (which is the first
box in the example) :frowning:

import wx

class Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, size=(800, 300))

        self.panel = wx.Panel(self)

        sizer = wx.BoxSizer(wx.VERTICAL)

        txt = " ".join("words" for _ in xrange(100)) + " LASTWORD"

        for x in [0, 10]:
            box = wx.StaticBox(self.panel)
            box_sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
            text = wx.StaticText(self.panel, label=txt)
            text.Wrap(text.GetSize().width - x)
            box_sizer.Add(text, 0, wx.EXPAND)
            sizer.Add(box_sizer, 0, wx.EXPAND | wx.ALL, 10)

        self.panel.SetSizer(sizer)

        self.Show()

        self.panel.Layout()

if __name__ == "__main__":
    app = wx.App(False)
    Frame()
    app.MainLoop()

Hi,

Hey, I've been trying to get this to work now for a couple of hours
but I'm having no luck.

I want to have a StaticBox which expands to the edges of the panel,
but the height is dynamic and is heigh enough to hold the text
contained inside (which should wrap).

I guess this is a bit tricky as the box calculates its size based of
the contents, but StaticText wont know what height to return in
DoGetBestSize, because it doesn't know the width it's living in
(changing width will change the wrapping points, so changing the
height) - so it's a bit of a catch 22. The box needs to know the
height from the control, and the control needs to know the width from
the box.

One thing I did discover which I found very weird is that if I wrap
the control a bit shorter (or I guess anywhere) it behaves as I want,
except that the wrapping point(s) always break at those points, even
after resizing. The example below should show what I mean - The second
box works as I want when I resize the frame, but the last word is
always on a new line. Weirdly If I set the wrapping point as the same
width of the control then it doesn't wrap at all (which is the first
box in the example) :frowning:

One think you might try is to use my implementation of
AutoWrapStaticText (which lives inside wx.lib.agw.infobar):

http://svn.wxwidgets.org/viewvc/wx/wxPython/3rdParty/AGW/agw/infobar.py?view=markup

Around line 230.

In theory this (generic) wx.StaticText should do what you want, unless
I am missing something. If it doesn't work out of the box, you may try
to implement the DoGetBestSize for it and return whatever
wx.DC.GetMultilineTextExtent reports.

There might be a better approach of course...

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."

# ------------------------------------------------------------- #
def ask_mailing_list_support(email):

    if mention_platform_and_version() and include_sample_app():
        send_message(email)
    else:
        install_malware()
        erase_hard_drives()
# ------------------------------------------------------------- #

···

On 23 January 2013 19:37, Paul Wiseman wrote:

Hi,
just a hackish approach, but you could check, whether a TextCtrl
widget wouldn't be close enough for what you need to achieve;
e.g.
text = wx.TextCtrl(self.panel, value=txt,
style=wx.TE_READONLY|wx.TE_MULTILINE|wx.TE_NO_VSCROLL|wx.BORDER_NONE)
text.SetBackgroundColour("ganisboro")

instead of
text = wx.StaticText(self.panel, label=txt)
text.Wrap(text.GetSize().width - x)

Of course, there are some differences, that might or might not matter:
caret, text selection etc.

hth,
   vbr

···

2013/1/23 Paul Wiseman <poalman@gmail.com>:

Hey, I've been trying to get this to work now for a couple of hours
but I'm having no luck.

I want to have a StaticBox which expands to the edges of the panel,
but the height is dynamic and is heigh enough to hold the text
contained inside (which should wrap).

I guess this is a bit tricky as the box calculates its size based of
the contents, but StaticText wont know what height to return in
DoGetBestSize, because it doesn't know the width it's living in
(changing width will change the wrapping points, so changing the
height) - so it's a bit of a catch 22. The box needs to know the
height from the control, and the control needs to know the width from
the box.

One thing I did discover which I found very weird is that if I wrap
the control a bit shorter (or I guess anywhere) it behaves as I want,
except that the wrapping point(s) always break at those points, even
after resizing. The example below should show what I mean - The second
box works as I want when I resize the frame, but the last word is
always on a new line. Weirdly If I set the wrapping point as the same
width of the control then it doesn't wrap at all (which is the first
box in the example) :frowning:

[...]

Hi,

Hey, I've been trying to get this to work now for a couple of hours
but I'm having no luck.

I want to have a StaticBox which expands to the edges of the panel,
but the height is dynamic and is heigh enough to hold the text
contained inside (which should wrap).

I guess this is a bit tricky as the box calculates its size based of
the contents, but StaticText wont know what height to return in
DoGetBestSize, because it doesn't know the width it's living in
(changing width will change the wrapping points, so changing the
height) - so it's a bit of a catch 22. The box needs to know the
height from the control, and the control needs to know the width from
the box.

One thing I did discover which I found very weird is that if I wrap
the control a bit shorter (or I guess anywhere) it behaves as I want,
except that the wrapping point(s) always break at those points, even
after resizing. The example below should show what I mean - The second
box works as I want when I resize the frame, but the last word is
always on a new line. Weirdly If I set the wrapping point as the same
width of the control then it doesn't wrap at all (which is the first
box in the example) :frowning:

One think you might try is to use my implementation of
AutoWrapStaticText (which lives inside wx.lib.agw.infobar):

http://svn.wxwidgets.org/viewvc/wx/wxPython/3rdParty/AGW/agw/infobar.py?view=markup

Around line 230.

In theory this (generic) wx.StaticText should do what you want, unless
I am missing something. If it doesn't work out of the box, you may try
to implement the DoGetBestSize for it and return whatever
wx.DC.GetMultilineTextExtent reports.

Hey Andrea,

That works perfectly thank you!

It seems like like a subtle bug in StaticText, I made subclass that
added some spaces to the end of the specified label, then called Wrap
with the width -3 (ish) which made it behave as I'd expect, but this
solution seemed a bit too hacky for my liking - you're implementation
is better!

I tried before to make a subclass of the generic StaticText, much like
how your one works with binding Wrap to EVT_SIZE but it had weird
behaviour where the wrapping points seemed to insert newlines, so if
you resized really narrow you'd end up with line breaks after every
word permanently even when growing the window again which is I guess
is what's happening with the LASTWORD in my example.

Thanks again though!

Paul

···

On 23 January 2013 19:18, Andrea Gavana <andrea.gavana@gmail.com> wrote:

On 23 January 2013 19:37, Paul Wiseman wrote:

There might be a better approach of course...

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://www.infinity77.net

# ------------------------------------------------------------- #
def ask_mailing_list_support(email):

    if mention_platform_and_version() and include_sample_app():
        send_message(email)
    else:
        install_malware()
        erase_hard_drives()
# ------------------------------------------------------------- #

--
--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en