Dillo v3.1.1-119-g140d9ebd
Loading...
Searching...
No Matches
Dillo Widget Usage

This document describes the usage of Dw, without going too much into detail.

Getting Started

In this section, a small runnable example is described, based on the FLTK implementation.

As described in Dillo Widget Overview, the following objects are needed:

First of all, the necessary #include's:

#include <FL/Fl_Window.H>
#include <FL/Fl.H>
#include "dw/core.hh"
#include "dw/fltkcore.hh"
#include "dw/textblock.hh"

Everything is put into one function:

int main(int argc, char **argv)
{
int main(void)
Definition bookmarks.c:1613

As the first object, the platform is instantiated:

Then, the layout is created, with the platform attached:

The central class for managing and drawing a widget tree.
Definition layout.hh:17
static Layout * layout

For the view, we first need a FLTK window:

Fl_Window *window = new Fl_Window(200, 300, "Dw Example");
window->begin();
static Fl_Window * window

After this, we can create a viewport, and attach it to the layout:

new dw::fltk::FltkViewport (0, 0, 200, 300);
layout->attachView (viewport);
static FltkViewport * viewport

Each widget needs a style (dw::core::style::Style, see dw::core::style), so we construct it here. For this, we need to fill a dw::core::style::StyleAttrs structure with values, and call dw::core::style::Style::create (latter is done further below):

dw::core::style::StyleAttrs::initValues sets several default values. The last line sets a margin of 5 pixels. Next, we need a font. Fonts are created in a similar way, first, the attributes are defined:

Now, the font can be created:

styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs);
static Font * create(Layout *layout, FontAttrs *attrs)
Definition style.cc:444

As the last attributes, the background and forground colors are defined, here dw::core::style::Color::createSimple must be called:

styleAttrs.color =
styleAttrs.backgroundColor =
static Color * create(Layout *layout, int color)
Definition style.cc:529

Finally, the style for the widget is created:

static Style * create(StyleAttrs *attrs)
Definition style.hh:629
static Style * widgetStyle

Now, we create a widget, assign a style to it, and set it as the toplevel widget of the layout:

dw::Textblock *textblock = new dw::Textblock (false);
textblock->setStyle (widgetStyle);
layout->setWidget (textblock);
A Widget for rendering text blocks, i.e.
Definition textblock.hh:206
virtual void setStyle(style::Style *style)
Change the style of a widget.
Definition widget.cc:1316

The style is not needed anymore (a reference is added in dw::core::Widget::setStyle), so it should be unreferred:

widgetStyle->unref();

Now, some text should be added to the textblock. For this, we first need another style. styleAttrs can still be used for this. We set the margin to 0, and the background color to "transparent":

styleAttrs.margin.setVal (0);
styleAttrs.backgroundColor = NULL;
static Style * wordStyle

This loop adds some paragraphs:

for(int i = 1; i <= 10; i++) {
char buf[4];
sprintf(buf, "%d.", i);
char *words[] = { "This", "is", "the", buf, "paragraph.",
"Here", "comes", "some", "more", "text",
"to", "demonstrate", "word", "wrapping.",
NULL };
for(int j = 0; words[j]; j++) {
textblock->addText(strdup(words[j]), wordStyle);
void addText(const char *text, size_t len, core::style::Style *style)
Add a word to the page structure.

Notice the strdup, dw::Textblock::addText will feel responsible for the string, and free the text at the end. (This has been done to avoid some overhead in the HTML parser.)

The rest is simple, it also includes spaces (which also have styles):

textblock->addSpace(wordStyle);
}
void addSpace(core::style::Style *style)
?

Finally, a paragraph break is added, which is 10 pixels high:

textblock->addParbreak(10, wordStyle);
}
void addParbreak(int space, core::style::Style *style)
Cause a paragraph break.

Again, this style should be unreferred:

wordStyle->unref();

After adding text, this method should always be called (for faster adding large text blocks):

textblock->flush ();

Some FLTK stuff to finally show the window:

window->resizable(viewport);
window->show();
int errorCode = Fl::run();

For cleaning up, it is sufficient to destroy the layout:

delete layout;

And the rest

return errorCode;
}

If you compile and start the program, you should see the following:

Try to scroll, or to resize the window, you will see, that everything is done automatically.

Of course, creating new widgets, adding text to widgets etc. can also be done while the program is running, i.e. after fltk::run has been called, within timeouts, idles, I/O functions etc. Notice that Dw is not thread safe, so that everything should be done within one thread.

With the exception, that you have to call dw::Textblock::flush, everything gets immediately visible, within reasonable times; Dw has been optimized for frequent updates.

List of all Widgets

These widgets are used within dillo:

If you want to create a new widget, refer to Layout and Widgets.

List of Views

There are three dw::core::View implementations for FLTK:

More informations about views in general can be found in Layout and Views.

Iterators

For examining generally the contents of widgets, there are iterators (dw::core::Iterator), created by the method dw::core::Widget::iterator (see there for more details).

These simple iterators only iterate through one widget, and return child widgets as dw::core::Content::WIDGET. The next call of dw::core::Iterator::next will return the piece of contents after (not within) this child widget.

If you want to iterate through the whole widget trees, there are two possibilities:

  1. Use a recursive function. Of course, with this approach, you are limited by the program flow.

  2. Maintain a stack of iterators, so you can freely pass this stack around. This is already implemented, as dw::core::DeepIterator.

As an example, dw::core::SelectionState represents the selected region as two instances of dw::core::DeepIterator.

Finding Text

See dw::core::Layout::findtextState and dw::core::FindtextState (details in the latter). There are delegation methods:

Anchors and Scrolling

In some cases, it is necessary to scroll to a given position, or to an anchor, programmatically.

Anchors

Anchors are defined by widgets, e.g. dw::Textblock defines them, when dw::Textblock::addAnchor is called. To jump to a specific anchor within the current widget tree, use dw::core::Layout::setAnchor.

This can be done immediately after assignig a toplevel widget, even when the anchor has not yet been defined. The layout will remember the anchor, and jump to the respective position, as soon as possible. Even if the anchor position changes (e.g., when an anchor is moved downwards, since some space is needed for an image in the text above), the position is corrected.

As soon as the user scrolls the viewport, this correction is not done anymore. If in dillo, the user request a page with an anchor, which is quite at the bottom of the page, he may be get interested in the text at the beginning of the page, and so scrolling down. If then, after the anchor has been read and added to the dw::Textblock, this anchor would be jumped at, the user would become confused.

The anchor is dismissed, too, when the toplevel widget is removed again.

Todo:
Currently, anchors only define vertical positions.

Scrolling

To scroll to a given position, use the method dw::core::Layout::scrollTo. It expects several parameters:

  • a horizontal adjustment parameter, defined by dw::core::HPosition,
  • a vertical adjustment parameter, defined by dw::core::VPosition, and
  • a rectangle (x, y, width and heigh) of the region to be adjusted.

If you just want to move the canvas coordinate (x, y) into the upper left corner of the viewport, you can call:

// ...
void scrollTo(HPosition hpos, VPosition vpos, int x, int y, int width, int height)
Scrolls all viewports, so that the region [x, y, width, height] is seen, according to hpos and vpos.
Definition layout.cc:539
@ VPOS_TOP
Definition types.hh:27
@ HPOS_LEFT
Definition types.hh:17

By using dw::core::HPOS_NO_CHANGE or dw::core::VPOS_NO_CHANGE, you can change only one dimension. dw::core::HPOS_INTO_VIEW and dw::core::VPOS_INTO_VIEW will cause the viewport to move as much as necessary, that the region is visible in the viewport (this is e.g. used for finding text).

Further Documentations