eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'ObjectView':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: ObjectView


Inheritance:

   Object
   |
   +--GraphicsMedium
      |
      +--DisplaySurface
         |
         +--SimpleView
            |
            +--View
               |
               +--ObjectView
                  |
                  +--BarChart3DWidget

Package:
stx:libwidg
Category:
Views-Basic
Version:
rev: 1.155 date: 2019/03/01 15:06:12
user: cg
file: ObjectView.st directory: libwidg
module: stx stc-classLibrary: libwidg
Author:
Claus Gittinger

Description:


a View which can hold DisplayObjects, can make selections, move them around etc.
ObjectView is an abstract class providing common mechanisms 
(i.e. a whiteBox framework, to be used by concrete subclasses).
Actual instances are DrawView, DirectoryView, LogicView or DocumentView.

If you want to use this class, have a special look at the pluggable behavior, especially,
pressAction, releaseAction etc.:

[Instance variables:]

    contents        <Collection>            the objects. The order in which
                                            these are in that collection defines
                                            their appearance in the z-plane:
                                            an object located after another one
                                            here will be drawn ABOVE the other.

    sorted          <Boolean>               if set, redraw and picking methods
                                            assume that the objects are sorted by 
                                            >= y-coordinates. These operations are
                                            a bit faster then, since a binary search
                                            can be done. (use with care).

    lastButt        <Point>                 last pointer press position
                                            (internal)

    pressAction     <Block>                 action to perform when mouse pointer
                                            is pressed. Can be set to something like
                                            [self startCreate], [self startSelectOrMove]
                                            etc.

    releaseAction   <Block>                 action to perform when mouse pointer is
                                            released. Typically set in one of the
                                            startXXX methods.

    shiftPressAction        <Block>         like pressAction, if shift key is
                                            pressed.

    doublePressAction       <Block>         same for double-clicks

    motionAction            <Block>         action to perform on mouse-pointer
                                            motion.

    keyPressAction          <Block>         action for keyboard events

    selection               <any>           the current selection; either a single
                                            object or a collection of objects.

    gridShown               <Boolean>       internal

    gridPixmap              <Form>          internal

    scaleMetric             <Symbol>        either #mm or #inch; used to
                                            decide how the grid is defined

    dragObject                              internal

    leftHandCursor                          cursor shown while dragging a rectangle

    oldCursor                               saved original cursor while dragging a rectangle

    movedObject                             internal
    moveStartPoint                          internal
    moveDelta                               internal

    documentFormat          <Symbol>        defines the size and layout of the
                                            document. Can be any of
                                            #letter, #a4, #a3 etc.

    canDragOutOfView        <Boolean>       if true, objects can be dragged out of the
                                            view. If false, dragging is restricted to within
                                            this view.

    rootMotion                              internal
    rootView                                internal

    aligning                <Boolean>       if true, pointer positions are
                                            aligned (snapped) to the point
                                            specified in gridAlign

    gridAlign               <Point>         if aligning is true, this point
                                            defines the snapping. For example,
                                            12@12 defines snap to the nearest
                                            12-point grid.

written spring/summer 89 by claus


Related information:

    DrawTool
    LogicTool
    DrawObject
    DisplayObject

Class protocol:

defaults
o  handleSize
size of blob drawn for handles

o  hitDelta
when clicking an object, allow for hitDelta pixels around object;
0 is exact; 1*pixelPerMillimeter is good for draw programs

o  mouseMotionDeltaForMove

o  mouseMotionTimeDeltaForMove


Instance protocol:

accessing
o  aligning

o  aligningMove

o  aligningMove: aBoolean

o  contents

o  gridShown

accessing-behavior
o  ctrlPressAction: aBlock

o  doublePressAction: aBlock

o  keyPressAction: aBlock

o  motionAction: aBlock

o  pressAction: aBlock

o  releaseAction: aBlock

o  setDefaultActions
setup actions for default behavior (do - nothing)

o  shiftPressAction: aBlock

adding & removing
o  add: something
add something, anObject or a collection of objects to the contents
with redraw

o  addObject: anObject
add the argument, anObject to the contents - with redraw

o  addObjectFirst: anObject
add the argument, anObject to the beginning of the contents - with redraw

o  addObjectFirstWithoutRedraw: anObject
add the argument, anObject to the start of the contents - no redraw

o  addObjectWithoutRedraw: anObject
add the argument, anObject to the contents - no redraw

o  addSelected: something
add something, anObject or a collection of objects to the contents
and select it

o  addWithoutRedraw: something
add something, anObject or a collection of objects to the contents
do not redraw

o  contents: aCollectionOfObjects

o  remove: something
remove something, anObject or a collection of objects from the contents
do redraw

o  removeAll
remove all - redraw

o  removeAllWithoutRedraw
remove all - no redraw

o  removeObject: anObject
remove the argument, anObject from the contents - no redraw

o  removeObjectWithoutRedraw: anObject
remove the argument, anObject from the contents - no redraw

o  removeWithoutRedraw: something
remove something, anObject or a collection of objects from the contents
do not redraw

cut & paste
o  convertForPaste: anObject
return a converted version of anObject to be pasted, or nil if
the object is not compatible with me.
Return nil here; concrete subclasses should try to convert.
Notice: anObject may be a collection of to-be-pasted objects.

o  copySelection
copy the selection into the cut&paste-buffer

o  cutSelection
cut the selection into the cut&paste buffer

o  deleteSelection
delete the selection

o  paste: something
add the objects in the cut&paste-buffer

o  pasteBuffer
add the objects in the paste-buffer

dragging-line
o  doLineDrag: aPoint
do drag a line

o  endLineDrag
cleanup after line drag; select them. Find the origin and destination
views and relative offsets, then dispatch to one of the endLineDrag methods.
These can be redefined in subclasses to allow connect between views.

o  invertDragLine
helper for line dragging - invert the dragged line.
Extracted for easier redefinition in subclasses
(different line width etc.)

o  lineDragFrom: startPoint to: endPoint
this is called after a line-drag. Nothing is done here.
- should be redefined in subclasses

o  lineDragFrom: startPoint to: endPoint in: destinationView
this is called after a line-drag crossing view boundaries.
- should be redefined in subclasses

o  lineDragFrom: startPoint to: endPoint inAlienViewId: destinationId
this is called after a line-drag with rootmotion set
to true, IFF the endpoint is in an alien view
- should be redefined in subclasses

o  setLineDragActions
setup to drag a line. Call this (for example) from your buttonPress
method, to make the view start to drag a line.
See startLineDrag and startRootLineDrag.

o  startLineDrag: startPoint
start a line drag within the view

o  startRootLineDrag: startPoint
start a line drag possibly crossing my view boundaries

dragging-object
o  doObjectMove: aPoint
do an object move - this is called for every motion
when moving objects.

o  endObjectMove
cleanup after object move - called when the object move ends.
Find the destination view and position and dispatch to
one of the moveObjectXXX-methods which should do the real move.
These can be redefined in subclasses.

o  invertDragObject: movedObject delta: moveDelta
draw inverting for an object move

o  setMoveActions
setup to drag an object. Call this (for example) from your buttonPress
method, to make the view start to drag some object.
See startObjectMove and startRootObjectMove.

o  startObjectMove: something at: aPoint
start an object move

o  startObjectMove: something at: aPoint inRoot: inRoot
start an object move; if inRoot is true, view
boundaries may be crossed.

o  startRootObjectMove: something at: aPoint
start an object move, possibly crossing view boundaries

dragging-rectangle
o  doRectangleDrag: aPoint
do drag a rectangle

o  endRectangleDrag
cleanup after rectangle drag; select them

o  invertDragRectangle
helper for rectangle drag - invert the dragRectangle.
Extracted into a separate method to allow easier redefinition
(different lineWidth etc)

o  setRectangleDragActions
setup to drag a rectangle. Call this (for example) from your buttonPress
method, to make the view start the drag.
See startRectangleDrag:.

o  startRectangleDrag: startPoint
start a rectangle drag

drawing
o  redraw
redraw complete View

o  redrawObjects
redraw all objects

o  redrawObjectsAbove: anObject in: aRectangle
redraw all objects which have part of themselfes in aRectangle
and are above (in front of) anObject.
draw only in (i.e. clip output to) aRectangle

o  redrawObjectsAbove: anObject inVisible: aRectangle
redraw all objects which have part of themselfes in a vis rectangle
and are above (in front of) anObject.
draw only in (i.e. clip output to) aRectangle

o  redrawObjectsAbove: anObject intersecting: aRectangle
redraw all objects which have part of themself in aRectangle
and are above (in front of) anObject

o  redrawObjectsAbove: anObject intersectingVisible: aRectangle
redraw all objects which have part of themself in a vis rectangle
and are above (in front of) anObject

o  redrawObjectsIn: aRectangle
redraw all objects which have part of themselfes in aRectangle
draw only in (i.e. clip output to) aRectangle

o  redrawObjectsInVisible: visRect
redraw all objects which have part of themselfes in a vis rectangle
draw only in (i.e. clip output to) aRectangle

o  redrawObjectsIntersecting: aRectangle
redraw all objects which have part of themself in aRectangle

o  redrawObjectsIntersectingVisible: aRectangle
redraw all objects which have part of themself in a vis rectangle
This is a leftOver from times when scrolling was not transparent.
Please use redrawObjectsIntersecting:, since this will vanish.

o  redrawObjectsOn: aGC
redraw all objects on a graphic context

o  redrawScale
redraw the scales

o  show: anObject
show the object, either selected or not

o  showDragging: something offset: anOffset
show an object while dragging

o  showSelected: anObject
show an object as selected

o  showUnselected: anObject
show an object as unselected

enumerating
o  contentsDo: aBlock

event handling
o  buttonCtrlPress: button x: x y: y
user pressed left button with ctrl

o  buttonMotion: buttonState x: buttX y: buttY
user moved mouse while button pressed

o  buttonMultiPress: button x: x y: y
user pressed left button twice (or more)

o  buttonPress: button x: x y: y
user pressed left button

o  buttonRelease: button x: x y: y
(comment from inherited method)
button was released - check my components for a hit.

o  buttonShiftPress: button x: x y: y
user pressed left button with shift

o  keyPress: key x: x y: y
(comment from inherited method)
a key has been pressed. If there are components,
pass it to the corresponding one.
Otherwise, forward it to the superview, if there is any.

o  redrawX: x y: y width: w height: h
self clearRectangle:redrawFrame.

focus control
o  wantsFocusWithPointerEnter

grid manipulation
o  alignOff
do no align point to grid

o  alignOn
align points to grid

o  defineGrid
define the grid pattern - this creates the gridPixmap, which is
used as viewBackground when a grid is to be shown.
The grid is specified by the value returned from gridParameters,
which can be redefined in subclasses. See the comment there on how
the numbers are interpreted.

o  getAlignParameters

o  gridParameters
used by defineGrid, and in a separate method for
easier redefinition in subclasses.
Returns the grid parameters in an array of 7 elements,
which control the appearance of the grid-pattern.
the elements are:

bigStepH number of pixels horizontally between 2 major steps
bigStepV number of pixels vertically between 2 major steps
littleStepH number of pixels horizontally between 2 minor steps
littleStepV number of pixels vertically between 2 minor steps
gridAlignH number of pixels for horizontal grid align (pointer snap)
gridAlignV number of pixels for vertical grid align (pointer snap)
docBounds true, if document boundary should be shown
bgColor grid bg-color [optional]
fgColor grid fg-color [optional]

if littleStepH/V are nil, only bigSteps are drawn.

o  hideGrid
hide the grid

o  newGrid
define a new grid - this is a private helper which has to be
called after any change in the grid. It (re)creates the gridPixmap,
clears the view and redraws all visible objects.

o  showGrid
show the grid. The grid is defined by the return value of
gridParameters, which can be redefined in concrete subclasses.

initialization
o  initEvents
self backingStore:true.

o  initialize
(comment from inherited method)
must be called if redefined

o  setInitialDocumentFormat

layout manipulation
o  alignBottom: something

o  alignHorizontal: something
align selection along their center horizontally

o  alignLeft: something

o  alignRight: something

o  alignTop: something

o  alignVertical: something
align selection along their center vertically

o  move: something by: delta
change the position of something, an Object or Collection
by delta, aPoint

o  move: something to: aPoint in: aView
can only happen when dragOutOfView is true
- should be redefined in subclasses

o  move: something to: aPoint inAlienViewId: aViewId
can only happen when dragOutOfView is true
- should be redefined in subclasses

o  moveObject: anObject by: delta
change the position of anObject by delta, aPoint

o  moveObject: anObject to: newOrigin
move anObject to newOrigin, aPoint

o  objectToBack: anObject
bring the argument, anObject to back

o  objectToFront: anObject
bring the argument, anObject to front

o  selectionAlignBottom
align selected objects at bottom

o  selectionAlignHorizontal
align selected objects horizontally

o  selectionAlignLeft
align selected objects left

o  selectionAlignRight
align selected objects right

o  selectionAlignTop
align selected objects at top

o  selectionAlignVertical
align selected objects vertically

o  selectionToBack
bring the selection to back

o  selectionToFront
bring the selection to front

o  toBack: something
bring the argument, anObject or a collection of objects to back

o  toFront: something
bring the argument, anObject or a collection of objects to front

misc
o  documentFormat: aFormatString
set the document format (mostly used by scrollbars).
The argument should be a string such as 'a4', 'a5'
or 'letter'.
See the UnitConverter class for supported formats.

o  hitDelta
when clicking an object, allow for hitDelta pixels around object.
We compensate for any scaling here, to get a constant physical
hitDelta (i.e. the value returned here is inverse scaled).

o  numberOfObjectsIntersecting: aRectangle
answer the number of objects intersecting the argument, aRectangle

o  numberOfObjectsIntersectingVisible: aRectangle
answer the number of objects intersecting the argument, aRectangle.
This is a leftOver from times when scrolling was not transparent.
Please use numberOfObjectsIntersecting:, since this will vanish.

o  object: anObject isContainedIn: aRectangle
true, if anObject is completely inside aRectangle (for rectangle drag)

o  objectsAbove: objectToBeTested do: aBlock
do something to every object above objectToBeTested
(does not mean obscured - simply above in hierarchy)

o  objectsAbove: anObject intersecting: aRectangle do: aBlock
do something to every object above objectToBeTested
and intersecting aRectangle

o  objectsBelow: objectToBeTested do: aBlock
do something to every object below objectToBeTested
(does not mean obscured by - simply below in hierarchy)

o  objectsIn: aRectangle do: aBlock
do something to every object which is completely in a rectangle

o  objectsInVisible: aRectangle do: aBlock
do something to every object which is completely in a
visible rectangle.
This is a leftOver from times when scrolling was not transparent.
Please use objectsIn:do:, since this will vanish.

o  objectsIntersecting: aRectangle
answer a Collection of objects intersecting the argument, aRectangle

o  objectsIntersecting: aRectangle do: aBlock
do something to every object which intersects a rectangle

o  objectsIntersectingVisible: aRectangle
answer a Collection of objects intersecting a visible aRectangle.
This is a leftOver from times when scrolling was not transparent.
Please use objectsIntersecting:, since this will vanish.

o  objectsIntersectingVisible: aRectangle do: aBlock
do something to every object which intersects a visible rectangle.
This is a leftOver from times when scrolling was not transparent.
Please use objectsIntersecting:do:, since this will vanish.

o  rectangleForScroll
find the area occupied by visible objects

o  visibleObjectsDo: aBlock
do something to every visible object

queries
o  hasSolidBackground
return true, if I have a solid color background, which can be pixel-copied
for optimized redraw in moveObject.

o  heightOfContents
answer the height of the document in pixels

o  heightOfContentsInMM
answer the height of the document in millimeters

o  widthOfContents
answer the width of the document in pixels

o  widthOfContentsInMM
answer the width of the document in millimeters

saving & restoring
o  fileInContentsFrom: aStream
remove all objects, load new contents from aStream and redraw

o  fileInContentsFrom: aStream redraw: redraw
remove all objects, load new contents from aStream
and redraw if the redraw argument is true

o  fileInContentsFrom: aStream redraw: redraw new: new
remove all objects, load new contents from aStream
and redraw if the redraw argument is true

o  fileInContentsFrom: aStream redraw: redraw new: new binary: binary
if the new argument is true, remove all objects.
Then load objects from aStream. If redraw is false, no redraw
is done
(allows fileIn of multiple files doing a single redraw at the end).

o  initializeFileInObject: anObject
each object may be processed here after its being filed-in
- subclasses may do whatever they want here ...
(see LogicView for example)

o  storeBinaryContentsOn: aStream
store the contents in binary representation on aStream.

o  storeContentsOn: aStream
store the contents in textual representation on aStream.
Notice, that for huge objects (such as DrawImages) this ascii output
can become quite large, and the time to save and reload can become
long.

o  withoutRedrawFileInContentsFrom: aStream
remove all objects, load new contents from aStream without any redraw

scrolling
o  horizontalScrollStep
return the amount to scroll when stepping left/right.
Redefined to scroll by inches or centimeters.

o  verticalScrollStep
return the amount to scroll when stepping left/right.
Redefined to scroll by inches or centimeters.

selection & handles
o  drawHandle: aPoint

o  drawHandlesFor: anObject

o  findAllObjectsHandleAt: aPoint

o  findAllObjectsHandleAt: aPoint suchThat: aBlock

o  findLastObjectHandleAt: aPoint

o  findLastObjectHandleAt: aPoint suchThat: aBlock

o  findObjectHandleAt: aPoint

o  handle: handlePoint isHitBy: aPoint

o  handleFor: aPoint
return the handle-rectangle for a handle at aPoint

o  handleSize
return the size of the handles - since handles should be
the same size regardless of scaling, inverse-scale from
what the default is.

o  handlesOf: anObject do: aBlock

o  invertHandle: aHandle

o  invertHandlesOf: aSelection

o  object: anObject hasHandleAt: aPoint

o  selectionHandlesDo: aBlock

selections
o  addToSelection: anObject
add anObject to the selection; redraw it selected

o  hideSelection
hide the selection - undraw hilights - whatever that is

o  removeFromSelection: anObject
remove anObject from the selection

o  select: something
select something - hide previous selection, set to something and hilight

o  selectAll
select all objects

o  selectAllIn: aRectangle
select all objects which are fully contained in aRectangle

o  selectAllIntersecting: aRectangle
select all objects which are touched by aRectangle

o  selection
return the selection as a collection or nil

o  selectionDo: aBlock
apply block to every object in selection

o  showSelection
show the selection - draw hilights - whatever that is

o  unselect
unselect - hide selection; clear selection

o  withSelectionHiddenDo: aBlock
evaluate aBlock while selection is hidden

testing objects
o  allObjectsHitAt: aPoint do: aBlock
for all objects (by enumerating from back to front) which are hit by
the argument, aPoint, evaluate aBlock

o  allObjectsHitAt: aPoint withDelta: hDelta do: aBlock
for all objects (by enumerating from back to front) which are hit by
the argument, aPoint, evaluate aBlock

o  canMove: something
return true, if the argument, anObject or a collection can be moved

o  canSelect: something
return true, if the argument, anObject or a collection can be selected

o  findNearestObjectAt: aPoint
find the nearest object (by looking from back to front) which is hit by
the argument, aPoint - this is the topmost object hit

o  findObjectAt: aPoint
find the last object (by looking from back to front) which is hit by
the argument, aPoint - this is the topmost object hit

o  findObjectAt: aPoint forWhich: aBlock
find the last object (by looking from back to front) which is hit by
the argument, aPoint - this is the topmost object hit

o  findObjectAt: aPoint suchThat: aBlock
find the last object (back to front ) which is hit by
the argument, aPoint and for which the testBlock, aBlock evaluates to true.
This is a leftOver from times when scrolling was not transparent.
Please use findObjectAt:forWhich:, since this will vanish.

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  findObjectAtVisible: aPoint
find the last object (by looking from back to front) which is hit by
a visible point - this is the topmost object hit.
This is a leftOver from times when scrolling was not transparent.
Please use findObjectAt:, since this will vanish.

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  findObjectAtVisible: aPoint suchThat: aBlock
find the last object (back to front ) which is hit by
the argument, aPoint and for which the testBlock, aBlock evaluates to
true.
This is a leftOver from times when scrolling was not transparent.
Please use findObjectAt:forWhich:, since this will vanish.

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  findObjectForSelectAt: aPoint
find the object for a select

o  frameIncludesSelectionHandlesOn: anObject
return true, if anObjects frame includes any selection
handles, false if not or if we do not know.
This can be used to optimize the redraw, in removeObjectFromSelection.
Subclasses which know how selections are highlighted may redefine this.

o  frameOf: anObjectOrCollection
answer the maximum extent defined by the argument, anObject or a
collection of objects

o  isObscured: something
return true, if the argument something, anObject or a collection of
objects is obscured (partially or whole) by any other object

o  isSelected: anObject
return true, if the argument, anObject is in the selection

o  objectIsObscured: objectToBeTested
return true, if the argument, anObject is obscured (partially or whole)
by any other object

user interface
o  alignToGrid: aPoint
round aPoint to the next nearest point on the grid

o  selectMore: aPoint
add/remove an object from the selection

o  startSelectMoreOrMove: aPoint
add/remove object hit by aPoint, then start a rectangleDrag or move
- if aPoint hits an object, a move is started, otherwise a rectangleDrag.
This is typically the button shiftPressAction.

o  startSelectOrMove: aPoint
start a rectangleDrag or objectMove - if aPoint hits an object,
an object move is started, otherwise a rectangleDrag.
This is typically the button pressAction.

view manipulation
o  inchMetric

o  millimeterMetric

o  zoom: factor
set a zoom factor; smaller than 1 is shrink; larger than 1 is magnify.
I.e. 1 is identity; 2 is magnify by 2; 0.5 is shrink by 2

o  zoomIn
zoom in - multiply the zoom factor by 1.5

o  zoomIn: factor
zoom in by multiplying the zoom factor by the argument

o  zoomOut
zoom in - divide the zoom factor by 1.5

o  zoomOut: factor
zoom out by dividing the zoom factor by the argument


Examples:


typically, ObjectViews are not used on their own, but instead subclassed and thereby provide the common functionality for views which show (possibly overlapping) objects. The methods here provide all mechanisms to handle redraws, picking (i.e. finding an object by position), gridding, moving objects with minimum redraw etc. Also, zooming and scrolling is handled. All objects which respond to the DisplayObject protocol can be handled by ObjectView - therefore, you can add almost any object and have it displayed and handled here. (as an example, try to copy a LogicGate from a LogicView and paste it into a DrawTool - it will work). Reminder: ObjectViews are not to be used as below, but instead to be subclassed. Therefore, the examples below are somewhat untypical. simple example:
    |v o|

    v := ObjectView new.
    v extent:200@200.

    o := DrawRectangle new.
    o origin:10@10 corner:100@100.
    v add:o.

    o := DrawText new.
    o text:'hello there'; origin:50@50; foreground:Color red.
    v add:o.

    v open
add scrolling:
    |v top o|

    top := HVScrollableView for:ObjectView.
    top extent:200@200.
    v := top scrolledView.

    o := DrawRectangle new.
    o origin:10@10 corner:100@100.
    v add:o.

    o := DrawText new.
    o text:'hello there'; origin:50@50; foreground:Color red.
    v add:o.

    top open
or, using miniscrollers:
    |v top o|

    top := HVScrollableView for:ObjectView 
                            miniScrollerH:true miniScrollerV:true.
    top extent:200@200.
    v := top scrolledView.

    o := DrawRectangle new.
    o origin:10@10 corner:100@100.
    v add:o.

    o := DrawText new.
    o text:'hello there'; origin:50@50; foreground:Color red.
    v add:o.

    top open
mix views and displayObjects:
    |v top o|

    top := HVScrollableView for:ObjectView.
    top extent:200@200.
    v := top scrolledView.

    o := DrawLine new.
    o origin:10@10 corner:50@50.
    v add:o.

    o := ClockView in:top.
    o origin:50@50 corner:100@100.
    v add:o.

    top open
grid:
    |v top o|

    top := HVScrollableView for:ObjectView 
                            miniScrollerH:true miniScrollerV:true.
    top extent:200@200.
    v := top scrolledView.
    v showGrid.

    o := DrawRectangle new.
    o origin:10@10 corner:100@100.
    v add:o.

    o := DrawText new.
    o text:'hello there'; origin:50@50; foreground:Color red.
    v add:o.

    top open
zoom:
    |v top o|

    top := HVScrollableView for:ObjectView 
                            miniScrollerH:true miniScrollerV:true.
    top extent:200@200.
    v := top scrolledView.
    v showGrid.

    o := DrawRectangle new.
    o origin:10@10 corner:100@100.
    v add:o.

    o := DrawText new.
    o text:'hello there'; origin:50@50; foreground:Color red.
    v add:o.

    top open.

    Delay waitForSeconds:5.
    v zoom:2.

    Delay waitForSeconds:5.
    v zoom:0.35.

    Delay waitForSeconds:5.
    v zoom:1.
private benchmark: display 10000 objects ...
    |v top o rnd|

    top := HVScrollableView for:ObjectView 
                            miniScrollerH:true miniScrollerV:true.
    top extent:200@200.
    v := top scrolledView.

    rnd := Random new.
    10000 timesRepeat:[
        o := DrawLine new.
        o origin:(rnd nextIntegerBetween:0 and:700) @ (rnd nextIntegerBetween:0 and:700)
          corner:(rnd nextIntegerBetween:0 and:700) @ (rnd nextIntegerBetween:0 and:700).
        v add:o.
    ].

    top openAndWait.

    Transcript showCR:(
        Time millisecondsToRun:[
            v redraw              
        ])


ST/X 7.2.0.0; WebServer 1.670 at bd0aa1f87cdd.unknown:8081; Fri, 19 Apr 2024 11:51:51 GMT