-
Notifications
You must be signed in to change notification settings - Fork 53
02 Canvas
RSCanvas is the main class for roassal visualizations, it is a container of shapes and animations, and describes how this elements interact with the Pharo ecosystem, you can inspect it or open it in a system window, or create a morph and put it into a new window.
canvas := RSCanvas new.
canvas color: Color white.
window := canvas open.
window setLabel: 'Roassal canvas'.

the previous example uses open
, this method open a new SystemWindow
instance, and then we can change the window title.
Shapes in RSCanvas are separated in different groups, shapes, fixedShapes, nodes and edges.
RSCanvas has a reference to an instance of RSCamera, this object modifies the position and the scale of the group shapes
, it has some methods to adjust the camera position and scale to focus to the elements.
canvas := RSCanvas new.
0 to: 10 do: [ :i |
canvas add: (RSBox new
position: (i@i)* 20;
color: (i even
ifTrue: [Color red ]
ifFalse: [ Color blue ] );
size: 20;
yourself) ].
canvas

In the previous example we put 10 red-blue boxes. The origin for these shapes is the center of the canvas. The first red box is the center of the visualization. But the visualization is not focus on the shapes, there are white areas that takes a lot of space. with the camera we can change the position to focus all the shapes.
...
canvas zoomToFit.

With zoomToFit
canvas changes the position and scale of the camera without changing the position and scale of each shape.
Also just for fun we can change the viewing area of the camera to focus only on the first 3 first boxes.
canvas := RSCanvas new.
0 to: 10 do: [ :i |
canvas add: (RSBox new
position: (i@i)* 20;
color: (i even
ifTrue: [Color red ]
ifFalse: [ Color blue ] );
size: 20;
yourself) ].
group := canvas shapes copyFrom: 1 to: 3.
canvas open.
canvas camera
zoomToFit: canvas extent*0.8
rectangle: group encompassingRectangle.
canvas signalUpdate

In previous example there is a group with the first 3 shapes, then we open the window, this creates the canvas and sets its extent. With zoomToFil:rectangle:
we change the position and the scale of the camera to fit in the 80% of the canvas extent, the rectangle that contains all the boxes of the group. This changes the canvas camera but it does not notify the change, thats why we need the signalUpdate. to refresh the canvas view.
RSCanvas has 2 big groups shapes
and fixedShapes
first canvas draws the group shapes
then draws the group fixedShapes
.
This is a generic list of shapes, the first shape in this collection is the first one to be draw in the canvas. The camera of the canvas applies its transformation to this collection of shapes, moving the origin to the middle of the canvas.
canvas := RSCanvas new.
canvas addShape: (RSLabel new text: 'Foo').
canvas addShape: (RSLine new
startPoint: -100@0;
endPoint: 100@0 ).
"this box will be hide the label"
canvas addShape: (RSBox new size: 50).
canvas shapes size.
"3"
canvas.
This collection of shapes are not affected by the canvas camera, that means that their positions are on the corner of the canvas. Fixed shapes
are drawn after Shapes
. Use method isFixed:true
to add a shape to the fixed group.
canvas := RSCanvas new.
canvas addShape: (RSBox new
size: 50;
position: 50 asPoint).
canvas addShape: (RSBox new
isFixed: true;
size: 50;
color: Color red;
position: 50 asPoint).
canvas addShape: (RSLine new
isFixed: true;
startPoint: 50 asPoint;
endPoint: 100 asPoint).
"This will change the camera scale
and will modify the size of the first box"
canvas camera scale: 0.2.
canvas.

You can access to this group with the method add:
with an instance of RSBoundingShape
or with or addAll:
and a collection of instances of RSBoundingShape
.
A valid node can be a RSBitmap, RSBox, RSEllipse, RSComposite, RSLabel, RSPolygon, RSPieSlice or RSSSVGPath
canvas := RSCanvas new.
canvas add: RSBox new.
canvas addAll: ((1 to: 20) collect: [ :i |
RSBox new
size: i;
color: Color black;
position: i* 10 asPoint] ).
"this changes the position and extent for the first box"
canvas nodes first
fromRectangle: canvas encompassingRectangle.
canvas zoomToFit.
canvas.

Like before Roassal uses this collection to know each instance of RSAbstractLine
added to the canvas with the method add:
or addAll:
.
A valid edge can be RSBezier, RSPolyline, RSLine, RSSVGPathLine
canvas := RSCanvas new.
canvas addAll: ( (1 to: 20 by: 2) collect: [ :i|
RSLine new
startPoint: 0@ i;
endPoint: 100@ i;
yourself ] ).
canvas edges size.
"10"
canvas zoomToFit.
canvas.

Creating edges can be complicated, then you should take a look to the RSEdgeBuilder
.
The canvas as their shapes react to certain events, like the extent changed, or when the camera change position or scale.
RSExtentChangedEvent is called each time that the canvas morph changes its extent. RSScaleChangedEvent is called when the camera scale changes its value. RSPositionChangedEvent is called each time that the camera position is changed.
canvas := RSCanvas new.
label := RSLabel new.
canvas add: label.
canvas
when: RSExtentChangedEvent
do: [ :evt |
label text: 'Extent: ', evt newExtent asString.
canvas zoomToFit; signalUpdate. ];
when: RSScaleChangedEvent
do: [ :evt |
label text: label text, ' Scale: ', evt newScale asString].
canvas
At this phase Roassal3 only runs on pharo, in order to communicate with the pharo ecosystem, RSCanvas defines a morph
an instance of RSMorph, the visual component for Pharo, this morph sends the events the drawing cycle to the RSAthensRenderer. Usually the user creates inderectly this morph when he opens the canvas or when he uses the inspector.
canvas := RSCanvas new.
canvas addAll: ( (1 to: 20 by: 2) collect: [ :i|
RSLine new
startPoint: 0@ i;
endPoint: 100@ i;
yourself ] ).
canvas edges size.
"10"
canvas zoomToFit.
morph := canvas createMorph.
root := Morph new.
root addMorph: morph.
morph extent: 300@300.
root color: Color black.
(root openInWindowLabeled: '2020') position: 100 asPoint.
In this example we can use Morphic to create a simple user interface. You can use SpRoassalPresenter
and Spec2 from Pharo to build complex user interfaces. Use Sp1RoassalPresenter
in Pharo7 for spec1.