*** empty log message ***
authorca
Mon, 17 Feb 1997 18:23:19 +0100
changeset 54 d0b5a33e6df0
parent 53 d03569a6ff03
child 55 19e021c8f1ef
*** empty log message ***
UIObjectView.st
UIPainter.st
UIPainterTreeView.st
--- a/UIObjectView.st	Mon Feb 17 18:22:30 1997 +0100
+++ b/UIObjectView.st	Mon Feb 17 18:23:19 1997 +0100
@@ -1,6 +1,5 @@
 ObjectView subclass:#UIObjectView
-	instanceVariableNames:'inputView testMode undoHistory copiedExtent resizedObject
-		resizeSelector createInWidget createFrame createdObject
+	instanceVariableNames:'inputView testMode undoHistory copiedExtent actionData
 		createClass clipChildren'
 	classVariableNames:''
 	poolDictionaries:''
@@ -8,12 +7,19 @@
 !
 
 Object subclass:#UndoHistory
-	instanceVariableNames:'history transaction enabled modifiedAction'
+	instanceVariableNames:'history transaction enabled'
 	classVariableNames:''
 	poolDictionaries:''
 	privateIn:UIObjectView
 !
 
+Object subclass:#Transaction
+	instanceVariableNames:'type text actions'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:UIObjectView::UndoHistory
+!
+
 
 !UIObjectView class methodsFor:'defaults'!
 
@@ -109,6 +115,22 @@
 
 ! !
 
+!UIObjectView methodsFor:'blocked'!
+
+addObject:anObject
+    "add the argument, anObject to the contents - with redraw"
+
+    self halt
+
+!
+
+addObjectWithoutRedraw:anObject
+    "add the argument, anObject to the contents - with redraw"
+
+    self halt
+
+! !
+
 !UIObjectView methodsFor:'event handling'!
 
 doKeyInput:key
@@ -215,13 +237,8 @@
 
     self setDefaultActions.
 
-    undoHistory := UndoHistory new.
-
-    undoHistory modifiedAction:[:what|
-        self changed:#undoHistory with:what
-    ].
-
-    testMode := false.
+    undoHistory  := UndoHistory new.
+    testMode     := false.
     clipChildren := true.
 
     (self class gridShown) ifTrue:[
@@ -293,25 +310,80 @@
 
 !UIObjectView methodsFor:'object creation'!
 
+actionCreate:anObject frame:aFrame delta:aDelta
+    "create and initialize action data
+    "
+    |extent x y selectors values|
+
+"minimum extent
+"
+    extent := self extent.
+    x := extent x // 3.
+    y := extent y // 3.
+    extent := anObject preferredExtent.
+
+    (extent x > x) ifTrue:[extent x:x].
+    (extent y > y) ifTrue:[extent y:y].
+
+"setup structure
+"
+    selectors := #( object frame delta vertical horizontal minExtent ).
+    values    := Array new:(selectors size).
+
+    values at:1 put:anObject.
+    values at:2 put:aFrame.
+    values at:3 put:aDelta.
+    values at:4 put:(self isVerticalResizable:anObject).
+    values at:5 put:(self isHorizontalResizable:anObject).
+    values at:6 put:extent.
+
+    actionData := Structure newWith:selectors values:values.
+
+
+"can change cursor dependent on vertical/horizontal resizing
+"
+    oldCursor := cursor.
+    self cursor:(Cursor leftHand).
+
+
+
+!
+
+createWidgetWithClass:aClass
+    "prepare to create new widgets
+    "
+    createClass := aClass.
+    pressAction := [:pressPoint | self startCreate:pressPoint].
+    self cursor:Cursor origin.
+
+
+!
+
 doDragCreate:aPoint
     "do a widget create drag
     "
-    |p|
-
-    p := self alignToGrid:aPoint.
-    createFrame corner:(p - (createInWidget originRelativeTo:self)).
-
-    (createFrame extent x < 10) ifTrue:[
-        createFrame extent x:10
+    |frame object extent minimum|
+
+    frame   := actionData frame.
+    frame corner:((self alignToGrid:aPoint) - (actionData delta)).
+
+    object  := actionData object.
+    minimum := actionData minExtent.
+    extent  := frame extent.
+
+    ((extent x < minimum x) or:[actionData horizontal not]) ifTrue:[
+        extent x:(minimum x)
     ].
 
-    (createFrame extent y < 10) ifTrue:[
-        createFrame extent y:10
+    ((extent y < minimum y) or:[actionData vertical not]) ifTrue:[
+        extent y:(minimum y)
     ].
 
-    self invertOutlineOf:createdObject.
-    createdObject origin:(createFrame origin) extent:(createFrame extent).
-    self invertOutlineOf:createdObject.
+    frame extent:extent.
+
+    self invertOutlineOf:object.
+    object origin:(frame origin) extent:(frame extent).
+    self invertOutlineOf:object.
 !
 
 endCreate
@@ -319,15 +391,15 @@
     "
     |layout x y|
 
-    self invertOutlineOf:createdObject.
+    self invertOutlineOf:(actionData object).
     inputView raise.
 
-    layout := createdObject bounds asLayout.
-    createdObject geometryLayout:layout.
+    layout := (actionData object) bounds asLayout.
+    (actionData object) geometryLayout:layout.
 
     self changed:#tree.
-    self select:createdObject.
-    createdObject := nil.
+    self select:(actionData object).
+    actionData := nil.
 
     self setDefaultActions.
 
@@ -340,7 +412,7 @@
 startCreate:aPoint
     "start a widget create
     "
-    |startPoint|
+    |widget object start frame delta|
 
     createClass isNil ifTrue:[
         ^ self setDefaultActions
@@ -350,35 +422,33 @@
       ^ self setDefaultActions.
     ].
 
-    startPoint    := self alignToGrid:aPoint.
     motionAction  := [:movePoint| self doDragCreate:movePoint].
     releaseAction := [ self endCreate].
 
     selection notNil ifTrue:[
         (    (self isPoint:aPoint containedIn:selection)
-         and:[selection specClass basicNew supportsSubComponents]
+         and:[self supportsSubComponents:selection]
         ) ifFalse:[
             self unselect
         ]
     ].
 
-    oldCursor := cursor.
-    self cursor:(Cursor leftHand).
-
-    createInWidget := selection ? self.
-    createdObject  := createClass new.
-    createInWidget addSubView:createdObject.
-
-    createFrame := Rectangle origin:(startPoint - (createInWidget originRelativeTo:self))
-                             corner:startPoint.
-
-    createdObject origin:(createFrame origin).
-
-    undoHistory transactionNamed:'create' do:[
-        self setupCreatedObject:createdObject.
-    ].
-    createdObject realize.
-    self invertOutlineOf:createdObject.
+    widget := selection ? self.
+    object := createClass new.
+    widget addSubView:object.
+
+    start := self alignToGrid:aPoint.
+    delta := widget originRelativeTo:self.
+    frame := Rectangle origin:(start - delta) corner:start.
+
+    object origin:(frame origin).
+    self setupCreatedObject:object.
+    object realize.
+
+    self actionCreate:object frame:frame delta:delta.
+    self invertOutlineOf:object.
+
+
 ! !
 
 !UIObjectView methodsFor:'object moving'!
@@ -419,6 +489,26 @@
     ].
 !
 
+moveObject:anObject to:aPoint
+    "move anObject to newOrigin, aPoint
+    "
+    |dX dY org delta|
+
+    anObject notNil ifTrue:[
+        org := anObject computeOrigin.
+
+        delta := aPoint - org.
+        delta := (self alignToGrid:aPoint) - org.
+        dX := delta x.
+        dY := delta y.
+
+        undoHistory disabledTransitionDo:[
+            self shifLayout:anObject top:dY bottom:dY left:dX right:dX
+        ]
+    ]
+
+!
+
 startObjectMoveAt:aPoint
 
     self startObjectMove:selection at:aPoint.
@@ -434,12 +524,13 @@
         aPoint - aView computeOrigin
     ].
 
-    undoHistory transactionNamed:'move' do:[
-        movedObject do:[:aView|
-            self invertOutlineOf:aView.
-            self undoBlockPositionChanged:aView
-        ]
-    ]
+    selection := movedObject.
+    self transaction:#move selectionDo:[:aView|
+        self invertOutlineOf:aView.
+        self undoBlockPositionChanged:aView
+    ].
+    selection := nil
+
 !
 
 startSelectMoreOrMove:aPoint
@@ -472,7 +563,7 @@
         b := self whichHandleOf:selection isHitBy:aPoint.
 
         (b notNil and:[b ~~ #view]) ifTrue:[
-            ^ self startResizeBorder:b of:selection at:aPoint.
+            ^ self startResizeBorder:b of:selection.
         ]
     ].
 
@@ -501,12 +592,80 @@
     "prepare move operation for an object
     "
     motionAction := [:movePoint|
-        (aPoint dist:movePoint) > 2.0 ifTrue:[
+        (aPoint dist:movePoint) > 4.0 ifTrue:[
             self startObjectMoveAt:aPoint
         ]
     ].
 ! !
 
+!UIObjectView methodsFor:'object resize'!
+
+actionResize:anObject selector:aSelector
+    "create and initialize action for resize
+    "
+    |selector delta|
+
+    delta    := anObject container originRelativeTo:self.
+    selector := ('resize:', aSelector, ':') asSymbol.
+
+    actionData := Structure with:(#object->anObject)
+                            with:(#selector->selector)
+                            with:(#delta->delta).
+
+"can change cursor dependent on vertical/horizontal resizing
+"
+    oldCursor := cursor.
+    self cursor:(Cursor leftHand).
+
+
+
+!
+
+doDragResize:aPoint
+    "do a widget resize drag"
+
+    |p object|
+
+    object := actionData object.
+
+    self invertOutlineOf:object.
+    p := (self alignToGrid:aPoint) - (actionData delta).
+    self perform:(actionData selector) with:object with:p.
+    object geometryLayout:(object geometryLayout).
+    self invertOutlineOf:object
+
+!
+
+endResize
+    "cleanup after object resize"
+
+    self invertOutlineOf:(actionData object).
+    self setDefaultActions.
+    self select:(actionData object).
+    actionData := nil
+
+    "Modified: 5.9.1995 / 17:11:17 / claus"
+
+!
+
+startResizeBorder:b of:selection
+    "resize selected view
+    "
+    |object|
+
+    object := self singleSelection.
+    self actionResize:object selector:b.
+
+    self transaction:#extent selectionDo:[:aView|
+        self undoBlockDimensionChanged:aView
+    ].
+    super unselect.
+
+    motionAction  := [:movePoint | self doDragResize:movePoint].
+    releaseAction := [self endResize].
+    self invertOutlineOf:object
+! !
+
 !UIObjectView methodsFor:'private handles'!
 
 handlesOf:aComponent do:aBlock
@@ -545,7 +704,6 @@
         aBlock value:(aComponent bottomLeft + delta) value:#view.
     ].
 
-
 !
 
 showSelected:aComponent
@@ -616,7 +774,7 @@
         ].
     ].
 
-    ^ #view
+    ^ nil
 
     "Modified: 5.9.1995 / 14:39:34 / claus"
 
@@ -631,6 +789,19 @@
     ]
 !
 
+resize:aView bottomLeft:aPoint
+
+    undoHistory disabledTransitionDo:[
+        self shifLayout:aView top:0
+                           bottom:((aPoint y) - (aView computeCorner y))
+                             left:((aPoint x) - (aView computeOrigin x))
+                            right:0
+
+    ]
+
+
+!
+
 resize:aView corner:aPoint
     |delta|
 
@@ -649,6 +820,17 @@
 
 !
 
+resize:aView origin:aPoint
+    |delta|
+
+    delta := aPoint - aView computeOrigin.
+
+    undoHistory disabledTransitionDo:[
+        self shifLayout:aView top:(delta y) bottom:0 left:(delta x) right:0
+    ]
+
+!
+
 resize:aView right:aPoint
 
     undoHistory disabledTransitionDo:[
@@ -661,21 +843,33 @@
     undoHistory disabledTransitionDo:[
         self shifLayout:aView top:((aPoint y) - (aView computeOrigin y)) bottom:0
     ]
+!
+
+resize:aView topRight:aPoint
+
+    undoHistory disabledTransitionDo:[
+        self shifLayout:aView top:((aPoint y) - (aView computeOrigin y))
+                           bottom:0
+                             left:0
+                            right:((aPoint x) - (aView computeCorner x))
+
+    ]
+
 ! !
 
 !UIObjectView methodsFor:'private shift-layout'!
 
 shifLayout:aView left:l right:r
-    "shift layout for a view; in case of an open transaction, the
-     undoAction will be defined
+    "shift layout for a view; in case of an open transaction, the undo
+     action is registered
     "
     self shifLayout:aView top:0 bottom:0 left:l right:r
 
 !
 
 shifLayout:aView top:t bottom:b
-    "shift layout for a view; in case of an open transaction, the
-     undoAction will be defined
+    "shift layout for a view; in case of an open transaction, the undo
+     action is registered
     "
     self shifLayout:aView top:t bottom:b left:0 right:0
 
@@ -683,8 +877,8 @@
 !
 
 shifLayout:aView top:t bottom:b left:l right:r
-    "shift layout for a view; in case of an open transaction, the
-     undoAction will be defined
+    "shift layout for a view; in case of an open transaction, the undo
+     action is registered
     "
     |layout|
 
@@ -706,34 +900,6 @@
 
 ! !
 
-!UIObjectView methodsFor:'private undo-actions'!
-
-undoBlockDimensionChanged:aView
-
-    undoHistory isTransactionOpen ifTrue:[
-        |layout|
-
-        layout := aView geometryLayout copy.
-
-        undoHistory addUndoBlock:[
-            aView geometryLayout:layout.
-            aView superView sizeChanged:nil.
-        ]
-    ]
-
-!
-
-undoBlockPositionChanged:aView
-
-    undoHistory isTransactionOpen ifTrue:[
-        |layout|
-
-        layout := aView geometryLayout copy.
-        undoHistory addUndoBlock:[aView geometryLayout:layout]
-    ]
-
-! !
-
 !UIObjectView methodsFor:'searching'!
 
 findObjectAt:aPoint
@@ -921,26 +1087,84 @@
     ^ self subclassResponsibility
 
 
+!
+
+supportsSubComponents:something
+    "returns true if somrthing supports subcomponents
+    "
+    |specClass|
+
+    something notNil ifTrue:[
+        something isCollection ifFalse:[
+            specClass := something specClass
+        ] ifTrue:[
+            something size == 1 ifTrue:[
+                specClass := (something at:1) specClass
+            ]
+        ].
+        specClass notNil ifTrue:[
+            ^ specClass basicNew supportsSubComponents
+        ]
+    ].
+    ^ false
 ! !
 
-!UIObjectView methodsFor:'user actions'!
-
-createWidgetWithClass:aClass
-    "prepare to create new widgets
+!UIObjectView methodsFor:'transaction & undo'!
+
+transaction:aType objects:something do:aOneArgBlock
+    "opens a transaction and evaluates a block within the transaction; the
+     argument to the block is a view from derived from something
     "
-    createClass := aClass.
-    pressAction := [:pressPoint | self startCreate:pressPoint].
-    self cursor:Cursor origin.
+    self subclassResponsibility
 
 
 !
 
-undoAction
-    undoHistory notEmpty ifTrue:[
-        self unselect.
-        undoHistory undoLast
+transaction:aType selectionDo:aOneArgBlock
+    "opens a transaction and evaluates a block within the transaction; the
+     argument to the block is a view from the selection
+    "
+    self transaction:aType objects:selection do:aOneArgBlock
+
+
+!
+
+undoBlockDimensionChanged:aView
+
+    undoHistory isTransactionOpen ifTrue:[
+        |layout|
+
+        layout := aView geometryLayout copy.
+
+        undoHistory addUndoBlock:[
+            aView geometryLayout:layout.
+            aView superView sizeChanged:nil.
+        ]
     ]
 
+!
+
+undoBlockPositionChanged:aView
+
+    undoHistory isTransactionOpen ifTrue:[
+        |layout|
+
+        layout := aView geometryLayout copy.
+        undoHistory addUndoBlock:[aView geometryLayout:layout]
+    ]
+
+!
+
+undoLast
+    self undoLast:1
+!
+
+undoLast:n
+
+    self unselect.
+    undoHistory undoLast:n.
+    self changed:#tree
+
 
 ! !
 
@@ -958,7 +1182,7 @@
 
 pasteExtent
     copiedExtent notNil ifTrue:[
-        self transition:'paste extent' dimensionDo:[:v|
+        self transition:#extent dimensionDo:[:v|
             self resize:v corner:(v computeOrigin + copiedExtent)
         ]    
     ]    
@@ -983,26 +1207,28 @@
 !
 
 setDimension:aLayout
-    |undoText|
-
-    undoText := 'change layout'.
+    |type|
+
     aLayout isLayout ifTrue:[
-        undoText := 'change to layout frame'.
-        aLayout isAlignmentOrigin ifTrue:[
-            undoText := 'change to layout alignOrigin'.
+        aLayout isLayoutFrame ifTrue:[
+            type := #layoutFrame
         ] ifFalse:[
             aLayout isAlignmentOrigin ifTrue:[
-                undoText := 'change to layout origin'.
+                type := #layoutAlignOrigin.
+            ] ifFalse:[
+                type := #layoutOrigin
             ]
         ]
+    ] ifFalse:[
+        type := #layout
     ].
 
-    self transition:undoText dimensionDo:[:v| v geometryLayout:(aLayout copy)]    
+    self transition:type dimensionDo:[:v| v geometryLayout:(aLayout copy)]    
 
 !
 
 setToDefaultExtent
-    self transition:'default extent' dimensionDo:[:v|
+    self transition:#extent dimensionDo:[:v|
         self resize:v corner:(v computeOrigin + (v preferredExtent))
     ]    
 
@@ -1022,18 +1248,17 @@
 
 !
 
-transition:what dimensionDo:aOneArgBlock
+transition:aType dimensionDo:aOneArgBlock
     "change dimension within a transaction for the selected elements by evaluating
      the block with the argument a view.
     "
     self selectionHiddenDo:[
-        undoHistory transactionNamed:what do:[
-            self selectionDo:[:aView|
-                self undoBlockDimensionChanged:aView.
-                aOneArgBlock value:aView.
-                self elementChangedLayout:aView.
-            ]
-        ]
+        self transaction:aType selectionDo:[:aView|
+            self undoBlockDimensionChanged:aView.
+            aOneArgBlock value:aView.
+            aView superView sizeChanged:nil
+        ].
+        self changed:#layout
     ]
 ! !
 
@@ -1044,9 +1269,7 @@
      move right: n > 0
     "
     self selectionHiddenDo:[
-        undoHistory transactionNamed:'move' do:[
-            self selectionDo:[:aView|self shifLayout:aView left:n right:n]
-        ].
+        self transaction:#move selectionDo:[:v| self shifLayout:v left:n right:n].
         self changed:#layout
     ]
 
@@ -1058,9 +1281,7 @@
      move down: n > 0
     "
     self selectionHiddenDo:[
-        undoHistory transactionNamed:'move' do:[
-            self selectionDo:[:aView| self shifLayout:aView top:n bottom:n ]
-        ].
+        self transaction:#move selectionDo:[:v| self shifLayout:v top:n bottom:n ].
         self changed:#layout
     ]
 
@@ -1068,27 +1289,6 @@
 
 !
 
-moveObject:anObject to:aPoint
-    "move anObject to newOrigin, aPoint
-    "
-    |dX dY org delta|
-
-    anObject notNil ifTrue:[
-        org := anObject computeOrigin.
-
-        delta := aPoint - org.
-        delta := (self alignToGrid:aPoint) - org.
-        dX := delta x.
-        dY := delta y.
-
-        undoHistory disabledTransitionDo:[
-            self shifLayout:anObject top:dY bottom:dY left:dX right:dX
-        ].
-        self elementChangedLayout:anObject.
-    ]
-
-!
-
 moveSelectionDown
     self moveSelectionDown:1
 
@@ -1170,11 +1370,9 @@
         bmost := 0.
         self selectionDo:[:v| bmost := bmost max:(v computeCorner y)].
 
-        undoHistory transactionNamed:'align' do:[
-            self selectionDo:[:v|
-                (delta := bmost - (v computeCorner y)) ~~ 0 ifTrue:[
-                    self shifLayout:v top:delta bottom:delta
-                ]
+        self transaction:#align selectionDo:[:v|
+            (delta := bmost - (v computeCorner y)) ~~ 0 ifTrue:[
+                self shifLayout:v top:delta bottom:delta.
             ]
         ].
         self changed:#layout
@@ -1197,16 +1395,14 @@
         ].
         centerX := centerX // (counter * 2).
 
-        undoHistory transactionNamed:'align' do:[
+        self transaction:#align selectionDo:[:v|
             |newX oldX delta|
 
-            self selectionDo:[:v|
-                oldX  := v computeOrigin x.
-                newX  := centerX - ((v computeCorner x - oldX) // 2).
-                delta := newX - oldX.
-
-                self shifLayout:v left:delta right:delta
-            ]
+            oldX  := v computeOrigin x.
+            newX  := centerX - ((v computeCorner x - oldX) // 2).
+            delta := newX - oldX.
+
+            self shifLayout:v left:delta right:delta
         ].
         self changed:#layout
     ]
@@ -1228,16 +1424,14 @@
         ].
         centerY := centerY // (counter * 2).
 
-        undoHistory transactionNamed:'align' do:[
+        self transaction:#align selectionDo:[:v|
             |newY oldY delta|
 
-            self selectionDo:[:v|
-                oldY  := v computeOrigin y.
-                newY  := centerY - ((v computeCorner y - oldY) // 2).
-                delta := newY - oldY.
-
-                self shifLayout:v top:delta bottom:delta
-            ]
+            oldY  := v computeOrigin y.
+            newY  := centerY - ((v computeCorner y - oldY) // 2).
+            delta := newY - oldY.
+
+            self shifLayout:v top:delta bottom:delta
         ].
         self changed:#layout
     ]
@@ -1249,11 +1443,9 @@
     self selectionHiddenDo:[
         lmost := self selectionFindMinimum:[:v| v computeOrigin x].
 
-        undoHistory transactionNamed:'align' do:[
-            self selectionDo:[:v|
-                (delta := lmost - (v computeOrigin x)) ~~ 0 ifTrue:[
-                    self shifLayout:v left:delta right:delta
-                ]
+        self transaction:#align selectionDo:[:v|
+            (delta := lmost - (v computeOrigin x)) ~~ 0 ifTrue:[
+                self shifLayout:v left:delta right:delta
             ]
         ].
         self changed:#layout
@@ -1269,11 +1461,9 @@
         rmost := 0.
         self selectionDo:[:v | rmost := rmost max:(v computeCorner x)].
 
-        undoHistory transactionNamed:'align' do:[
-            self selectionDo:[:v|
-                self shifLayout:v left:(lmost - (v computeOrigin x))
-                                 right:(rmost - (v computeCorner x))
-            ]
+        self transaction:#align selectionDo:[:v|
+            self shifLayout:v left:(lmost - (v computeOrigin x))
+                             right:(rmost - (v computeCorner x))
         ].
         self changed:#layout
     ]
@@ -1286,11 +1476,9 @@
         rmost := 0.
         self selectionDo:[:v| rmost := rmost max:(v computeCorner x)].
 
-        undoHistory transactionNamed:'align' do:[
-            self selectionDo:[:v|
-                (delta := rmost - (v computeCorner x)) ~~ 0 ifTrue:[
-                    self shifLayout:v left:delta right:delta
-                ]
+        self transaction:#align selectionDo:[:v|
+            (delta := rmost - (v computeCorner x)) ~~ 0 ifTrue:[
+                self shifLayout:v left:delta right:delta
             ]
         ].
         self changed:#layout
@@ -1304,11 +1492,9 @@
     self selectionHiddenDo:[
         tmost := self selectionFindMinimum:[:v| v computeOrigin y].
 
-        undoHistory transactionNamed:'align' do:[
-            self selectionDo:[:v||delta|
-                (delta := tmost - (v computeOrigin y)) ~~ 0 ifTrue:[
-                    self shifLayout:v top:delta bottom:delta
-                ]
+        self transaction:#align selectionDo:[:v|
+            (delta := tmost - (v computeOrigin y)) ~~ 0 ifTrue:[
+                self shifLayout:v top:delta bottom:delta
             ]
         ].
         self changed:#layout
@@ -1324,17 +1510,15 @@
         bmost := 0.
         self selectionDo:[:v| bmost := bmost max:(v computeCorner y)].
 
-        undoHistory transactionNamed:'align' do:[
-            self selectionDo:[:v|
-                self shifLayout:v top:(tmost - (v computeOrigin y))
-                               bottom:(bmost - (v computeCorner y))
-            ]
+        self transaction:#align selectionDo:[:v|
+            self shifLayout:v top:(tmost - (v computeOrigin y))
+                           bottom:(bmost - (v computeCorner y))
         ].
         self changed:#layout
     ]
 !
 
-centerSelection:aOneArgBlockXorY
+centerSelection:aOneArgBlockXorY orientation:orientation
     "center selection horizontal or vertical dependant on the block result( x or y).
      The argument to the block is the point.
     "
@@ -1366,12 +1550,15 @@
         max == min ifFalse:[
             delta := max - min.
 
-            undoHistory transactionNamed:'center' do:[
-                self selectionDo:[:aView|
-                    self shifLayout:aView top:delta bottom:delta]
-            ]
-        ].
-        self changed:#layout
+            self transaction:#center selectionDo:[:v|
+                orientation == #y ifTrue:[
+                    self shifLayout:v top:delta bottom:delta
+                ] ifFalse:[
+                    self shifLayout:v left:delta right:delta
+                ]
+            ].
+            self changed:#layout
+        ]
     ]
 
 
@@ -1380,7 +1567,7 @@
 centerSelectionHor
     "center selection horizontal
     "
-    self centerSelection:[:aPoint| aPoint x]
+    self centerSelection:[:aPoint| aPoint x] orientation:#x
 
 
 !
@@ -1388,7 +1575,7 @@
 centerSelectionVer
     "center selection vertical
     "
-    self centerSelection:[:aPoint| aPoint y]
+    self centerSelection:[:aPoint| aPoint y] orientation:#y
 !
 
 spreadSelectionHor
@@ -1416,14 +1603,12 @@
 
         space := (((max - min) - sumWidths) / (count - 1)) rounded asInteger.
 
-        undoHistory transactionNamed:'spread' do:[
-            viewsInOrder do:[:aView | 
-                |delta|
-
-                delta := min - aView computeOrigin x.
-                self shifLayout:aView left:delta right:delta.
-                min := min + aView computeExtent x + space
-            ]
+        self transaction:#spread objects:viewsInOrder do:[:aView|
+            |delta|
+
+            delta := min - aView computeOrigin x.
+            self shifLayout:aView left:delta right:delta.
+            min := min + aView computeExtent x + space
         ].
         self changed:#layout
     ]
@@ -1455,108 +1640,17 @@
 
         space := (((max - min) - sumHeights) / (count - 1)) rounded asInteger.
 
-        undoHistory transactionNamed:'spread' do:[
-            viewsInOrder do:[:aView||delta|
-                delta := min - aView computeOrigin y.
-                self shifLayout:aView top:delta bottom:delta.
-                min := min + aView height + space
-            ]
+        self transaction:#spread objects:viewsInOrder do:[:aView|
+            |delta|
+
+            delta := min - aView computeOrigin y.
+            self shifLayout:aView top:delta bottom:delta.
+            min := min + aView height + space
         ].
         self changed:#layout
     ]
 ! !
 
-!UIObjectView methodsFor:'user actions - resize'!
-
-doDragResize:aPoint
-    "do a widget resize drag"
-
-    |p|
-
-    self invertOutlineOf:resizedObject.
-    p := (self alignToGrid:aPoint) - (resizedObject container originRelativeTo:self).
-    self perform:('x' , resizeSelector , ':') asSymbol with:p.
-    resizedObject geometryLayout:(resizedObject geometryLayout).
-    self invertOutlineOf:resizedObject
-
-    "Modified: 5.9.1995 / 17:11:46 / claus"
-
-!
-
-endResize
-    "cleanup after object resize"
-
-    self invertOutlineOf:resizedObject.
-    self setDefaultActions.
-    self select:resizedObject.
-    resizedObject := nil
-
-    "Modified: 5.9.1995 / 17:11:17 / claus"
-
-!
-
-startResizeBorder:b of:selection at:aPoint
-    "resize selected view
-    "
-    resizedObject := self singleSelection.
-
-    resizedObject notNil ifTrue:[
-        resizeSelector := b.
-        super unselect.
-
-        undoHistory transactionNamed:'extent' do:[
-            self undoBlockDimensionChanged:resizedObject.
-        ].
-
-        motionAction := [:movePoint | self doDragResize:movePoint].
-        releaseAction := [self endResize].
-        self invertOutlineOf:resizedObject
-    ]
-!
-
-xbottom:aPoint
-    self resize:resizedObject bottom:aPoint
-
-!
-
-xbottomLeft:aPoint
-    self resize:resizedObject   left:aPoint.
-    self resize:resizedObject bottom:aPoint.
-
-!
-
-xcorner:aPoint
-    self resize:resizedObject corner:aPoint.
-
-!
-
-xleft:aPoint
-    self resize:resizedObject left:aPoint
-
-!
-
-xorigin:aPoint
-    self resize:resizedObject left:aPoint.
-    self resize:resizedObject  top:aPoint.
-
-!
-
-xright:aPoint
-    self resize:resizedObject right:aPoint
-
-!
-
-xtop:aPoint
-    self resize:resizedObject top:aPoint
-
-!
-
-xtopRight:aPoint
-    self resize:resizedObject right:aPoint.
-    self resize:resizedObject   top:aPoint.
-
-! !
-
 !UIObjectView::UndoHistory class methodsFor:'constants'!
 
 maxHistorySize
@@ -1578,13 +1672,8 @@
 
 !UIObjectView::UndoHistory methodsFor:'accessing'!
 
-modifiedAction:aBlockWithOneArg
-    "the block is evaluated whenever the history changed; the argument to the
-     block is the newest transaction identifier retrived from 'openTransaction'
-    "
-    modifiedAction := aBlockWithOneArg
-
-
+historySize
+    ^ history size
 ! !
 
 !UIObjectView::UndoHistory methodsFor:'initialization'!
@@ -1599,27 +1688,24 @@
 reinitialize
     "reinitialize all attributes
     "
-    history := OrderedCollection new.
+    history     := OrderedCollection new.
     transaction := nil.
-    enabled := true.
+    enabled     := true.
 
 
 ! !
 
-!UIObjectView::UndoHistory methodsFor:'notifications'!
-
-modified
-    "raise notification; history changed
+!UIObjectView::UndoHistory methodsFor:'menu'!
+
+popupMenu
+    "returns a submenu for undo
     "
-    modifiedAction notNil ifTrue:[
-        |what|
-
-        history isEmpty ifTrue:[what := nil]
-                       ifFalse:[what := history last first].
-
-        modifiedAction value:what
-    ]
-
+    |labels|
+
+    labels := OrderedCollection new:(history size).
+    history reverseDo:[:aRecord| labels add:(aRecord asString) ].
+
+    ^ PopUpMenu labels:labels selectors:#undoLast:.
 
 ! !
 
@@ -1650,36 +1736,8 @@
 addUndoBlock:anUndoBlock
     "undo block to restore changes; add block to current transaction
     "
-    enabled ifTrue:[
-        transaction isNil ifTrue:[
-            "no existing transaction
-            "
-            self halt
-        ] ifFalse:[
-            (transaction at:2) add:anUndoBlock
-        ]
-    ]
-
-
-!
-
-closeTransaction
-    "close current transaction
-    "
     self isTransactionOpen ifTrue:[
-        transaction last isEmpty ifTrue:[
-            "empty undo transaction
-            "
-            transaction := nil
-        ] ifFalse:[
-            history addLast:transaction.
-            transaction := nil.
-
-            history size > (self class maxHistorySize) ifTrue:[
-                history removeFirst
-            ].
-            self modified
-        ]
+        transaction add:anUndoBlock
     ]
 
 
@@ -1696,68 +1754,140 @@
     enabled  := oldState.
 !
 
-openTransaction:what
-    "open a new transaction
-    "
-    enabled ifTrue:[
-        transaction notNil ifTrue:[
-            "transaction within transaction
-            "
-            self halt.
-        ] ifFalse:[
-            transaction := Array with:what with:OrderedCollection new
-        ]
-    ]
-
+transaction:aType do:aBlock
+    self transaction:aType text:nil do:aBlock
 !
 
-transactionNamed:what do:aBlock
+transaction:aType text:aTextOrNil do:aBlock
     "open a transaction; perform the block; at least close the transaction
     "
-    self isTransactionOpen ifFalse:[
-        self openTransaction:what.
+    (enabled and:[transaction isNil]) ifTrue:[
+        transaction := Transaction type:aType text:aTextOrNil.
+
         aBlock value.
-        self closeTransaction
-    ] ifTrue:[
+
+        transaction isEmpty ifFalse:[
+            history addLast:transaction.
+            history size > (self class maxHistorySize) ifTrue:[history removeFirst]
+        ].
+        transaction := nil
+
+    ] ifFalse:[
         aBlock value
     ]
 ! !
 
 !UIObjectView::UndoHistory methodsFor:'undo'!
 
-undoLast
-    "undo last transactions; an open transaction will be closed;
-     transactions during undo are disabled
-    "
-    self undoLast:1
-
-
-!
-
 undoLast:nTransactions
     "undo last n transactions; an open transaction will be closed;
      transactions during undo are disabled
     "
-    |actions n|
+    |n|
 
     transaction := nil.
     n := nTransactions min:(history size).
 
     n ~~ 0 ifTrue:[
         enabled := false.
-
-        n timesRepeat:[
-            actions := (history removeLast) last.
-
-            actions reverseDo:[:aUndoBlock|
-                aUndoBlock value
-            ]
+        n timesRepeat:[ (history removeLast) undo ].
+        enabled := true.
+    ]
+
+
+! !
+
+!UIObjectView::UndoHistory::Transaction class methodsFor:'instance creation'!
+
+type:aType text:aTextOrNil
+    ^ self new type:aType text:aTextOrNil
+
+
+! !
+
+!UIObjectView::UndoHistory::Transaction methodsFor:'accessing'!
+
+asString
+    "returns printable string
+    "
+    |string|
+
+    string := type asString.
+
+    text notNil ifTrue:[^ string, '  ', text ]
+               ifFalse:[^ string ]
+!
+
+text
+    "returns text or nil assigned to transition
+    "
+    ^ text
+!
+
+type
+    "returns type assigned to transition
+    "
+    ^ type
+!
+
+type:aType
+    "change type assigned to transition
+    "
+    type := aType
+! !
+
+!UIObjectView::UndoHistory::Transaction methodsFor:'add & undo'!
+
+add:anUndoBlock
+    "add an undo action to the transition
+    "
+    actions isNil ifTrue:[
+        actions := anUndoBlock
+    ] ifFalse:[
+        actions isCollection ifFalse:[
+            |temp|
+
+            temp := OrderedCollection new.
+            temp add:actions.
+            actions := temp.
         ].
-        enabled := true.
-        self modified.
+        actions add:anUndoBlock.
+    ]
+!
+
+undo
+    "undo transition
+    "
+    actions notNil ifTrue:[
+        actions isCollection ifFalse:[
+            actions value
+        ] ifTrue:[
+            actions reverseDo:[:anUndoBlock| anUndoBlock value ]
+        ]
     ]
-
-
+! !
+
+!UIObjectView::UndoHistory::Transaction methodsFor:'initialization'!
+
+type:aType text:aTextOrNil
+    "initialize transition
+    "
+    type := aType.
+    text := aTextOrNil.
+! !
+
+!UIObjectView::UndoHistory::Transaction methodsFor:'testing'!
+
+isEmpty
+    "returns true if no undo action is registered
+    "
+    ^ actions isNil
+!
+
+notEmpty
+    "returns true if any undo action is registered
+    "
+    ^ actions notNil
 ! !
 
 !UIObjectView class methodsFor:'documentation'!
--- a/UIPainter.st	Mon Feb 17 18:22:30 1997 +0100
+++ b/UIPainter.st	Mon Feb 17 18:23:19 1997 +0100
@@ -952,29 +952,53 @@
 
 
 
+!
+
+propertyFrameSpec
+    "this window spec was automatically generated by the ST/X UIPainter"
+
+    "do not manually edit this - the painter/builder may not be able to
+     handle the specification if its corrupted."
+
+    "UIPainter new openOnClass:UIPainter andSelector:#propertyFrameSpec"
+    "UIPainter new openInterface:#propertyFrameSpec"
+
+    <resource: #canvas>
+
+    ^
+     
+       #(#FullSpec
+          #'window:' 
+           #(#WindowSpec
+              #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+              #'label:' 'unnamed'
+              #'bounds:' #(#Rectangle 0 0 309 326)
+          )
+          #'component:' 
+           #(#SpecCollection
+              #'collection:' 
+               #(
+                 #(#ArbitraryComponentSpec
+                    #'name:' 'view1'
+                    #'layout:' #(#LayoutFrame 0 0 0 0 0 1.0 -40 1.0)
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'button1'
+                    #'layout:' #(#LayoutFrame 108 0 291 0 200 0 323 0)
+                    #'label:' 'apply'
+                )
+              )
+          )
+      )
 ! !
 
 !UIPainter methodsFor:'BuilderView interface'!
 
-setUndoLabel:aString
-    aString isNil ifTrue:[
-        (menu menuAt:#edit) labelAt:#undoAction put:'undo'.
-        (menu menuAt:#edit) disable:#undoAction
-    ] ifFalse:[
-        (menu menuAt:#edit) labelAt:#undoAction put:'undo: ' , aString.
-        (menu menuAt:#edit) enable:#undoAction
-    ]
-!
-
-update:something with:parameter
+update:something
     |singleSelection|
 
     elementMenu deselect.
 
-    something == #undoHistory ifTrue:[
-        ^ self setUndoLabel:parameter
-    ].
-
     singleSelection := workView singleSelection.
 
     (something == #layout or:[something == #any]) ifTrue:[
@@ -1220,12 +1244,10 @@
 initPullDownMenu
     menu labels:(resources  array:#(
                                     'file'
-                                    'edit'
                                     'font'
                                     'type'
                                     'align'
                                     'dimension'
-                                    'form'
                                     'special'
                                     'code'
                                     'debug'
@@ -1233,15 +1255,12 @@
                                  )).
 
     menu selectors:#(#file
-                     #edit
                      #font
                      #type
                      #align 
                      #dimension 
-                     #form
                      #special
                      #code
-                     #debugging
                      #test
                     ).
 
@@ -1283,21 +1302,6 @@
                        )
              receiver:self.
 
-    menu at:#edit 
-            putLabels:(resources  array:#(
-                        'undo' 
-"/                        'copy' 
-                        'cut'
-"/                        'paste'
-                       ))
-            selectors:#(
-                        undoAction
-"/                        copySelection 
-                        deleteSelection
-"/                        pasteBuffer
-                       )
-             receiver:workView.
-
     menu at:#font 
             putLabels:(resources  array:#(
                         'larger' 
@@ -1344,80 +1348,8 @@
                        )
              receiver:self.
 
-    menu at:#align 
-            putLabels:(resources  array:#(
-"/                        'raise' 
-"/                        'lower'
-"/                        '-'
-                        'align left' 
-                        'align right'
-                        'align left & right'
-                        'align top' 
-                        'align bottom'
-                        'align centered vertical'
-                        'align centered horizontal'
-                        '-'
-                        'spread horizontal'
-                        'spread vertical'
-                        'center horizontal in frame'
-                        'center vertical in frame'
-                       ) )
-            selectors:#(
-"/                        raiseSelection 
-"/                        lowerSelection
-"/                        nil
-                        alignSelectionLeft
-                        alignSelectionRight
-                        alignSelectionLeftAndRight
-                        alignSelectionTop
-                        alignSelectionBottom
-                        alignSelectionCenterHor
-                        alignSelectionCenterVer
-                        nil
-                        spreadSelectionHor
-                        spreadSelectionVer
-                        centerSelectionHor
-                        centerSelectionVer
-                       )
-             receiver:workView.
-
-    menu at:#dimension 
-            putLabels:(resources  array:#(
-                        'default extent' 
-                        'default width' 
-                        'default height'
-                        '-'
-                        'copy extent' 
-                        'paste extent'
-                        'paste width'
-                        'paste height'
-                        '-'
-                        'insert'
-                       ) )
-            selectors:#(
-                        setToDefaultExtent
-                        setToDefaultWidth
-                        setToDefaultHeight
-                        nil
-                        copyExtent
-                        pasteExtent
-                        pasteWidth
-                        pasteHeight
-                        nil
-                        insertSelection
-                       )
-             receiver:workView.
-
-    menu at:#form 
-            putLabels:(resources  array:#(
-                        'align to grid'
-                        'show grid' 
-                       ) )
-            selectors:#(
-                        alignOn
-                        toggleGrid
-                       )
-             receiver:self.
+    menu at:#align     putMenu:(workView subMenuAlign menuView).
+    menu at:#dimension putMenu:(workView subMenuDimension menuView).
 
     menu at:#special 
             putLabels:(resources  array:#(
@@ -1439,17 +1371,6 @@
                        )
              receiver:self.
 
-    menu at:#debugging 
-            putLabels:(resources array:#(
-                        'inspect'
-                        'inspect attributes'
-                       ) )
-            selectors:#(
-                        inspectSelection
-                        inspectAttributes
-                       )
-             receiver:workView.
-
     menu at:#test 
             putLabels:(resources array:#(
                         'test on' 
@@ -1457,8 +1378,6 @@
             selectors:#(toggleTest 
                        )
              receiver:self.
-
-    self setUndoLabel:nil.
 !
 
 openInterface 
@@ -2106,40 +2025,6 @@
     self setupPropertyFromSpec:(self class geometrySpecForLayoutOrigin)
 ! !
 
-!UIPainter methodsFor:'user actions - form'!
-
-alignOff
-    |m|
-
-    m := menu menuAt:#form.
-    m labelAt:#alignOff put:(resources string:'align to grid').
-    m selectorAt:#alignOff put:#alignOn.
-    workView alignOff
-!
-
-alignOn
-    |m|
-
-    m := menu menuAt:#form.
-    m labelAt:#alignOn put:(resources string:'do not align to grid').
-    m selectorAt:#alignOn put:#alignOff.
-    workView alignOn
-!
-
-toggleGrid
-    |m|
-
-    m := menu menuAt:#form.
-
-    workView gridShown ifFalse:[
-        m labelAt:#toggleGrid put:(resources string:'hide grid').
-        workView showGrid
-    ] ifTrue:[
-        m labelAt:#toggleGrid put:(resources string:'show grid').
-        workView hideGrid
-    ]
-! !
-
 !UIPainter methodsFor:'user interaction'!
 
 closeRequest
--- a/UIPainterTreeView.st	Mon Feb 17 18:22:30 1997 +0100
+++ b/UIPainterTreeView.st	Mon Feb 17 18:23:19 1997 +0100
@@ -94,7 +94,7 @@
             ]
         ]
     ].
-    builderView selectName:sel
+    builderView selectNames:sel
 
 !
 
@@ -117,6 +117,9 @@
         idx ~~ 0 ifTrue:[
             self addToSelection:idx
         ]
+    ].
+    selection isNil ifTrue:[
+        self setSelection:1
     ]
 ! !
 
@@ -138,11 +141,11 @@
 editMenu
     |menu ispMenu|
 
-    menu := PopUpMenu labels:#( 'inspect' )
+    menu := PopUpMenu labels:( resources array:#('inspect') )
                    selectors:#( #inspect  )
                     receiver:self.
 
-    ispMenu := PopUpMenu labels:#( 'view'        'property'     )
+    ispMenu := PopUpMenu labels:( resources array:#('view' 'property') )
                       selectors:#( #inspectView  #inspectProps  )
                        receiver:self.