ORIGIN '~beta/guienv/guienv'; LIB_DEF 'bifrost' '../lib'; BODY 'private/Impl/BifrostImpl'; INCLUDE '~beta/containers/list'; INCLUDE '~beta/basiclib/math'; (* Bifrost - An Interactive Object Oriented Device * Independent Graphics System * * Refer to DAIMI IR-100 - Internal Report * Computer Science Department * Aarhus University, Denmark * * COPYRIGHT * Copyright Mjolner Informatics, 1990-94 * All rights reserved. *)
-- BifrostAttributes: attributes -- (* Specifications used to test for key and/or pointer modification *) Modifier: (# m: @Integer; enter m do INNER exit m #); NoModifier: Modifier (# ... #); ShiftModifier: Modifier (# ... #); ControlModifier: Modifier (# ... #); LockModifier: Modifier (# ... #); MetaModifier: Modifier (# ... #); CommandModifier: Modifier (# ... #); (* Constants used to specify fill rules *) EvenOddRule: (# exit 0 #); WindingRule: (# exit 1 #); (* Cap styles *) CapStyleDesc: (# s: @integer; enter s do INNER exit s #); CapButt: CapStyleDesc(# ... #); CapRounded: CapStyleDesc(# ... #); CapSquare: CapStyleDesc(# ... #); (* Join styles *) JoinStyleDesc: (# s: @integer; enter s do INNER exit s #); JoinMiter: JoinStyleDesc(# ... #); JoinRound: JoinStyleDesc(# ... #); JoinBevel: JoinStyleDesc(# ... #); (* Fontnames to use in TextShape and GraphicText *) fontName: integerObject(# do INNER #); Courier: fontname(# ... #); Times: fontname(# ... #); Helvetica: fontname(# ... #); (* Styles to use in TextShape and GraphicText *) Style: integerObject(# do INNER #); Plain: Style(# ... #); Italic: Style(# ... #); Bold: Style(# ... #); MaxRGB: (* The upper limit for the range of RGB values *) (# max: @Integer ... (* Device dependent *) exit max #); (* Constants specifying the range for hue, saturation and value *) DefaultMaxHue: (# exit 360 #); DefaultMaxSat: (# exit 32768 #); (* (2^15) *) DefaultMaxVal: (# exit 32768 #); (* (2^15) *) UnImplemented: (* Used to notify the user on features, that are not yet * implemented in Bifrost. *) (# feature: ^text enter feature[] ... #); DebugGraphic: (# exit false #);
Point: (# x, y: @integer; enter (x,y) exit (x,y) #); Vector: (# x,y: @Real; enter (x,y) exit (x,y) #); Rectangle: (# x,y: @Integer (* Upper left *); width,height: @Integer enter (x,y,width,height) exit (x,y,width,height) #); EqualPoint: (# p1,p2: @Point; enter (p1,p2) exit (p1.x=p2.x) and (p1.y=p2.y) #); AddPoints: (# p1,p2: @Point; enter (p1,p2) exit (p1.x+p2.x,p1.y+p2.y) #); SubPoints: (# p1,p2: @Point; enter (p1,p2) exit (p1.x-p2.x,p1.y-p2.y) #); ExpandRectangle: (# r: @rectangle; e: @integer; enter (r,e) exit (r.x-e, r.y+e, r.width+2*e, r.height+2*e) #); PointInRect: (# p: @Point; r: @Rectangle; enter (p,r) exit ((r.x <= p.x) and (p.x <= r.x+r.width) and (r.y >= p.y) and (p.y >= r.y-r.height)) #); Matrix: (# a,b,c,d,tx,ty: @Real; (* a b 0 * c d 0 * tx ty 1 *) set: (# enter (a,b,c,d,tx,ty) #); invalidate: (* Call invalidate if you manipulate a, b, c, d, tx, or ty *) ...; transformPoint: @ (# p,result: @Point; enter p ... exit result #); inverseTransformPoint: @ (# p1,p2: @Point; enter p1 ... exit p2 #); transformRectangle: @ (# r,result: @Rectangle; enter r do ... exit result #); inverseTransformRectangle: (# r,result: @Rectangle; enter r ... exit result #); getInverse: @ (# get: @...; inverse: ^Matrix; do get; exit inverse[] #); private: @...; do INNER; exit (a,b,c,d,tx,ty) #); IDMatrix: (* Exit an identity matrix *) (# ID: ^Matrix ... exit ID[] #); MoveMatrix: Matrix (* A matrix specifying a translation *) (# itx,ity: @Integer; enter (itx,ity) ... #); ScaleMatrix: Matrix (* A matrix specifying a scaling *) (# enter (a,d) ... #); RotateMatrix: Matrix (* A matrix specifying a rotation *) (# theta: @Real; enter theta ... #); MatrixMul: (* Multiply two matrices *) (# A,B,res: ^Matrix; enter (A[],B[]) ... exit res[] #); EllipseAngle: (* Returns the angle a (in radians) and cos(a), sin(a), * assuming that (x,y) is a point on the ellipse with center in * (cx,cy) and horizontal radius hr and verticalradius vr, * i.e. (x,y) = (cx,cy) + (hr*cos(a),vr*sin(a)) *) (# cx, cy, hr, vr, x, y: @integer; a, cos_a, sin_a: @real; angle: @...; enter (cx, cy, hr, vr, x, y) do angle exit (a, cos_a, sin_a) #); CircleAngle: (* Returns the angle a (in radians) and cos(a), sin(a), * assuming that (x,y) is a point on the circle with center in * (cx,cy) and radius r, for some r * i.e. (x,y) = (cx,cy) + (r*cos(a),r*sin(a)) *) (# cx, cy, x, y: @integer; a, cos_a, sin_a: @real; angle: @...; enter (cx, cy, x, y) do angle exit (a, cos_a, sin_a) #);
PointArray: (* Array of points, extended when needed *) (# <<SLOT PointArrayAttributes: Attributes >>; npoints: @Integer (* Number of points currently in THIS(PointArray) *); initPoints: (* Must be called first *) (# initialsize: @integer; enter initialsize do ...; #); copy: (* Return a deep copy of THIS(PointArray) *) (# p: ^PointArray; ... exit p[] #); scanPoints: (* scan the points in THIS(PointArray). Inx will be the index * of current *) (# current: ^Point; inx: @integer ... #); addPoint: @(* Add p as the last point in THIS(PointArray) *) (# p: @Point; enter p do ...; #); deletePoint: @(* delete the i'th point in THIS(PointArray) *) (# i: @Integer; enter i do ...; #); insertPoint: @(* insert p between the i'th and i+1'th point in THIS(PointArray) *) (# i: @Integer; p: @Point; enter (p, i) do ...; #); getPoint: @ (* Return point no i in THIS(PointArray); 1<=i<=npoints *) (# i: @Integer; p: @Point; enter i ... exit p #); setPoint: @ (* Change the value of point no i to p; 1<=i<=npoints *) (# i: @Integer; p: @Point; enter (p,i) do ...; #); firstPoint: @(* Return first point of THIS(PointArray) *) (# exitPoint: @Point; ... exit exitPoint #); lastPoint: @(* Return last point of THIS(PointArray) *) (# exitPoint: @Point; ... exit exitPoint #); private: @...; #); TextList: list (# element:: Text; copy:<(# c: ^TextList; ... exit c[] #); do INNER; #); IntegerList: list (# IntegerElement: (# i: @integer #); element:: IntegerElement; #); PointArrayList: (* List of PointArrays, used internally *) (# private: @...; appendPointArray: (# p: ^PointArray; enter p[] ... #); scanPointArrays: (# p: ^PointArray; ... #); empty: booleanValue (# ... #); #);
Segment: (# <<SLOT SegmentAttributes: attributes>>; firstPoint:< (# p: @Point do INNER exit p #); lastPoint:< (# p: @Point do INNER exit p#); setFirstPoint:< (# p: @Point enter p do INNER #); setLastPoint:< (# p: @Point enter p do INNER #); nextToFirstPoint:< (# p: @Point do INNER exit p #); nextToLastPoint:< (# p: @Point do INNER exit p #); copy:< (* Returns a deep copy of THIS(Segment) *) (# aCopy: ^Segment; ... exit aCopy[] #); transform:< (* Transform all control points in THIS(Segment) by M *) (# M: ^Matrix enter M[] do INNER #); reverseOrientation:< object; (* INTERACTION *) drawRubberBand:< (* Draw an thin curve along THIS(Segment). Useful when * drawing rubber feedback *) (# theCanvas: ^BifrostCanvas (* The BifrostCanvas to draw the rubberband on *); newPoint: @Point; theGOToDevice: ^Matrix; controlIndex: @Integer; nextSeg: ^Segment; enter (theCanvas[],theGOToDevice[], newPoint,controlIndex,nextSeg[]) do INNER #); getControls:< (* Add all the defining points in THIS(Segment) to spots. If * spots[] is NONE, a PointArray is instantiated. canvasTM is * applied to all controls before they are appended to spots. * If canvasTM[] is NONE, IDmatrix is used. *) (# spots: ^PointArray; canvasTM: ^Matrix; enter (spots[], canvasTM[]) ... exit spots[] #); (* PRIVATE, but virtual and hence cannot be in slots *) prepareReshape:< (* private *) (# theGOToDevice: ^Matrix; controlIndex: @Integer; nextSeg: ^Segment; movingp: @Point; theCanvas: ^BifrostCanvas; enter (theCanvas[],theGOToDevice[],controlIndex,nextSeg[]) do INNER; #); endReshape:< (* private *) (# theGOToDevice: ^Matrix; finalPoint: @Point; controlIndex: @Integer; nextSeg: ^Segment; theCanvas: ^BifrostCanvas; enter (theCanvas[],theGOToDevice[],finalPoint,controlIndex,nextSeg[]) do INNER; #); findSegments:< (* private *) (# p: @point; s1,s2: ^Segment; controlIndex: @Integer; enter p do INNER exit (s1[],s2[],controlIndex) #); calculatePoints:< (* private *) (# thePoints: ^PointArray; thePointList: ^PointArrayList; enter (thePoints[],thePointList[]) do INNER; exit thePointList[] #); makeOffset:< (* private *) (# nextPoint: @Point; offsets: ^PointArray; width: @Integer; enter (offsets[],nextPoint) do INNER; #); makeSecondOffset:< (* private *) (# theShape: ^Shape; index: @Integer; offsets: ^PointArray; enter (theShape[],offsets[],index) do INNER; exit index #); writePS:< (# out: ^stream enter out[] do INNER #); do INNER; exit THIS(Segment)[] #);
LineSegment: Segment (# begin,end: @Point; firstPoint::< (# do begin -> p #); lastPoint::< (# do end -> p #); setFirstPoint::< (# do p -> begin #); setLastPoint::< (# do p -> end #); nextToFirstPoint::< (# do end -> p; #); nextToLastPoint::< (# do begin -> p #); copy::< (# do INNER; ... #); transform::< (# ... #); reverseOrientation::< (# ... #); (* INTERACTION *) drawRubberBand::< (# ... #); getControls::< (# ... #); (* PRIVATE, but virtual and hence cannot be in slots *) writePS::< (# do ... #); prepareReshape::< (* private *) (# ... #); endReshape::< (* private *) (# ... #); findSegments::< (* private *) (# ... #); calculatePoints::< (* private *) (# ... #); makeOffset::< (* private *) (# do ... #); makeSecondOffset::< (* private *) (# do ... #); #);
SplineSegment: Segment (* abstract pattern *) (# <<SLOT SplineAttributes: Attributes >>; controls: ^PointArray; smoothness: @Real (* default 1.0 decrease to get a smoother spline increase to * get a coarser spline *); firstPoint::< (# ... #); lastPoint::< (# ... #); setFirstPoint::< (# ... #); setLastPoint::< (# ... #); nextToFirstPoint::< (# ... #); open:< (* Prepare THIS(SplineSegment) for adding control points *) (# startPoint: @Point; enter startPoint ... #); addControl:< (* Add p as a control point in THIS(SplineSegment) *) (# p: @Point; enter p ... #); insert:< (* Insert p as a control point after the control point at * position index *) (# p: @point; index: @integer; enter (p,index) do INNER #); delete:< (* Delete the control point at position index *) (# index: @integer; enter index do INNER #); copy::< (# do INNER; ... #); transform::< (# ... #); reverseOrientation::< (# do ... #); (* PRIVATE *) writePS::< (# do ... #); prepareReshape::< (* private *) (# ... #); endReshape::< (* private *) (# ... #); DrawRubberSplineDesc:< (* private *) (# track: @Point; controlIndex: @Integer; theCanvas: ^BifrostCanvas; enter (theCanvas[],track,controlIndex) do INNER #); calculatePoints::< (* private *) (# splinePoints: ^PointArray; ... #); splineprivate: @...; do INNER; #); (* SplineSegment *)
CircularSplineSegment: SplineSegment (# nextToLastPoint::< (# ... #); copy::< (# do ... #); drawRubberBand::< (# ... #); (* PRIVATE *) writePS::< (# do ... #); DrawRubberSplineDesc::< (* private *) (# do ... #); findSegments::< (* private *) (# ... #); calculatePoints::< (* private *) (# ... #); getControls::< (* private *) (# ... #); makeOffset::< (* private *) (# do ... #); makeSecondOffset::< (* private *) (# do ... #); do INNER; #);
NonCircularSplineSegment: SplineSegment (# nextToLastPoint::< (# ... #); copy::< (# do ... #); close: (# ... #); isClosed: booleanValue (# ... #); open::< (# ... #); addControl::< (# ... #); drawRubberBand::< (# ... #); (* PRIVATE *) writePS::< (# do ... #); private: @...; DrawRubberSplineDesc::< (* private *) (# do ... #); findSegments::< (* private *) (# ... #); calculatePoints::< (* private *) (# ... #); getControls::< (* private *) (# ... #); makeOffset::< (* private *) (# do ... #); makeSecondOffset::< (* private *) (# do ...#); do INNER; #);
AbstractShape: Segment (# <<SLOT AShapeAttributes: attributes >>; copy::< (# do INNER; ... #); fillRule: @ (* Rule to determine what is inside and what is outside * THIS(AbstractShape). Used, e.g. when filling * THIS(AbstractShape) with some Paint. Defaults to * WindingRule. *) (# r: @Integer; changed: @Boolean; (* initialized as false *) changeRule: (# enter r do True -> changed #); enter changeRule do (if not changed then WindingRule -> r if); exit r #); invalidate:< (* invalidate THIS(AbstractShape), so it will be recalculated * next time used in fill or clip operation. *) (# ... #); invalid: (* Answer true if THIS(AbstractShape) has been invalidated *) (# b: @Boolean; ... exit b #); getBounds:< (* Return the bounding box of THIS(AbstractShape) *) (# bound: @rectangle; ... exit bound #); (* QUERY *) containsPoint:< booleanValue (* Answer whether thePoint is inside THIS(AbstractShape), * thePoint is assumed to be in coordinates relative to * theCanvas. *) (# theCanvas: ^BifrostCanvas; thePoint: @Point; enter (theCanvas[],thePoint) ... #); hotspot: @ (* The default value of hotspot is firstpoint *) (# p: @Point; changed: @Boolean; (* initialized as false *) changeHotspot: (# enter p do True -> changed #); enter changeHotspot do (if not changed then firstPoint -> p if); exit p #); (* HIGHLIGHTING *) hiliteDesc: (* Qualification for highlighting patterns *) (# doneInInner: @boolean; theCanvas: ^BifrostCanvas (* The BifrostCanvas to do the highlighting on *); draw: @boolean (* Should the feedback be drawn or erased ? *); TM: ^Matrix (* TM is applied before the feedback is drawn *); copy:< (* Return a deep copy of THIS(HiliteDesc) *) (# aCopy: ^hiliteDesc; ... exit aCopy[] #); enter (theCanvas[], draw, TM[]) ... #); (* PREDEFINED HIGHLIGHTING PATTERNS *) hiliteControls:< hiliteDesc (* Highlight control points *) (# copy::< (# do INNER; ... #); do INNER; ... #); hiliteOutline:< hiliteDesc (* Highlight outline of THIS(AbstractShape). To be further * bound *) (# hiliteWidth: @integer (* The width of the lines used when highlighting outline. * 0 means as thin as possible (default). Should be the * same as the corresponding hilitewidth. *); copy::< (# do ... #); do INNER #); hiliteBound:< hiliteDesc (* Highlight bounding box *) (# Width: @integer; copy::< (# ... #); do INNER; ...; #); (* The actual highlight patterns used. drawhilite points to one * of hc, ho, hb or some user supplied specialization of * hilitedesc *) hc, ho, hb: ^hiliteDesc; drawHilite: ^hiliteDesc; (* DEFINITION LANGUAGE *) open:< (* Must be called first *) (# p: @Point enter p ... #); (* INTERACTION *) Interaction: (* Prefix for interaction patterns *) (# theCanvas: ^BifrostCanvas; theModifier: @Modifier; startPoint: @Point; enter (theCanvas[], startPoint, theModifier) do INNER; #); InteractiveCreate:< Interaction (* Provide feedback for creating THIS(AbstractShape) * interactively. Make the feedback constrained if * theModifier is on. Start the interaction in startpoint. *); InteractiveCombine:< Interaction (* Create a Shape interactively and combine that Shape with * THIS(AbstractShape). Make the feedback constrained if * theModifier is on. Start the interaction in startpoint. *); InteractiveReshape:< Interaction (* Provide feedback for reshaping THIS(AbstractShape) * interactively. Make the feedback constrained if * theModifier is on. Start the interaction in startpoint. *); transform::< (# ... #); getcontrols::< (# ... #); (* PRIVATE *) writePS::< (# invisible: @boolean; enter invisible do INNER #); privatePart: @...; calculatePoints::< (* private *) (# do ... #); do INNER; #); (* Abstract Shape *)
Shape: AbstractShape (* For making user defined objects *) (# <<SLOT ShapeAttributes: attributes >>; copy::< (# do INNER; ... #); getBounds::< (# ... #); containsPoint::< (# do ...; INNER #); currentPoint:< (* The last control point added *) (# p: @Point; do ...; INNER; exit p #); firstPoint::< (# do ...; INNER #); lastPoint::< (# ... #); nextToFirstPoint::< (# ... #); nextToLastPoint::< (# ... #); open::< (# ... #); (* DEFINITION LANGUAGE *) addSpline: (* Add Spline beginning at currentpoint. Spline.lastpoint * becomes new currentpoint *) (# Spline: ^SplineSegment; enter spline[] do ...; #); lineTo: (* If currentPoint is a control point in a spline being * defined with splineTo, that spline is ended. Add a * LineSegment beginning at currentPoint and ending at p. p * becomes new currentPoint. *) (# p: @Point; enter p do ...; #); splineTo: (* If currentPoint is the end point in a line segment, a new * spline segment is opened. That spline segment becomes the * "current spline segment". Add currenPoint as the first * control point of the current spline segment. Add p as a * control point to the current spline segment. p becomes new * currentPoint. *) (# p: @Point; enter p ... #); close:< (* Should be called after the definition is finished *) (# ... #); (* QUERY FUNCTIONS *) isClosed: booleanValue (* NOTICE: an empty shape is considered closed!!*) (# ... #); isEmpty: booleanValue (# ... #); isFlat: booleanValue (* THIS(AbstractShape) is flat iff it contains no splines *) (# ... #); (* MANIPULATING THE SHAPE *) reverseOrientation::< (# do ...; INNER #); stroke: (* Change THIS(Shape) to be the shape obtained by stroking a * "pen" with the witdh W along THIS(Shape). When stroking an * open Shape, the look of the "ends" of the resulting shape * is specified with capStyle. At joining points the joining * style is specified by joinStyle. *) (# W: @Integer; capstyle: @capstyledesc; joinstyle: @joinstyledesc; enter (W, capstyle, joinstyle) do ...; #); insert: (* Not Yet Implemented *) (* If p1 is in the neighborhood of an existing control point, * P2 is added as a new control point is between the neighbor * point and the next point. *) (# p1, p2: @point; enter (p1,p2) ... #); delete: (* Not Yet Implemented *) (* If p is in the neighborhood of an existing control point, * this control point is deleted *) (# p: @point; enter p ... #); (* COMBINING SHAPES *) appendShape: (* Not Yet Implemented *) (* Add sourceShape to THIS(Shape). Place * sourceShape.firstPoint in THIS(Shape).lastPoint by * translating the entire sourceShape. This is the only * transformation involved. After the operation, * THIS(Shape).lastPoint is the translated * sourceShape.lastPoint. sourceShape cannot consist of * circularSplines only. *) (# sourceShape: ^Shape; enter sourceShape[] ... #); connectShape: (* Not Yet Implemented *) (* Add sourceShape to THIS(Shape). TM is applied to * sourceShape before the addition. THIS(Shape).lastpoint is * connected to sourceShape.firstPoint with a line segment. * After the operation, THIS(Shape).lastPoint is the * translated sourceShape.lastPoint. * sourceShape cannot consist of circularSplines only. *) (# TM: ^Matrix; sourceShape: ^Shape; enter (TM[],sourceShape[]) ... #); connectShapeSmooth: (* Not Yet Implemented *) (* Add sourceShape to THIS(Shape). TM is applied to * sourceShape before the addition. THIS(Shape).lastpoint is * connected to sourceShape.firstPoint with a spline segment * constructed from the last two points in THIS(Shape) and * sourceShape.firstPoint. After the operation, * THIS(Shape).lastPoint is the translated * sourceShape.lastPoint. sourceShape cannot consist of * circularSplines only. *) (# TM: ^Matrix; sourceShape: ^Shape; enter (TM[],sourceShape[]) ... #); combineShape: (* Add sourceShape to THIS(Shape). TM is applied to * sourceShape before the addition. sourceShape and * THIS(Shape) do *not* become connected. At least one of * THIS(Shape) and sourceShape must be closed. If sourceShape * is closed, THIS(Shape).lastPoint is unchanged. If * sourceShape is open, THIS(Shape).lastPoint is * sourceshape.lastPoint after the operation. *) (# TM: ^Matrix; sourceShape: ^Shape; enter (TM[],sourceShape[]) do ...; #); (* HIGHLIGHTING *) hiliteOutline::< (# ... #); (* INTERACTION *) InteractiveCreate::< (# do ...; INNER #); InteractiveCombine::< (# do ...; INNER #); InteractiveReshape::< (# do ...; INNER #); transform::< (# do ...; INNER #); getControls::< (# do ... #); (* PRIVATE *) findSegments::< (* private *) (# do ... #); writePS::< (# do ... #); do INNER; #); (* Shape *)
PredefinedShape: AbstractShape (# CalculateShape:< (* Return (approximating) Shape, if possible *) (# s: ^Shape do INNER exit (# ... exit s[] #) #); invalidate::< (# ... #); containsPoint::< (# ... #); transform::< (# do ...; INNER #); (* Patterns behaving like standard "types", but that have the * side-effect of invalidating THIS(PredefinedShape) when * changed. *) invalidatePoint: (# p: @Point; enter (# enter p do Invalidate #) exit p #); invalidateInteger: integerValue (# enter (# enter value do Invalidate #) #); invalidateReal: (# r: @Real; enter (# enter r do Invalidate #) exit r #); invalidateDash: (* For instance {1,2,4,2} yields '= ==== = ==== =' etc. *) (# d: ^IntegerList; enter (# enter d[] do invalidate #) exit d[] #); invalidateCapStyle: (# c: @CapStyleDesc; enter (# enter c do invalidate #) exit c #); invalidateJoinStyle: (# j: @JoinStyleDesc; enter (# enter j do invalidate #) exit j #); writePS::< (# do ... #); prePrivate: @...; do INNER; #);
LineShape: PredefinedShape (# <<SLOT LineShapeAttributes: attributes>>; firstPoint::< (# do begin -> p #); begin: @InvalidatePoint; end: @InvalidatePoint; width: @InvalidateInteger; dashes: @InvalidateDash; (* Not Yet Implemented *) cap: @InvalidateCapStyle; coordinates: (# enter (begin, end) exit (begin, end) #); open::< (# ... #); getBounds::< (# do ...; INNER #); containsPoint::< (# ... #); getControls::< (# ... #); copy::< (# do INNER; ... #); (* HIGHLIGHTING *) hiliteOutline::< (# do INNER; ... #); (* INTERACTION *) interactiveCreate::< (# do ...; INNER #); interactiveReshape::< (# do ...; INNER #); writePS::< (# do ... #); transform::< (# ... #); CalculateShape::< (* private *) (# ... #); do INNER; #);
MultiLineShape: PredefinedShape (# <<SLOT MultiLineShapeAttributes: attributes>>; firstPoint::< (# ... #); lastPoint::< (# ... #); points: @ (# p: ^PointArray; enter (# enter p[] do invalidate #) exit p[] #); width: @InvalidateInteger; dashes: @InvalidateDash; (* Not Yet Implemented *) cap: @InvalidateCapStyle; join: @InvalidateJoinStyle; open::< (# ... #); addPoint: (* Add p at the end of points *) (# p: @point; enter p ... #); deletePoint: (* Delete p at from points *) (# p: @point; enter p ... #); insertPoint: (* Insert p in points at position i *) (# p: @point; i: @integer enter (p,i) ... #); getPoint: (* Return point no i in THIS(MultiLineShape); 1<=i<=npoints *) (# i: @Integer; p: @Point; enter i ... exit p #); setPoint: (* Change the value of point no i to p; 1<=i<=npoints *) (# i: @Integer; p: @Point; enter (p,i) ... #); closestLineSegment: (# p: @point; i: @integer enter p do ... exit i #); getBounds::< (# do ...; INNER #); containsPoint::< (# ... #); getControls::< (# ... #); copy::< (# do INNER; ... #); (* HIGHLIGHTING *) hiliteOutline::< (# do INNER; ... #); (* INTERACTION *) interactiveCreate::< (# do ...; INNER #); interactiveReshape::< (# do ...; INNER #); writePS::< (# do ... #); transform::< (# ... #); calculateShape::< (* private *) (# ... #); do INNER; #);
TextShape: PredefinedShape (# <<SLOT TextShapeAttributes: attributes>>; firstPoint::< (# do position -> p #); initText: (* Specify several attributes simultaneously *) (# enter (position, theFontname, theStyle, size, underline, theText) #); position: (* Where to place the baseline of the first line of theText *) (# p: @Point; enter (# enter p ... #) ... exit p #); theFontName: (* one of Courier, Times, Helvetica *) (# nam: @fontname; enter (# enter nam ... #) ... exit nam #); theStyle: (* Either Plain, Italic or Bold *) (# sty: @Style; enter (# enter sty ... #) ... exit sty #); size: (* The size in points (1/72 inch) of the text drawn *) (# siz: @Integer; enter (# enter siz ... #) ... exit siz #); underline: (* Specifies if the text is to be underlined *) (# ul: @Boolean; enter (# enter ul ... #) ... exit ul #); theText: (* Holds the characters of THIS(TextShape). i.e. it joins * the text lines in theLines into one text, where newlines * are inserted for line breaks. *) (# t: ^Text; enter (# enter t[] ... #) ... exit t[] #); theLines: (* Each text element in this list corresponds to one line * of text in THIS(TextShape). *) (# l: ^TextList; enter (# enter l[] ... #) ... exit l[] #); numberOfLines: integerValue (* Number of Texts in theLines *) (# ... #); getBounds::< (# do ...; INNER #); containsPoint::< (# ... #); getControls::< (# do ...; INNER #); copy::< (# do INNER; ... #); (* HIGHLIGHTING *) hiliteOutline::< (# do INNER; ... #); (* INTERACTION *) interactiveCreate::< (# lastCh: @char; (* Last character typed in interaction *) do ...; INNER exit lastCh #); interactiveReshape::< (# lastCh: @char; (* Last character typed in interaction *) ... exit lastCh #); writePS::< (# do ... #); transform::< (# ... #); TextPrivate: @ ...; calculateShape::< (* private *) (# ... #); do INNER; #);
PieShape: PredefinedShape (# <<SLOT PieShapeAttributes: attributes>>; firstPoint::< (# do center -> p #); center: @InvalidatePoint; horizontalRadius: @InvalidateInteger; verticalRadius: @InvalidateInteger; (* Use: 0 <= angle1 <= 360 a1 <= angle2 <= 360+angle1 *) angle1: @InvalidateReal; angle2: @InvalidateReal; open::< (# do ...; INNER #); getBounds::< (# do ...; INNER #); containsPoint::< (# do ...; INNER #); getControls::< (# do ...; INNER #); copy::< (# do INNER; ... #); (* HIGHLIGHTING *) hiliteOutline::< (# do INNER; ... #); (* INTERACTION *) interactiveCreate::< (# do ...; INNER #); interactiveReshape::< (# do ...; INNER #); writePS::< (# do ... #); transform::< (# ... #); calculateShape::< (* private *) (# ... #); do INNER #);
ArcShape: PredefinedShape (# <<SLOT ArcShapeAttributes: attributes>>; firstPoint::< (# do center -> p #); center: @InvalidatePoint; horizontalRadius: @InvalidateInteger; verticalRadius: @InvalidateInteger; (* Use: 0 <= angle1 <= 360 a1 <= angle2 <= 360+angle1 *) angle1: @InvalidateReal; angle2: @InvalidateReal; arcWidth: @InvalidateInteger; open::< (# ... #); getBounds::< (# do ...; INNER #); containsPoint::< (# do ...; INNER #); getControls::< (# do ...; INNER #); copy::< (# do INNER; ... #); (* HIGHLIGHTING *) hiliteOutline::< (# do INNER; ... #); (* INTERACTION *) interactiveCreate::< (# do ...; INNER #); interactiveReshape::< (# do ...; INNER #); writePS::< (# do ... #); transform::< (# ... #); calculateShape::< (* private *) (# ... #); do INNER #);
StrokeableShape: PredefinedShape (# stroked: @Boolean; strokewidth: @Integer; writePS::< (# do ... #); getBounds::< (# ... #); copy ::< (# do INNER; ... #); do INNER #);
RectShape: StrokeableShape (# <<SLOT RectShapeAttributes: attributes>>; firstPoint::< (# do upperleft -> p #); upperleft: @InvalidatePoint; width: @InvalidateInteger; height: @InvalidateInteger; corners: (# lowerright: @Point; changeCorners: (# enter (upperleft,lowerright) ... #); enter changeCorners exit (upperleft, ((upperleft.p.x+width), (upperleft.p.y+height)) ) #); open::< (# ... #); getBounds::< (# ... #); containsPoint::< (# ... #); getControls::< (# ... #); copy::< (# do INNER; ... #); (* HIGHLIGHTING *) hiliteOutline::< (# do INNER; ... #); (* INTERACTION *) interactiveCreate::< (# do ...; INNER #); interactiveReshape::< (# do ...; INNER #); writePS::< (# do ... #); transform::< (# ... #); calculateShape::< (* Private *) (# ... #); do INNER; #);
EllipseShape: StrokeableShape (# <<SLOT EllipseShapeAttributes: attributes>>; firstPoint::< (# do center -> p #); center: @InvalidatePoint; horizontalradius: @InvalidateInteger; verticalradius: @InvalidateInteger; geometry: (# enter (center, verticalradius, horizontalradius) exit (center, verticalradius, horizontalradius) #); open::< (# ... #); getBounds::< (# ... #); containsPoint::< (# ... #); getControls::< (# do ...; INNER #); copy::< (# do INNER; ... #); (* HIGHLIGHTING *) hiliteOutline::< (# do INNER; ... #); (* INTERACTION *) interactiveCreate::< (# ... #); interactiveReshape::< (# do ...; INNER #); writePS::< (# do ... #); transform::< (# ... #); calculateShape::< (* private *) (# do ... #); do INNER; #);
Raster: (* An abstract superpattern for all Rasters. A raster is a * rectangular grid of pixels. *) (# <<SLOT RasterAttributes: attributes>>; hotspot: (* When used in a filling operation hotspot is placed in * hotspot of the shape being filled. Defaults to (0,0). *) (# p: @Point; enter (# enter p ... #) exit (# ... exit p #) #); pixel:< Object; init:< (# width, height: @integer; enter (width, height) ... #); copy:< (* Return a deep copy of THIS(Raster) *) (# aCopy: ^Raster; ... exit aCopy[] #); width: integerValue (* returns the width set by init or by read operations *) (# ... #); height: integerValue (* returns the height set by init or by read operations *) (# ... #); putPixel:< (# i, j: @integer; p: ^pixel; enter (i,j,p[]) ... #); getPixel:< (# i, j: @integer; p: ^pixel; enter (i,j) ... exit p[] #); (* Private *) calculate:< (# ... #); RasterPrivatePart: @ ...; do INNER; calculate; exit THIS(Raster)[] #); BitMap: Raster (* Raster in which the pixels are booleans *) (# <<SLOT BitmapAttributes: attributes>>; pixel::< (# b: @boolean enter b exit b #); init::< (# do ...; INNER #); putPixel::< (# do ...; INNER #); getPixel::< (# do ...; INNER #); copy::< (# do INNER; ... #); writeToPBMfile: (* Not Yet Implemented *) (# pbmfilename: ^text; rawbits: @boolean (* If true, the RAWBITS format is used *); enter (pbmfilename[],rawbits) ... #); readFromPBMfile: (# pbmfilename: ^text; enter pbmfilename[] do ...; #); (* Private *) calculate::< (# ... #); BitMapPrivatePart: @ ...; do INNER; #); GrayMap: Raster (* Not Yet Implemented *) (# <<SLOT GraymapAttributes: attributes>>; pixel::< (# g: @integer enter g exit g #); init::< (# ... #); putPixel::< (# ... #); getPixel::< (# ... #); copy::< (# do INNER; ... #); writeToPGMfile: (# pgmfilename: ^text; rawbits: @boolean (* If true, the RAWBITS format is used *); enter (pgmfilename[],rawbits) ... #); readFromPGMfile: (# pgmfilename: ^text; enter pgmfilename[] ... #); (* Private *) calculate::< (# ... #); GrayMapPrivatePart: @ ...; do INNER; #); PixMap: Raster (* Raster in which the pixels are RGB values *) (# <<SLOT PixmapAttributes: attributes>>; pixel::< (# r,g,b: @integer enter (r,g,b) exit (r,g,b) #); init::< (# maxVal: @integer; (* Maximum RGB value *) enter maxVal do ...; INNER #); putPixel::< (# do ...; INNER #); getPixel::< (# ... #); copy::< (# do INNER; ... #); writeToPPMfile: (* Not Yet Implemented *) (# ppmfilename: ^text; rawbits: @boolean (* If true, the RAWBITS format is used *); enter (ppmfilename[],rawbits) ... #); readFromPPMfile: (* Not Yet Implemented *) (# ppmfilename: ^text; enter ppmfilename[] ... #); (* Private *) calculate::< (# ... #); PixMapPrivatePart: @ ...; do INNER; #);
Paint: (* An abstract superpattern for all paint *) (# <<SLOT PaintAttributes: attributes>>; init:< object; copy:< (* Return a deep copy of THIS(Paint) *) (# aCopy: ^Paint; ... exit aCopy[] #); fill: (* Prefix for fill operations *) (# theCanvas: ^BifrostCanvas enter theCanvas[] do INNER #); fillShape:< fill (* Fill theShape with THIS(Paint) in theCanvas. *) (# theShape: ^Shape; enter (theShape[]) ... #); fillLine:< fill (* Fill theLine with THIS(Paint) in theCanvas. *) (# theLine: ^LineShape; enter (theLine[]) ... #); fillMultiLine:< fill (* Fill theMultiLine with THIS(Paint) in theCanvas. *) (# theMultiLine: ^MultiLineShape; enter (theMultiLine[]) ... #); fillText:< fill (* Fill the specified text with THIS(Paint) in theCanvas *) (# theText: ^TextShape; enter (theText[]) ... #); fillPie:< fill (* Fill thePie with THIS(Paint) in theCanvas. *) (# thePie: ^pieShape; enter (thePie[]) ... #); fillArc:< fill (* Fill theArc with THIS(Paint) in theCanvas. *) (# theArc: ^arcShape; enter (theArc[]) ... #); fillRect:< fill (* Fill theRect with THIS(Paint) in theCanvas. *) (# theRect: ^RectShape; enter (theRect[]) ... #); fillEllipse:< fill (* Fill the theEllipse with THIS(Paint) in theCanvas *) (# theEllipse: ^EllipseShape; enter (theEllipse[]) ... #); fillOther:< fill (* Used to fill other, e.g. user defined, shapes *) (# theShape: ^AbstractShape; enter theShape[] do INNER; #); (* PRIVATE *) writePS:< (# out: ^stream; shape_hotspot: @point enter (out[], shape_hotspot) do INNER #); paintprivate: @ ...; setSpecialPaint: (* Private *) (# theCanvas: ^BifrostCanvas; doneInInner: @boolean; enter theCanvas[] do INNER #); setCanvasPaint:< (* Private *) setSpecialPaint; setBorderPaint:< (* Private *) setSpecialPaint; SetBackgroundPaint:< (* Private *) setSpecialPaint; do INNER; exit THIS(Paint)[] #);
SolidColor: Paint (* A solid color specified relative to the RGB, HSV, or CMY color * spaces, or by naming the color, using one of the name patterns * in the fragment ColorNames. *) (# <<SLOT SolidColorAttributes: attributes>>; init::< (# ... #); copy::< (# do INNER; ... #); Name: (* Change THIS(SolidColor) to the color specified. The color * names are define as descriptors in the fragment * 'ColorNames'. NOTICE: This is different from earlier * versions of Bifrost. *) (# enter RGBvalues #); RGBvalues: (* Set or query the Red-Green-Blue values of THIS(SolidColor) * r, g and b all ranges from 0 to MaxRGB. *) (# r,g,b: @Integer; changeRGB: (# enter (r,g,b) ... #); getRGB: (# ... exit (r,g,b) #); enter changeRGB exit GetRGB #); HSVvalues: (* Set or query the Hue-Saturation-Value values of * THIS(SolidColor). h, s and v are taken to range from 0 to * MaxHue, MaxSat and MaxVal respectively. Specializations may * alter the default bindings of these. *) (# h,s,v: @Integer; changeHSV: (# enter (h,s,v) do ... #); getHSV: (# do ... exit (h,s,v) #); MaxHue:< integerValue (# do DefaultMaxHue -> value; INNER #); MaxSat:< integerValue (# do DefaultMaxSat -> value; INNER #); MaxVal:< integerValue (# do DefaultMaxVal -> value; INNER #); enter changeHSV exit getHSV #); CMYvalues: (* RGB complementaries *) (* Set or query the Cyan-Magenta-Yellow values of * THIS(SolidColor). c, m and y all ranges from 0 to MaxRGB. *) (# c,m,y: @Integer; changeCMY: (# enter (c,m,y) do ... #); getCMY: (# do ...; exit (c,m,y) #); enter changeCMY exit getCMY #); fillShape::< (# ... #); fillLine::< (# do INNER; ... #); fillMultiLine::< (# ... #); fillText::< (# do INNER; ... #); fillPie::< (# do INNER; ... #); fillArc::< (# do INNER; ... #); fillRect::< (# do INNER; ... #); fillEllipse::< (# do INNER; ... #); (* PRIVATE *) writePS::< (# do ... #); setBorderPaint::< (* Private *) (# ...#); setBackgroundPaint::< (* Private *) (# ...#); setCanvasPaint::< (* Private *) (# ...#); privatePart: @ ...; do INNER; #);
SolidGray: (# g: ^SolidColor; percentage: @Integer; enter percentage ... exit g[] #); SolidGrey: SolidGray (# do INNER #);
RasterPaint: Paint (* Use thePixmap and optionally paddingSolidColor to fill out the * shape *) (# (* If paddingSolidColor[]=NONE thePixmap will be repeated when * filling out the shape. If not, paddingSolidColor will be used * to fill out any parts of the shape the pixmap doesn't cover. *) paddingSolidColor: ^SolidColor; thePixMap: (# p: ^PixMap; enter (# enter p[] ... #) exit (# ... exit p[] #) #); init::< (# ... #); copy::< (# do INNER; ... #); fillShape::< (# do INNER; ...; #); fillLine::< (# ... #); fillMultiLine::< (# ... #); fillText::< (# ... #); fillArc::< (# ... #); fillPie::< (# ... #); fillRect::< (# ... #); fillEllipse::< (# ... #); (* PRIVATE *) writePS::< (# do ... #); private: @...; setBorderPaint::< (* Private *) (# do INNER; ... #); setBackgroundPaint::< (* Private *) (# do INNER; ... #); setCanvasPaint::< (* Private *) (# do INNER; ... #); do INNER; #);
TiledSolidColor: SolidColor (* A SolidColor extended with a BitMap. The BitMap will be tiled in * the Shape before the SolidColor is applied, and only where the * bits of the BitMap are true, the SolidColor will be visible. *) (# theTile: (# t: ^BitMap; enter (# enter t[] ... #) exit (# ... exit t[] #) #); init::< (# ... #); copy::< (# do INNER; ... #); fillShape::< (# ... #); fillLine::< (# ... #); fillMultiLine::< (# ... #); fillText::< (# ... #); fillArc::< (# ... #); fillPie::< (# ... #); fillRect::< (# ... #); fillEllipse::< (# ... #); (* PRIVATE *) writePS::< (# do ... #); tiledPrivate: @ ...; setBorderPaint::< (* Private *) (# do INNER; ... #); setBackgroundPaint::< (* Private *) (# do INNER; ... #); setCanvasPaint::< (* Private *) (# do INNER; ... #); do INNER; #);
AbstractGraphicalObject: (* To be further specialized *) (* The graphical object is the smallest entity that can be drawn * in a BifrostCanvas. It is a aggregation of a Paint and a Shape. * ANY graphical object MUST be initialized before used (init). * After a paint and a shape has been specified, it can be drawn by * giving the reference of it as enter parameter to the method * "draw" in a BifrostCanvas. Graphical objects may also be * created by using InteractiveCreateShape. *) (# <<SLOT AbstractGraphicalObjectAttributes: attributes>>; shapeDesc:< AbstractShape (* Specify actual shape in specializations *); TMDesc:< (# m: ^Matrix; transformpoint: @ (# p: @Point enter p do p->m.transformpoint->p exit p #); CalcCanvasTM:< (# theTM: ^Matrix enter theTM[] ... #); enterTM:< (# enter m[] ... #); enterIt: @enterTM; enter enterIt do INNER; exit m[] #); (* TM describes the transformation from the coordinate system of * theShape (also known as GO coordinates) to the the Picture it * is part of, if any. *) TM: @TMDesc; init:< (* MUST be called first *) (# ... #); readUserData:< (# userdata: ^text; success: @boolean; parseNotification: notification (# do false -> success; INNER #); parseError:< parseNotification enter userdata[] do true -> success; INNER exit success #); writeUserData:< (# userdata: ^text do &text[] -> userdata[]; INNER exit userdata[] #); setPaint:< (* Specify the paint to use for THIS(AbstractGraphicalObject) *) (# enter thePaint[] do INNER #); getPaint:< (* Obtain the paint to use *) (# do INNER exit thePaint[] #); getShape:< (* Obtain the shape to use. The specialization * PredefinedGraphicalObject returns an approximating Shape. * Only the specialization Shape has a corresponding SetShape. *) (# s: ^Shape do INNER exit s[] #); draw:< (* Draw THIS(AbstractGraphicalObject) in theCanvas. * Normally this is not used by the user directly. Instead * THIS(AbstractGraphicalObject)[] should be given to the draw * method of a BifrostCanvas. *) (# doneInInner: @boolean; theCanvas: ^BifrostCanvas (* BifrostCanvas to draw THIS(AbstractGraphicalObject) on *); enter theCanvas[] ... #); erase:< (* Erase THIS(AbstractGraphicalObject) from theCanvas. * Normally this is not used by the user directly. Instead * THIS(AbstractGraphicalObject)[] should be given to the erase * method of a BifrostCanvas. *) (# doneInInner: @boolean; theCanvas: ^BifrostCanvas (* BifrostCanvas to erase THIS(AbstractGraphicalObject) from *); enter theCanvas[] ... #); copy:< (* Return a deep copy of THIS(AbstractGraphicalObject) *) (# aCopy: ^AbstractGraphicalObject; ... exit aCopy[] #); getBounds:< (* Exit a Rectangle containing the bounding box of * THIS(AbstractGraphicalObject) in BifrostCanvas coordinates. *) (# r: @rectangle; doneInInner: @boolean; ... exit r #); hilite:< (* Highlight THIS(AbstractGraphicalObject) *) (# doneInInner: @boolean; theCanvas: ^BifrostCanvas (* The BifrostCanvas to do the highlighting on *) enter theCanvas[] ... #); unHilite:< (* Unhighlight THIS(AbstractGraphicalObject) *) (# doneInInner: @boolean; theCanvas: ^BifrostCanvas (* The BifrostCanvas to do the unhighlighting on *) enter theCanvas[] ... #); (* INTERACTION *) hitControl:< (* Answer whether thePoint is inside a 2x2mm box around a * control point of THIS(AbstractGraphicalObject). thePoint is * in BifrostCanvas coordinates. Exits reference to exact point * if hit, NONE otherwise. *) (# thePoint: @Point; res: ^Point; enter thePoint do ...; INNER; exit res[] #); interaction: (* Prefix for interactive operations *) (# theCanvas: ^BifrostCanvas (* The BifrostCanvas to show feedback in *); startPoint: @Point; theModifier: @Modifier; doneInInner: @boolean; enter (theCanvas[], startPoint, theModifier) do INNER; #); interactiveCreateShape:< interaction (* Initialize the shape of THIS(AbstractGraphicalObject) by * providing feedback in a BifrostCanvas. Normally this is not * used by the user directly. Instead * THIS(AbstractGraphicalObject)[] should be given to the * interactiveCreateShape method of a BifrostCanvas. *) (# ... #); interactiveCombineShape:< interaction (* Combine a shape with the shape of * THIS(AbstractGraphicalObject) by providing feedback for * creating the new shape in a BifrostCanvas, and then combining * the shape of THIS(AbstractGraphicalObject) with the obtained * shape. Normally this is not used by the user directly. * Instead THIS(AbstractGraphicalObject)[] should be given to * the interactiveCombineShape method of a BifrostCanvas. *) (# ... #); interactiveReshape:< interaction (* Change the shape of THIS(AbstractGraphicalObject) by * providing feedback in a BifrostCanvas. Normally this is not * used by the user directly. Instead * THIS(AbstractGraphicalObject)[] should be given to the * interactiveReShape method of a BifrostCanvas. *) (# do ... #); interactiveMove:< interaction (* Move the shape of THIS(AbstractGraphicalObject) using * theshape.(un)hiliteoutline for feedback in the BifrostCanvas * THIS(AbstractGraphicalObject) is drawn in. Calls "move" to * do the transformation. Normally this is not used by the user * directly. Instead THIS(AbstractGraphicalObject)[] should be * given to the interactiveMove method of a BifrostCanvas. *) (# do INNER; ...; #); interactiveScale:< interaction (* Not Yet Implemented *) (* Scale the shape of THIS(AbstractGraphicalObject) using * theshape.(un)hiliteoutline for feedback in the BifrostCanvas * THIS(AbstractGraphicalObject) is drawn in. Calls "scale" to * do the transformation. Normally this is not used by the user * directly. Instead THIS(AbstractGraphicalObject)[] should be * given to the interactiveScale method of a BifrostCanvas. *) (# ... #); interactiveRotate:< interaction (* Not Yet Implemented *) (* Rotate the shape of THIS(AbstractGraphicalObject) using * theshape.(un)hiliteoutline for feedback in the BifrostCanvas * THIS(AbstractGraphicalObject) is drawn in. Calls "rotate" to * do the transformation. Normally this is not used by the user * directly. Instead THIS(AbstractGraphicalObject)[] should be * given to the interactiveRotate method of a BifrostCanvas. *) (# ... #); (* TRANSFORMATIONS *) transform:< (* Transform THIS(AbstractGraphicalObject) by M, by multiplying * THIS(AbstractGraphicalObject).TM with M *) (# M: ^Matrix; enter M[] ... #); move:< (* Translate THIS(AbstractGraphicalObject) by offset *) (# offset: @Point; enter offset do ...; INNER; #); moveTo:< (* Move THIS(AbstractGraphicalObject).theShape.hotSpot to pos *) (# pos: @Point; enter pos do ...; INNER; #); scale:< (* Scale THIS(AbstractGraphicalObject) by factor *) (# factor: @Vector; (* Real point *) enter factor do ...; INNER; #); rotate:< (* Rotate THIS(AbstractGraphicalObject) by angle (degrees) *) (# angle: @Real; enter angle do ...; INNER; #); (* QUERY *) containsPoint:< booleanValue (* Answer if thePoint is inside the shape of * THIS(AbstractGraphicalObject). thePoint is assumed to be in * coordinates relative to theCanvas. *) (# theCanvas: ^BifrostCanvas; thePoint: @Point; doneInInner: @boolean; enter (theCanvas[], thePoint) ... #); (* The aggregation parts *) theShape: ^ShapeDesc; thePaint: ^Paint; (* PRIVATE *) writePS:< (# out: ^stream; invisible: @boolean enter out[] do ... #); private: @ ...; recalculateShape:< (* private *) (# theCanvas: ^BifrostCanvas enter theCanvas[] do INNER #); do INNER; exit THIS(AbstractGraphicalObject)[] #);
GraphicalObject: AbstractGraphicalObject (# shapeDesc::< (* The real shape with lines and splines *) Shape; setShape: (* Set the Shape of THIS(GraphicalObject) *) (# enter theShape[] #); getShape::< (* Get the Shape of THIS(GraphicalObject) *) (# do theShape[] -> s[] #); copy::< (# ... #); draw::< (# ... #); writePS::< (# do ... #); hilite::< (# ... #); unHilite::< (# ... #); recalculateShape::< (* private *) (# ... #); do INNER #);
PictureShape: AbstractShape (* To be further specialized *) (# <<SLOT PictureShapeAttributes: attributes>>; firstpoint::< (# ... #); copy::< (# do INNER; ... #); getBounds::< (# do ... #); containsPoint::< (# ... #); getControls::< (# ... #); hiliteControls::< (# ... #); hiliteOutline::< (# ... #); transform::< (# do ...; INNER #); (* Private *) writePS::< (# do ... #); pictureprivate: @...; do INNER #);
Picture: AbstractGraphicalObject (* A collection of graphical objects *) (# <<SLOT PictureAttributes: attributes >>; shapeDesc::< PictureShape; TMDesc::< (# CalcCanvasTM::<(# do ...; INNER #); enterTM::< (# do ...; INNER #); do INNER; #); init::< (# ... #); add:< (* Add go to THIS(Picture) *) (# go: ^AbstractGraphicalObject; enter go[] ... #); delete:< (* Delete go from THIS(Picture) *) (# go: ^AbstractGraphicalObject; enter go[] ... #); drawOnPixmap: (* Not Yet Implemented *) (* Draw THIS(Picture) on pm *) (# pm: ^Pixmap; enter pm[] do ...; #); draw::< (# ... #); erase::< (# ... #); copy::< (# do INNER; ... #); setPaint::< (* Specify the paint to use for all AbstractGraphicalObjects * in THIS(Picture). If they are shown on the Canvas, their * visual appearance is changed instantly. *) (# theCanvas: ^BifrostCanvas; enter theCanvas[] ... #); getBounds::< (# ... #); hilite::< (# ... #); unHilite::< (# ... #); bringForward: (* Make aGO the last AbstractGraphicalObject of THIS(Picture) * aGO must already be a member of THIS(Picture) *) (# aGO: ^AbstractGraphicalObject; enter aGO[] ... #); sendBehind: (* Make aGO the first AbstractGraphicalObject of THIS(Picture) * aGO must already be a member of THIS(Picture) *) (# aGO: ^AbstractGraphicalObject; enter aGO[] ... #); scanGOs: (* Scan through each AbstractGraphicalObject in THIS(Picture) * in order from the bottommost to the frontmost one. *) (# go: ^AbstractGraphicalObject; ... #); scanGOsReverse: (* Scan through each AbstractGraphicalObject in THIS(Picture) * in order from the frontmost to the bottommost one. *) (# go: ^AbstractGraphicalObject; ... #); (* INTERACTION *) interactiveCreateShape::< (# ... #); interactiveCombineShape::< (# ... #); interactiveReshape::< (# ... #); (* QUERY *) lastGO: (* Exit reference to last AbstractGraphicalObject in * THIS(Picture) *) (# aGO: ^AbstractGraphicalObject; ... exit aGO[] #); firstGO: (* Exit reference to last AbstractGraphicalObject in * THIS(Picture) *) (# aGO: ^AbstractGraphicalObject; ... exit aGO[] #); noOfGOs: integerValue (* Exit number of AbstractGraphicalObjects in THIS(Picture) *) (# ... #); isEmpty: booleanValue (* True iff no graphical objects has been added to * THIS(Picture) *) (# ... #); isMember: booleanValue (* True iff aGO has been added to THIS(Picture) *) (# aGO: ^AbstractGraphicalObject; enter aGO[] ... #); containsPoint::< (* Answer if thePoint (canvascoordinates) is inside the shape * of any graphical object of THIS(Picture) *) (# ... #); firstContaining:< (* Returns reference to first AbstractGraphicalObject in * THIS(Abstract) that contains thePoint. * thePoint is assumed to be in coordinates relative to * theCanvas. *) (# theCanvas: ^BifrostCanvas; thePoint: @Point; aGO: ^AbstractGraphicalObject; enter (theCanvas[], thePoint) ... exit aGO[] #); lastContaining:< (* Returns reference to last AbstractGraphicalObject in * THIS(Picture) that contains thePoint. * thePoint is assumed to be in coordinates relative to * theCanvas. *) (# theCanvas: ^BifrostCanvas; thePoint: @Point; aGO: ^AbstractGraphicalObject; enter (theCanvas[], thePoint) ... exit aGO[] #); writePS::< (# do ... #); do INNER; #); (* Picture *)
(* The BifrostCanvas is the connection between the graphic * definitions and the device. Graphical objects become visible on * the output device when they are added to a BifrostCanvas by the * use of the draw-method. *) BifrostCanvas: Canvas (# <<SLOT CanvasAttributes: attributes >>; thePicture: (* Picture holding the graphical objects *) ^Picture; visualShape: (* The part of THIS(BifrostCanvas) that is visible *) ^Shape; clipShape: (* Shape used for clipping in THIS(BifrostCanvas). Defaults to * visualShape *) ^Shape; draw: (* Put GO on THIS(BifrostCanvas) *) (# GO: ^AbstractGraphicalObject enter GO[] ... #); erase: (* Erase GO from THIS(BifrostCanvas) *) (# aGO: ^AbstractGraphicalObject; enter aGO[] ... #); refresh: (* Mark entire BifrostCanvas as damaged and repair *) ...; scanThePicture: (* Scan through each AbstractGraphicalObject in thePicture in * order from the bottommost to the frontmost one. *) (# go: ^AbstractGraphicalObject; ... #); scanThePictureReverse: (* Scan through each AbstractGraphicalObject in thePicture in * order from the frontmost to the bottommost one. *) (# go: ^AbstractGraphicalObject; ... #); firstContaining: (* Returns reference to first AbstractGraphicalObject in * thePicture that contains thePoint. * thePoint is assumed to be in coordinates relative to * THIS(BifrostCanvas). *) (# thePoint: @Point; enter thePoint exit (THIS(BifrostCanvas)[],thePoint) ->thePicture.firstContaining #); lastContaining: (* Returns reference to last AbstractGraphicalObject in * thePicture that contains thePoint. * thePoint is assumed to be in coordinates relative to * THIS(BifrostCanvas). *) (# thePoint: @Point; enter thePoint exit (THIS(BifrostCanvas)[],thePoint) ->thePicture.lastContaining #); (* EVENT HANDLING *) eventHandler::< (# onOpen:< (* Called immediately after the BifrostCanvas has been * made visible. *) (# ... #); onMouseDown::< (* Called when a mouse button is pressed *) (# mousePos: @Point (* the position of the mouse in device coordinates *); button: (# exit buttonState #); shiftModified: (# exit shiftKey #); (*lockModified: (# exit capsLock #);*) controlModified: (# exit controlKey #); metaModified: (# exit metaKey #); altModified: (# exit altKey #); ... #); onKeyDown::< (* Called when a key is pressed *) (# ... #); onRefresh::< (* Called when THIS(BifrostCanvas) is being refreshed *) (# do ... #); onFrameChanged::< (* Called when THIS(BifrostCanvas) changes its frame * (size). *) (# ... #); onActivate::< (* Called when the BifrostCanvas is activated, e.g. by * entering it with the mouse. *) (# ... #); onDeactivate::< (* Called when the BifrostCanvas is deactivated, e.g. by * leaving it with the mouse. *) (# ... #); onFatalError:< (# err: ^text; enter err[] do INNER #); #); borderwidth: @ (* The width of the border if present. Defaults to 0 *) (# value: @integer; enter (# enter value ... #) exit (# ... exit value #) #); borderpaint: @ (* The Paint used to fill the border if present. Defaults to * black *) (# p: ^Paint; enter (# enter p[] ... #) exit (# ... exit p[] #) #); backgroundpaint: @ (* The Paint used as background. Defaults to white *) (# p: ^Paint; enter (# enter p[] ... #) exit (# ... exit p[] #) #); size: (* The size of THIS(BifrostCanvas) *) (# w, h: @integer; enter (# enter (w, h) ... #) exit THIS(Canvas).size #); open::< (* Open the BifrostCanvas, i.e. make it visible and start to * handle events. *) (# create::< (# ... #); defaultbackground: @boolean (* If defaultbackground is set to true, * THIS(BifrostCanvas) will appear with the same * background color as the surrounding window, otherwise * it will be set to white (unless otherwise specified by * backgroundpaint *); ... #); close::< (* Close the BifrostCanvas, i.e. make it disappear and forget * all information stored in it. *) (# ... #); writeEPS:< (* Write Encapsulated PostScript to the stream out *) (# out: ^Stream; pagesize: @rectangle; vertical: @boolean; noOfCopies: @integer; enter (pagesize, vertical, noOfCopies, out[]) do ... #); readEPS:< (* Reads an EPS file written with writeEPS from stream inFile *) (# inFile: ^Stream; enter inFile[] ... #); setClip: (* Make clipShape the new clipping region in * THIS(BifrostCanvas) *) (# enter clipShape[] do ...; #); getClip: (* Exit the clipping region of THIS(BifrostCanvas) *) (# exit clipShape[] #); deviceToCanvas: (* Transform p1 from Device coordinates to BifrostCanvas * coordinates. *) (# p1,p2: @Point; enter p1 ... exit p2 #); canvasToDevice: (* Transform p1 from BifrostCanvas coordinates to Device * coordinates. *) (# p1,p2: @Point; enter p1 ... exit p2 #); canvasToDeviceRectangle: (* Transform r from BifrostCanvas coordinates to Device coordinates. *) (# r: @Rectangle; enter r do r -> TM.transformRectangle -> r; exit r #); deviceToCanvasRectangle: (* Transform r from BifrostCanvas coordinates to Device coordinates. *) (# r: @Rectangle; enter r do r -> TM.inverseTransformRectangle -> r; exit r #); (* DAMAGE / REPAIR *) damaged: (* Inform THIS(BifrostCanvas) that r has been damaged, and * thus should be a part of the area redrawn upon the next * repair. *) (# r: @Rectangle; enter r do ...; #); repair: (* Redraw all damaged areas in THIS(BifrostCanvas) *) (# do ... #); (* INTERACTION *) interactionHandler: (* Specialize THIS(BifrostCanvas).InteractionHandler to * perform an interaction. Specialize the different virtuals * inside THIS(InteractionHandler) to perform actions in * response to various events. Of course, using an * InteractionHandler only gives meaning if a pointing device * and/or a keyboard is connected to the actual device. * * NOTICE: At most one InteractionHandler may active at any * given time *) (# initialize:< (* Called before THIS(InteractionHandler) is started *) (# ... #); motion:< (* Called when the the pointing device has been moved *) object; idle:< (* Called repeatedly when no events are ready *) object; buttonPress:< (* Called when a button of the pointing device has been * pressed. *) (# button: @Integer enter button do INNER; #); buttonRelease:< object (* Called when a button of the pointing device has been * released *); keyPress:< (* Called when a key on the keyboard has been pressed *) (# ch: @Char; enter ch do INNER #); keyRelease:< (* Called when a key on the keyboard has been released *) (# ch: @Char; enter ch do INNER #); terminateCondition:< booleanObject (* Specifies under what condition to stop * THIS(InteractionHandler) *) (# ... #); terminated:< (* Called just before THIS(InteractionHandler) ends *) (# ... #); getPointerLocation: @ (* Returns the current pointer location in device * coordinates *) (# thePoint: @Point; do ...; exit thePoint #); getGlobalPointerLocation: @ (* Returns the current pointer location in screen * coordinates *) (# thePoint: @Point; do ...; exit thePoint #); isModifierOn: @booleanValue (* Tell if theModifier is currently being pressed *) (# theModifier: @Modifier; enter theModifier do ...; #); doubleClick: @booleanValue (* Answer if the last button press on the pointing device * was a double click *) (# ... #); do ...; #); interactiveCreateShape: (* Tell GO to start an interaction for creation on * THIS(BifrostCanvas) *) (# GO: ^AbstractGraphicalObject; p: @Point (* start interaction at p *); theModifier: @Modifier; enter (GO[],p,theModifier) ... #); interactiveCombineShape: (* Tell GO to start an interaction for combination on * THIS(BifrostCanvas) *) (# GO: ^AbstractGraphicalObject; p: @Point (* start interaction at p *); theModifier: @Modifier; enter (GO[],p,theModifier) ... #); interactiveReshape: (* Tell GO to start an interaction for reshaping on * THIS(BifrostCanvas) *) (# GO: ^AbstractGraphicalObject; p: @Point (* start interaction at p *); theModifier: @Modifier; enter (GO[],p,theModifier) ... #); interactiveMove: (* Tell GO to start an interaction for motion on * THIS(BifrostCanvas). *) (# GO: ^AbstractGraphicalObject; p: @Point (* start interaction at p *); theModifier: @Modifier; enter (GO[],p,theModifier) ... #); interactiveRotate: (* Not Yet Implemented *) (* Tell pict to start an interaction for rotation on * THIS(BifrostCanvas) *) (# GO: ^AbstractGraphicalObject; p: @Point (* start interaction at p *); theModifier: @Modifier; enter (GO[],p,theModifier) ... #); interactiveScale: (* Not Yet Implemented *) (* Tell pict to start an interaction for scaling on * THIS(BifrostCanvas) *) (# GO: ^AbstractGraphicalObject; p: @Point (* start interaction at p *); theModifier: @Modifier; enter (GO[],p,theModifier) ... #); bringForward: (* Bring aGO forward in THIS(BifrostCanvas).thePicture *) (# aGO: ^AbstractGraphicalObject; enter aGO[] ... #); sendBehind: (* Send aGO behind in THIS(BifrostCanvas).thePicture *) (# aGO: ^AbstractGraphicalObject; enter aGO[] ... #); hitControl: (* Answer whether p is within 2 mm of a control point of aGO * Exits exact point if hit, NONE otherwise *) (# aGO: ^AbstractGraphicalObject; p: @Point; res: ^Point; enter (aGO[],p) ... exit res[] #); hilite: (* Tell GO to highlight itself on THIS(BifrostCanvas) *) (# GO: ^AbstractGraphicalObject enter GO[] ... #); unHilite: (* Tell GO to unhighlight itself on THIS(BifrostCanvas) *) (# GO: ^AbstractGraphicalObject enter GO[] ... #); (* Primitives for immediate drawing (sometimes also known as * transient drawing). For efficiency all of these use DEVICE * coordinates. Nothing drawn by means of these primitives can * be repaired automatically by THIS(BifrostCanvas). Uses an * arbitrary color, that is guarentied to be different to what * is underneath. May be erased by repeating the draw-request, * and is thus very useful for feedback in interaction. *) setImmediateLineWidth: (* Set the width used for immediate lines and arcs *) (# lineWidth: @Integer; enter lineWidth ... #); immediatespot: (* Draw a small filled rectangle around center *) (# center: @Point; enter (center) ... #); immediateLine: (* Draw an immediate line from p1 to p2 *) (# p1,p2: @Point; enter (p1,p2) ... #); immediateDot: (* Draw a dot of the size of one device-pixel at p *) (# p1: @Point; enter (p1) ... #); immediateMultiLine: (* Draw an immediate multiline specified by the points in p. * If close is true, the multiline will be closed by a line * from the first point to the last point. *) (# p: ^PointArray; close: @Boolean; enter (p[], close) do ...; #); immediateArc: (# cx, cy: @integer; (* Center coordinates *) hr, vr: @integer; (* Horizontal/vertical radius *) a1, a2: @integer; (* Defining angles in degrees *) enter (cx, cy, hr, vr, a1, a2) ... #); immediaterect: (* Draw the outline of r *) (# r: @Rectangle; enter r ... #); immediateText: (* Draw theString at pos, with appearance as specified with * theFontName, theStyle, theSize, and underline *) (# pos: @Point; theFontName: @FontName; theStyle: @Style; theSize: @integer; underline: @boolean; theString: ^text; enter (pos, theFontName, theStyle, theSize, underline, theString[]) do ... #); (* Utility functions to convert between pixels and * milimeter. *) MMToPixel: (* Exits p scaled from mm to pixels *) (# p: @Point; enter p do ... exit p #); pixelToMM: (* Exits p scaled from pixels to mm *) (# p: @Point; enter p do ... exit p #); (* Utility to set zoom factor of THIS(BifrostCanvas). * The value 1.0 correponds to unzoomed state. *) ZoomFactor: (# set: (# z: @vector; enter z do ... #); get: (# z: @vector; ... exit z #) enter set exit get #); (* PRIVATE *) privatePart: @ ...; TM: ^Matrix (* Transformation from THIS(BifrostCanvas) to the actual * device *); #);
-- LIB: attributes --
Bifrost: Guienv(# do INNER #)
14.1 Bifrost Interface | © 1991-2002 Mjølner Informatics |
[Modified: Thursday September 23rd 1999 at 10:32]
|