1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
|
/** \page dw-usage Dillo Widget Usage
This document describes the usage of Dw, without going too much into
detail.
<h2>Getting Started</h2>
In this section, a small runnable example is described, based on the
FLTK implementation.
As described in \ref dw-overview, the following objects are needed:
<ul>
<li> dw::core::Layout,
<li> an implementation of dw::core::Platform (we will use
dw::fltk::FltkPlatform),
<li> at least one implementation of dw::core::View (dw::fltk::FltkViewport),
and
<li> some widgets (for this example, only a simple dw::Textblock).
</ul>
First of all, the necessary \#include's:
\code
#include <fltk/Window.h>
#include <fltk/run.h>
#include "dw/core.hh"
#include "dw/fltkcore.hh"
#include "dw/fltkviewport.hh"
#include "dw/textblock.hh"
\endcode
Everything is put into one function:
\code
int main(int argc, char **argv)
{
\endcode
As the first object, the platform is instantiated:
\code
dw::fltk::FltkPlatform *platform = new dw::fltk::FltkPlatform ();
\endcode
Then, the layout is created, with the platform attached:
\code
dw::core::Layout *layout = new dw::core::Layout (platform);
\endcode
For the view, we first need a FLTK window:
\code
fltk::Window *window = new fltk::Window(200, 300, "Dw Example");
window->begin();
\endcode
After this, we can create a viewport, and attach it to the layout:
\code
dw::fltk::FltkViewport *viewport =
new dw::fltk::FltkViewport (0, 0, 200, 300);
layout->attachView (viewport);
\endcode
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):
\code
dw::core::style::StyleAttrs styleAttrs;
styleAttrs.initValues ();
styleAttrs.margin.setVal (5);
\endcode
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:
\code
dw::core::style::FontAttrs fontAttrs;
fontAttrs.name = "Bitstream Charter";
fontAttrs.size = 14;
fontAttrs.weight = 400;
fontAttrs.style = dw::core::style::FONT_STYLE_NORMAL;
\endcode
Now, the font can be created:
\code
styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs);
\endcode
As the last attributes, the background and forground colors are
defined, here dw::core::style::Color::createSimple must be called:
\code
styleAttrs.color =
dw::core::style::Color::createSimple (layout, 0x000000);
styleAttrs.backgroundColor =
dw::core::style::Color::createSimple (layout, 0xffffff);
\endcode
Finally, the style for the widget is created:
\code
dw::core::style::Style *widgetStyle =
dw::core::style::Style::create (layout, &styleAttrs);
\endcode
Now, we create a widget, assign a style to it, and set it as the
toplevel widget of the layout:
\code
dw::Textblock *textblock = new dw::Textblock (false);
textblock->setStyle (widgetStyle);
layout->setWidget (textblock);
\endcode
The style is not needed anymore (a reference is added in
dw::core::Widget::setStyle), so it should be unreferred:
\code
widgetStyle->unref();
\endcode
Now, some text should be added to the textblock. For this, we first
need another style. \em styleAttrs can still be used for this. We set
the margin to 0, and the background color to "transparent":
\code
styleAttrs.margin.setVal (0);
styleAttrs.backgroundColor = NULL;
dw::core::style::Style *wordStyle =
dw::core::style::Style::create (layout, &styleAttrs);
\endcode
This loop adds some paragraphs:
\code
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);
\endcode
Notice the \em 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):
\code
textblock->addSpace(wordStyle);
}
\endcode
Finally, a paragraph break is added, which is 10 pixels high:
\code
textblock->addParbreak(10, wordStyle);
}
\endcode
Again, this style should be unreferred:
\code
wordStyle->unref();
\endcode
After adding text, this method should always be called (for faster
adding large text blocks):
\code
textblock->flush ();
\endcode
Some FLTK stuff to finally show the window:
\code
window->resizable(viewport);
window->show();
int errorCode = fltk::run();
\endcode
For cleaning up, it is sufficient to destroy the layout:
\code
delete layout;
\endcode
And the rest
\code
return errorCode;
}
\endcode
If you compile and start the program, you should see the following:
\image html dw-example-screenshot.png
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.
<h2>List of all Widgets</h2>
These widgets are used within dillo:
<ul>
<li>dw::core::ui::Embed
<li>dw::AlignedTextblock
<li>dw::Bullet
<li>dw::Ruler
<li>dw::Image
<li>dw::ListItem
<li>dw::Table
<li>dw::TableCell
<li>dw::Textblock
</ul>
If you want to create a new widget, refer to \ref dw-layout-widgets.
<h2>List of Views</h2>
There are three dw::core::View implementations for FLTK:
<ul>
<li> dw::fltk::FltkViewport implements a viewport, which is used in the
example above.
<li> dw::fltk::FltkPreview implements a preview window, together with
dw::fltk::FltkPreviewButton, it is possible to have a scaled down
overview of the whole canvas.
<li> dw::fltk::FltkFlatView is a "flat" view, i.e. it does not support
scrolling. It is used for HTML buttons, see
dw::fltk::ui::FltkComplexButtonResource and especially
dw::fltk::ui::FltkComplexButtonResource::createNewWidget for details.
</ul>
More informations about views in general can be found in \ref
dw-layout-views.
<h2>Iterators</h2>
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 \em after
(not within) this child widget.
If you want to iterate through the whole widget trees, there are two
possibilities:
<ol>
<li> Use a recursive function. Of course, with this approach, you are
limited by the program flow.
<li> Maintain a stack of iterators, so you can freely pass this stack
around. This is already implemented, as dw::core::DeepIterator.
</ol>
As an example, dw::core::SelectionState represents the selected region
as two instances of dw::core::DeepIterator.
<h2>Finding Text</h2>
See dw::core::Layout::findtextState and dw::core::FindtextState
(details in the latter). There are delegation methods:
<ul>
<li> dw::core::Layout::search and
<li> dw::core::Layout::resetSearch.
</ul>
<h2>Anchors and Scrolling</h2>
In some cases, it is necessary to scroll to a given position, or to
an anchor, programmatically.
<h3>Anchors</h3>
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.
<h3>Scrolling</h3>
To scroll to a given position, use the method
dw::core::Layout::scrollTo. It expects several parameters:
<ul>
<li>a horizontal adjustment parameter, defined by dw::core::HPosition,
<li>a vertical adjustment parameter, defined by dw::core::VPosition, and
<li>a rectangle (\em x, \em y, \em width and \em heigh) of the region
to be adjusted.
</ul>
If you just want to move the canvas coordinate (\em x, \em y) into the
upper left corner of the viewport, you can call:
\code
dw::core::Layout *layout;
// ...
layout->scrollTo(dw::core::HPOS_LEFT, dw::core::VPOS_TOP, 0, 0, 0, 0);
\endcode
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).
<h2>Further Documentations</h2>
<ul>
<li> dw::core::style
<li> dw::core::ui
<li> \ref dw-images-and-backgrounds
</ul>
*/
|