Rescaling a window to fit it's text

For help with general CEGUI usage:
- Questions about the usage of CEGUI and its features, if not explained in the documentation.
- Problems with the CMAKE configuration or problems occuring during the build process/compilation.
- Errors or unexpected behaviour.

Moderators: CEGUI MVP, CEGUI Team

User avatar
cippyboy
Quite a regular
Quite a regular
Posts: 51
Joined: Wed Jul 30, 2008 13:23

Rescaling a window to fit it's text

Postby cippyboy » Mon Sep 21, 2009 15:16

Hi,

Recently we began having the need to display a text in a box and rescale the text widget and the box accordingly so that it won't have big empty spaces when switching the text widget's contents. How do I determine the necesary size of a defaultwindow's text ? I know it is internally clipped for example and trying to use getUnclippedInnerRect()/getInnerRect()/getUnclippedPixelRect() all return me the same sizes as getSize() which is the current size. How do I retrieve the internal size so to speak so I can change the widget's size to fit the text inside it accurately ?

EDIT : Alternatively, is there a way to determine how much space is needed by analyzing the text to be inserted ?

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Rescaling a window to fit it's text

Postby CrazyEddie » Mon Sep 21, 2009 18:26

I'm not 100% certain what window type you're using, you mention DefaultWindow and then go on to talk about inner rects and such. The DefaultWindow is just a rectangular area and has no notion of an inner rendering area (so I'm confused). There is no other internal representation of the window area or size other than what's returned by those functions - they access the same CEGUI::Rect objects that CEGUI itself uses within the library code. Note also that there's also a bug in all versions of CEGUI prior to 0.7.0 that renders the concept of the 'inner rect' or client area pretty much broken. The solution you ultimately use is dependant upon the type of window, the window renderer assigned and the looknfeel, but generally the approach is what's covered in this thread: viewtopic.php?f=10&t=4310 It's an interesting read because it covers some of the issues and pitfalls.

Largely it also depends heavily upon what - if any - formatting you intend to use. For example, how do you dynamically size the width of a window that is to contain word-wrapped text? So for those types of cases you need some kind of limits imposed. For the general case, you use font functions to measure the extent and number of lines for formatted text, add the size of any frame used by the window, then set the size of the window using absolute pixel values (UDIm offsets, with zero scale components). If you just have a single line of text, it's really simple - if you can't work it out from the above, let us know if you're really using DefaultWindow, or some other window and I'll post the code to do it.

CE.

User avatar
cippyboy
Quite a regular
Quite a regular
Posts: 51
Joined: Wed Jul 30, 2008 13:23

Re: Rescaling a window to fit it's text

Postby cippyboy » Tue Sep 22, 2009 10:34

Thanks for the code ! It was a StaticText which should be the DefaultWindow in code I figure. Anyway, it seems to work accurately and I can make an artist happy :D.

This is the working code if anyone bumps through here looking for a quick solve (deleted a few consts, I know) :

Code: Select all

CEGUI::Rect getStaticTextArea(const CEGUI::Window* static_text)
{
   const CEGUI::WidgetLookFeel& wlf =
      CEGUI::WidgetLookManager::getSingleton().
         getWidgetLook(static_text->getLookNFeel());

   bool AreaExists = wlf.isNamedAreaDefined("WithFrameTextRenderArea");
   if (AreaExists)
   {
      const CEGUI::NamedArea & RenderArea = wlf.getNamedArea("WithFrameTextRenderArea");
      return RenderArea.getArea().getPixelRect(*static_text);
   }
   else
   {
      const ImagerySection& ImageSection = wlf.getImagerySection("image_noframe");
      return ImageSection.getBoundingRect(*static_text);
   }
}
int setHeight(CEGUI::Window* static_text)
{
    // Get the area the text is formatted and drawn into.
    CEGUI::Rect fmt_area(getStaticTextArea(static_text));

    // Calculate the pixel height of the frame by subtracting the height of the
    // area above from the total height of the window.
    float frame_height =
        static_text->getUnclippedPixelRect().getHeight() - fmt_area.getHeight();

    // Get the formatted line count - using the formatting area obtained above.
    int lines = static_text->getFont()->getFormattedLineCount(
            static_text->getText(), fmt_area, CEGUI::WordWrapLeftAligned);

    // Calculate pixel height of window, which is the number of formatted lines
    // multiplied by the spacing of the font, plus the pixel height of the
    // frame.
    float height = (float)lines * static_text->getFont()->getLineSpacing() + frame_height;

    // set the height to the window.
    static_text->setHeight(CEGUI::UDim(0, height));

    return static_cast<int>(height);
}


PS: Solves like this should be edited into the first post at the end of it upon marking a thread [Solved]. Just my opinion though.

EDIT: A slight change in code makes the same thing possible for static texts without a named area (like I found out that I have :D)

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Rescaling a window to fit it's text

Postby CrazyEddie » Tue Sep 22, 2009 13:18

cool. Glad you have a solution.

PS: Solves like this should be edited into the first post at the end of it upon marking a thread [Solved]. Just my opinion though.

The OP of the thread should do that, it's not something I want to start doing myself :)

CE.


Return to “Help”

Who is online

Users browsing this forum: No registered users and 33 guests