Dillo v3.1.1-119-g140d9ebd
Loading...
Searching...
No Matches
GROWS - Grand Redesign Of Widget Sizes
The complex "widget sizes" is currently divided into three documents: Sizes of Dillo Widgets, Grand Redesign Of Widget Sizes (this document), and Size requisitions depending on positions.
Furthermore, there are some notes in Miscellaneous Notes on Dw.

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:**

Update: 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.

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:

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.)
Notice: Currently, dw::core::Widget::getExtremesImpl must set all four members in dw::core::Extremes; this may change.

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 <em>new</em> 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_inline_dotgraph_1.png

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 adjust_min_width, 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.