UIObjectView.st
changeset 60 7542ab7fbbfe
parent 59 0a2b2ff030a0
child 61 85ef247db6b1
equal deleted inserted replaced
59:0a2b2ff030a0 60:7542ab7fbbfe
       
     1 'From Smalltalk/X, Version:3.1.4 on 25-feb-1997 at 2:17:24 pm'                  !
       
     2 
       
     3 ObjectView subclass:#UIObjectView
       
     4 	instanceVariableNames:'inputView testMode undoHistory copiedExtent actionData
       
     5 		createClass clipChildren'
       
     6 	classVariableNames:''
       
     7 	poolDictionaries:''
       
     8 	category:'Interface-UIPainter'
       
     9 !
       
    10 
       
    11 Object subclass:#UndoHistory
       
    12 	instanceVariableNames:'history transaction enabled'
       
    13 	classVariableNames:''
       
    14 	poolDictionaries:''
       
    15 	privateIn:UIObjectView
       
    16 !
       
    17 
     1 Object subclass:#Transaction
    18 Object subclass:#Transaction
     2 	instanceVariableNames:'type text actions'
    19 	instanceVariableNames:'type text actions'
     3 	classVariableNames:''
    20 	classVariableNames:''
     4 	poolDictionaries:''
    21 	poolDictionaries:''
     5 	privateIn:UIObjectView::UndoHistory
    22 	privateIn:UIObjectView::UndoHistory
     6 !
    23 !
       
    24 
       
    25 
       
    26 !UIObjectView class methodsFor:'defaults'!
       
    27 
       
    28 defaultGrid
       
    29     ^ 4 @ 4
       
    30 
       
    31 !
       
    32 
       
    33 gridShown
       
    34     ^ false
       
    35 
       
    36 !
       
    37 
       
    38 handleSize
       
    39     "size of blob drawn for handles"
       
    40     ^ 4
       
    41 
       
    42 !
       
    43 
       
    44 hitDelta
       
    45     ^ 4
       
    46 
       
    47 ! !
       
    48 
       
    49 !UIObjectView methodsFor:'accessing'!
       
    50 
       
    51 gridAlign
       
    52     ^ aligning
       
    53 
       
    54 !
       
    55 
       
    56 gridAlign:aBool
       
    57     aBool ifTrue:[self alignOn]
       
    58          ifFalse:[self alignOff]
       
    59 
       
    60 !
       
    61 
       
    62 gridParameters
       
    63     "used by defineGrid, and in a separate method for
       
    64      easier redefinition in subclasses. 
       
    65      Returns the grid parameters in an array of 7 elements,
       
    66      which control the appearance of the grid-pattern.
       
    67      the elements are:
       
    68 
       
    69         bigStepH        number of pixels horizontally between 2 major steps
       
    70         bigStepV        number of pixels vertically between 2 major steps
       
    71         littleStepH     number of pixels horizontally between 2 minor steps
       
    72         littleStepV     number of pixels vertically between 2 minor steps
       
    73         gridAlignH      number of pixels for horizontal grid align (pointer snap)
       
    74         gridAlignV      number of pixels for vertical grid align (pointer snap)
       
    75         docBounds       true, if document boundary should be shown
       
    76 
       
    77      if littleStepH/V are nil, only bigSteps are drawn.
       
    78     "
       
    79 
       
    80     ^ #(10 10 nil nil 10 10 false)
       
    81 
       
    82 
       
    83 !
       
    84 
       
    85 gridShown:aBool
       
    86     aBool ifTrue:[self showGrid]
       
    87          ifFalse:[self hideGrid]
       
    88 !
       
    89 
       
    90 hideGrid
       
    91     gridShown ifTrue:[
       
    92         self withSelectionHiddenDo:[
       
    93             super hideGrid
       
    94         ]
       
    95     ]
       
    96 
       
    97 
       
    98 !
       
    99 
       
   100 showGrid
       
   101     self withSelectionHiddenDo:[
       
   102         super showGrid
       
   103     ]
       
   104 
       
   105     "Modified: 5.9.1995 / 12:47:46 / claus"
       
   106 
       
   107 
       
   108 !
       
   109 
       
   110 testMode
       
   111     "returns testMode
       
   112     "
       
   113     ^ testMode
       
   114 
       
   115 
       
   116 !
       
   117 
       
   118 testMode:aBoolean
       
   119     "change testMode
       
   120     "
       
   121     (aBoolean == testMode) ifFalse:[
       
   122         testMode := aBoolean.
       
   123 
       
   124         testMode ifTrue:[
       
   125             self unselect.
       
   126             inputView unrealize
       
   127         ] ifFalse:[
       
   128             inputView raise.
       
   129             inputView realize
       
   130         ]
       
   131     ]
       
   132 
       
   133 
       
   134 ! !
       
   135 
       
   136 !UIObjectView methodsFor:'blocked'!
       
   137 
       
   138 addObject:anObject
       
   139     "add the argument, anObject to the contents - with redraw"
       
   140 
       
   141     self halt
       
   142 
       
   143 !
       
   144 
       
   145 addObjectWithoutRedraw:anObject
       
   146     "add the argument, anObject to the contents - with redraw"
       
   147 
       
   148     self halt
       
   149 
       
   150 ! !
       
   151 
       
   152 !UIObjectView methodsFor:'event handling'!
       
   153 
       
   154 elementChanged:aView 
       
   155     "some element has been changed - kludge to force a resizing
       
   156      operation (for child layout recomputation) in its superView"
       
   157 
       
   158     aView superView sizeChanged:nil.
       
   159     self changed:#any.
       
   160 
       
   161 
       
   162 !
       
   163 
       
   164 elementChangedLayout:aView 
       
   165     "some element has been changed - kludge to force a resizing
       
   166      operation (for child layout recomputation) in its superView"
       
   167 
       
   168     aView superView sizeChanged:nil.
       
   169     self changed:#layout.
       
   170 
       
   171 
       
   172 !
       
   173 
       
   174 exposeX:x y:y width:w height:h
       
   175     "handle an expose event from device; redraw selection
       
   176     "
       
   177     super exposeX:x y:y width:w height:h.
       
   178     self selectionDo:[:v | self showSelected:v]
       
   179 
       
   180 
       
   181 !
       
   182 
       
   183 keyPress:key x:x y:y
       
   184     <resource: #keyboard ( #InspectIt #Delete #BackSpace #Cut) >
       
   185 
       
   186     key == #InspectIt ifTrue:[
       
   187         ^ self inspectSelection
       
   188     ].
       
   189 
       
   190     (key == #Cut or:[key == #Delete or:[key == #BackSpace]]) ifTrue: [
       
   191         ^ self deleteSelection
       
   192     ].
       
   193 
       
   194     super keyPress:key x:x y:y
       
   195 
       
   196 
       
   197 !
       
   198 
       
   199 processEvent:anEvent
       
   200     "catch expose events for components, and redraw its handles after
       
   201      the redraw when this happens
       
   202     "
       
   203     |view|
       
   204 
       
   205     selection notNil ifTrue:[
       
   206         anEvent type == #damage ifTrue:[
       
   207             view := anEvent view.
       
   208             (selection == view
       
   209             or:[selection isCollection
       
   210                 and:[selection includes:view]]) ifTrue:[
       
   211                     self showSelected:view
       
   212             ]
       
   213         ]
       
   214     ].
       
   215     ^ false.
       
   216 
       
   217 
       
   218 !
       
   219 
       
   220 sizeChanged:how
       
   221     self withSelectionHiddenDo:[
       
   222         super sizeChanged:how
       
   223     ]
       
   224 
       
   225 
       
   226 ! !
       
   227 
       
   228 !UIObjectView methodsFor:'initialization'!
       
   229 
       
   230 initialize
       
   231     super initialize.
       
   232 
       
   233     "funny: since I do not want the created widgets to get pointer
       
   234      events, I put an InputView on top of them, which catches those events
       
   235      and passes them back to me - have to take care, that this inputView
       
   236      is always on top
       
   237     "
       
   238     inputView := InputView origin:0.0@0.0 extent:1.0@1.0 in:self.
       
   239 
       
   240     inputView eventReceiver:self.
       
   241     inputView enableButtonEvents.
       
   242     inputView enableButtonMotionEvents.
       
   243 
       
   244     self setDefaultActions.
       
   245 
       
   246     undoHistory  := UndoHistory new.
       
   247     testMode     := false.
       
   248     clipChildren := true.
       
   249 
       
   250     (self class gridShown) ifTrue:[
       
   251         super showGrid
       
   252     ].
       
   253 
       
   254 !
       
   255 
       
   256 realize
       
   257     super realize.
       
   258     self windowGroup postEventHook:self
       
   259 
       
   260 ! !
       
   261 
       
   262 !UIObjectView methodsFor:'misc'!
       
   263 
       
   264 cursor:aCursor
       
   265     inputView realized ifTrue:[
       
   266         inputView cursor:aCursor
       
   267     ].
       
   268     super cursor:aCursor
       
   269 
       
   270 
       
   271 !
       
   272 
       
   273 invertOutlineOf:anObject
       
   274     |wasClipped delta|
       
   275 
       
   276     (wasClipped := clipChildren) ifTrue:[
       
   277         self clippedByChildren:(clipChildren := false).
       
   278     ].
       
   279     delta := (anObject originRelativeTo:self) - anObject origin.
       
   280 
       
   281     self xoring:[
       
   282         self displayRectangle:((anObject origin + delta) extent:anObject extent).
       
   283     ].
       
   284 
       
   285     wasClipped ifTrue:[
       
   286         self clippedByChildren:(clipChildren := true).
       
   287     ].
       
   288 
       
   289     "Modified: 5.9.1995 / 12:25:25 / claus"
       
   290 
       
   291 
       
   292 !
       
   293 
       
   294 setDefaultActions
       
   295 
       
   296     pressAction      := [:pressPoint | self startSelectOrMove:pressPoint].
       
   297     shiftPressAction := [:pressPoint | self startSelectMoreOrMove:pressPoint].
       
   298     motionAction     := [:movePoint  | nil].
       
   299     releaseAction    := [nil].
       
   300     keyPressAction   := nil.
       
   301 
       
   302     self cursor:Cursor normal.
       
   303 
       
   304 !
       
   305 
       
   306 showDragging:something offset:anOffset
       
   307     "drag around a View"
       
   308 
       
   309     |top|
       
   310 
       
   311     self forEach:something do:[:anObject |
       
   312         self drawRectangle:((anObject origin + anOffset) extent:(anObject extent))
       
   313     ]
       
   314 
       
   315 ! !
       
   316 
       
   317 !UIObjectView methodsFor:'object creation'!
       
   318 
       
   319 XXstartCreate:aPoint
       
   320     "start a widget create
       
   321     "
       
   322     |widget object start frame delta|
       
   323 
       
   324     (createClass isNil or:[self numberOfSelections > 1]) ifTrue:[
       
   325         self unselect.
       
   326       ^ self setDefaultActions.
       
   327     ].
       
   328 
       
   329     motionAction  := [:movePoint| self doDragCreate:movePoint].
       
   330     releaseAction := [ self endCreate].
       
   331 
       
   332     widget := self singleSelection.
       
   333 
       
   334     (     widget notNil
       
   335      and:[(self isPoint:aPoint containedIn:widget)
       
   336      and:[self supportsSubComponents:widget]]
       
   337     ) ifFalse:[
       
   338         self unselect.
       
   339         widget := self.
       
   340     ].
       
   341 
       
   342     object := createClass new.
       
   343     widget addSubView:object.
       
   344 
       
   345     start := self alignToGrid:aPoint.
       
   346     delta := widget originRelativeTo:self.
       
   347     frame := Rectangle origin:(start - delta) corner:start.
       
   348 
       
   349     object origin:(frame origin).
       
   350     self setupCreatedObject:object.
       
   351     object realize.
       
   352 
       
   353     self actionCreate:object frame:frame delta:delta.
       
   354     self invertOutlineOf:object.
       
   355 
       
   356 
       
   357 !
       
   358 
       
   359 actionCreate:anObject frame:aFrame delta:aDelta
       
   360     "create and initialize action data
       
   361     "
       
   362     |extent x y selectors values|
       
   363 
       
   364 "minimum extent
       
   365 "
       
   366     extent := self extent.
       
   367     x := extent x // 3.
       
   368     y := extent y // 3.
       
   369     extent := anObject preferredExtent.
       
   370 
       
   371     (extent x > x) ifTrue:[extent x:x].
       
   372     (extent y > y) ifTrue:[extent y:y].
       
   373 
       
   374 "setup structure
       
   375 "
       
   376     selectors := #( object frame delta vertical horizontal minExtent ).
       
   377     values    := Array new:(selectors size).
       
   378 
       
   379     values at:1 put:anObject.
       
   380     values at:2 put:aFrame.
       
   381     values at:3 put:aDelta.
       
   382     values at:4 put:(self isVerticalResizable:anObject).
       
   383     values at:5 put:(self isHorizontalResizable:anObject).
       
   384     values at:6 put:extent.
       
   385 
       
   386     actionData := Structure newWith:selectors values:values.
       
   387 
       
   388 
       
   389 "can change cursor dependent on vertical/horizontal resizing
       
   390 "
       
   391     oldCursor := cursor.
       
   392     self cursor:(Cursor leftHand).
       
   393 
       
   394 
       
   395 
       
   396 !
       
   397 
       
   398 createWidgetWithClass:aClass
       
   399     "prepare to create new widgets
       
   400     "
       
   401     createClass := aClass.
       
   402     pressAction := [:pressPoint | self startCreate:pressPoint].
       
   403     self cursor:Cursor origin.
       
   404 
       
   405 
       
   406 !
       
   407 
       
   408 doDragCreate:aPoint
       
   409     "do a widget create drag
       
   410     "
       
   411     |frame object extent minimum|
       
   412 
       
   413     frame   := actionData frame.
       
   414     frame corner:((self alignToGrid:aPoint) - (actionData delta)).
       
   415 
       
   416     object  := actionData object.
       
   417     minimum := actionData minExtent.
       
   418     extent  := frame extent.
       
   419 
       
   420     ((extent x < minimum x) or:[actionData horizontal not]) ifTrue:[
       
   421         extent x:(minimum x)
       
   422     ].
       
   423 
       
   424     ((extent y < minimum y) or:[actionData vertical not]) ifTrue:[
       
   425         extent y:(minimum y)
       
   426     ].
       
   427 
       
   428     frame extent:extent.
       
   429 
       
   430     self invertOutlineOf:object.
       
   431     object origin:(frame origin) extent:(frame extent).
       
   432     self invertOutlineOf:object.
       
   433 !
       
   434 
       
   435 endCreate
       
   436     "end a widget create drag
       
   437     "
       
   438     |layout x y object|
       
   439 
       
   440     object := actionData object.
       
   441     self invertOutlineOf:object.
       
   442     inputView raise.
       
   443 
       
   444     object superView specClass basicNew setupInitialLayoutFor:object.
       
   445 
       
   446     self changed:#tree.
       
   447     self select:object.
       
   448     actionData := nil.
       
   449 
       
   450     self setDefaultActions.
       
   451 
       
   452 !
       
   453 
       
   454 setupCreatedObject:anObject
       
   455     self subclassResponsibility
       
   456 !
       
   457 
       
   458 startCreate:aPoint
       
   459     "start a widget create
       
   460     "
       
   461     |widget object start frame delta|
       
   462 
       
   463     (createClass isNil or:[self numberOfSelections > 1]) ifTrue:[
       
   464         self unselect.
       
   465       ^ self setDefaultActions.
       
   466     ].
       
   467 
       
   468     (widget := self singleSelection) notNil ifTrue:[
       
   469         self unselect.
       
   470 
       
   471         (self isPoint:aPoint containedIn:widget) ifFalse:[
       
   472             widget := self
       
   473         ] ifTrue:[
       
   474             (self supportsSubComponents:widget) ifFalse:[
       
   475                 ^ self setDefaultActions.
       
   476             ]
       
   477         ]
       
   478     ] ifFalse:[
       
   479         widget := self
       
   480     ].
       
   481 
       
   482     motionAction  := [:movePoint| self doDragCreate:movePoint].
       
   483     releaseAction := [ self endCreate].
       
   484 
       
   485     object := createClass new.
       
   486     widget addSubView:object.
       
   487 
       
   488     start := self alignToGrid:aPoint.
       
   489     delta := widget originRelativeTo:self.
       
   490     frame := Rectangle origin:(start - delta) corner:start.
       
   491 
       
   492     object origin:(frame origin).
       
   493     self setupCreatedObject:object.
       
   494     object realize.
       
   495 
       
   496     self actionCreate:object frame:frame delta:delta.
       
   497     self invertOutlineOf:object.
       
   498 
       
   499 
       
   500 ! !
       
   501 
       
   502 !UIObjectView methodsFor:'object moving'!
       
   503 
       
   504 doObjectMove:aPoint
       
   505     "move selection
       
   506     "
       
   507     movedObject notNil ifTrue:[
       
   508         movedObject keysAndValuesDo:[:nr :aView|
       
   509             self invertOutlineOf:aView.
       
   510             self moveObject:aView to:(aPoint - (moveDelta at:nr)).
       
   511             self invertOutlineOf:aView.
       
   512         ]
       
   513     ]
       
   514 
       
   515 !
       
   516 
       
   517 endObjectMove
       
   518     "cleanup after object move"
       
   519 
       
   520     movedObject notNil ifTrue:[
       
   521         movedObject do:[:aView|
       
   522             self invertOutlineOf:aView
       
   523         ].
       
   524 
       
   525         movedObject do:[:aView|
       
   526             self showSelected:aView
       
   527         ].
       
   528         movedObject size == 1 ifTrue:[
       
   529             selection := movedObject at:1
       
   530         ] ifFalse:[
       
   531             selection := movedObject
       
   532         ].
       
   533 
       
   534         movedObject := nil.
       
   535         self setDefaultActions.
       
   536         self changed:#layout.
       
   537     ].
       
   538 !
       
   539 
       
   540 moveObject:anObject to:aPoint
       
   541     "move anObject to newOrigin, aPoint
       
   542     "
       
   543     |dX dY org delta|
       
   544 
       
   545     anObject notNil ifTrue:[
       
   546         org := anObject computeOrigin.
       
   547 
       
   548         delta := aPoint - org.
       
   549         delta := (self alignToGrid:aPoint) - org.
       
   550         dX := delta x.
       
   551         dY := delta y.
       
   552 
       
   553         undoHistory disabledTransitionDo:[
       
   554             self shiftLayout:anObject top:dY bottom:dY left:dX right:dX
       
   555         ]
       
   556     ]
       
   557 
       
   558 !
       
   559 
       
   560 startObjectMoveAt:aPoint
       
   561 
       
   562     self startObjectMove:selection at:aPoint.
       
   563 
       
   564     selection isCollection ifTrue:[
       
   565         movedObject := selection
       
   566     ] ifFalse:[
       
   567         movedObject := Array with:selection
       
   568     ].
       
   569     super unselect.
       
   570 
       
   571     moveDelta := movedObject collect:[:aView|
       
   572         aPoint - aView computeOrigin
       
   573     ].
       
   574 
       
   575     self transaction:#move objects:movedObject do:[:aView|
       
   576         self invertOutlineOf:aView.
       
   577         self undoLayoutView:aView
       
   578     ].
       
   579 
       
   580 !
       
   581 
       
   582 startSelectMoreOrMove:aPoint
       
   583     "add/remove to/from selection"
       
   584 
       
   585     |anObject|
       
   586 
       
   587     testMode ifTrue:[^ self].
       
   588 
       
   589     anObject := self findObjectAt:aPoint.
       
   590     anObject notNil ifTrue:[
       
   591         (self isSelected:anObject) ifTrue:[
       
   592             self removeFromSelection:anObject
       
   593         ] ifFalse:[
       
   594             self addToSelection:anObject
       
   595         ]
       
   596     ]
       
   597 !
       
   598 
       
   599 startSelectOrMove:aPoint
       
   600     "a button is pressed at a point
       
   601     "
       
   602     |anObject b|
       
   603 
       
   604     testMode ifTrue:[^ self].
       
   605 
       
   606     "if there is one object selected and point hits a handle, start a resize
       
   607     "
       
   608     anObject := self singleSelection.
       
   609 
       
   610     anObject notNil ifTrue:[
       
   611         b := self whichHandleOf:anObject isHitBy:aPoint.
       
   612 
       
   613         (b notNil and:[b ~~ #view]) ifTrue:[
       
   614             ^ self startResizeBorder:b of:anObject.
       
   615         ]
       
   616     ].
       
   617 
       
   618     anObject := self findObjectAt:aPoint.
       
   619 
       
   620     "nothing is selected
       
   621     "
       
   622     anObject isNil ifTrue:[
       
   623         ^ self unselect
       
   624     ].
       
   625 
       
   626     (self isSelected:anObject) ifFalse:[
       
   627         super unselect.
       
   628         self select:anObject.
       
   629     ].
       
   630 
       
   631     (self numberOfSelections ~~ 1) ifTrue:[
       
   632         releaseAction := [
       
   633             self setDefaultActions.
       
   634             self select:anObject
       
   635         ]
       
   636     ] ifFalse:[
       
   637         releaseAction := [self setDefaultActions]
       
   638     ].
       
   639 
       
   640     "prepare move operation for an object
       
   641     "
       
   642     motionAction := [:movePoint|
       
   643         (aPoint dist:movePoint) > 4.0 ifTrue:[
       
   644             self startObjectMoveAt:aPoint
       
   645         ]
       
   646     ].
       
   647 ! !
       
   648 
       
   649 !UIObjectView methodsFor:'object resize'!
       
   650 
       
   651 actionResize:anObject selector:aSelector
       
   652     "create and initialize action for resize
       
   653     "
       
   654     |selector delta|
       
   655 
       
   656     delta    := anObject container originRelativeTo:self.
       
   657     selector := ('resize:', aSelector, ':') asSymbol.
       
   658 
       
   659     actionData := Structure with:(#object->anObject)
       
   660                             with:(#selector->selector)
       
   661                             with:(#delta->delta).
       
   662 
       
   663 "can change cursor dependent on vertical/horizontal resizing
       
   664 "
       
   665     oldCursor := cursor.
       
   666     self cursor:(Cursor leftHand).
       
   667 
       
   668 
       
   669 
       
   670 !
       
   671 
       
   672 doDragResize:aPoint
       
   673     "do a widget resize drag"
       
   674 
       
   675     |p object|
       
   676 
       
   677     object := actionData object.
       
   678 
       
   679     self invertOutlineOf:object.
       
   680     p := (self alignToGrid:aPoint) - (actionData delta).
       
   681     self perform:(actionData selector) with:object with:p.
       
   682     object geometryLayout:(object geometryLayout).
       
   683     self invertOutlineOf:object
       
   684 
       
   685 !
       
   686 
       
   687 endResize
       
   688     "cleanup after object resize"
       
   689 
       
   690     self invertOutlineOf:(actionData object).
       
   691     self setDefaultActions.
       
   692     super select:(actionData object).
       
   693     self changed:#layout.
       
   694     actionData := nil
       
   695 !
       
   696 
       
   697 startResizeBorder:b of:selection
       
   698     "resize selected view
       
   699     "
       
   700     |object|
       
   701 
       
   702     object := self singleSelection.
       
   703 
       
   704     (object geometryLayout) isNil ifTrue:[
       
   705         ^ self setDefaultActions.
       
   706     ].
       
   707 
       
   708     self actionResize:object selector:b.
       
   709 
       
   710     self transaction:#extent selectionDo:[:aView|
       
   711         self undoLayoutView:aView
       
   712     ].
       
   713     super unselect.
       
   714 
       
   715     motionAction  := [:movePoint | self doDragResize:movePoint].
       
   716     releaseAction := [self endResize].
       
   717     self invertOutlineOf:object
       
   718 ! !
       
   719 
       
   720 !UIObjectView methodsFor:'private handles'!
       
   721 
       
   722 handlesOf:aComponent do:aBlock
       
   723     |delta layout vertical horizontal|
       
   724 
       
   725     layout := aComponent geometryLayout.
       
   726     delta  := (aComponent originRelativeTo:self) - aComponent origin.
       
   727 
       
   728     (layout isLayout not or:[layout isLayoutFrame]) ifTrue:[
       
   729         vertical   := self isVerticalResizable:aComponent.
       
   730         horizontal := self isHorizontalResizable:aComponent.
       
   731     ] ifFalse:[
       
   732         vertical   := false.
       
   733         horizontal := false.
       
   734     ].
       
   735 
       
   736     horizontal ifTrue:[
       
   737         aBlock value:(aComponent leftCenter   + delta) value:#left.
       
   738         aBlock value:(aComponent rightCenter  + delta) value:#right.
       
   739     ].
       
   740 
       
   741     vertical ifTrue:[
       
   742         aBlock value:(aComponent topCenter    + delta) value:#top.
       
   743         aBlock value:(aComponent bottomCenter + delta) value:#bottom.
       
   744     ].
       
   745 
       
   746     (horizontal and:[vertical]) ifTrue:[
       
   747         aBlock value:(aComponent origin     + delta) value:#origin.
       
   748         aBlock value:(aComponent corner     + delta) value:#corner.
       
   749         aBlock value:(aComponent topRight   + delta) value:#topRight.
       
   750         aBlock value:(aComponent bottomLeft + delta) value:#bottomLeft.
       
   751     ] ifFalse:[
       
   752         aBlock value:(aComponent origin     + delta) value:#view.
       
   753         aBlock value:(aComponent corner     + delta) value:#view.
       
   754         aBlock value:(aComponent topRight   + delta) value:#view.
       
   755         aBlock value:(aComponent bottomLeft + delta) value:#view.
       
   756     ].
       
   757 
       
   758 !
       
   759 
       
   760 showSelected:aComponent
       
   761     |wasClipped delta oldPaint|
       
   762 
       
   763     self paint:Color black.
       
   764 
       
   765     (wasClipped := clipChildren) ifTrue:[
       
   766         self clippedByChildren:(clipChildren := false). 
       
   767     ].
       
   768 
       
   769     self handlesOf:aComponent do:[:pnt :what |
       
   770         what == #view ifTrue:[self displayRectangle:(pnt - (4@4) extent:7@7)]
       
   771                      ifFalse:[self    fillRectangle:(pnt - (4@4) extent:7@7)]
       
   772     ].
       
   773 
       
   774     wasClipped ifTrue:[
       
   775         self clippedByChildren:(clipChildren := true).
       
   776     ].
       
   777     self paint:oldPaint.
       
   778 !
       
   779 
       
   780 showUnselected:aComponent
       
   781     |wasClipped delta r oldPaint|
       
   782 
       
   783     r := aComponent origin extent:8@8.
       
   784 
       
   785     (wasClipped := clipChildren) ifTrue:[
       
   786         self clippedByChildren:(clipChildren := false). 
       
   787     ].
       
   788 
       
   789     self handlesOf:aComponent do:[:pnt :what |
       
   790         self clearRectangle:(pnt - (4@4) extent:7@7).
       
   791     ].
       
   792 
       
   793     wasClipped ifTrue:[
       
   794         self clippedByChildren:(clipChildren := true). 
       
   795     ].
       
   796 
       
   797     "/ must redraw all components which are affected b the handles
       
   798 
       
   799     r := (aComponent originRelativeTo:self) - (4@4)
       
   800              extent:(aComponent extent + (4@4)).
       
   801 
       
   802     subViews do:[:anotherComponent |
       
   803         |absOrg absFrame|
       
   804 
       
   805         anotherComponent ~~ inputView ifTrue:[
       
   806             absOrg := anotherComponent originRelativeTo:self.
       
   807             absFrame := absOrg extent:(anotherComponent extent).
       
   808             (absFrame intersects:r) ifTrue:[
       
   809                 anotherComponent withAllSubViewsDo:[:v |
       
   810                     v clear.
       
   811                     v exposeX:0 y:0 width:9999 height:9999.
       
   812                 ]
       
   813             ]
       
   814         ]
       
   815     ]
       
   816 
       
   817 !
       
   818 
       
   819 whichHandleOf:aView isHitBy:aPoint
       
   820     |bounds|
       
   821 
       
   822     self handlesOf:aView do:[:pnt :what |
       
   823         ((pnt - (4@4) extent:7@7) containsPoint:aPoint) ifTrue:[
       
   824             ^ what
       
   825         ].
       
   826     ].
       
   827 
       
   828     ^ nil
       
   829 
       
   830     "Modified: 5.9.1995 / 14:39:34 / claus"
       
   831 
       
   832 ! !
       
   833 
       
   834 !UIObjectView methodsFor:'private resizing-subviews'!
       
   835 
       
   836 resize:aView bottom:aPoint
       
   837 
       
   838     undoHistory disabledTransitionDo:[
       
   839         self shiftLayout:aView top:0 bottom:((aPoint y) - (aView computeCorner y))
       
   840     ]
       
   841 !
       
   842 
       
   843 resize:aView bottomLeft:aPoint
       
   844 
       
   845     undoHistory disabledTransitionDo:[
       
   846         self shiftLayout:aView top:0
       
   847                             bottom:((aPoint y) - (aView computeCorner y))
       
   848                               left:((aPoint x) - (aView computeOrigin x))
       
   849                              right:0
       
   850 
       
   851     ]
       
   852 
       
   853 
       
   854 !
       
   855 
       
   856 resize:aView corner:aPoint
       
   857     |delta|
       
   858 
       
   859     delta := aPoint - aView computeCorner.
       
   860 
       
   861     undoHistory disabledTransitionDo:[
       
   862         self shiftLayout:aView top:0 bottom:(delta y) left:0 right:(delta x)
       
   863     ]
       
   864 !
       
   865 
       
   866 resize:aView left:aPoint
       
   867 
       
   868     undoHistory disabledTransitionDo:[
       
   869         self shiftLayout:aView left:((aPoint x) - (aView computeOrigin x)) right:0
       
   870     ]
       
   871 
       
   872 !
       
   873 
       
   874 resize:aView origin:aPoint
       
   875     |delta|
       
   876 
       
   877     delta := aPoint - aView computeOrigin.
       
   878 
       
   879     undoHistory disabledTransitionDo:[
       
   880         self shiftLayout:aView top:(delta y) bottom:0 left:(delta x) right:0
       
   881     ]
       
   882 
       
   883 !
       
   884 
       
   885 resize:aView right:aPoint
       
   886 
       
   887     undoHistory disabledTransitionDo:[
       
   888         self shiftLayout:aView left:0 right:((aPoint x) - (aView computeCorner x))
       
   889     ]
       
   890 !
       
   891 
       
   892 resize:aView top:aPoint
       
   893 
       
   894     undoHistory disabledTransitionDo:[
       
   895         self shiftLayout:aView top:((aPoint y) - (aView computeOrigin y)) bottom:0
       
   896     ]
       
   897 !
       
   898 
       
   899 resize:aView topRight:aPoint
       
   900 
       
   901     undoHistory disabledTransitionDo:[
       
   902         self shiftLayout:aView top:((aPoint y) - (aView computeOrigin y))
       
   903                             bottom:0
       
   904                               left:0
       
   905                              right:((aPoint x) - (aView computeCorner x))
       
   906 
       
   907     ]
       
   908 
       
   909 ! !
       
   910 
       
   911 !UIObjectView methodsFor:'private shift-layout'!
       
   912 
       
   913 shiftLayout:aView left:l right:r
       
   914     "shift layout for a view; in case of an open transaction, the undo
       
   915      action is registered
       
   916     "
       
   917     self shiftLayout:aView top:0 bottom:0 left:l right:r
       
   918 
       
   919 !
       
   920 
       
   921 shiftLayout:aView top:t bottom:b
       
   922     "shift layout for a view; in case of an open transaction, the undo
       
   923      action is registered
       
   924     "
       
   925     self shiftLayout:aView top:t bottom:b left:0 right:0
       
   926 
       
   927 
       
   928 !
       
   929 
       
   930 shiftLayout:aView top:t bottom:b left:l right:r
       
   931     "shift layout for a view; in case of an open transaction, the undo
       
   932      action is registered
       
   933     "
       
   934     |layout|
       
   935 
       
   936     layout := aView geometryLayout.
       
   937 
       
   938     self undoLayoutView:aView.
       
   939 
       
   940     layout isLayout ifTrue:[
       
   941         layout leftOffset:(layout leftOffset + l)
       
   942                 topOffset:(layout topOffset  + t).
       
   943 
       
   944         layout isLayoutFrame ifTrue:[
       
   945             layout bottomOffset:(layout bottomOffset + b).
       
   946             layout  rightOffset:(layout rightOffset  + r).
       
   947         ].
       
   948         aView geometryLayout:layout.
       
   949     ] ifFalse:[
       
   950         |pixelOrigin|
       
   951 
       
   952         pixelOrigin := aView pixelOrigin.
       
   953         pixelOrigin := pixelOrigin + (l@t).
       
   954         aView pixelOrigin:pixelOrigin
       
   955     ]
       
   956 
       
   957 
       
   958 ! !
       
   959 
       
   960 !UIObjectView methodsFor:'searching'!
       
   961 
       
   962 findObjectAt:aPoint
       
   963     "find the origin/corner of the currentWidget
       
   964     "
       
   965     |view viewId lastId point listOfViews|
       
   966 
       
   967     viewId := rootView id.
       
   968     point  := aPoint + (device translatePoint:0@0 from:(self id) to:viewId).
       
   969 
       
   970     inputView lower.
       
   971 
       
   972     [viewId notNil] whileTrue:[
       
   973         lastId := viewId.
       
   974         viewId := device viewIdFromPoint:point in:lastId
       
   975     ].
       
   976 
       
   977     inputView raise.
       
   978 
       
   979     view := device viewFromId:lastId.
       
   980 
       
   981     view ~~ inputView ifTrue:[^ view].
       
   982 
       
   983     "/ look for 'hidden' views ...
       
   984 
       
   985     listOfViews := OrderedCollection new.
       
   986     self allSubViewsDo:[:aView |
       
   987         |org|
       
   988 
       
   989         aView ~~ inputView ifTrue:[
       
   990             org := device translatePoint:0@0 from:(aView id) to:self id.
       
   991             ((org extent:aView extent) containsPoint:aPoint) ifTrue:[
       
   992                 listOfViews add:aView.
       
   993             ]
       
   994         ]
       
   995     ].
       
   996 
       
   997     listOfViews size > 0 ifTrue:[
       
   998         ^ listOfViews last
       
   999     ].
       
  1000     ^ nil
       
  1001 
       
  1002 
       
  1003 !
       
  1004 
       
  1005 isPoint:aPoint containedIn:aView
       
  1006     "checks whether a point is covered by a view.
       
  1007     "
       
  1008     |p|
       
  1009 
       
  1010     p := device translatePoint:aPoint from:inputView id to:aView id.
       
  1011 
       
  1012     (p x >= 0 and:[p y >= 0]) ifTrue:[
       
  1013         p := aView extent - p.
       
  1014 
       
  1015         (p x >= 0 and:[p y >= 0]) ifTrue:[
       
  1016             ^ true
       
  1017         ]
       
  1018     ].
       
  1019     ^ false
       
  1020 !
       
  1021 
       
  1022 whichBorderOf:aView isHitBy:aPoint
       
  1023     |p r bw org|
       
  1024 
       
  1025     bw := aView borderWidth.
       
  1026     p := aPoint - (aView superView originRelativeTo:self).
       
  1027 
       
  1028     r := Rectangle origin:(aView origin)
       
  1029                    extent:(aView width @ bw).
       
  1030     (r containsPoint:p) ifTrue:[^ #top:].
       
  1031 
       
  1032     r origin:(aView left @ (aView bottom + bw)) extent:(aView width @ bw).
       
  1033     (r containsPoint:p) ifTrue:[^ #bottom:].
       
  1034 
       
  1035     r top:(aView top).
       
  1036     r extent:(bw @ aView height).
       
  1037     (r containsPoint:p) ifTrue:[^ #left:].
       
  1038 
       
  1039     r origin:((aView right + bw) @ aView top).
       
  1040     (r containsPoint:p) ifTrue:[^ #right:].
       
  1041 
       
  1042     ^ nil
       
  1043 
       
  1044 
       
  1045 ! !
       
  1046 
       
  1047 !UIObjectView methodsFor:'selections'!
       
  1048 
       
  1049 addToSelection:something
       
  1050     (self canSelect:something) ifTrue:[
       
  1051         super addToSelection:something.
       
  1052         self changed:#selection.
       
  1053     ]
       
  1054 !
       
  1055 
       
  1056 inspectSelection
       
  1057     self singleSelectionDo:[:aView |
       
  1058         aView inspect
       
  1059     ]
       
  1060 !
       
  1061 
       
  1062 numberOfSelections
       
  1063     "return the number of selected entries"
       
  1064 
       
  1065     |sz|
       
  1066 
       
  1067     selection isNil ifTrue:[^ 0].
       
  1068 
       
  1069     selection isCollection ifTrue:[^ selection size]
       
  1070                           ifFalse:[^ 1 ]
       
  1071 !
       
  1072 
       
  1073 removeFromSelection:something
       
  1074     super removeFromSelection:something.
       
  1075     self changed:#selection
       
  1076 
       
  1077 !
       
  1078 
       
  1079 select:something
       
  1080     (self canSelect:something) ifTrue:[
       
  1081         super select:something.
       
  1082         self changed:#selection
       
  1083     ]
       
  1084 
       
  1085 !
       
  1086 
       
  1087 selection
       
  1088     ^ selection
       
  1089 
       
  1090 
       
  1091 !
       
  1092 
       
  1093 selectionHiddenDo:aBlock
       
  1094     "apply block to every object in selection"
       
  1095 
       
  1096     self selectionDo:[:aView |
       
  1097         self showUnselected:aView.
       
  1098     ].
       
  1099     device flush.
       
  1100     aBlock value.
       
  1101     self selectionDo:[:aView |
       
  1102         self showSelected:aView
       
  1103     ]
       
  1104 
       
  1105 
       
  1106 !
       
  1107 
       
  1108 singleSelection
       
  1109     "returns single selection or nil
       
  1110     "
       
  1111     selection isCollection ifFalse:[
       
  1112         ^ selection
       
  1113     ].
       
  1114     selection size == 1 ifTrue:[ ^ selection at:1]
       
  1115                        ifFalse:[ ^ nil].
       
  1116 !
       
  1117 
       
  1118 singleSelectionDo:aBlock
       
  1119     |view|
       
  1120 
       
  1121     (view := self singleSelection) notNil ifTrue:[
       
  1122         aBlock value:view
       
  1123     ]
       
  1124 !
       
  1125 
       
  1126 unselect
       
  1127     selection notNil ifTrue:[
       
  1128         super unselect.
       
  1129         self changed:#selection
       
  1130     ]
       
  1131 
       
  1132 !
       
  1133 
       
  1134 withSelectionHiddenDo:aBlock
       
  1135     "evaluate aBlock while selection is hidden"
       
  1136 
       
  1137     |sel|
       
  1138 
       
  1139     selection isNil ifTrue:[
       
  1140         aBlock value
       
  1141     ] ifFalse:[
       
  1142         sel := selection.
       
  1143         super unselect.
       
  1144         aBlock value.
       
  1145         super select:sel
       
  1146     ]
       
  1147 
       
  1148     "Modified: 6.9.1995 / 01:46:16 / claus"
       
  1149 
       
  1150 
       
  1151 ! !
       
  1152 
       
  1153 !UIObjectView methodsFor:'testing'!
       
  1154 
       
  1155 canMove:something
       
  1156     ^ true
       
  1157 
       
  1158 
       
  1159 !
       
  1160 
       
  1161 canPaste:something
       
  1162     "returns true if something could be paste
       
  1163     "
       
  1164     something notNil ifTrue:[
       
  1165         something isCollection ifTrue:[
       
  1166             something notEmpty ifTrue:[
       
  1167                 ^ (something at:1) isKindOf:UISpecification
       
  1168             ]
       
  1169         ] ifFalse:[
       
  1170             ^ something isKindOf:UISpecification
       
  1171         ]
       
  1172     ].
       
  1173     ^ false
       
  1174 
       
  1175 !
       
  1176 
       
  1177 canSelect:something
       
  1178     ^ (testMode not and:[something ~~ selection])
       
  1179 
       
  1180 !
       
  1181 
       
  1182 hasUndos
       
  1183     "returns true if undoHistory not empty
       
  1184     "
       
  1185     ^ undoHistory notEmpty
       
  1186 !
       
  1187 
       
  1188 isHorizontalResizable:aComponent
       
  1189     ^ self subclassResponsibility
       
  1190 
       
  1191 
       
  1192 !
       
  1193 
       
  1194 isVerticalResizable:aComponent
       
  1195     ^ self subclassResponsibility
       
  1196 
       
  1197 
       
  1198 !
       
  1199 
       
  1200 supportsSubComponents:something
       
  1201     "returns true if somrthing supports subcomponents
       
  1202     "
       
  1203     |specClass|
       
  1204 
       
  1205     something notNil ifTrue:[
       
  1206         something isCollection ifFalse:[
       
  1207             specClass := something specClass
       
  1208         ] ifTrue:[
       
  1209             something size == 1 ifTrue:[
       
  1210                 specClass := (something at:1) specClass
       
  1211             ]
       
  1212         ].
       
  1213         specClass notNil ifTrue:[
       
  1214             ^ specClass basicNew supportsSubComponents
       
  1215         ]
       
  1216     ].
       
  1217     ^ false
       
  1218 ! !
       
  1219 
       
  1220 !UIObjectView methodsFor:'transaction'!
       
  1221 
       
  1222 transaction:aType objects:something do:aOneArgBlock
       
  1223     "opens a transaction and evaluates a block within the transaction; the
       
  1224      argument to the block is a view from derived from something
       
  1225     "
       
  1226     self subclassResponsibility
       
  1227 
       
  1228 
       
  1229 !
       
  1230 
       
  1231 transaction:aType selectionDo:aOneArgBlock
       
  1232     "opens a transaction and evaluates a block within the transaction; the
       
  1233      argument to the block is a view from the selection
       
  1234     "
       
  1235     self transaction:aType objects:selection do:aOneArgBlock
       
  1236 
       
  1237 
       
  1238 !
       
  1239 
       
  1240 undoLayoutView:aView
       
  1241     "prepare undo action for a view changing its layout
       
  1242     "
       
  1243     self subclassResponsibility
       
  1244 
       
  1245 ! !
       
  1246 
       
  1247 !UIObjectView methodsFor:'user actions - arrange'!
       
  1248 
       
  1249 lowerSelection
       
  1250     self selectionDo:[:aView| aView lower ].
       
  1251 
       
  1252 
       
  1253 !
       
  1254 
       
  1255 raiseSelection
       
  1256     self selectionDo:[:aView| aView raise ].
       
  1257     inputView raise.
       
  1258 
       
  1259 
       
  1260 ! !
       
  1261 
       
  1262 !UIObjectView methodsFor:'user actions - dimension'!
       
  1263 
       
  1264 copyExtent
       
  1265     |object|
       
  1266 
       
  1267     object := self singleSelection.
       
  1268 
       
  1269     object notNil ifTrue:[
       
  1270         copiedExtent := object computeExtent
       
  1271     ] ifFalse:[
       
  1272         self warn:'exactly one element must be selected'.
       
  1273     ]
       
  1274 
       
  1275 
       
  1276 
       
  1277 !
       
  1278 
       
  1279 pasteExtent
       
  1280     copiedExtent notNil ifTrue:[
       
  1281         self transition:#extent dimensionDo:[:v|
       
  1282             self resize:v corner:(v computeOrigin + copiedExtent)
       
  1283         ]    
       
  1284     ]    
       
  1285 !
       
  1286 
       
  1287 pasteHeight
       
  1288     copiedExtent notNil ifTrue:[
       
  1289         self transition:'paste height' dimensionDo:[:v|
       
  1290             self resize:v bottom:(v computeOrigin + copiedExtent)
       
  1291         ]    
       
  1292     ]    
       
  1293 
       
  1294 !
       
  1295 
       
  1296 pasteWidth
       
  1297     copiedExtent notNil ifTrue:[
       
  1298         self transition:'paste width' dimensionDo:[:v|
       
  1299             self resize:v right:(v computeOrigin + copiedExtent)
       
  1300         ]    
       
  1301     ]    
       
  1302 
       
  1303 !
       
  1304 
       
  1305 setDimension:aLayout
       
  1306     |type|
       
  1307 
       
  1308     aLayout isLayout ifTrue:[
       
  1309         aLayout isLayoutFrame ifTrue:[
       
  1310             type := #layoutFrame
       
  1311         ] ifFalse:[
       
  1312             aLayout isAlignmentOrigin ifTrue:[
       
  1313                 type := #layoutAlignOrigin.
       
  1314             ] ifFalse:[
       
  1315                 type := #layoutOrigin
       
  1316             ]
       
  1317         ]
       
  1318     ] ifFalse:[
       
  1319         type := #layout
       
  1320     ].
       
  1321 
       
  1322     self transition:type dimensionDo:[:v| v geometryLayout:(aLayout copy)]    
       
  1323 
       
  1324 !
       
  1325 
       
  1326 setToDefaultExtent
       
  1327     self transition:#extent dimensionDo:[:v|
       
  1328         self resize:v corner:(v computeOrigin + (v preferredExtent))
       
  1329     ]    
       
  1330 
       
  1331 !
       
  1332 
       
  1333 setToDefaultHeight
       
  1334     self transition:'default height' dimensionDo:[:v|
       
  1335         self resize:v bottom:(v computeOrigin + (v preferredExtent))
       
  1336     ]    
       
  1337 
       
  1338 !
       
  1339 
       
  1340 setToDefaultWidth
       
  1341     self transition:'default width' dimensionDo:[:v|
       
  1342         self resize:v right:(v computeOrigin + (v preferredExtent))
       
  1343     ]    
       
  1344 
       
  1345 !
       
  1346 
       
  1347 transition:aType dimensionDo:aOneArgBlock
       
  1348     "change dimension within a transaction for the selected elements by evaluating
       
  1349      the block with the argument a view.
       
  1350     "
       
  1351     self selectionHiddenDo:[
       
  1352         self transaction:aType selectionDo:[:aView|
       
  1353             self undoLayoutView:aView.
       
  1354             aOneArgBlock value:aView.
       
  1355         ].
       
  1356         self changed:#layout
       
  1357     ]
       
  1358 ! !
       
  1359 
       
  1360 !UIObjectView methodsFor:'user actions - move'!
       
  1361 
       
  1362 moveSelectionDown:aNumber
       
  1363     |gridY|
       
  1364 
       
  1365     gridAlign notNil ifTrue:[
       
  1366         gridY := gridAlign y.
       
  1367     ].
       
  1368 
       
  1369     self selectionHiddenDo:[
       
  1370         self transaction:#move selectionDo:[:aView|
       
  1371             |n d|
       
  1372 
       
  1373             n := aNumber.
       
  1374 
       
  1375             aligning ifTrue:[
       
  1376                 d := ((aView computeCorner y) \\ gridY).
       
  1377                 n := n * gridY.
       
  1378 
       
  1379                 d ~~ 0 ifTrue:[
       
  1380                     n := n - d + 1.
       
  1381                 ]
       
  1382             ].
       
  1383             self shiftLayout:aView top:n bottom:n
       
  1384         ].
       
  1385         self changed:#layout
       
  1386     ]
       
  1387 
       
  1388 
       
  1389 !
       
  1390 
       
  1391 moveSelectionLeft:aNumber
       
  1392     "move selection left
       
  1393     "
       
  1394     |gridX|
       
  1395 
       
  1396     gridAlign notNil ifTrue:[
       
  1397         gridX := gridAlign x.
       
  1398     ].
       
  1399 
       
  1400     self selectionHiddenDo:[
       
  1401         self transaction:#move selectionDo:[:aView|
       
  1402             |n d|
       
  1403 
       
  1404             n := aNumber.
       
  1405 
       
  1406             aligning ifTrue:[
       
  1407                 d := ((aView computeOrigin x) \\ gridX).
       
  1408                 d ~~ 0 ifTrue:[
       
  1409                     n := n-1.
       
  1410                 ].
       
  1411                 n := (n * gridX) + d.
       
  1412             ].
       
  1413             n := n negated.
       
  1414             self shiftLayout:aView left:n right:n
       
  1415 
       
  1416         ].
       
  1417         self changed:#layout
       
  1418     ]
       
  1419 !
       
  1420 
       
  1421 moveSelectionRight:aNumber
       
  1422     "move selection right
       
  1423     "
       
  1424     |gridX|
       
  1425 
       
  1426     gridAlign notNil ifTrue:[
       
  1427         gridX := gridAlign x.
       
  1428     ].
       
  1429 
       
  1430     self selectionHiddenDo:[
       
  1431         self transaction:#move selectionDo:[:aView|
       
  1432             |n d|
       
  1433 
       
  1434             n := aNumber.
       
  1435 
       
  1436             aligning ifTrue:[
       
  1437                 d := ((aView computeCorner x) \\ gridX).
       
  1438                 n := n * gridX.
       
  1439 
       
  1440                 d ~~ 0 ifTrue:[
       
  1441                     n := n - d + 1.
       
  1442                 ]
       
  1443             ].
       
  1444             self shiftLayout:aView left:n right:n
       
  1445 
       
  1446         ].
       
  1447         self changed:#layout
       
  1448     ]
       
  1449 !
       
  1450 
       
  1451 moveSelectionUp:aNumber
       
  1452     "move selection up
       
  1453     "
       
  1454     |gridY|
       
  1455 
       
  1456     gridAlign notNil ifTrue:[
       
  1457         gridY := gridAlign y.
       
  1458     ].
       
  1459 
       
  1460     self selectionHiddenDo:[
       
  1461         self transaction:#move selectionDo:[:aView|
       
  1462             |n d|
       
  1463 
       
  1464             n := aNumber.
       
  1465 
       
  1466             aligning ifTrue:[
       
  1467                 d := ((aView computeOrigin x) \\ gridY).
       
  1468                 d ~~ 0 ifTrue:[
       
  1469                     n := n-1.
       
  1470                 ].
       
  1471                 n := (n * gridY) + d.
       
  1472             ].
       
  1473             n := n negated.
       
  1474             self shiftLayout:aView top:n bottom:n
       
  1475         ].
       
  1476         self changed:#layout
       
  1477     ]
       
  1478 
       
  1479 
       
  1480 ! !
       
  1481 
       
  1482 !UIObjectView methodsFor:'user actions - position'!
       
  1483 
       
  1484 alignSelectionBottom
       
  1485     |bmost delta layout|
       
  1486 
       
  1487     selection notNil ifTrue:[
       
  1488         self selectionHiddenDo:[
       
  1489             self numberOfSelections > 1 ifTrue:[
       
  1490                 bmost := (selection at:1) computeCorner y.
       
  1491 
       
  1492                 self transaction:#align selectionDo:[:v|
       
  1493                     (delta := bmost - (v computeCorner y)) ~~ 0 ifTrue:[
       
  1494                         self shiftLayout:v top:delta bottom:delta.
       
  1495                     ]
       
  1496                 ]
       
  1497             ] ifFalse:[
       
  1498                 layout := selection geometryLayout.
       
  1499 
       
  1500                 (layout isLayout and:[layout isLayoutFrame]) ifFalse:[
       
  1501                     ^ self
       
  1502                 ].
       
  1503 
       
  1504                 self transaction:#layout selectionDo:[:aView|
       
  1505                     self undoLayoutView:aView.
       
  1506                     layout := aView geometryLayout.
       
  1507                     layout bottomOffset:0.
       
  1508                     layout bottomFraction:1.0.
       
  1509                     aView geometryLayout:layout.
       
  1510                 ]
       
  1511             ]
       
  1512         ].
       
  1513         self changed:#layout
       
  1514     ]
       
  1515 
       
  1516 
       
  1517 
       
  1518 !
       
  1519 
       
  1520 alignSelectionCenterHor
       
  1521     |view center|
       
  1522 
       
  1523     selection notNil ifTrue:[
       
  1524         self selectionHiddenDo:[
       
  1525             view := self singleSelection.
       
  1526 
       
  1527             view notNil ifTrue:[
       
  1528                 view   := view superView.
       
  1529                 center := view computeExtent
       
  1530             ] ifFalse:[
       
  1531                 view   := selection at:1.
       
  1532                 center := view computeCorner + view computeOrigin.
       
  1533             ].
       
  1534             center := center x // 2.
       
  1535 
       
  1536             self transaction:#align selectionDo:[:v|
       
  1537                 |newX oldX delta|
       
  1538 
       
  1539                 oldX  := v computeOrigin x.
       
  1540                 newX  := center - ((v computeCorner x - oldX) // 2).
       
  1541                 delta := newX - oldX.
       
  1542 
       
  1543                 self shiftLayout:v left:delta right:delta
       
  1544             ].
       
  1545             self changed:#layout
       
  1546         ]
       
  1547     ]
       
  1548 
       
  1549 
       
  1550 
       
  1551 !
       
  1552 
       
  1553 alignSelectionCenterVer
       
  1554     |view center|
       
  1555 
       
  1556     selection notNil ifTrue:[
       
  1557         self selectionHiddenDo:[
       
  1558             view := self singleSelection.
       
  1559 
       
  1560             view notNil ifTrue:[
       
  1561                 view   := view superView.
       
  1562                 center := view computeExtent
       
  1563             ] ifFalse:[
       
  1564                 view   := selection at:1.
       
  1565                 center := view computeCorner + view computeOrigin.
       
  1566             ].
       
  1567             center := center y // 2.
       
  1568 
       
  1569             self transaction:#align selectionDo:[:v|
       
  1570                 |newY oldY delta|
       
  1571 
       
  1572                 oldY  := v computeOrigin y.
       
  1573                 newY  := center - ((v computeCorner y - oldY) // 2).
       
  1574                 delta := newY - oldY.
       
  1575 
       
  1576                 self shiftLayout:v top:delta bottom:delta
       
  1577             ].
       
  1578             self changed:#layout
       
  1579         ]
       
  1580     ]
       
  1581 !
       
  1582 
       
  1583 alignSelectionLeft
       
  1584     |lmost delta layout|
       
  1585 
       
  1586     selection notNil ifTrue:[
       
  1587         self selectionHiddenDo:[
       
  1588             self numberOfSelections > 1 ifTrue:[
       
  1589                 lmost := (selection at:1) computeOrigin x.
       
  1590 
       
  1591                 self transaction:#align selectionDo:[:v|
       
  1592                     (delta := lmost - (v computeOrigin x)) ~~ 0 ifTrue:[
       
  1593                         self shiftLayout:v left:delta right:delta
       
  1594                     ]
       
  1595                 ]
       
  1596             ] ifFalse:[
       
  1597                 self transaction:#layout selectionDo:[:aView|
       
  1598                     layout := aView geometryLayout.
       
  1599 
       
  1600                     layout isLayout ifTrue:[
       
  1601                         self undoLayoutView:aView.
       
  1602                         layout leftOffset:0.
       
  1603                         layout leftFraction:0.0.
       
  1604                         aView geometryLayout:layout.
       
  1605                     ]
       
  1606                 ]
       
  1607             ]
       
  1608         ].
       
  1609         self changed:#layout
       
  1610     ]
       
  1611 !
       
  1612 
       
  1613 alignSelectionLeftAndRight
       
  1614     |lmost rmost layout|
       
  1615 
       
  1616     selection notNil ifTrue:[
       
  1617         self selectionHiddenDo:[
       
  1618             self numberOfSelections > 1 ifTrue:[
       
  1619                 lmost := (selection at:1) computeOrigin x.
       
  1620                 rmost := (selection at:1) computeCorner x.
       
  1621 
       
  1622                 self transaction:#align selectionDo:[:v|
       
  1623                     self shiftLayout:v left:(lmost - (v computeOrigin x))
       
  1624                                      right:(rmost - (v computeCorner x))
       
  1625                 ]
       
  1626             ] ifFalse:[
       
  1627                 self transaction:#layout selectionDo:[:aView|
       
  1628                     layout := aView geometryLayout.
       
  1629 
       
  1630                     layout isLayout ifTrue:[
       
  1631                         self undoLayoutView:aView.
       
  1632                         layout leftOffset:0.
       
  1633                         layout leftFraction:0.0.
       
  1634 
       
  1635                         (layout isLayout and:[layout isLayoutFrame]) ifTrue:[
       
  1636                             layout rightOffset:0.
       
  1637                             layout rightFraction:1.0.
       
  1638                         ].
       
  1639                         aView geometryLayout:layout.
       
  1640                     ]
       
  1641                 ]
       
  1642             ]
       
  1643         ].
       
  1644         self changed:#layout
       
  1645     ]
       
  1646 !
       
  1647 
       
  1648 alignSelectionRight
       
  1649     |rmost delta layout|
       
  1650 
       
  1651     selection notNil ifTrue:[
       
  1652         self selectionHiddenDo:[
       
  1653             self numberOfSelections > 1 ifTrue:[
       
  1654                 rmost := (selection at:1) computeCorner x.
       
  1655 
       
  1656                 self transaction:#align selectionDo:[:v|
       
  1657                     (delta := rmost - (v computeCorner x)) ~~ 0 ifTrue:[
       
  1658                         self shiftLayout:v left:delta right:delta
       
  1659                     ]
       
  1660                 ]
       
  1661             ] ifFalse:[
       
  1662                 layout := selection geometryLayout.
       
  1663 
       
  1664                 (layout isLayout and:[layout isLayoutFrame]) ifFalse:[
       
  1665                     ^ self
       
  1666                 ].
       
  1667 
       
  1668                 self transaction:#layout selectionDo:[:aView|
       
  1669                     self undoLayoutView:aView.
       
  1670                     layout := aView geometryLayout.
       
  1671                     layout rightOffset:0.
       
  1672                     layout rightFraction:1.0.
       
  1673                     aView geometryLayout:layout.
       
  1674                 ]
       
  1675             ]
       
  1676         ].
       
  1677         self changed:#layout
       
  1678     ]
       
  1679 !
       
  1680 
       
  1681 alignSelectionTop
       
  1682     |tmost delta layout|
       
  1683 
       
  1684     selection notNil ifTrue:[
       
  1685         self selectionHiddenDo:[
       
  1686             self numberOfSelections > 1 ifTrue:[
       
  1687                 tmost := (selection at:1) computeOrigin y.
       
  1688 
       
  1689                 self transaction:#align selectionDo:[:v|
       
  1690                     (delta := tmost - (v computeOrigin y)) ~~ 0 ifTrue:[
       
  1691                         self shiftLayout:v top:delta bottom:delta
       
  1692                     ]
       
  1693                 ]
       
  1694             ] ifFalse:[
       
  1695                 self transaction:#layout selectionDo:[:aView|
       
  1696                     layout := aView geometryLayout.
       
  1697 
       
  1698                     layout isLayout ifTrue:[
       
  1699                         self undoLayoutView:aView.
       
  1700                         layout topOffset:0.
       
  1701                         layout topFraction:0.0.
       
  1702                         aView geometryLayout:layout.
       
  1703                     ]
       
  1704                 ]
       
  1705             ]
       
  1706         ].
       
  1707         self changed:#layout
       
  1708     ]
       
  1709 
       
  1710 !
       
  1711 
       
  1712 alignSelectionTopAndBottom
       
  1713     |tmost bmost layout|
       
  1714 
       
  1715     selection notNil ifTrue:[
       
  1716         self selectionHiddenDo:[
       
  1717             self numberOfSelections > 1 ifTrue:[
       
  1718                 tmost := (selection at:1) computeOrigin y.
       
  1719                 bmost := (selection at:1) computeCorner y.
       
  1720 
       
  1721                 self transaction:#align selectionDo:[:v|
       
  1722                     self shiftLayout:v top:(tmost - (v computeOrigin y))
       
  1723                                     bottom:(bmost - (v computeCorner y))
       
  1724                 ]
       
  1725             ] ifFalse:[
       
  1726                 self transaction:#layout selectionDo:[:aView|
       
  1727                     layout := aView geometryLayout.
       
  1728 
       
  1729                     layout isLayout ifTrue:[
       
  1730                         self undoLayoutView:aView.
       
  1731                         layout topOffset:0.
       
  1732                         layout topFraction:0.0.
       
  1733 
       
  1734                         (layout isLayout and:[layout isLayoutFrame]) ifTrue:[
       
  1735                             layout bottomOffset:0.
       
  1736                             layout bottomFraction:1.0.
       
  1737                         ].
       
  1738                         aView geometryLayout:layout.
       
  1739                     ]
       
  1740                 ]
       
  1741             ]
       
  1742         ].
       
  1743         self changed:#layout
       
  1744     ]
       
  1745 !
       
  1746 
       
  1747 centerSelection:aOneArgBlockXorY orientation:orientation
       
  1748     "center selection horizontal or vertical dependant on the block result( x or y).
       
  1749      The argument to the block is the point.
       
  1750     "
       
  1751     |superview min max delta val|
       
  1752 
       
  1753     self selectionHiddenDo:[
       
  1754         max := 0.
       
  1755 
       
  1756         self selectionDo:[:aView |
       
  1757             superview isNil ifTrue:[
       
  1758                 superview := aView superView
       
  1759             ] ifFalse:[
       
  1760                 (aView superView == superview) ifFalse:[
       
  1761                     ^ self notify:'views must have same superview'.
       
  1762                 ]
       
  1763             ].
       
  1764             val := aOneArgBlockXorY value:(aView computeOrigin).    
       
  1765 
       
  1766             min isNil ifTrue:[min := val]
       
  1767                      ifFalse:[min := min min:val].
       
  1768 
       
  1769             val := aOneArgBlockXorY value:(aView computeCorner).
       
  1770             max := max max:val.
       
  1771         ].
       
  1772 
       
  1773         val := aOneArgBlockXorY value:(superview computeExtent).
       
  1774         max := (min + val - max) // 2.
       
  1775 
       
  1776         max == min ifFalse:[
       
  1777             delta := max - min.
       
  1778 
       
  1779             self transaction:#center selectionDo:[:v|
       
  1780                 orientation == #y ifTrue:[
       
  1781                     self shiftLayout:v top:delta bottom:delta
       
  1782                 ] ifFalse:[
       
  1783                     self shiftLayout:v left:delta right:delta
       
  1784                 ]
       
  1785             ].
       
  1786             self changed:#layout
       
  1787         ]
       
  1788     ]
       
  1789 
       
  1790 
       
  1791 !
       
  1792 
       
  1793 centerSelectionHor
       
  1794     "center selection horizontal
       
  1795     "
       
  1796     self centerSelection:[:aPoint| aPoint x] orientation:#x
       
  1797 
       
  1798 
       
  1799 !
       
  1800 
       
  1801 centerSelectionVer
       
  1802     "center selection vertical
       
  1803     "
       
  1804     self centerSelection:[:aPoint| aPoint y] orientation:#y
       
  1805 !
       
  1806 
       
  1807 spreadSelectionHor
       
  1808     |sumWidths min max viewsInOrder topsInOrder count space|
       
  1809 
       
  1810     (self numberOfSelections > 1) ifFalse:[
       
  1811         ^ self
       
  1812     ].
       
  1813 
       
  1814     self selectionHiddenDo:[
       
  1815         count := 0.
       
  1816         sumWidths := 0.
       
  1817         max := 0.
       
  1818 
       
  1819         self selectionDo:[:aView |
       
  1820             sumWidths := sumWidths + aView width.
       
  1821 
       
  1822             min isNil ifTrue:[min := aView left]
       
  1823                      ifFalse:[min := min min:(aView left)].
       
  1824 
       
  1825             max := max max:(aView right).
       
  1826             count := count + 1
       
  1827         ].
       
  1828         viewsInOrder := Array withAll:selection.
       
  1829         topsInOrder  := viewsInOrder collect:[:aView | aView left].
       
  1830         topsInOrder sortWith:viewsInOrder.
       
  1831 
       
  1832         space := (((max - min) - sumWidths) / (count - 1)) rounded asInteger.
       
  1833 
       
  1834         self transaction:#spread objects:viewsInOrder do:[:aView|
       
  1835             |delta|
       
  1836 
       
  1837             delta := min - aView computeOrigin x.
       
  1838             self shiftLayout:aView left:delta right:delta.
       
  1839             min := min + aView computeExtent x + space
       
  1840         ].
       
  1841         self changed:#layout
       
  1842     ]
       
  1843 
       
  1844 !
       
  1845 
       
  1846 spreadSelectionVer
       
  1847     |sumHeights min max viewsInOrder topsInOrder count space|
       
  1848 
       
  1849     (self numberOfSelections > 1) ifFalse:[
       
  1850         ^ self
       
  1851     ].
       
  1852 
       
  1853     self selectionHiddenDo:[
       
  1854         count := 0.
       
  1855         sumHeights := 0.
       
  1856         max := 0.
       
  1857 
       
  1858         self selectionDo:[:aView |
       
  1859             sumHeights := sumHeights + aView height.
       
  1860 
       
  1861             min isNil ifTrue:[min := aView top]
       
  1862                      ifFalse:[min := min min:(aView top)].
       
  1863 
       
  1864             max   := max max:(aView bottom).
       
  1865             count := count + 1
       
  1866         ].
       
  1867         viewsInOrder := Array withAll:selection.
       
  1868         topsInOrder  := viewsInOrder collect:[:aView|aView top].
       
  1869         topsInOrder sortWith:viewsInOrder.
       
  1870 
       
  1871         space := (((max - min) - sumHeights) / (count - 1)) rounded asInteger.
       
  1872 
       
  1873         self transaction:#spread objects:viewsInOrder do:[:aView|
       
  1874             |delta|
       
  1875 
       
  1876             delta := min - aView computeOrigin y.
       
  1877             self shiftLayout:aView top:delta bottom:delta.
       
  1878             min := min + aView height + space
       
  1879         ].
       
  1880         self changed:#layout
       
  1881     ]
       
  1882 ! !
       
  1883 
       
  1884 !UIObjectView methodsFor:'user actions - undo history'!
       
  1885 
       
  1886 openUndoMenu
       
  1887     self unselect.
       
  1888     undoHistory openUndoMenu.
       
  1889     self changed:#tree
       
  1890 
       
  1891 !
       
  1892 
       
  1893 removeUndoHistory
       
  1894     "delete total undo history
       
  1895     "
       
  1896     undoHistory reinitialize
       
  1897 !
       
  1898 
       
  1899 undoLast
       
  1900     self unselect.
       
  1901     undoHistory undoLast:1.
       
  1902     self changed:#tree
       
  1903 ! !
       
  1904 
       
  1905 !UIObjectView::UndoHistory class methodsFor:'constants'!
       
  1906 
       
  1907 maxHistorySize
       
  1908     "returns maximum size of history before removing oldest
       
  1909      record
       
  1910     "
       
  1911     ^ 50
       
  1912 
       
  1913 
       
  1914 ! !
       
  1915 
       
  1916 !UIObjectView::UndoHistory class methodsFor:'instance creation'!
       
  1917 
       
  1918 new
       
  1919     ^ self basicNew initialize
       
  1920 
       
  1921 
       
  1922 ! !
       
  1923 
       
  1924 !UIObjectView::UndoHistory methodsFor:'accessing'!
       
  1925 
       
  1926 historySize
       
  1927     ^ history size
       
  1928 ! !
       
  1929 
       
  1930 !UIObjectView::UndoHistory methodsFor:'initialization'!
       
  1931 
       
  1932 initialize
       
  1933     super initialize.
       
  1934     self  reinitialize.
       
  1935 
       
  1936 
       
  1937 !
       
  1938 
       
  1939 reinitialize
       
  1940     "reinitialize all attributes
       
  1941     "
       
  1942     history     := OrderedCollection new.
       
  1943     transaction := nil.
       
  1944     enabled     := true.
       
  1945 
       
  1946 
       
  1947 ! !
       
  1948 
       
  1949 !UIObjectView::UndoHistory methodsFor:'menu'!
       
  1950 
       
  1951 openUndoMenu
       
  1952     |list top slv hzp inset selection okButton|
       
  1953 
       
  1954     history isEmpty ifTrue:[
       
  1955         ^ self
       
  1956     ].
       
  1957 
       
  1958     top  := StandardSystemView new label:'undo history'; extent:250@350.
       
  1959     slv  := ScrollableView for:SelectionInListView origin:0.0@0.0 corner:1.0@1.0 in:top.
       
  1960     hzp  := HorizontalPanelView origin:0.0@1.0 corner:1.0@1.0 in:top.
       
  1961     hzp horizontalLayout:#fitSpace.
       
  1962 
       
  1963     (Button abortButtonIn:hzp) action:[ selection := nil. top destroy ].
       
  1964     okButton := Button okButtonIn:hzp.
       
  1965     okButton label:'undo to end'.
       
  1966     okButton action:[ top destroy ].
       
  1967 
       
  1968     inset := hzp preferredExtent y.
       
  1969     hzp topInset:(inset negated).
       
  1970     slv   bottomInset:inset.
       
  1971     slv := slv scrolledView.
       
  1972 
       
  1973     list := history collect:[:aTrans||e|
       
  1974         e := MultiColListEntry new.
       
  1975         e colAt:1 put:(aTrans type asString).
       
  1976         e colAt:2 put:(aTrans text ? '').
       
  1977         e
       
  1978     ].
       
  1979 
       
  1980     slv list:list.
       
  1981     slv action:[:index | selection := index ].
       
  1982     top openModal.
       
  1983 
       
  1984     selection notNil ifTrue:[
       
  1985         self undoLast:(history size - selection + 1).
       
  1986     ]
       
  1987 ! !
       
  1988 
       
  1989 !UIObjectView::UndoHistory methodsFor:'testing'!
       
  1990 
       
  1991 isEmpty
       
  1992     "returns true if undo history is empty
       
  1993     "
       
  1994     ^ history isEmpty
       
  1995 
       
  1996 
       
  1997 !
       
  1998 
       
  1999 isTransactionOpen
       
  2000     ^ (enabled and:[transaction notNil])
       
  2001 !
       
  2002 
       
  2003 notEmpty
       
  2004     "returns true if undo history is not empty
       
  2005     "
       
  2006     ^ history notEmpty
       
  2007 
       
  2008 
       
  2009 ! !
       
  2010 
       
  2011 !UIObjectView::UndoHistory methodsFor:'transaction'!
       
  2012 
       
  2013 addUndoBlock:anUndoBlock
       
  2014     "undo block to restore changes; add block to current transaction
       
  2015     "
       
  2016     self isTransactionOpen ifTrue:[
       
  2017         transaction add:anUndoBlock
       
  2018     ]
       
  2019 
       
  2020 
       
  2021 !
       
  2022 
       
  2023 disabledTransitionDo:aBlock
       
  2024     "disable transitions during evaluating the block
       
  2025     "
       
  2026     |oldState|
       
  2027 
       
  2028     oldState := enabled.
       
  2029     enabled  := false.
       
  2030     aBlock value.
       
  2031     enabled  := oldState.
       
  2032 !
       
  2033 
       
  2034 transaction:aType do:aBlock
       
  2035     self transaction:aType text:nil do:aBlock
       
  2036 !
       
  2037 
       
  2038 transaction:aType text:aTextOrNil do:aBlock
       
  2039     "open a transaction; perform the block; at least close the transaction
       
  2040     "
       
  2041     (enabled and:[transaction isNil]) ifTrue:[
       
  2042         transaction := Transaction type:aType text:aTextOrNil.
       
  2043 
       
  2044         aBlock value.
       
  2045 
       
  2046         transaction isEmpty ifFalse:[
       
  2047             history addLast:transaction.
       
  2048             history size > (self class maxHistorySize) ifTrue:[history removeFirst]
       
  2049         ].
       
  2050         transaction := nil
       
  2051 
       
  2052     ] ifFalse:[
       
  2053         aBlock value
       
  2054     ]
       
  2055 ! !
       
  2056 
       
  2057 !UIObjectView::UndoHistory methodsFor:'undo'!
       
  2058 
       
  2059 undoLast:nTransactions
       
  2060     "undo last n transactions; an open transaction will be closed;
       
  2061      transactions during undo are disabled
       
  2062     "
       
  2063     |n|
       
  2064 
       
  2065     transaction := nil.
       
  2066     n := nTransactions min:(history size).
       
  2067 
       
  2068     n ~~ 0 ifTrue:[
       
  2069         enabled := false.
       
  2070         n timesRepeat:[ (history removeLast) undo ].
       
  2071         enabled := true.
       
  2072     ]
       
  2073 
       
  2074 
       
  2075 ! !
       
  2076 
       
  2077 !UIObjectView::UndoHistory::Transaction class methodsFor:'documentation'!
       
  2078 
       
  2079 version
       
  2080     ^ '$Header$'
       
  2081 ! !
     7 
  2082 
     8 !UIObjectView::UndoHistory::Transaction class methodsFor:'instance creation'!
  2083 !UIObjectView::UndoHistory::Transaction class methodsFor:'instance creation'!
     9 
  2084 
    10 type:aType text:aTextOrNil
  2085 type:aType text:aTextOrNil
    11     ^ self new type:aType text:aTextOrNil
  2086     ^ self new type:aType text:aTextOrNil
    96     "returns true if any undo action is registered
  2171     "returns true if any undo action is registered
    97     "
  2172     "
    98     ^ actions notNil
  2173     ^ actions notNil
    99 ! !
  2174 ! !
   100 
  2175 
       
  2176 !UIObjectView class methodsFor:'documentation'!
       
  2177 
       
  2178 version
       
  2179     ^ '$Header$'
       
  2180 ! !