Boost logo

Boost :

From: Reece Dunn (msclrhd_at_[hidden])
Date: 2004-12-22 05:13:49


Hi All,

In the "thoughts on a GUI component library" thread there have been
various discussions about the layout of a rectangle and come relating to
CSS. Note that point and size are stable.

The CSS3 Values and Units module
(http://www.w3.org/TR/2001/WD-css3-values-20010713/) defines various
units (e.g. inches, picas and em). This is a good basis for a GUI
library metric type. The type should store the values as a floating
point to allow things like 2.71cm and also to support platforms that
store coordinates as floating points (e.g. Cocoa).

The CSS3 relative values (em and ex) are dependant on the inherited
font-size property, so it is difficult to use these units as there is no
associated font-size property. Another issue relating to this is how to
resolve metric values between units that are not directly convertable. I
have suggested using a device::resolve method that takes metric, point,
size and rect types, but it may not always be possible to get access to
a device.

A further complication is the location of the origin. If we treat the
origin as being in the top left corner (which is true for Windows,
HTML/CSS and other document models such as text editors) this will
simplify the design and for platforms that have a different model (e.g.
Mac) then the implementation on that platform will need to map between
the different representations.

I personally like the CSS box model (http://www.w3.org/TR/css3-box/)
which can be defined as:

    struct css::box_model
    {
       rect margin;
       rect border;
       rect padding;
       size dimensions; // width and height
       // T content;
    };

The problem with supporting it by default is that we would need:

class component: public css::box_model;
class graphics::object: public css::box_model;

This clearly violates the don't pay for what you don't need rule of C++,
so for a css_block_layout, it needs to contain the box model properties
and a pointer to the component/graphical object. Obviously some level of
support for the CSS box model should be provided, allowing an
implementation of it to be written.

There has been some discussion and disagreement as to what
representation a rectangle takes. It is a good idea to hide the
representation of a rectangle and provide accessors to the various
values. This is because different people will want different things from
it. However, for efficiency, it is a good idea to expose the members of
point and size. In supporting the CSS box model and adoption of top-left
as (0, 0) the representation becomes:

class rect
{
    point tl;
    point br;
};

with:
    top() = tl.y; left() = tl.x;
    bottom() = br.y; right() = br.x;
    width() = br.x - tl.x;
    width( w ): br.x = tl.x + w;
    size() = ::size( width(), height())
    center() = tl + ( size() / 2 )

An issue with this is: do we keep the width of the rectangle when
setting left/right? In order to keep things simple, the answer has to be no.

Construction of a rect should have the following variants:
    rect() = rect( 0, 0, 0, 0 )
    rect( n ) = rect( n, n, n, n )
       // This models the CSS "margin: 2px;" behaviour.
    rect( t, r, b, l ): tl( t, l ), br( b, r )
       // This models "margin: 1pt 2pt 3pt 4pt;"
    rect( point p, size s ) =
       rect( p.x, p.y, p.x + s.dx, p.y + s.dy )
       // This allows for support for traditional GUI representations

Note that this model will change the nature of a program that uses the
current model.

We also have inflate/deflate operations that should take size *and* rect
variants. This will allow easier box-model calculations:

    rect disp( point( 0, 0 ), size( 500, 700 ));
    rect margin( 1, 2, 3, 4 );
    rect box = disp;
    box.deflate( margin ); // apply margin adjustments
    // ...

Regards,
Reece


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk