Shapes are visual elements meant to be added to a canvas. A shape may be configured using various aspects, including color, border, line thickness, and many other parameters. This chapter details a number of shapes supported by Roassal.
All the code provided in this chapter is available at https://github.com/bergel/AgileVisualizationAPressCode/blob/main/02-03-Shapes.txt.
Box
Without any settings, as in this example, a box is gray and has a default size of 10 pixels per side. Its position is (0, 0), which corresponds to the center of the canvas when open.
The width and the height of a box can be set using width: and height:. Both expect a positive number (a float or integer). The size: message takes a number as a parameter and sets the height and the width. The extent: message, expecting a point, can be used to set the height and width in one message.
The color is set using color: and taking a Color object as an argument.
Circle and Ellipse
The RSCircle and RSEllipse classes are similar to RSBox, since classes are subclasses of RSBoundingShape. Obviously, the height: and width: methods cannot be invoked on a circle. Furthermore, RSCircle and RSEllipse do not provide the method cornerRadius: as RSBox does .
Label
The loremIpsum method defined on the class size of String gives a lorem ipsum, a classical placeholder text. Sending substrings to this text provides a list of words.
Roassal offers various strategies to compute the shape of a label. Such a strategy may have an impact when applying a layout or when composing shapes. The RSMetricsProvider class is the root class of the supported strategy and may be set in a RSLabel using the metricsProvider: method.
Polygon
You can round a polygon’s corners using cornerRadii:, which expects a positive integer as an argument.
SVG Path
A SVG shape requires a string describing its path, itself encoded into some commands. For example, the token M is the command moveto, C is curveto, and S is smooth curveto. A description of these tokens can easily be found online. w3schools.com is a reliable source of documentation.
These SVG paths are from svgrepo.com and are distributed under the public domain license.
Common Features
All the shapes described so far inherit from the RSBoundingShape class. Therefore, a number of common features are supported for all these shapes.
Color may be set using color:, which accepts either a color object (e.g., Color blue or Color r: 0.5 g: 0.3 b: 0.2) or a symbol (e.g., #red, #cyan). If a symbol is provided, it is executed on the Color class. Methods defined on the class side of Color represent valid symbols to be provided to color:.
translateBy: aDeltaPoint, which moves a shape by a given step expressed as a point.
translateTo: aPoint, which moves a shape to a new position.
I encourage you to browse the definition of the RSBorder class to see an exhaustive list of how borders are handled.
Model
A shape can have a model object that it is intended to represent. All the shapes defined in this chapter do not have a model object. Setting a model in a shape is useful to define lines, use a normalizer, and set interactions. Having shapes that support a model object is a significant advantage that Roassal has over other visualization engines.
The script creates nine circles in a canvas. Each circle has a number, and the represented numbers range from 1 to 9. Each circle has a popup interaction, which makes a little window appear when the mouse is above a circle. The popup interaction obtains a textual representation of each model object to define the small window’s content.
Another significant benefit of using a model object is to enjoy the support of the Pharo’s Inspector. Chapter 13 is dedicated to that topic.
Line
Although apparently simple, representing lines remains a complex task. As any other shape, a line has many visual attributes (e.g., width, color, style, and shapes as extremities). Difficulties in handling lines include the way they are built and how to react to user interactions. In its simplest form, a line may be set between two points. However, the way a line has to be configured becomes more complex when a line connect two shapes. For example, the line needs to be adapted when one of its extremities is translated.
RSLine describes a direct line between two points or shapes.
RSPolyline represents a line with multiple control points.
RSBezier represents a Bezier line with two, three, or four control points.
RSArrowedLine models a straight arrowed line between two points.
The two shapes—box and circle—are draggable. Moving one of these leaves the line properly attached to the shape.
Line Attach Point
The previous example uses a border attach point as a way to make the extremities stick to the border of those shapes. The RSAttachPoint class is the root of the attach point class hierarchy. It may happen that some layout requires particular attach points. For example, a vertical tree layout may be combined with a vertical attach point.
The RSAbstractLine class provides useful shortcut methods, including withBorderAttachPoint, withCenteredAttachPoint, withHorizontalAttachPoint, and withVerticalAttachPoint. In the previous script, you can replace the line attachPoint: RSBorderAttachPoint new expression with line withBorderAttachPoint.
Line Marker
markerStart: To set the provided marker at the origin of the line, i.e., where the line starts.
markerEnd: To set the marker at the target, i.e., where the line ends.
marker: To set the marker at both extremities of the line.
offset: Sets a fixed number of pixels between the extremity and the marker.
offsetRatio: Sets a ratio, between 0.0 and 1.0, to determine the position of the marker.
Removing the markerShape offsetRatio: 0.3. line has the effect of having all the markers on the border of the label target. All the markers superimpose each other, which defeats the purpose of having markers. Having distance between the marker and the target is useful to avoid clutter.
Line with Control Points
The RSVerticalCPAPController controller replaces the control points that are manually specified. Similarly, RSHorizontalCPAPController defines control points that are adequate for an horizontal alignment.
What Have You Learned in This Chapter?
Simple shapes, including boxes, circles, ellipses, and labels
The benefits of having a model behind a shape
A line may be set between two points or two shapes
Bezier lines and polylines can have controlled points, statically or dynamically computed
The coming chapters will build on top of the notions presented in this chapter.