clickable link widget

For help with anything that CEGUI doesn't offer straight out-of-the-box, e.g.:
- Implementation of new features, such as new Core classes, widgets, WindowRenderers, etc. ...
- Modification of any existing features for specific purposes
- Integration of CEGUI in new engines or frameworks and writing of new plugins (Renderer, Parser, ...) or modules

Moderators: CEGUI MVP, CEGUI Team

overlord
Just popping in
Just popping in
Posts: 7
Joined: Thu May 31, 2007 19:21

clickable link widget

Postby overlord » Thu May 31, 2007 20:28

Hi,

I'm trying to make an html style link widget. I'm wondering
what a good strategy would be for me to do this.

At this point i'm interested in just getting it rendered correctly
(no interaction).

The main problem is the underline. I made a custom window
with a StaticText child (the text), had it colored and thats fine.

Can i just draw a colored line in my Window? How do i do something
like that? draw on a texture, etc?
Should i just add another child StaticText with just '_' in it, and figure
out how many underline chars it should be (probably won't work
with non monospaced fonts)

any ideas?

thanks

Rackle
CEGUI Team (Retired)
Posts: 534
Joined: Mon Jan 16, 2006 11:59
Location: Montréal

Postby Rackle » Thu May 31, 2007 22:37

One approach could be to draw a line. The getBaseline() function from thefont API could be useful with this approach.

Another approach could be to create a falagard widget based on the StaticText widget. It would have a text component and an image component, an underline image. As the width of the widget increases so would the underline (think of how a frame window works, with the borders expanding).

One difficulty is dealin with line breaks.

One day I'll need this, and will have to figure this out. Unless someone else posts a solution.

overlord
Just popping in
Just popping in
Posts: 7
Joined: Thu May 31, 2007 19:21

Postby overlord » Fri Jun 01, 2007 17:43

Well for what i'm using now, it basically fits on one line
and i'm trying to keep it as simple as possible. I don't know
how to draw a line in CEGUI (i'd like to draw the line, so if
you want to explain how that works i'd be grateful). instead
i just made 2 static texts, one with the text, the other
just _____'s and then when the text one changes length
i just query its textExtents and limit the size of the ____ one.

kinda cheesy but it works for what i need

Rackle wrote:One approach could be to draw a line. The getBaseline() function from thefont API could be useful with this approach.

Another approach could be to create a falagard widget based on the StaticText widget. It would have a text component and an image component, an underline image. As the width of the widget increases so would the underline (think of how a frame window works, with the borders expanding).

One difficulty is dealin with line breaks.

One day I'll need this, and will have to figure this out. Unless someone else posts a solution.

Rackle
CEGUI Team (Retired)
Posts: 534
Joined: Mon Jan 16, 2006 11:59
Location: Montréal

Postby Rackle » Wed Jun 06, 2007 12:32

I haven't figured out how to draw but here's something. First I create an imageset from an image, basically a line in a bitmat:

Code: Select all

// Create an imageset
Imageset *is = ImagesetManager::getSingleton ().createImageset (
            "Underline",
            System::getSingleton ().getRenderer ()->createTexture ());

is->getTexture()->loadFromFile("Underline.bmp", "imagesets");
is->defineImage("full_image", Point(0.0f, 0.0f), Size(1.0f, 1.0f), Point(0.0f, 0.0f));


Then I modified CEGUIFont.cpp's drawTextLine() around line 454:

Code: Select all

Vector3 position(cur_pos);
position.d_y += 5.0f;
Size size(glyph->getSize(x_scale, y_scale));
size.d_height = ImagesetManager::getSingleton().getImageset("Underline")->getImage("full_image").getHeight();
ImagesetManager::getSingleton().getImageset("Underline")->getImage("full_image").draw(position, size,clip_rect, colours);


Not the best approach and it does not provide the best results either.

My idea was that the underline should be user-customizable, such as either a straight line (a traditional underline) or a squiggly line (such as when there's a typo). However this approach would not easily handle clicking.

I'm still leaning toward the Falagard widget as the better solution. Remains to be seen if the font "baseline" property is accessible, to properly position the underline. And by making the underline image a property then that widget could be used to display the two types I mentioned above. However I don't know how to handle line wraps, in the case where the underlined word does not completely fits on a single line. This approach has the bonus of making it easier to program an action on mouse click.

Rackle
CEGUI Team (Retired)
Posts: 534
Joined: Mon Jan 16, 2006 11:59
Location: Montréal

Postby Rackle » Fri Jun 08, 2007 12:49

Second attempt within CEGUIFont.cpp's drawTextLine() around line 435:

Code: Select all

void Font::drawTextLine(const String& text, const Vector3& position, const Rect& clip_rect, const ColourRect& colours, float x_scale, float y_scale)
{
    Vector3   cur_pos(position);

    const FontGlyph* glyph;
    float base_y = position.d_y;

   const FontGlyph* glyphUnderline = getGlyphData(0x5F); // full line
   const Image* imgUnderline = 0;
   colour underlineColour(1.0f, 0.0f, 0.0f);
   ColourRect underlineColourRect(underlineColour, underlineColour, underlineColour, underlineColour);
   float underlineThickness = y_scale * 1.5;
   if(glyphUnderline)
   {
      imgUnderline = glyphUnderline->getImage();
   }

   const FontGlyph* glyphStrikethrough = getGlyphData(0xAD); // soft hyphen
   const Image* imgStrikethrough = 0;
   colour strikethroughColour(1.0f, 0.0f, 0.0f);
   ColourRect strikethroughColourRect(strikethroughColour, strikethroughColour, strikethroughColour, strikethroughColour);
   float strikethroughThickness = y_scale;
   if(glyphStrikethrough)
   {
      imgStrikethrough = glyphStrikethrough->getImage();
   }

    for (size_t c = 0; c < text.length(); ++c)
    {
        glyph = getGlyphData(text[c]);

        if (glyph)
        {
            const Image* img = glyph->getImage();
            cur_pos.d_y = base_y - (img->getOffsetY() - img->getOffsetY() * y_scale);
            img->draw(cur_pos, glyph->getSize(x_scale, y_scale), clip_rect, colours);
         if(imgUnderline)
         {
            imgUnderline->draw(cur_pos, glyphUnderline->getSize(x_scale, underlineThickness), clip_rect, underlineColourRect);
         }
         if(imgStrikethrough)
         {
            imgStrikethrough->draw(cur_pos, glyphStrikethrough->getSize(x_scale * 3, strikethroughThickness), clip_rect, strikethroughColourRect);
         }
            cur_pos.d_x += glyph->getAdvance(x_scale);
        }
    }
}


Not clickable but does display an underline and a strikethrough of "programmable" thickness and color. By adjusting the offset it should be possible to display a wavy line (0x7E) as an underline. I tried to use "En Dash" (0x96) and "Em Dash" (0x97) for the strikethrough but those did not want to display. These unicode code points were obtained via Window's CharMap.exe application, with the Tahoma font.

This approach can be merged with the coloring approach discussed in another thread.


Return to “Modifications / Integrations / Customisations”

Who is online

Users browsing this forum: No registered users and 1 guest