[gui] rectangles and the CSS box model

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

* Reece Dunn <msclrhd@hotmail.com> [2004-12-22 05:22]:
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.
Maybe, in this sense, a font is a "device" that can resolve? -- Alan Gutierrez - alan@engrm.com

Alan Gutierrez wrote:
* Reece Dunn <msclrhd@hotmail.com> [2004-12-22 05:22]:
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.
Maybe, in this sense, a font is a "device" that can resolve?
Maybe what would be better is a css_device, since this would allow font-size property inheriting and resolution of the em unit. It should therefore be possible to extend/override the default resolution behaviour for a device: struct device { virtual metric resolve_unit( metric v, metric::type t, orientation o ); inline point resolve( const point & p, metric::type t ) { return point ( resolve_unit( p.x, t, orientation::x_axis ), resolve_unit( p.y, t, orientation::y_axis ) ); } // similar resolve method for size and rect }; Therefore the css_device would override the resolve_unit method. Regards, Reece

* Reece Dunn <msclrhd@hotmail.com> [2004-12-22 06:42]:
Alan Gutierrez wrote:
* Reece Dunn <msclrhd@hotmail.com> [2004-12-22 05:22]:
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.
Maybe, in this sense, a font is a "device" that can resolve?
Maybe what would be better is a css_device, since this would allow font-size property inheriting and resolution of the em unit. It should therefore be possible to extend/override the default resolution behaviour for a device:
struct device { virtual metric resolve_unit( metric v, metric::type t, orientation o ); inline point resolve( const point & p, metric::type t ) { return point ( resolve_unit( p.x, t, orientation::x_axis ), resolve_unit( p.y, t, orientation::y_axis ) ); } // similar resolve method for size and rect };
Therefore the css_device would override the resolve_unit method.
Would the css_device be implemented as a device decorator? -- Alan Gutierrez - alan@engrm.com

* Reece Dunn <msclrhd@hotmail.com> [2004-12-22 05:22]:
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.
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.
I'd imagined a division class that would have the block properties. If you don't want to pay for the borders if they are not needed, and in many cases, they would be the same from division to division, could you use a reference to shared set of demenions? This may aid in the cascading asepct of the stylesheet. struct css::division { box_model *block; size dimensions; }; Each division is going to need it's own size, but the block properties, margin, border, padding, are likely to be common for many divisions. -- Alan Gutierrez - alan@engrm.com

* Alan Gutierrez <alan-boost@engrm.com> [2004-12-22 05:41]:
* Reece Dunn <msclrhd@hotmail.com> [2004-12-22 05:22]:
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.
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.
I'd imagined a division class that would have the block properties. If you don't want to pay for the borders if they are not needed, and in many cases, they would be the same from division to division, could you use a reference to shared set of demenions?
This may aid in the cascading asepct of the stylesheet.
struct css::division { box_model *block; size dimensions; };
Each division is going to need it's own size, but the block properties, margin, border, padding, are likely to be common for many divisions.
Actually, now that I think about it, the css box is going to cost a lot if it has actual structures. It is going to need a to return a margin, say by inspecting the margin it was assigned, and if assigned none, return the margin that it inherited. In some cases, a division might have been explicitly assigned a border, but in most cases it will choose one based on context. -- Alan Gutierrez - alan@engrm.com

Alan Gutierrez wrote:
Actually, now that I think about it, the css box is going to cost a lot if it has actual structures. It is going to need a to return a margin, say by inspecting the margin it was assigned, and if assigned none, return the margin that it inherited.
There is no reason why it is not possible to implement a simplified box model specifically for GUI layouts. The width/height can be calculated using get_minimum_size() and area.deflate( margin + padding ). Border is not really necessary. As for inheriting, for simplicity, the box model will not inherit anything. If you want to implement a full CSS model (including a CSS device, box model, etc.) the library shgould provide enough functionality to allow you to do this.
In some cases, a division might have been explicitly assigned a border, but in most cases it will choose one based on context.
For sake of simplicity, it would be easier to disregard the border property in this context. Otherwise, you need to have border-color and border-style as well as border-size and you will also need to actually draw the border! Regards, Reece

* Reece Dunn <msclrhd@hotmail.com> [2004-12-22 06:57]:
Alan Gutierrez wrote:
Actually, now that I think about it, the css box is going to cost a lot if it has actual structures. It is going to need a to return a margin, say by inspecting the margin it was assigned, and if assigned none, return the margin that it inherited.
There is no reason why it is not possible to implement a simplified box model specifically for GUI layouts. The width/height can be calculated using get_minimum_size() and area.deflate( margin + padding ). Border is not really necessary. As for inheriting, for simplicity, the box model will not inherit anything.
If you want to implement a full CSS model (including a CSS device, box model, etc.) the library shgould provide enough functionality to allow you to do this.
This is indeed what I would like to do. I am on about how to implement CSS, including the cascading bit. For the record. Maybe, in terms of the gui library, I'm consiering the implementation of a specific layout. But, like I said elsewhere, it strikes me as an excellent means to develop plubbable look and feel. -- Alan Gutierrez - alan@engrm.com

Actually, now that I think about it, the css box is going to cost a lot if it has actual structures. It is going to need a to return a margin, say by inspecting the margin it was assigned, and if assigned none, return the margin that it inherited.
There is no reason why it is not possible to implement a simplified box model specifically for GUI layouts. The width/height can be calculated using get_minimum_size() and area.deflate( margin + padding ). Border is not really necessary. As for inheriting, for simplicity, the box model will not inherit anything.
Layout managers work this way... Layout managment is a capability of a window. When a window becomes a parent window (eg: you have added some butotns to it), the parent window will do the following: 1. It asks each child their minimum size 2. It tallies the minimum size needed by all children. 3. If the parent has the property that it is to use a minimum size, then it will call setSize() to be the size of the tallied size of the children. If it is to be smaller/larger, then it will adjust the tallied value to the specified size. 4. Each child is then told to setSize() to a specific size, which is based on the value of the tally and an appropriate algorithm (of say, equal width per child). Mathew
participants (3)
-
Alan Gutierrez
-
Mathew Robertson
-
Reece Dunn