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
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.8"/>
<title>Dillo: Sizes of Dillo Widgets</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="https://www.dillo.org/dw/html/jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td style="padding-left: 0.5em;">
<div id="projectname">Dillo
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.8 -->
<div id="navrow1" class="tabs">
<ul class="tablist">
<li><a href="index.html"><span>Main Page</span></a></li>
<li class="current"><a href="pages.html"><span>Related Pages</span></a></li>
<li><a href="namespaces.html"><span>Namespaces</span></a></li>
<li><a href="annotated.html"><span>Classes</span></a></li>
<li><a href="files.html"><span>Files</span></a></li>
</ul>
</div>
</div><!-- top -->
<div class="header">
<div class="headertitle">
<div class="title">Sizes of Dillo Widgets </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><div style="border: 2px solid #ffff00; margin: 1em 0;
padding: 0.5em 1em; background-color: #ffffe0">The complex "widget
sizes" is currently divided into three documents: <b>Sizes of Dillo Widgets</b> (this document), <a class="el" href="dw-grows.html">GROWS - Grand Redesign Of Widget Sizes</a>, and <a class="el" href="dw-size-request-pos.html">Size requisitions depending on positions</a>. </div><div style="border: 2px solid #ff4040; margin: 1em 0;
padding: 0.5em 1em; background-color: #fff0f0"><b>Info:</b> Not up to date, see other documents.</div><h1>Allocation </h1>
<p>Each widget has an <em>allocation</em> at a given time, this includes</p>
<ul>
<li>the position (<em>x</em>, <em>y</em>) relative to the upper left corner of the canvas, and</li>
<li>the size (<em>width</em>, <em>ascent</em>, <em>descent</em>).</li>
</ul>
<p>The <em>canvas</em> is the whole area available for the widgets, in most cases, only a part is seen in a viewport. The allocation of the toplevel widget is exactly the allocation of the canvas, i.e.</p>
<ul>
<li>the position of the toplevel widget is always (0, 0), and</li>
<li>the canvas size is defined by the size of the toplevel widget.</li>
</ul>
<p>The size of a widget is not simply defined by the width and the height, instead, widgets may have a base line, and so are vertically divided into an ascender (which height is called <em>ascent</em>), and a descender (which height is called <em>descent</em>). The total height is so the sum of <em>ascent</em> and <em>descent</em>.</p>
<p>Sizes of zero are allowed. The upper limit for the size of a widget is defined by the limits of the C++ type <em>int</em>.</p>
<div class="image">
<img src="dw-size-of-widget.png" alt="dw-size-of-widget.png"/>
<div class="caption">
Allocation of a Widget</div></div>
<p>In the example in the image, the widget has the following allocation:</p>
<ul>
<li><em>x</em> = 50</li>
<li><em>y</em> = 50</li>
<li><em>width</em> = 150</li>
<li><em>ascent</em> = 150</li>
<li><em>descent</em> = 100</li>
</ul>
<p>The current allocation of a widget is hold in <a class="el" href="classdw_1_1core_1_1Widget.html#a2212fc4b9b2b0e26c7345f1b4adb7d28" title="The current allocation: size and position, always relative to the canvas. ">dw::core::Widget::allocation</a>. It can be set from outside by calling <a class="el" href="classdw_1_1core_1_1Widget.html#a0fa3284a21b20bd79f7de13bc0aca5e4" title="Wrapper for Widget::sizeAllocateImpl, calls the latter only when needed. ">dw::core::Widget::sizeAllocate</a>. This is a concrete method, which will call <a class="el" href="classdw_1_1core_1_1Widget.html#a756379942a5254e22c087f6bb62a23a5" title="See Sizes of Dillo Widgets. ">dw::core::Widget::sizeAllocateImpl</a> (see code of <a class="el" href="classdw_1_1core_1_1Widget.html#a0fa3284a21b20bd79f7de13bc0aca5e4" title="Wrapper for Widget::sizeAllocateImpl, calls the latter only when needed. ">dw::core::Widget::sizeAllocate</a> for details).</p>
<p>For trivial widgets (like <a class="el" href="classdw_1_1Bullet.html" title="Displays different kind of bullets. ">dw::Bullet</a>), <a class="el" href="classdw_1_1core_1_1Widget.html#a756379942a5254e22c087f6bb62a23a5" title="See Sizes of Dillo Widgets. ">dw::core::Widget::sizeAllocateImpl</a> does not need to be implemented. For more complex widgets, the implementation should call <a class="el" href="classdw_1_1core_1_1Widget.html#a0fa3284a21b20bd79f7de13bc0aca5e4" title="Wrapper for Widget::sizeAllocateImpl, calls the latter only when needed. ">dw::core::Widget::sizeAllocate</a> (not <a class="el" href="classdw_1_1core_1_1Widget.html#a756379942a5254e22c087f6bb62a23a5" title="See Sizes of Dillo Widgets. ">dw::core::Widget::sizeAllocateImpl</a>) on all child widgets, with appropriate child allocations. <a class="el" href="classdw_1_1core_1_1Widget.html#a2212fc4b9b2b0e26c7345f1b4adb7d28" title="The current allocation: size and position, always relative to the canvas. ">dw::core::Widget::allocation</a> should not be changed here, this is already done in <a class="el" href="classdw_1_1core_1_1Widget.html#a0fa3284a21b20bd79f7de13bc0aca5e4" title="Wrapper for Widget::sizeAllocateImpl, calls the latter only when needed. ">dw::core::Widget::sizeAllocate</a>.</p>
<h1>Requisitions </h1>
<p>A widget may prefer a given size for the allocation. This size, the <em>requisition</em>, should be returned by the method <a class="el" href="classdw_1_1core_1_1Widget.html#ac3764607155e58daee03db5cbb76d8e2" title="See Sizes of Dillo Widgets. ">dw::core::Widget::sizeRequestImpl</a>. In the simplest case, this is independent of the context, e.g. for an image. <a class="el" href="classdw_1_1core_1_1Widget.html#ac3764607155e58daee03db5cbb76d8e2" title="See Sizes of Dillo Widgets. ">dw::Image::sizeRequestImpl</a> returns the following size:</p>
<ul>
<li>If no buffer has yet been assigned (see <a class="el" href="classdw_1_1Image.html" title="Displays an instance of dw::core::Imgbuf. ">dw::Image</a> for more details), the size necessary for the alternative text is returned. If no alternative text has been set, zero is returned.</li>
<li>If a buffer has been assigned (by <a class="el" href="classdw_1_1Image.html#aba1218df074496b12176464c43022f7c" title="Called, when an image buffer is attached. ">dw::Image::setBuffer</a>), the root size is returned (i.e. the original size of the image to display).</li>
</ul>
<p>This is a bit simplified, <a class="el" href="classdw_1_1core_1_1Widget.html#ac3764607155e58daee03db5cbb76d8e2" title="See Sizes of Dillo Widgets. ">dw::Image::sizeRequestImpl</a> should also deal with margins, borders and paddings, see <a class="el" href="namespacedw_1_1core_1_1style.html" title="Anything related to Dillo Widget styles is defined here. ">dw::core::style</a>.</p>
<p>From the outside, <a class="el" href="classdw_1_1core_1_1Widget.html#a34dcfd744c6eec49fa87baaa8591896e" title="This method is a wrapper for Widget::sizeRequestImpl(); it calls the latter only when needed...">dw::Image::sizeRequest</a> should be called, which does a bit of optimization. Notice that in <a class="el" href="classdw_1_1core_1_1Widget.html#ac3764607155e58daee03db5cbb76d8e2" title="See Sizes of Dillo Widgets. ">dw::Image::sizeRequestImpl</a>, no optimization like lazy evaluation is necessary, this is already done in <a class="el" href="classdw_1_1core_1_1Widget.html#a34dcfd744c6eec49fa87baaa8591896e" title="This method is a wrapper for Widget::sizeRequestImpl(); it calls the latter only when needed...">dw::Image::sizeRequest</a>.</p>
<p>A widget, which has children, will likely call <a class="el" href="classdw_1_1core_1_1Widget.html#a34dcfd744c6eec49fa87baaa8591896e" title="This method is a wrapper for Widget::sizeRequestImpl(); it calls the latter only when needed...">dw::Image::sizeRequest</a> on its children, to calculate the total requisition.</p>
<p>The caller (this is either the <a class="el" href="classdw_1_1core_1_1Layout.html" title="The central class for managing and drawing a widget tree. ">dw::core::Layout</a>, or the parent widget), may, but also may not consider the requisition. Instead, a widget must deal with any allocation. (For example, <a class="el" href="classdw_1_1Image.html" title="Displays an instance of dw::core::Imgbuf. ">dw::Image</a> scales the image buffer when allocated at another size.)</p>
<h1>Size Hints </h1>
<div style="border: 2px solid #ff4040; margin-bottom: 0.5em;
padding: 0.5em 1em; background-color: #fff0f0"><b>Info:</b> Size hints have been removed, see <a class="el" href="dw-grows.html">GROWS - Grand Redesign Of Widget Sizes</a>.</div><h1>Width Extremes </h1>
<p><a class="el" href="classdw_1_1Table.html" title="A Widget for rendering tables. ">dw::Table</a> uses width extremes for fast calculation of column widths. The structure <a class="el" href="structdw_1_1core_1_1Extremes.html">dw::core::Extremes</a> represents the minimal and maximal width of a widget, as defined by:</p>
<ul>
<li>the minimal width is the smallest width, at which a widget can still display contents, and</li>
<li>the maximal width is the largest width, above which increasing the width- does not make any sense.</li>
</ul>
<p>Especially the latter is vaguely defined, here are some examples:</p>
<ul>
<li>For those widgets, which do not depend on size hints, the minimal and the maximal width is the inherent width (the one returned by <a class="el" href="classdw_1_1core_1_1Widget.html#a34dcfd744c6eec49fa87baaa8591896e" title="This method is a wrapper for Widget::sizeRequestImpl(); it calls the latter only when needed...">dw::core::Widget::sizeRequest</a>).</li>
<li>For a textblock, the minimal width is the width of the widest (unbreakable) word, the maximal width is the width of the total paragraph (stretching a paragraph further would only waste space). Actually, the implementation of <a class="el" href="classdw_1_1core_1_1Widget.html#a984eb786b8d9c9bf63cfd24bdf465e6f" title="See Sizes of Dillo Widgets. ">dw::Textblock::getExtremesImpl</a> is a bit more complex.</li>
<li><a class="el" href="classdw_1_1Table.html" title="A Widget for rendering tables. ">dw::Table</a> is an example, where the width extremes are calculated from the width extremes of the children.</li>
</ul>
<p>Handling width extremes is similar to handling requisitions, a widget must implement <a class="el" href="classdw_1_1core_1_1Widget.html#a984eb786b8d9c9bf63cfd24bdf465e6f" title="See Sizes of Dillo Widgets. ">dw::core::Widget::getExtremesImpl</a>, but a caller will use <a class="el" href="classdw_1_1core_1_1Widget.html#aec23092b0cfe5624b9751a59671fe251" title="Wrapper for Widget::getExtremesImpl(). ">dw::core::Widget::getExtremes</a>.</p>
<h1>Resizing </h1>
<p>When the widget changes its size (requisition), it should call <a class="el" href="classdw_1_1core_1_1Widget.html#ac00e44ccde79daf2b90247c352de67ef" title="This method should be called, when a widget changes its size. ">dw::core::Widget::queueResize</a>. The next call of <a class="el" href="classdw_1_1core_1_1Widget.html#ac3764607155e58daee03db5cbb76d8e2" title="See Sizes of Dillo Widgets. ">dw::core::Widget::sizeRequestImpl</a> should then return the new size. See <a class="el" href="classdw_1_1Image.html#aba1218df074496b12176464c43022f7c" title="Called, when an image buffer is attached. ">dw::Image::setBuffer</a> as an example.</p>
<p>Interna are described in the code of <a class="el" href="classdw_1_1core_1_1Widget.html#ac00e44ccde79daf2b90247c352de67ef" title="This method should be called, when a widget changes its size. ">dw::core::Widget::queueResize</a>.</p>
<h3>Incremental Resizing</h3>
<p>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 <a class="el" href="classdw_1_1core_1_1Widget.html#ac3764607155e58daee03db5cbb76d8e2" title="See Sizes of Dillo Widgets. ">dw::core::Widget::sizeRequestImpl</a> is necessary. To make use of this, a widget must implement the following:</p>
<ol type="1">
<li>There is a member <a class="el" href="classdw_1_1core_1_1Widget.html#a3a8324c1cc6859bd9bab133b44096f1b" title="This value is defined by the parent widget, and used for incremential resizing. ">dw::core::Widget::parentRef</a>, which is totally under control of the parent widget (and so sometimes not used at all). It is necessary to define how parentRef is used by a specific parent widget, and it has to be set to the correct value whenever necessary.</li>
<li>The widget must implement <a class="el" href="classdw_1_1core_1_1Widget.html#ac8b5d6fd4fe3868a154c638e66ad75a2" title="See Sizes of Dillo Widgets. ">dw::core::Widget::markSizeChange</a> and <a class="el" href="classdw_1_1core_1_1Widget.html#a30cb906a0382c1034bb398e7ea30a4a3" title="See Sizes of Dillo Widgets. ">dw::core::Widget::markExtremesChange</a>, these methods are called in two cases:<ol type="a">
<li>directly after <a class="el" href="classdw_1_1core_1_1Widget.html#ac00e44ccde79daf2b90247c352de67ef" title="This method should be called, when a widget changes its size. ">dw::core::Widget::queueResize</a>, with the argument ref was passed to <a class="el" href="classdw_1_1core_1_1Widget.html#ac00e44ccde79daf2b90247c352de67ef" title="This method should be called, when a widget changes its size. ">dw::core::Widget::queueResize</a>, and</li>
<li>if a child widget has called <a class="el" href="classdw_1_1core_1_1Widget.html#ac00e44ccde79daf2b90247c352de67ef" title="This method should be called, when a widget changes its size. ">dw::core::Widget::queueResize</a>, with the value of the parent_ref member of this child.</li>
</ol>
</li>
</ol>
<p>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 <a class="el" href="classdw_1_1Textblock.html" title="A Widget for rendering text blocks, i.e. paragraphs or sequences of paragraphs. ">dw::Textblock</a>.</p>
<h1>Rules for Methods Related to Resizing </h1>
<p>Which method can be called, when the call of another method is not finished? These rules are important in two circumstances:</p>
<ol type="1">
<li>To know which method can be called, and, especially, which methods must not* be called, within the implementation of sizeRequestImpl* (called by <em>sizeRequest</em>), <em>markSizeChange</em>, and markExtremesChange* (the latter two are called by <em>queueResize</em>).</li>
<li>On the other hand, to make sure that the calls, which are allowed, are handled correctly, especially in implementations of sizeRequestImpl*, <em>markSizeChange</em>, <em>markExtremesChange</em></li>
</ol>
<p>Generally, the rules defined below are, in case of doubt, rather strict; when changing the rules, loosening is simpler than to tighten them, since this will make it neccessary to review old code for calls previously allowed but now forbidden.</p>
<p>Short recap:</p>
<ul>
<li><em>QueueResize</em> directly calls <em>markSizeChange</em> and markExtremesChanges*, and queues an idle function for the actual resizing (<a class="el" href="classdw_1_1core_1_1Layout.html#a7792ba666460057e47208128719e4659">dw::core::Layout::resizeIdle</a>). (The idle function is called some time after <em>queueResize</em> is finished.)</li>
<li>The resize idle function first calls <em>sizeRequest</em>, then sizeAllocate*, for the toplevel widget.</li>
</ul>
<p>In the following table, the rules are defined in detail. "Within call
of ..." includes all methods called from the original method: the first row (<em>queueResize</em>) defines also the rules for markExtremesChanges* and <em>markExtremesChanges</em>, and in the second row (<em>sizeAllocate</em>), even <em>sizeRequest</em> has to be considered.</p>
<div style="border: 2px solid #ff4040; margin-bottom: 0.5em;
padding: 0.5em 1em; background-color: #fff0f0"><b>Info:</b> Not up to date: <em>queueResize</em> can now be called recursively (so to speak). See code there.</div><table class="doxtable">
<tr>
<th>Within call of ... ↓ </th><th>... is call allowed of ... ? → </th><th>queueResize </th><th>sizeAllocate </th><th>sizeRequest </th><th>getExtremes </th></tr>
<tr>
<th colspan="2">queueResize </th><td>No </td><td>No<sup>1</sup> </td><td>No<sup>1</sup> </td><td>No<sup>1</sup> </td></tr>
<tr>
<th colspan="2">sizeAllocate </th><td>Yes </td><td>Only for children<sup>2</sup> </td><td>Yes(?) </td><td>Yes(?) </td></tr>
<tr>
<th colspan="2">sizeRequest </th><td>Yes<sup>3</sup> </td><td>No </td><td>Limited<sup>4</sup> </td><td>Limited<sup>4</sup> </td></tr>
<tr>
<th colspan="2">getExtremes </th><td>Yes<sup>3</sup> </td><td>No </td><td>Limited<sup>4</sup> </td><td>Limited<sup>4</sup> </td></tr>
<tr>
<td colspan="6"><p class="starttd"><sup>1</sup>) Otherwise, since these other methods may be call <em>queueResize</em>, the limitation that <em>queueResize</em> must not call <em>queueResize</em> can be violated.</p>
<p><sup>2</sup>) Could perhaps be loosened as for <em>sizeRequest</em> and getExtremes*, but there is probably no need.</p>
<p><sup>3</sup>) Therefore the distinction between <em>RESIZE_QUEUED</em> and NEEDS_RESIZE*, and <em>EXTREMES_QUEUED</em> and <em>EXTREMES_CHANGED</em>, respectively.</p>
<p class="endtd"><sup>4</sup>) Calls only for children are safe. In other cases, you take a large responsibility to prevent endless recursions by (typically indirectly) calling <em>sizeRequest</em> / <em>getExtremes</em> for direct ancestors. </p>
</td></tr>
</table>
<p>Furthermore, <em>sizeAllocate</em> can only be called within a call of <a class="el" href="classdw_1_1core_1_1Layout.html#a207403098d5487ea6fdcd4b6d31cee5a">dw::core::Layout::resizeIdleId</a>, so (if you do not touch <a class="el" href="namespacedw_1_1core.html" title="The core of Dw is defined in this namespace. ">dw::core</a>) do not call it outside of <em>sizeAllocateImpl</em>. The other methods can be called outsize; e. g. <em>sizeRequest</em> is called in <a class="el" href="classdw_1_1Textblock.html#a1bebe0d704f071b07066bfb671cede7c">dw::Textblock::addWidget</a>.</p>
<p>To avoid painful debugging, there are some tests for the cases that one method call is strictly forbidden while another method is called.</p>
<p>This could be done furthermore:</p>
<ul>
<li>The tests could be refined.</li>
<li>Is it possible to define exacter rules, along with a proof that no problems (like endless recursion) can occur? </li>
</ul>
</div></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Sat May 28 2016 11:47:43 for Dillo by  <a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.8
</small></address>
</body>
</html>
|