aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/dw-out-of-flow.doc409
-rw-r--r--doc/dw-widget-sizes.doc186
2 files changed, 527 insertions, 68 deletions
diff --git a/doc/dw-out-of-flow.doc b/doc/dw-out-of-flow.doc
new file mode 100644
index 00000000..b6f65a28
--- /dev/null
+++ b/doc/dw-out-of-flow.doc
@@ -0,0 +1,409 @@
+/** \page dw-out-of-flow Handling Elements Out Of Flow
+
+<div style="border: 2px solid #ffff00; margin-bottom: 0.5em;
+padding: 0.5em 1em; background-color: #ffffe0"><b>Info:</b>
+Should be incorporated into dw::Textblock.</div>
+
+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.</li>
+ </ul>
+
+which may be rendered like this
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - .
+ | * Some text.
+ * Some more and - - - - - - - - - - - -.|
+ | longer text. |Some longer text, so that
+ * Final text. the effect described ||
+ ` - - - - - - - - - - - |above in this passage can '
+ be demonstrated. |
+ ` - - - - - - - - - - - -
+
+The float (the DIV section) is defined ("generated") within the list
+item, 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.
+
+Definition of "containing block"
+================================
+
+The following definition follows the definition in the CSS 2
+specification. For a given dw::Textblock, the containing block is
+defined as the one dw::Textblock following these rules:
+
+- For the toplevel widget, the containing block is itself (see
+ dw::Textblock::notifySetAsTopLevel).
+
+- Otherwise, ... TODO: Has been changed; see
+ dw::Textblock::notifySetParent.
+
+TODO:
+
+1. Compare this to
+ <http://www.w3.org/TR/CSS2/visudet.html#containing-block-details>.
+2. Handle fixed positions: in this case, the viewport is the
+ containing box, but the viewport is not represented by a widget.
+3. Clarify: the element out of flow must not be a dw::Textblock.
+
+
+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 the rules
+defined above.
+
+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 |
+ +---+---+- - - - - - - - - - -+---+
+
+ +---+---+- - - - - - - - -+---+---+
+ | number of left float | 0 | 1 |
+ +---+---+- - - - - - - - -+---+---+
+
+ +---+---+- - - - - - - - -+---+---+
+ | number of right float | 1 | 1 |
+ +---+---+- - - - - - - - -+---+---+
+
+The latter two must be changed, as soom as absolute positions are
+introduced. Details are hidden by static inline methods of
+dw::OutOfFlowMgr.
+
+
+Interaction between generating box and containing box
+=====================================================
+
+<div style="border: 2px solid #ff0000; margin-bottom: 0.5em; padding:
+0.5em 1em; background-color: #ffefe0"><b>Warning:</b> This section
+documents the current state, which is not free of errors.</div>
+
+A new widget out of flow is added to the generating block
+---------------------------------------------------------
+With the respective style attributes set, this is delegated to the
+dw::OutOfFlowMgr of the containing block:
+
+ ,-------------. ,-------------. ,-------------. ,-------------.
+ | float | | OOFM | | cont. block | | gen. block |
+ `-------------' `-------------' `-------------' `-------------'
+ | | | |
+ ------------------------------------------------------------>|
+ | | | addWidget |
+ | | | (with an |
+ | | | appr. style) |
+ | | | |
+ | |<----------------------------------|
+ | | addWidget | |
+
+As with widgets in flow, dw::Textblock::wordWrap is called by/for the
+generating block:
+
+ | | | |--.
+ | | | | |wordWrap
+ | | | |<-'
+
+First, the generating block will tell the dw::OutOfFlowMgr about the
+float position:
+
+ | |<----------------------------------|
+ | | tellPosition | |
+ | | [1] | |
+ | | | |
+ | |---------------->| |
+ | | borderChanged | |
+ | | | |
+ | | |---------------->|
+ | | | borderChanged |
+ | | | |
+ | | | |--.
+ | | | | |queueResize
+ | | | |<-'
+
+After this, the line with must be calculated, with some implications:
+
+ | | | |--.
+ | | | | |calcAvail\
+ | | | | |Width
+ | | | |<-'
+ | | | |
+ | | | |--.
+ | | | | |lineLeft\
+ | | | | |Border [1]
+ | | | |<-'
+ | | | |
+ | |<----------------------------------|
+ | | getLeftBorder | |
+ | | | |
+ | |--. | |
+ | | |ensureFloat\ | |
+ | | |Size | |
+ | |<-' | |
+ | | | |
+ |<----------------| | |
+ | sizeRequest | | |
+ | (perhaps) | | |
+
+"getRightBorder" in an analogue way.
+
+[1] Here, the values of diffXToContainingBlock,
+ restWidthToContainingBlock, and diffYToContainingBlock are
+ used. TODO: These may not be set correctly.
+
+The size of a float changes its size
+------------------------------------
+First, the standard part:
+
+ ,-------------. ,-------------. ,-------------. ,-------------.
+ | float | | OOFM | | cont. block | | gen. block |
+ `-------------' `-------------' `-------------' `-------------'
+ | | | |
+ |--. | | |
+ | |queueResize | | |
+ |<-' | | |
+ | | | |
+ |---------------------------------->| |
+ | | markSizeChange | |
+
+Since dw::core::Widget::parentRef indicates this child as out of flow,
+this is delegated to the dw::OutOfFlowMgr:
+
+ | |<----------------| |
+ | | markSizeChange | |
+ | | | |
+ | |---------------->| |
+ | | borderChanged | |
+ | | | |
+ | | |---------------->|
+ | | | borderChanged |
+ | | | |
+ | | | |--.
+ | | | | |queueResize
+ | | | |<-'
+
+Notice that the size of the float is not yet calculated, instead a
+size request is queued (dw::OutOfFlowMgr::Float::dirty is set), which
+will result in a new calculation of the size of the containing block.
+
+Also, queueResize is called recursively here: before the call for the
+float is finished, it is called for the generating block. (See \ref
+dw-widget-sizes for details.)
+
+Calculating the size
+--------------------
+As usually, it starts at the top of the widget tree; in this case, the
+containing block is regarded:
+
+ ,-------------. ,-------------. ,-------------. ,-------------.
+ | Float | | OOFM | | cont. block | | gen. block |
+ `-------------' `-------------' `-------------' `-------------'
+ | | | |
+ ------------------------------------------>| |
+ | | sizeRequest | |
+ | | | |
+ | | |--. |
+ | | | sizeRequestImpl |
+ | | |<-' |
+
+During rewrapping, the size of the child is requested. We omit some
+steps, since nothing has changed, except that
+
+- dw::Textblock::diffXToContainingBlock,
+- dw::Textblock::restWidthToContainingBlock, and
+- dw::Textblock::diffYToContainingBlock
+
+are set for the child, before this call:
+
+ | | |---------------->|
+ | | | sizeRequest |
+ | | | |
+ | | | |--.
+ | | | | sizeRequest\
+ | | | | Impl
+ | | | |<-'
+
+It may be that the child, the generating block, has to rewrap the
+lines:
+
+ | | | |--.
+ | | | | rewrap
+ | | | |<-'
+ | | | |
+ | |<----------------------------------|
+ | | tellNoPosition | |
+ | | | |
+The rest is then similar to above:
+
+ | | | |--.
+ | | | | wordWrap
+ | | | |<-'
+ | | | |
+ | |<----------------------------------|
+ | | tellPosition | |
+ | | [1] | |
+ | | | |
+ | |---------------->| |
+ | | borderChanged | |
+ | | | |
+ | | |---------------->|
+ | | | borderChanged |
+ | | | |
+ | | | |--.
+ | | | | |queueResize
+ | | | |<-'
+ | | | |
+ | | | |--.
+ | | | | |calcAvail\
+ | | | | |Width
+ | | | |<-'
+ | | | |
+ | | | |--.
+ | | | | |lineLeft\
+ | | | | |Border [1]
+ | | | |<-'
+ | | | |
+ | |<----------------------------------|
+ | | getLeftBorder | |
+ | | | |
+ | |--. | |
+ | | |ensureFloat\ | |
+ | | |Size | |
+ | |<-' | |
+ | | | |
+ |<----------------| | |
+ | sizeRequest | | |
+ | (perhaps) | | |
+
+Notice the nested sizeRequest (containing block -- generating block --
+float), but also the call of dw::core::Widget::queueResize within
+dw::core::Widget::sizeRequestImpl, which is allowed, see
+\ref dw-widget-sizes.
+
+[1] Here, the values of diffXToContainingBlock,
+ restWidthToContainingBlock, and diffYToContainingBlock are used.
+
+
+Bugs and Things Needing Improvement
+===================================
+
+High Priority
+-------------
+**Misplaced/missing floats, wrong widths etc.:** Best is to provide
+test pages with these errors, which are as simple as possible.
+
+**Extremes:** Extremes will be implemented by
+dw::OutOfFlowMgr::getExtremes, which must be considered by
+dw::Textblock::getExtremesImpl, like dw::OutOfFlowMgr::getSize is used
+by dw::Textblock::sizeRequestImpl. The last two points (lines with no
+contents/collisions of floats) lead to a very simple of
+dw::OutOfFlowMgr::getExtremes: the result is simply the maximum of the
+floats extremes. (This is at least correct for the minimal width.)
+
+**Rewrapping** (via dw::Textblock::borderChanged) sometimes does not
+imply redrawing. Reproduce?
+
+(Plus some more; list must be updated.)
+
+Medium Priority
+---------------
+**Position of a text block:** Setting,
+dw::Textblock::diffXToContainingBlock,
+dw::Textblock::restWidthToContainingBlock, and
+dw::Textblock::diffYToContainingBlock in the current way is ugly,
+should be replaced by something like size hints.
+
+**Determining the containing block:** In
+dw::Textblock::notifySetAsTopLevel and dw::Textblock::notifySetParent:
+should other widgets be able to be generating/containing block?
+
+**Determining whether a widget cares about floats:** Both variants of
+_mustBorderBeRegarded_, and all variants of _getTextblockForLine_:
+Perhaps, there should be only one widget of this type per line.
+
+**Implementing the attribute "clear":** ...
+
+**Exact positions of floats:** See dw::OutOfFlowMgr::calcBorderDiff.
+
+Low Priority
+-------------
+**Absolute positions:** Will be incorporated into the
+dw::OutOfFlowMgr.
+
+**Fixed elements:** Some notes about what has do be done for fixed
+elements: (i) In the current design, there is only one containing
+block for a given generating block. However, a given generating block
+may contain an element with absolute position (or, a float),
+
+Not a Bug (Kind of)
+-------------------
+
+*Floats too far left?* Sometimes, floats seem too far on the
+left side, as in test/floats-and-absolute.html, and also in
+Wikipedia. This is only due to the fact that dillo does not yet
+support absolute positions, and so absolutely positioned elements are
+not regarded as containing block. (Or related to *Exact positions of
+floats* above?)
+
+**Update:** Floats refer to the border of the *generating* box, not of
+the *containing* box, so this is not an issue at all; furthermore,
+this has been fixed.
+
+*/ \ No newline at end of file
diff --git a/doc/dw-widget-sizes.doc b/doc/dw-widget-sizes.doc
index 419a4a73..a4675c8a 100644
--- a/doc/dw-widget-sizes.doc
+++ b/doc/dw-widget-sizes.doc
@@ -1,22 +1,20 @@
/** \page dw-widget-sizes Sizes of Dillo Widgets
-<h2>Allocation</h2>
+Allocation
+==========
Each widget has an \em allocation at a given time, this includes
-<ul>
-<li> the position (\em x, \em y) relative to the upper left corner of the
- canvas, and
-<li> the size (\em width, \em ascent, \em descent).
-</ul>
+- the position (\em x, \em y) relative to the upper left corner of the
+ canvas, and
+- the size (\em width, \em ascent, \em descent).
The \em canvas 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.
+cases, only a part is seen in a viewport. The allocation of the
+toplevel widget is exactly the allocation of the canvas, i.e.
-<ul>
-<li> the position of the toplevel widget is always (0, 0), and
-<li> the canvas size is defined by the size of the toplevel widget.
-</ul>
+- the position of the toplevel widget is always (0, 0), and
+- the canvas size is defined by the size of the toplevel widget.
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
@@ -31,13 +29,11 @@ defined by the limits of the C++ type \em int.
In the example in the image, the widget has the following allocation:
-<ul>
-<li>\em x = 50
-<li>\em y = 50
-<li>\em width = 150
-<li>\em ascent = 150
-<li>\em descent = 100
-</ul>
+- \em x = 50
+- \em y = 50
+- \em width = 150
+- \em ascent = 150
+- \em descent = 100
The current allocation of a widget is hold in
dw::core::Widget::allocation. It can be set from outside by
@@ -54,7 +50,9 @@ appropriate child allocations. dw::core::Widget::allocation should not
be changed here, this is already done in
dw::core::Widget::sizeAllocate.
-<h2>Requisitions</h2>
+
+Requisitions
+============
A widget may prefer a given size for the allocation. This size, the
\em requisition, should be returned by the method
@@ -62,14 +60,12 @@ dw::core::Widget::sizeRequestImpl. In the simplest case, this is
independent of the context, e.g. for an
image. dw::Image::sizeRequestImpl returns the following size:
-<ul>
-<li> If no buffer has yet been assigned (see dw::Image for more details),
- the size necessary for the alternative text is returned. If no
- alternative text has been set, zero is returned.
+- If no buffer has yet been assigned (see dw::Image for more details),
+ the size necessary for the alternative text is returned. If no
+ alternative text has been set, zero is returned.
-<li> If a buffer has been assigned (by dw::Image::setBuffer), the root
- size is returned (i.e. the original size of the image to display).
-</ul>
+- If a buffer has been assigned (by dw::Image::setBuffer), the root
+ size is returned (i.e. the original size of the image to display).
This is a bit simplified, dw::Image::sizeRequestImpl should also deal
with margins, borders and paddings, see dw::core::style.
@@ -87,7 +83,9 @@ widget), may, but also may not consider the requisition. Instead, a
widget must deal with any allocation. (For example, dw::Image scales
the image buffer when allocated at another size.)
-<h2>Size Hints</h2>
+
+Size Hints
+==========
Some widgets do not have an inherent size, but depend on the context,
e.g. the viewport size. These widgets should adhere to <i>size hints</i>,
@@ -95,11 +93,9 @@ i.e. implement the methods dw::core::Widget::setWidth,
dw::core::Widget::setAscent and dw::core::Widget::setDescent. The values
passed to the callees are
-<ul>
-<li> the viewport size (ascent is the heigt here, while descent is 0) for
- the toplevel widget, and
-<li> determined by the parent for its child widgets.
-</ul>
+- the viewport size (ascent is the heigt here, while descent is 0) for
+ the toplevel widget, and
+- determined by the parent for its child widgets.
Generally, the values should define the available space for the
widget.
@@ -109,42 +105,41 @@ dw::core::Widget::queueResize, when apropriate.
\todo There should be a definition of "available space".
-<h2>Width Extremes</h2>
+
+Width Extremes
+==============
dw::Table uses width extremes for fast calculation of column
widths. The structure dw::core::Extremes represents the minimal and
maximal width of a widget, as defined by:
-<ul>
-<li> the minimal width is the smallest width, at which a widget can still
- display contents, and
-<li> the maximal width is the largest width, above which increasing the width
- does not make any sense.
-</ul>
+- the minimal width is the smallest width, at which a widget can still
+ display contents, and
+- the maximal width is the largest width, above which increasing the
+ width- does not make any sense.
Especially the latter is vaguely defined, here are some examples:
-<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
- dw::core::Widget::sizeRequest).
+- For those widgets, which do not depend on size hints, the minimal
+ and the maximal width is the inherent width (the one returned by
+ dw::core::Widget::sizeRequest).
-<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 dw::Textblock::getExtremesImpl is
- a bit more complex.
+- 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 dw::Textblock::getExtremesImpl is a
+ bit more complex.
-<li> dw::Table is an example, where the width extremes are calculated
- from the width extremes of the children.
-</ul>
+- dw::Table is an example, where the width extremes are calculated
+ from the width extremes of the children.
Handling width extremes is similar to handling requisitions, a widget
must implement dw::core::Widget::getExtremesImpl, but a caller will
use dw::core::Widget::getExtremes.
-<h2>Resizing</h2>
+Resizing
+========
When the widget changes its size (requisition), it should call
dw::core::Widget::queueResize. The next call of
@@ -160,27 +155,82 @@ done before. In this case, a widget must exactly know the reasons, why
a call of dw::core::Widget::sizeRequestImpl is necessary. To make use
of this, a widget must implement the following:
-<ol>
-<li> There is a member dw::core::Widget::parentRef, 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> The widget must implement dw::core::Widget::markSizeChange and
+1. There is a member dw::core::Widget::parentRef, 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.
+2. The widget must implement dw::core::Widget::markSizeChange and
dw::core::Widget::markExtremesChange, these methods are called in
two cases:
-
- <ol>
- <li> directly after dw::core::Widget::queueResize, with the argument
- ref was passed to dw::core::Widget::queueResize, and
- <li> if a child widget has called dw::core::Widget::queueResize,
- with the value of the parent_ref member of this child.
- </ol>
-</ol>
+ 1. directly after dw::core::Widget::queueResize, with the
+ argument ref was passed to dw::core::Widget::queueResize,
+ and
+ 2. if a child widget has called dw::core::Widget::queueResize,
+ 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 dw::Textblock.
+
+Rules for Methods Related to Resizing
+=====================================
+
+<div style="border: 2px solid #ff0000; margin-bottom: 0.5em;
+padding: 0.5em 1em; background-color: #ffefe0"><b>Warning:</b>
+This section still needs some work.</div>
+
+Which method can be called, when the call of another method is not
+finished? These rules are important in two circumstances:
+
+1. To know which method can be called, and, especially, which methods
+ _must not_ be called, within the implementation of
+ dw::core::Widget::sizeRequestImpl (called by
+ dw::core::Widget::sizeRequest), dw::core::Widget::markSizeChange,
+ and dw::core::Widget::markExtremesChange (the latter two are
+ called by dw::core::Widget::queueResize).
+2. On the other hand, to make sure that the calls, which are allowed,
+ are handled correctly, especially in implementations of
+ dw::core::Widget::sizeRequestImpl,
+ dw::core::Widget::markSizeChange, and
+ dw::core::Widget::markExtremesChange.
+
+The rules in detail:
+
+- Within dw::core::Widget::sizeRequest /
+ dw::core::Widget::sizeRequestImpl:
+ 1. dw::core::Widget::sizeRequest must only be called for
+ children. Otherwise, an endless recursion would easily occur.
+ 2. dw::core::Widget::queueResize can be called. See below for
+ details.
+
+- Within queueResize / dw::core::Widget::markSizeChange /
+ dw::core::Widget::markExtremesChange.
+ 1. dw::core::Widget::sizeRequest must _not_ be called. As a example,
+ look at dw::Image::setBuffer: Here, dw::core::Widget::queueResize
+ is called at the beginning, while dw::Image::buffer, which is
+ needed by dw::Image::sizeRequest, is set later. If the
+ implementation of dw::core::Widget::markSizeChange or
+ dw::core::Widget::markExtremesChange of a parent widget calls
+ dw::core::Widget::sizeRequest for the image widget, a wrong value
+ for the buffer would be used. (Of course, it is possible to first
+ set dw::Image::buffer, and the call
+ dw::core::Widget::queueResize, but this does not change the fact
+ that these considerations should not be necessary on this level.)
+ 2. dw::core::Widget::queueResize can be called with some
+ limitations. It has to be ensured that no endless recursion is
+ caused, e.&nbsp;g. by calling dw::core::Widget::queueResize for a
+ child. (But this is not the only case.) See below for details.
+
+The facts that dw::core::Widget::queueResize can be called within
+other methods, leads to following guidelines:
+
+- dw::core::Widget::queueResize simply goes up in the hierarchy of
+ widgeds, sets some flags, and calls dw::core::Widget::markSizeChange
+ and dw::core::Widget::markExtremesChange.
+- dw::core::Widget::markSizeChange and
+ dw::core::Widget::markExtremesChange should be kept extremely
+ simple. (TODO: Details)
+
*/