Geometry, visual and layout bounds explained

A bound is a territorial limit, a boundary. In terms of a graphical element, it is a space in which the graphical element is rendered. For simplicity, bounds are rectangular areas. Bloc defines three different bounds (layout, geometry, and visual) that we will explain using the following example:

centeredOutskirts
	<gtExample>
	<label: 'Rectangle and star elements with centered stroke'>
	| aContainer |

	aContainer := self container.
	aContainer addChild: self rectangleWithSmallerGeometryCentered.
	aContainer addChild: self starWithSmallerGeometryCentered.

	^ aContainer
    

"Layout" bounds are drawn with gray dashed rectangles in the figure above. They are of this size in this particula example, because each element defines its size explicitly using size: method. Layout bounds are considered by layout algorithms to define mutual locations for all considered elements.

"Geometry" bounds are drawn with red dashed rectangles in the figure above. The area is defined by minimum and maximum values of a polygon vertices. In case of rectangle, geometry bounds are defined by the following polygon:

BlGeometryVisualAndLayoutBoundsExamples>>#rectanglePolygon
	<gtExample>
	<label: 'Rectangle polygon'>
	^ BlPolygon vertices: {
		(50@50). (150@50). (150@100). (50@100)
	}
        

"Visual" bounds are drawn with blue rectangles in the figure above. It is an exact area occupied by an element. Computing visual bounds is the most expensive computation as it takes strokes and rendering into account.

Different Bounds Setups

The first figure above draws all strokes centered around the defined vertices. For that reason, the geometry bounds are in the middle. The following example draws strokes outside:

BlGeometryVisualAndLayoutBoundsExamples>>#outsideOutskirts
	<gtExample>
	<label: 'Rectangle and star elements with outside stroke'>
	| aContainer |

	aContainer := self container.
	aContainer addChild: self rectangleWithSmallerGeometryOutside.
	aContainer addChild: self starWithSmallerGeometryOutside.
		
	^ aContainer
        

In case of the rectangle, you can notice that its stroke is inside of the visual (blue, outside) and the geometry (red, inside) bounds. If the strokes are drawn inside, then visual and geometry bounds are equal:

BlGeometryVisualAndLayoutBoundsExamples>>#insideOutskirts
	<gtExample>
	<label: 'Rectangle and star elements with inside stroke'>
	| aContainer |

	aContainer := self container.
	aContainer addChild: self rectangleWithSmallerGeometryInside.
	aContainer addChild: self starWithSmallerGeometryInside.
		
	^ aContainer
        

Debugging Bounds

Being able to display those three bounds helps when elements are not visually aligned as expected. Consider the following example:

BlGeometryVisualAndLayoutBoundsExamples>>#misalignedIcon
	<gtExample>
	| anIconElement aLabelElement aContainerElement |
	anIconElement := self emptyIconElement
		geometry: self misalignedTrianglePolygon.
	aLabelElement := self textElementWithRunText.
	aContainerElement := self iconAndTextContainer.
	aContainerElement
		addChildren:
			{anIconElement.
			aLabelElement}.
	^ aContainerElement
        

The triangle (icon) and text are not vertically centered despide the fact that we have BlLinearLayout horizontal alignCenter in the code. To understand why it happens, aTriangleElement debug: true can be added to the code with the following result:

BlGeometryVisualAndLayoutBoundsExamples>>#debuggingMisalignedIcon
	<gtExample>
	| aContainerElement |
	aContainerElement := self misalignedIcon.
	aContainerElement children first.
	^ aContainerElement
        

As we can see the layout bounds (gray dashed rectangle) consider larger area then expected. Looking at the definition of the triangle polygon, we can spot that the polygon starts at 0@3 instead of 0@0:

BlGeometryVisualAndLayoutBoundsExamples>>#misalignedTrianglePolygon
	<gtExample>
	<label: 'Triangle polygon'>
	^ BlPolygon
		vertices:
			{(0 @ 3).
			(8 @ 7.5).
			(0 @ 12)}
        

If we fix it to:

BlGeometryVisualAndLayoutBoundsExamples>>#trianglePolygon
	<gtExample>
	<label: 'Triangle polygon'>
	^ BlPolygon
		vertices:
			{(0 @ 0).
			(8 @ 6).
			(0 @ 12)}
        

The icon and text are aligned as expected:

BlGeometryVisualAndLayoutBoundsExamples>>#debuggingAlignedIcon
	<gtExample>
	| aContainerElement |
	aContainerElement := self alignedIcon.
	^ aContainerElement
        

And we can disactivate the debug mode:

BlGeometryVisualAndLayoutBoundsExamples>>#alignedIcon
	<gtExample>
	| anIconElement aLabelElement aContainerElement |
	anIconElement := self emptyIconElement
		geometry: self trianglePolygon.
	aLabelElement := self textElementWithRunText.
	aContainerElement := self iconAndTextContainer.
	aContainerElement
		addChildren:
			{anIconElement.
			aLabelElement}.
	^ aContainerElement
        

The debugging mode is also possible to activate in the GT-Inspector's menu, next to the tabs.