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
374
375
376
377
378
379
380
381
382
383
|
Jan 2001, S.Geerken@ping.de
Last update: Dec 2004
================
Dw: Dillo Widget
================
NOTE (Aug 2004): The rendering has changed quite much, and many other
documents are out of date, in ways described in DwRendering.txt. They
will be updated some day.
Dw is mainly the module for rendering HTML. It provides a framework
for widgets, based on the Gtk+ object framework, and is very similar
to Gtk+, so that experiences in using and extending Gtk+ help very
much in understanding Dw. There is some documentation at www.gtk.org
(and probably on your local harddisk, somewhere in /usr/doc/*gtk*),
you should especially have read the chapter "Writing Your Own
Widgets" in the tutorial.
Why Not Gtk+?
=============
There are two reasons for designing a new model instead of simply
using Gtk+ objects:
1. Most important, Gtk+ widgets are limited in size, because X
windows are so.
2. There are a few extensions which are due to the different needs
for HTML rendering compared to GUI's. (Of course, this could
have been solved by defining a new object derived from
GtkWidget.)
Notes On Naming
===============
According to the naming standards, functions beginning with "a_Dw_"
may be used outside of Dw, while, as an extention, functions used
within Dw (e.g. p_Dw_widget_queue_resize) are prefixed with "p_Dw_".
[todo: This could be included in NC_design.txt.]
Non-static functions beginning with "Dw_" are only used between
GtkDwViewport and DwWidget (e.g. Dw_gtk_viewport_remove_dw), they
belong to the core of Dw. And, of course, functions only used within a
sub-module (e.g. a specific widget) start with "Dw_" and are static
(e.g. Dw_page_find_line_index).
Dw widgets and some other structures have the prefix "Dw", while Gtk+
widgets in Dw have the prefix "GtkDw", but functions of them begin
with "Dw_gtk_" or "a_Dw_gtk", respectively.
Basic Overview
==============
Dw widgets are objects derived from DwWidget, which itself derives
from GtkObject. DwWidget is quite similar to GtkWidget, the main
difference is that Dw widgets are always windowless and that they are
presented in a viewport, so there is no need to limit the size. Much
of the functionality normally provided by the X server is simulated
by Dw.
The interface between Gtk+ and Dw is the Gtk+ widget GtkDwViewport,
which contains (at most) one top-level Dw widget.
A Few Definitions:
- world coordinates: coordinates relative to the upper left corner
of the whole scrolled area ("the world")
- viewport coordinates: coordinates relative to the upper left
corner of the visible area
- widget coordinates: coordinates relative to the upper left corner
of the widget
Dw widgets draw into the viewport window, and must adhere to
*viewport coordinates*: the "world" is only an abstract term, there
is no window for it. When GtkDwViewport processes expose events, they
are automatically delivered to the Dw widgets. Redrawing requests due
to scrolling of the viewport is done by the base object GtkLayout,
you will not find any code for this in Dw.
Mouse events also contain viewport coordinates. Dw will try to find
the right Dw widget to deliver the event to.
Resizing the GtkDwViewport will not resize the top-level Dw widget,
but the latter will get some hints, so that, e.g., the page widget
rewraps the lines at the appropriate width.
See DwWidget.txt for more details.
Embedding Gtk+ Widgets In Dw
----------------------------
Dw Widgets may embed Gtk+ widgets, this is done by the Dw widget
DwEmbedGtk. For Gtk+, these embedded Gtk+ widgets are themselves
children of the GtkDwViewport, since Gtk+ does not care about Dw.
Of course, embedded Gtk+ widgets are again limited in size, but but
in position: GtkDwViewport is derived from GtkLayout which is exactly
designed for positioning widgets in an infinite scrolled area.
How To Get The Top-Level Dw Widget From A BrowserWindow
-------------------------------------------------------
The member "docwin" of BrowserWindow points on a GtkDwScrolledWindow,
which contains a GtkDwScrolledFrame, which contains a GtkDwViewport.
The member "child" of the latter points on the top-level Dw widget,
or may be NULL. The top-level Dw is (currently) a DwPage (HTML and
plain text documents) or a DwImage (images).
There is a function a_Dw_gtk_scrolled_window_get_dw for this.
Sizes
-----
A feature adapted from the old Dw are baselines. As well DwAllocation
as DwRequisition do not have a height member, but instead ascent and
descent, both positive or zero. (Originally I removed this, but there
will be a few widgets in future depending on this, e.g., math
formulas.)
Unlike in Gtk, sizes of zero are allowed. The upper limit for the
size of a widget is 2^31 (this will be enough to show the contents of
a small library in a web page).
Resizing
========
From outside: When writing a new widget, you should implement the
signal "size_request". When the widget changes its size, it should
call p_Dw_widget_queue_resize, as in a_Dw_image_size. See "Incremental
Resizing" below for a way to increase the speed.
Even if the implementation of "size_request" gets quite expensive,
you do not have to check whether the size has changed, this is done
by a_Dw_widget_size_request.
Inside: q_Dw_widget_queue_resize will set the DW_NEEDS_RESIZE flag, a
further call of a_Dw_widget_size_request will only then emit the
"size_request" signal. Furthermore, mark_size_change and
mark_extremes_change are called (see below). After that, the resizing
is done in an idle loop, this prevents too many size requests. The
algorithm is quite simple: any widget with a child which needs
resizing, needs resizing, thus all parents up to top-level widget are
marked.
Incremental Resizing
---------------------
A widget may calculate its size based on size calculations already
done before. In this case, a widget must exactly know the reasons, why
a call of size_request is necessary. To make use of this, a widget
must implement the following:
1. There is a member in DwWidget, called parent_ref, which is
totally under control of the parent widget (and so sometimes not
used at all). It is necessary to define how parent_ref is used
by a specific parent widget, and it has to be set to the correct
value whenever necessary.
2. The widget must implement mark_size_change and
mark_extremes_change, these methods are called in two cases:
a) directly after q_Dw_widget_queue_resize, with the argument
ref was passed to q_Dw_widget_queue_resize, and
b) if a child widget has called q_Dw_widget_queue_resize,
with the value of the parent_ref member of this child.
This way, a widget can exactly keep track on size changes, and so
implement resizing in a faster way. A good example on how to use this
is the DwPage widget, see DwPage.txt for details.
Anchors and Scrolling
=====================
Anchors
-------
todo: This section is out of sync with the actual code.
To set the anchor a page is viewed at, you can use one of the
following functions:
- void a_Dw_gtk_viewport_set_anchor (GtkDwViewport *viewport,
gchar *anchor)
Scroll directly to an anchor. The anchor does not need to exist
already, see below.
- void a_Dw_gtk_viewport_queue_anchor (GtkDwViewport *viewport,
gchar *anchor)
Set the anchor for the next top-level DwWidget (the next call
of a_Dw_gtk_viewport_add_dw).
There are wrappers, a_Dw_gtk_scrolled_window_queue_anchor and
a_Dw_gtk_scrolled_window_set_anchor.
After a_Dw_gtk_viewport_set_anchor has been called (indirectly by
Nav_open_url, or by a_Dw_gtk_viewport_add_dw), changes of anchor
positions (e.g., if widgets change there size or the anchor was not
known before) will correct the viewport adjustment (in function
p_Dw_gtk_viewport_update_anchor), but only as long as the user did not
change it directly. Look at Dw_gtk_scrolled_window_init for details
about the latter.
Use p_Dw_widget_set_anchor to add anchors to a widget, see
DwWidget.txt.
Scrolling
---------
Here is an overview on more functions for scrolling:
- To scroll to a given position, there are two possibilities:
a_Dw_gtk_viewport_set_scrolling_position simply scrolls to this
position, while Dw_gtk_viewport_scroll_to has more facilities:
you specify a rectangle you want to see, and the way how it is
seen (at the border, centered, or just scroll as much as
necessary, that it is seen). If you have a widget, you can also
use Dw_widget_scroll_to. There is also a wrapper for
GtkDwScrolledWindow,
a_Dw_gtk_scrolled_window_set_scrolling_position, and two
functions for getting the position,
a_Dw_gtk_scrolled_window_get_scrolling_position_x, and
a_Dw_gtk_scrolled_window_get_scrolling_position_y.
- If you have a region, and want to display it, use
a_Dw_iterator_scroll_to. For example, the findtext module makes
use of it. There are equivalents for DwExtIterator and
DwWordIterator. See comments on and in the function for more
informations.
- If you just want to determine where some content is allocated,
represented by an iterator, you can use
a_Dw_iterator_get_allocation. There are equivalents for
DwExtIterator and DwWordIterator.
The Objects
===========
This is the hierarchy of all objects of Dw:
(GtkObject)
+-DwWidget
| +----DwBullet
| +----DwContainer
| | `----DwPage
| +----DwEmbedGtk
| +----DwHruler
| `----DwImage
`----(GtkWidget)
`----(GtkContainer)
+----(GtkBin)
| +----(GtkScrolledWindow)
| | `----GtkDwScrolledWindow
| `----GtkDwScrolledFrame
`----(GtkLayout)
`----GtkDwViewport
Objects in parentheses are part of Gtk+, not of Dw.
DwBullet
--------
Simple widget used for unnumbered list (<ul>).
DwContainer
-----------
The base object for Dw widgets which contain other Dw widgets. As in
Gtk+, containers are responsible for storing the children, there is
no common data structure. There are a few signals:
- void add (DwContainer *container,
DwWidget *child);
Currently not used, but may be in future.
- void remove (DwContainer *container,
DwWidget *widget);
*Recognize* that a widget is destroyed, i.e., an implementation
should remove *the pointer* from the list or so, but not
destroy the child widget. It is called by Dw_widget_shutdown.
- void forall (DwContainer *container,
DwCallback callback,
gpointer callback_data);
Process callback for all children, in the form
(*callback)(child, callback_data).
The include_internals of the Gtk+ equivalent was not adapted,
since it is used for more sophisticated purposes not needed in
Dw.
DwEmbedGtk
----------
This Dw widget is used to embed Gtk+ widgets into Dw container
widgets. The Gtk+ widget is set by a_Dw_embed_gtk_add_gtk, and can
simply be removed by destroying it.
If the DwEmbedGtk contains no Gtk+ widget, it always returns 0x0x0 as
size, so, for speed reasons, first add the Gtk+ widget into the
DwEmbedGtk, and then the DwEmbedGtk into the other Dw widget, as at
the end of Html_tag_open_input.
DwHruler
--------
Simple widget used for the <hr> tag.
DwImage
-------
Widget for displaying image. See DwImage.txt for details.
DwPage
------
A widget for displaying texts. See DwPage.txt for details.
DwTable
-------
A container widget for rendering tables. See DwTable.txt for details.
DwWidget
--------
The base object for all Dw widgets. See DwWidget.txt for details.
GtkDwScrolledWindow
-------------------
Adds a few functionalities to GtkScrolledWindow: it creates the
GtkDwScrolledFrame and the GtkDwViewport, connects some signals, and
provides some wrappers for using the GtkDwViewport.
GtkDwScrolledFrame
------------------
General purpose scrolled widget containing another scrolled widget,
adding a border and a focus frame. Furthermore, it processes key
presses and mouse drags (button 2, as in Gimp) to move the viewport.
There are two signals (except "set_scroll_adjustments"),
"user_hchanged" and "user_vchanged", which are emitted when the user
changed the viewport adjustments horizontally/vertically by using the
keys or button 2 dragging.
GtkDwViewport
-------------
The interface between Gtk+ and Dw. It is responsible for displaying
Dw Widgets and processing their events. It is derived from GtkLayout,
to make embedding Gtk+ widgets into Dw widgets simpler, see the
documentation of GtkLayout in the Gtk+ tutorial for details.
GtkDwViewport contains at most one top-level Dw Widget, if it exists.
The Gtk+ methods of GtkDwViewport are more or less mapped on the
methods of the DwWidget. In detail:
- Dw_gtk_viewport_size_allocate will call a_Dw_widget_set_width,
a_Dw_widget_set_ascent (with allocation->height) and
a_Dw_widget_set_descent (with zero as argument), and then allocate
the Dw widget at the size returned by a_Dw_widget_size_request.
- Dw_gtk_viewport_draw and Dw_gtk_viewport_expose will call
a_Dw_widget_draw, which will emit the "draw" signal.
- Handling of mouse events is mostly done in Dw_widget_mouse_event,
see DwWidget.txt for details. Note that the functions return
FALSE, if the event was not processed, so that they are delivered
to the parent widget(s) of the GtkDwViewport, this scheme e.g.
prevents dragging of the viewport (done by GtkScrolledFrame) when
pressing mouse button 2 on a link.
You may call gtk_container_set_border_width for a border around the
scrolled area.
|