,

DCIprogram: #MoveShape

" Exported from Squeak 7179-basic.226 last modified on 3 November 2014 by: Trygve"

Reader friendly version

projection: Context

Class: MoveShape

Context subclass: #MoveShape
    instanceVariableNames: 'drawing movingShapeName delta'
    category: 'MoveShape-Context'

" System operation.
Consider a Draw progam such as the PowerPoint slide editor. A user can create and place different shapes such as ovals, polygons, lines and other shapes. A Connector is a special line that runs from one shape to another. The line will always connect the two shapes even if the shapes move. This program implements the shape:move: operation.

THIS EXAMPLE HAS LIMITED FUNCTIONALITY
A constraint of this example is that the code shall be so simple that it can be explained in a regular talk. The code is therefore limited to a single connector. Also, Context classes are sunclasses of Context, the context base class that provides general runtime mechanisms. In this case, the remap method has been overridden to make the binding mechanism easier to explain (but not as general).

A NOTE ON THE IMPLEMENTATION
There is one Context class with one system operation:
        
shape: aShape move: aPoint inData: drawing

"

instanceMethods: operations

shape: shapeName move: deltaPoint data: aDrawing
    movingShapeName := shapeName.
    drawing := aDrawing.
    delta := deltaPoint.
    self triggerInteractionFrom: #MOVINGSHAPE with: #move.

instanceMethods: role binding

DELTA
    ^delta

LINE
    ^drawing at: #Connector

MOVINGSHAPE
    ^drawing at: movingShapeName


Interaction: MoveShape

No diagram

roleMethods: LINE

instanceMethods: role methods

shapeHasMoved
    self pointAt: MOVINGSHAPE put: MOVINGSHAPE center

roleMethods: MOVINGSHAPE

instanceMethods: role methods

move
    self setOrigin: self origin + DELTA corner: self corner + DELTA.
    LINE shapeHasMoved



projection: Data

Class: Connector

Object subclass: #Connector
    instanceVariableNames: 'startShape endShape line'
    category: 'MoveShape-Data'

" The line object in the Connector is not visible from outside the Connector.
No outside code can corrupt it. "

instanceMethods: initialize-release

startShape: start endShape: end
    startShape := start.
    endShape := end.
    (line := Line new) beginPoint: startShape center; endPoint: endShape center.

instanceMethods: attributes-write

pointAt: shape put: aPoint
    startShape == shape
        ifTrue: [line beginPoint: aPoint rounded].
    endShape == shape
        ifTrue: [line endPoint: aPoint rounded].

instanceMethods: operations

testLineStartPoint: start endPoint: end
    ^(line beginPoint = start) & (line endPoint = end)

projection: Test

Class: Test

Object subclass: #Test
    instanceVariableNames: ''
    category: 'MoveShape-Test'

instanceMethods: operations

test
    " Test new test. "
    "Set up test data. "
    | rect1A rect1B rect2 data delta connPt1A connPt2 connPt1B |
    rect1A := Rectangle origin: 0@5 corner: 10@15.
    rect1B := Rectangle origin: 100@115 corner: 110@125.
    rect2 := Rectangle origin: 20@25 corner: 30@35.
    (data := IdentityDictionary new)
        at: #Shape1 put: rect1A;
        at: #Shape2 put: rect2;
        at: #Connector put: (Connector new startShape: (data at: #Shape1) endShape: (data at: #Shape2)).
    delta := 100@110.
    " Check test Data. "
    connPt1A := rect1A center rounded.
    connPt2 := rect2 center rounded.
    self assert: [(
        (data at: #Shape1) = rect1A &
        (data at: #Shape2) = rect2 &
        (data at: #Connector) testLineStartPoint: connPt1A endPoint: connPt2
        ).
    ].
    " Move. "
    MoveShape new shape: #Shape1 move: delta data: data.
    " Check final Data. "
    connPt1B := rect1B center rounded.
    " Check result of move. "
    self assert: [(
        (data at: #Shape1) = rect1B&
        (data at: #Shape2) = rect2 &
        (data at: #Connector) testLineStartPoint: connPt1B endPoint: connPt2
        ).
    ].
    self inform: 'MoveShape test successful.'.

classMethods: instance creation

run
    self basicNew test