210 lines
8.9 KiB
Plaintext
210 lines
8.9 KiB
Plaintext
/** \page dw-grows GROWS - Grand Redesign Of Widget Sizes
|
|
|
|
<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: \ref
|
|
dw-widget-sizes, **Grand Redesign Of Widget Sizes** (this document),
|
|
and \ref dw-size-request-pos. Furthermore, there are some notes in
|
|
\ref dw-miscellaneous.</div>
|
|
|
|
This paper describes (will describe) some design changes to
|
|
calculating widget sizes. Goals are:
|
|
|
|
- Simplification of widget size calculation by the parent widget;
|
|
dw::Textblock::calcWidgetSize, dw::OutOfFlowMgr::ensureFloatSize
|
|
etc. should become simpler or perhaps even obsolete.
|
|
|
|
- Making the implementation of some features possible:
|
|
|
|
- *max-width*, *max-height*, *min-width*, *min-height*;
|
|
- correct aspect ratio for images with only one percentage size defined;
|
|
- *display: inline-block*;
|
|
- <button>.
|
|
|
|
|
|
A short sketch
|
|
==============
|
|
|
|
**dw::core::Widget::sizeRequest and dw::core::Widget::getExtremes will
|
|
return final results.** The caller does not have to correct the size,
|
|
e. g. when percentages are defined. As an example,
|
|
dw::Textblock::calcWidgetSize has already become much simpler.
|
|
|
|
**A new hierarchy, *container*:** Aside from dw::core::Widget::parent
|
|
and dw::core::Widget::generator, there is a third hierarchy
|
|
dw::core::Widget::container, which is (unlike *generator*) always a
|
|
direct ancestor, and represents what in CSS is called *containing
|
|
block*. Containers are important to define the "context size", which
|
|
is (not solely) used for percentage sizes.
|
|
|
|
(There is another "containing block", dw::Textblock::containingBlock;
|
|
these may be consolidated some day.)
|
|
|
|
**The process of size calculation is split between the widget itself
|
|
and its container:**
|
|
|
|
- The container provides some abstract methods:
|
|
dw::core::Widget::getAvailWidthOfChild,
|
|
dw::core::Widget::getAvailHeightOfChild,
|
|
dw::core::Widget::correctRequisitionOfChild, and
|
|
dw::core::Widget::correctExtremesOfChild, which can be used in the
|
|
actual implementation of dw::core::Widget::sizeRequestImpl;
|
|
different containers with different ways how to arrange their
|
|
children will implement these methods in a different way. (Simple
|
|
example: the *available width* for children within a textblock is
|
|
the *available width* for the textblock itself, minus
|
|
margin/border/padding; on the other hand, it is completely different
|
|
for children of tables, for which a complex column width calculation
|
|
is used.)
|
|
|
|
- The actual size calculation is, however, controlled by the widget
|
|
itself, which only *uses* these methods above.
|
|
|
|
<div style="border: 2px solid #ffff00; margin-top: 0.5em;
|
|
margin-bottom: 0.5em; padding: 0.5em 1em; background-color: #ffffe0">
|
|
<b>Update:</b> This is not fully correct; the parents are also involved
|
|
for calculating available widths and heights, at least when CSS 'width'
|
|
and 'height' are not set.</div>
|
|
|
|
**Size hints are removed.** Instead, the container methods in the
|
|
previous paragraph are used. Changes of container sizes (especially
|
|
viewport the size) are handled in a different way.
|
|
|
|
**Extremes are extended by intrinsic values.** In some cases (see
|
|
dw::Table::forceCalcCellSizes, case *minWidth* > *totalWidth*, for an
|
|
example) it is useful to know about minimal and maximal width of a
|
|
widget independent of CSS attributes. For this, dw::core::Extremes is
|
|
extended by:
|
|
|
|
- dw::core::Extremes::minWidthIntrinsic and
|
|
- dw::core::Extremes::maxWidthIntrinsic.
|
|
|
|
The rules for the calculation:
|
|
|
|
1. If a widget has no children, it calculates *minWidthIntrinsic* and
|
|
*maxWidthIntrinsic* as those values not affected by CSS hints.
|
|
(dw::core::Widget::correctExtremes will not change these values.)
|
|
2. A widget must calculate *minWidthIntrinsic* and *maxWidthIntrinsic*
|
|
from *minWidthIntrinsic* and *maxWidthIntrinsic* of its children,
|
|
and *minWidth* and *maxWidth* from *minWidth* and *maxWidth* of its
|
|
children.
|
|
3. At the end, *minWidth* and *maxWidth* of a widget are corrected by
|
|
CSS attributes. (dw::core::Widget::correctExtremes will do this.)
|
|
|
|
<div style="border: 2px solid #ffff00; margin-top: 0.5em;
|
|
margin-bottom: 0.5em; padding: 0.5em 1em; background-color: #ffffe0">
|
|
<b>Notice:</b> Currently, dw::core::Widget::getExtremesImpl must
|
|
set all four members in dw::core::Extremes; this may change.</div>
|
|
|
|
Another **extension of extremes: *adjustmentWidth*.** This is used as
|
|
minimum for the width, when "adjust_min_width" (or,
|
|
"adjust_table_min_width", respectively) is set.
|
|
|
|
The rules for the calculation:
|
|
|
|
1. If a widget has no children, it can choose a suitable value,
|
|
typically based on dw::core::Extremes::minWidth and
|
|
dw::core::Extremes::minWidthIntrinsic.
|
|
2. A widget must calculate *adjustmentWidth* from *adjustmentWidth* of
|
|
its children.
|
|
|
|
*Note:* An implementation of dw::core::Widget::getExtremesImpl may set
|
|
this value *after* calling dw::core::Widget::correctExtremesOfChild,
|
|
so that it cannot be used for the correction of extremes. In this case
|
|
*useAdjustmentWidth = false* should be passed to
|
|
dw::core::Widget::correctExtremesOfChild. On the other hand, if known
|
|
before, *useAdjustmentWidth* should be set to *true*.
|
|
|
|
Rules for *new* methods related to resizing
|
|
===========================================
|
|
|
|
- Of course, *sizeRequestImpl* may (should) call *correctRequisition*,
|
|
and *getExtremesImpl* may (should) call *correctExtremes*.
|
|
|
|
- *sizeRequestImpl* (and *correctRequisition*) is allowed to call
|
|
*getAvailWidth* and *getAvailHeight* with *forceValue* set, but
|
|
*getExtremesImpl* (and *correctExtremes*) is allowed to call these
|
|
only with *forceValue* unset.
|
|
|
|
- For this reason, *sizeRequestImpl* is indeed allowed to call
|
|
*getExtremes* (dw::Table does so), but the opposite
|
|
(*getExtremesImpl* calling *sizeRequest*) is not allowed
|
|
anymore. (Before GROWS, the standard implementation
|
|
dw::core::Widget::getExtremesImpl did so.)
|
|
|
|
- Finally, *getAvailWidth* and *getAvailHeight* may call
|
|
*getExtremes*, if and only if *forceValue* is set.
|
|
|
|
Here is a diagram showing all permitted dependencies:
|
|
|
|
\dot
|
|
digraph G {
|
|
node [shape=record, fontname=Helvetica, fontsize=10, color="#c0c0c0"];
|
|
edge [arrowhead="open", arrowtail="none", color="#404040"];
|
|
|
|
"sizeRequest[Impl]" -> "getExtremes[Impl]";
|
|
"sizeRequest[Impl]" -> correctRequisition;
|
|
"getExtremes[Impl]" -> correctExtremes;
|
|
"sizeRequest[Impl]" -> "getAvail[Width|Height] (true)";
|
|
"getExtremes[Impl]" -> "getAvail[Width|Height] (false)";
|
|
correctRequisition -> "getAvail[Width|Height] (true)";
|
|
correctExtremes -> "getAvail[Width|Height] (false)";
|
|
"getAvail[Width|Height] (true)" -> "getExtremes[Impl]";
|
|
}
|
|
\enddot
|
|
|
|
Open issues
|
|
===========
|
|
|
|
**Do CSS size dimensions override intrinsic sizes in all cases?** If a
|
|
textblock needs at least, say, 100 pixels width so that the text can
|
|
be read, but has a specification "width: 50px", should half of the
|
|
text be invisible? Or should the width be corrected again to 100
|
|
pixels?
|
|
|
|
Currently, in the CSS size specification is honoured in all cases,
|
|
with one exception: see dw::Textblock::sizeRequestImpl and see
|
|
dw::Textblock::getExtremesImpl (the time when
|
|
dw::core::Widget::correctRequisition and
|
|
dw::core::Widget::correctExtremes, respectively, is called).
|
|
|
|
*Not* honouring the CSS size specification in all cases could improve
|
|
readability in some cases, so this could depend on a user preference.
|
|
|
|
**Update:** There is now a dillorc option <tt>adjust_min_width</tt>,
|
|
which is implemented for widths, but not heights (since it is based on
|
|
width extremes, but there are currently no height extremes).
|
|
|
|
Another problem is that in most cases, there is no clippping, so that
|
|
contents may exceed the allocation of the widget, but redrawing is not
|
|
necessarily triggered.
|
|
|
|
**Percentage values for margins and paddings, as well as negative
|
|
margins** are interesting applications, but have not been considered
|
|
yet. For negative margins, a new attribute
|
|
dw::core::Widget::extraSpace could solve the problem of widgets
|
|
sticking out of the allocation of parent.
|
|
|
|
**Clarify percentage heights.** Search in widget.cc, and compare
|
|
section 10.5 ('height') of the CSS 2.1 specification to section 10.2
|
|
('width').
|
|
|
|
**Fast queue resize does not work fully.** Example: run
|
|
*test/dw-simple-container-test* (dw_simple_container_test.cc), resize
|
|
(best maximize) the window and follow (e. g. by using RTFL) what
|
|
happens in consequence of dw::core::Layout::viewportSizeChanged. The
|
|
dw::SimpleContainer in the middle is not affected, so only the two
|
|
dw::Textblock's (at the top and at the bottom) call queueResize with
|
|
*fast = true*, and so get *NEEDS_RESIZE* set; but since it is not set
|
|
for the dw::SimpleContainer, *sizeRequest* is never called for the
|
|
bottom dw::Textblock.
|
|
|
|
There does not seem to be a real case for this problem in dillo, since
|
|
all widgets which may contain other widgets (except
|
|
dw::SimpleContainer, which is not used outside tests) use the
|
|
available width and height (dw::core::Widget::usesAvailWidth and
|
|
dw::core::Widget::usesAvailHeight), and so are always affected by
|
|
viewport size changes.
|
|
|
|
*/
|