summaryrefslogtreecommitdiff
path: root/doc/dw-out-of-flow.doc
blob: 2a43b876a3548784280496411ee2cf48f26cdead (plain)
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
/** \page dw-out-of-flow Handling Elements Out Of Flow

<div style="border: 2px solid #ff4040; margin-bottom: 0.5em;
padding: 0.5em 1em; background-color: #fff0f0"><b>Info:</b>
Not up to date; incorporate these two changes: (i) there are different
containing blocks for floats and absolutely (furthermore also fixedly)
positioned elements; (ii) dw::OutOfFlowMgr is now only the base class;
floats and absolutely positioned elements are seperated:
\dot
digraph G {
   node [shape=record, fontname=Helvetica, fontsize=10];
   edge [arrowhead="none", arrowtail="empty", dir="both"];
   fontname=Helvetica; fontsize=8;

   OutOfFlowMgr [URL="\ref dw::oof::OutOfFlowMgr"];
   OOFFloatsMgr [URL="\ref dw::oof::OOFFloatsMgr"];
   OOFPositionedMgr [URL="\ref dw::oof::OOFPositionedMgr"];
   OOFPosAbsLikeMgr [URL="\ref dw::oof::OOFPosAbsLikeMgr"];
   OOFPosAbsMgr [URL="\ref dw::oof::OOFPosAbsMgr"];
   OOFPosFixedMgr [URL="\ref dw::oof::OOFPosFixedMgr"];
   OOFPosRelMgr [URL="\ref dw::oof::OOFPosRelMgr"];

   OutOfFlowMgr -> OOFFloatsMgr;
   OutOfFlowMgr -> OOFPositionedMgr;
   OOFPositionedMgr -> OOFPosAbsLikeMgr;
   OOFPosAbsLikeMgr -> OOFPosAbsMgr;
   OOFPosAbsLikeMgr -> OOFPosFixedMgr;  
   OOFPositionedMgr -> OOFPosRelMgr;
}
\enddot
</div>

Introduction
============

This texts deals with both floats and absolute positions, which have
in common that there is a distinction between generating block and
containing block (we are here using the same notation as in the
CSS&nbsp;2 specification). Consider this snippet (regarding floats):


    <ul>
      <li>Some text.</li>
      <li>
        <div style="float:right; width=50%">Some longer text, so
          that the effect described in this passage can be
          demonstrated.
        </div>
        Some more and longer text.</li>
      <li>Final text. Plus some more to demonstrate how text flows
        around the float on the right side.</li>
    </ul>

which may be rendered like this

\image html dw-floats-01.png

The float (the DIV section, yellow in the image) is defined
("generated") within the list item (blue), so, in CSS 2 terms, the
list item is the generating block of the float. However, as the image
shows, the float is not contained by the list item, but another block,
several levels above (not shown here). In terms of ::dw, this means
that the dw::Textblock representing the float cannot be a child of the
dw::Textblock representing the generating block, the list item, since
the allocation of a child widget must be within the allocation of the
parent widget. Instead, to each dw::Textblock, another dw::Textblock
is assigned as the containing box.

(Notice also that other text blocks must regard floats to calculate
their borders, and so their size. In this example, the following list
item (green) must consider the position of the float. This is
discussed in detail in the next section.)

Both in this text and the code, generating and containing block are
abbreviated with **GB** and **CB**, respectively.


Implementation overview
=======================

Widget level
------------
The terms *generating block* and *containing block* have been raised
to a higher level, the one of dw::core::Widget, and are here called
*generating widget* and *containing widget*. To represent the
distinction, the type of dw::core::Content has been split into three
parts:

- If a widget is out of flow, the generating widget keeps a reference
  with the type dw::core::Content::WIDGET_OOF_REF, while the
  containing block refers to it as dw::core::Content::WIDGET_OOF_CONT.
- For widgets within flow, dw::core::Content::WIDGET_IN_FLOW is used.

Notice that in the first case, there are two pieces of content
referring to the same widget.

An application of this distinction is iterators. [TODO: more. And
still missing: DeepIterator may need the generating parent widget in
some cases.]


Textblock level
---------------
Both dw::Textblock::notifySetAsTopLevel and
dw::Textblock::notifySetParent set the member
dw::Textblock::containingBlock appropriately, (according to rules
which should be defined in this document).

Handling widgets out of flow is partly the task of the new class
dw::OutOfFlowMgr, which is stored by dw::Textblock::outOfFlowMgr, but
only for containing blocks. Generating blocks should refer to
*containingBlock->outOfFlowMgr*. (Perhaps dw::OutOfFlowMgr may become
independent of dw::Textblock.)

dw::Textblock::addWidget is extended, so that floats and absolutely
positioned elements can be added. Notice that not *this* widget, but
the containing block becomes the parent of the newly added child, if
it is out of flow. dw::Textblock::addWidget decides this by calling
dw::OutOfFlowMgr::isOutOfFlow. (See new content types above.)

dw::core::Widget::parentRef has become a new representation. Before,
it represented the line numer. Now (least signifant bit left):

    +---+ - - - +---+---+- - - - - -+---+---+---+---+
    |                line number                | 0 |
    +---+ - - - +---+---+- - - - - -+---+---+---+---+

    +---+ - - - +---+---+- - - - - -+---+---+---+---+
    |          left float index         | 0 | 0 | 1 |
    +---+ - - - +---+---+- - - - - -+---+---+---+---+

    +---+ - - - +---+---+- - - - - -+---+---+---+---+
    |         right float index         | 1 | 0 | 1 |
    +---+ - - - +---+---+- - - - - -+---+---+---+---+

    +---+ - - - +---+---+- - - - - -+---+---+---+---+
    |      absolutely positioned index      | 1 | 1 |
    +---+ - - - +---+---+- - - - - -+---+---+---+---+

Details are hidden by static inline methods of dw::OutOfFlowMgr.


The sizeRequest/sizeAllocate problem
========================================

*See also:* \ref dw-widget-sizes, especially the section *Rules for
Methods Related to Resizing*.

The size/position model of ::dw consists mainly of the following two
steps:

1. First, the size of the toplevel widget is calculated. Size
   calculation typically depends on the sizes of the widgets, which
   are calculated recursively, but not more.
2. After this, the toplevel widget is allocated at position (0, 0),
   with the previosly calculated size. Each widget must allocate its
   children; here, the condition for the toplevel widget (allocated
   size equals requested size) is not necessary; instead, each widget
   may be allocated at every size.

Especially for floats, this model becomes a bit difficult, for reasons
described below. For the solutions, much is centralized at the level
of the containing block, which delegates most to an instance of
dw::OutOfFlowMgr (details below).

**The size of a widget depends on the size not only of the children.**
In the example above, the last list item (green, following the
generating list item) must know the size of the the float (which is
not a child or, generally, descendant) to determine the borders, which
is done in dw::Textblock::sizeRequestImpl.

For this, the size model has been extended (see \ref dw-widget-sizes,
section *Rules for Methods Related to Resizing*): *sizeRequest* can be
called within *sizeRequestImpl* for other widgets that children (with
some caution). Namely, dw::Textblock::sizeRequestImpl calls
dw::core::Widget::sizeRequest for the float, via
dw::OutOfFlowMgr::getBorder and dw::OutOfFlowMgr::ensureFloatSize.

**The size of a widget depends on the allocation of another widget.**
In the example above, both list items (blue and green) must know the
position of the float widget, within dw::Textblock::sizeRequestImpl,
to calculate the borders. The position, however, is stored in the
allocation, which is typically calculated later.

Here, two cases must be distinguished. The position of a float is
always **relative to its generating block**, so for calculating the
borders for the generating block, the allocation needs not to be
know. For other textblocks, it needs to be known, so the calculation
of the borders will ignore floats generated by other textblocks, until
all widgets are allocated. The latter will call (when neccessary)
dw::core::Widget::queueResize, so that all border calculations are
repeated. See below (*hasRelationChanged*) for details.

Generally, this pattern (distinguishing between GB and CB) can be
found everywhere in dw::OutOfFlowMgr.

For details see:

- dw::OutOfFlowMgr::getLeftBorder, dw::OutOfFlowMgr::getRightBorder,
  dw::OutOfFlowMgr::getBorder (called by the first two), and
  especially, dw::OutOfFlowMgr::getFloatsListForTextblock (called by
  the latter), where these three cases are distinguished;
- dw::OutOfFlowMgr::sizeAllocateStart,
  dw::OutOfFlowMgr::sizeAllocateEnd which are called by the containing
  block.

(This could be solved in a more simple, elegant way, when
*sizeRequest* would depend on the position. This is, however, only a
vague idea, perhaps not even feasible, and for which there are no
concrete plans, certainly not in \ref dw-grows.)


Implementation details
======================

- CB and GB lists (general pattern) (see previous section)
- binary search; different search criteria, how they accord
- lastLeftTBIndex, lastRightTBIndex etc.
- limitiation of search; extIndex etc.


How *hasRelationChanged* works
==============================

...


Integration of line breaking and floats
=======================================

(Positioning of floats, loop, recent works.)


Absolute and fixed positiones
=============================

To be documented.


See also
========

→ \ref dw-miscellaneous.

*/