UILayoutTool.st
changeset 163 dff48b7ca574
child 184 700f2ee9911e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UILayoutTool.st	Fri Jun 20 19:23:43 1997 +0200
@@ -0,0 +1,1277 @@
+"
+ COPYRIGHT (c) 1995 by eXept Software AG
+              All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+
+
+
+
+ApplicationModel subclass:#UILayoutTool
+	instanceVariableNames:'modifiedHolder aspects selection layoutView'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Interface-UIPainter'
+!
+
+ApplicationModel subclass:#LayoutOrigin
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:UILayoutTool
+!
+
+ApplicationModel subclass:#Rectangle
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:UILayoutTool
+!
+
+ApplicationModel subclass:#Point
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:UILayoutTool
+!
+
+ApplicationModel subclass:#LayoutFrame
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:UILayoutTool
+!
+
+ApplicationModel subclass:#AlignmentOrigin
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:UILayoutTool
+!
+
+ApplicationModel subclass:#Extent
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:UILayoutTool
+!
+
+!UILayoutTool class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 1995 by eXept Software AG
+              All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+
+
+
+!
+
+documentation
+"
+    used by the UIPainter to manipulate the layout of the selected component
+
+    [author:]
+        Claus Atzkern
+
+    [see also:]
+        UIPainter
+        UIHelpTool
+        UISpecificationTool
+"
+
+
+! !
+
+!UILayoutTool class methodsFor:'constants'!
+
+label
+    ^ 'Layout'
+! !
+
+!UILayoutTool class methodsFor:'interface specs'!
+
+slices
+    ^ #(
+        ( 'Frame'          LayoutFrame)
+        ( 'Origin'         LayoutOrigin)
+        ( 'Alig.Origin'    AlignmentOrigin)
+        ( 'Point'          Point)
+        ( 'Rectangle'      Rectangle)
+        ( 'Extent'         Extent)
+       ) 
+
+!
+
+windowSpec
+    "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:UILayoutTool andSelector:#windowSpec
+     UILayoutTool new openInterface:#windowSpec
+    "
+    "UILayoutTool open"
+
+    <resource: #canvas>
+
+    ^
+     
+       #(#FullSpec
+          #'window:' 
+           #(#WindowSpec
+              #'name:' 'uIPainterView'
+              #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+              #'label:' 'unnamed canvas'
+              #'bounds:' #(#Rectangle 0 0 300 300)
+          )
+          #'component:' 
+           #(#SpecCollection
+              #'collection:' 
+               #(
+                 #(#NoteBookViewSpec
+                    #'name:' 'NoteBook'
+                    #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+                    #'tabable:' true
+                    #'menu:' #noteBookList
+                    #'enableChannel:' #enableChannel
+                    #'style:' 
+                     #(#FontDescription
+                        #helvetica #medium
+                        #roman #'10'
+                    )
+                    #'model:' #noteBookModel
+                    #'tabWidget:' #Window
+                    #'direction:' #bottom
+"/                    #'useIndex:' true
+                    #'canvas:' #noteBookView
+                )
+              )
+          )
+      )
+! !
+
+!UILayoutTool methodsFor:'accessing'!
+
+layout
+    "returns configued layout or nil
+    "
+    |appl|
+
+    (appl := self noteBookView application) notNil ifTrue:[
+        ^ appl layout
+    ].
+  ^ nil
+!
+
+layoutType
+    "returns current layout type or nil
+    "
+    |slice|
+
+    (slice := self selectedSlice) notNil ifTrue:[
+        ^ slice last
+    ].
+  ^ nil
+!
+
+layoutView
+    "returns current edited view
+    "
+    ^ layoutView
+!
+
+layoutView:aView
+    "change current edited view
+    "
+    |type name list|
+
+    layoutView := aView.
+
+    (type := UIPainterView layoutType:layoutView) notNil ifTrue:[
+        self class slices findFirst:[:e|
+            e last == type ifTrue:[name := e first. true]
+        ].
+        type == #Extent ifTrue:[
+            list := Array with:name
+        ] ifFalse:[
+            list := self class slices collect:[:e| e first ].
+            list removeLast.
+        ].
+    ].
+    self noteBookList  value:list.
+    self noteBookModel value:name.
+    self update.
+!
+
+modifiedHolder:aValueHolder
+    "set the value holder set to true in case of modifying attributes
+    "
+    modifiedHolder notNil ifTrue:[
+        modifiedHolder removeDependent:self. 
+    ].
+
+    (modifiedHolder := aValueHolder) notNil ifTrue:[
+        modifiedHolder addDependent:self.
+    ].
+
+!
+
+update
+    "update from view
+    "
+    |view appl|
+
+    selection notNil ifTrue:[
+        (view := self layoutView) notNil ifTrue:[
+            (appl := self noteBookView application) notNil ifTrue:[
+                appl fetch:view
+            ]
+        ]
+    ].
+        
+! !
+
+!UILayoutTool methodsFor:'aspects'!
+
+aspectFor:aKey
+    "returns aspect for a key or nil
+    "
+  ^ aspects at:aKey ifAbsent:[ super aspectFor:aKey ]
+
+
+!
+
+noteBookList
+    "returns list of tab labels
+    "
+    |holder|
+
+    (holder := builder bindingAt:#noteBookList) isNil ifTrue:[
+        holder := nil asValue.
+        builder aspectAt:#noteBookList put:holder
+    ].
+  ^ holder
+!
+
+noteBookModel
+    "automatically generated by UIPainter ..."
+
+    |holder|
+
+    (holder := builder bindingAt:#noteBookModel) isNil ifTrue:[
+        holder := AspectAdaptor new subject:self; forAspect:#selection.
+        builder aspectAt:#noteBookModel put:holder.
+    ].
+    ^ holder
+!
+
+noteBookView
+    "automatically generated by UIPainter ...
+    "
+    |holder|
+
+    (holder := builder bindingAt:#noteBookView) isNil ifTrue:[
+        holder := SubCanvas new.
+        builder aspectAt:#noteBookView put:holder
+    ].
+  ^ holder
+! !
+
+!UILayoutTool methodsFor:'change & update'!
+
+update:something with:aParameter from:changedObject
+    "one of my models changed its value
+    "
+    changedObject ~~ modifiedHolder ifTrue:[
+        modifiedHolder value ~~ true ifTrue:[
+            modifiedHolder isNil ifFalse:[
+                modifiedHolder value:true
+            ]
+        ]
+    ]
+
+! !
+
+!UILayoutTool methodsFor:'converting absolute'!
+
+absolute:what xOrY:xOrY
+    |extent fraction offset fractSymb offsetSymb|
+
+    extent     := (self layoutView superView computeExtent) perform:xOrY.
+    fractSymb  := (what, 'Fraction') asSymbol.
+    offsetSymb := (what,   'Offset') asSymbol.
+    fraction   := (self aspectFor:fractSymb)  value.
+    offset     := (self aspectFor:offsetSymb) value.
+    offset     := offset + ((fraction * extent) asInteger).
+
+    (self aspectFor:offsetSymb) value:offset.
+    (self aspectFor:fractSymb)  value:0.
+
+
+
+!
+
+absoluteBottom
+    self absolute:'bottom' xOrY:#y
+
+!
+
+absoluteLeft
+    self absolute:'left' xOrY:#x
+
+!
+
+absoluteRight
+    self absolute:'right' xOrY:#x
+
+!
+
+absoluteTop
+    self absolute:'top' xOrY:#y
+
+! !
+
+!UILayoutTool methodsFor:'converting relative'!
+
+relative:what xOrY:xOrY
+    |extent fraction offset fractSymb offsetSymb|
+
+    extent     := (self layoutView superView computeExtent) perform:xOrY.
+    fractSymb  := (what, 'Fraction') asSymbol.
+    offsetSymb := (what,   'Offset') asSymbol.
+    fraction   := (self aspectFor:fractSymb)  value.
+    offset     := (self aspectFor:offsetSymb) value.
+    fraction   := (fraction + (offset / extent)) asFloat.
+
+    (fraction > 1.0) ifTrue:[ fraction := 1.0 ].
+    (fraction < 0.0) ifTrue:[ fraction := 0 ].
+
+    (self aspectFor:offsetSymb) value:0.
+    (self aspectFor:fractSymb)  value:fraction.
+
+
+
+!
+
+relativeBottom
+    self relative:'bottom' xOrY:#y
+
+
+!
+
+relativeLeft
+    self relative:'left' xOrY:#x
+
+!
+
+relativeRight
+    self relative:'right' xOrY:#x
+
+!
+
+relativeTop
+    self relative:'top' xOrY:#y
+
+! !
+
+!UILayoutTool methodsFor:'initialization'!
+
+initialize
+    "initialize channels
+    "
+    super initialize.
+
+    aspects  := IdentityDictionary new.
+
+    #(  bottomFraction          bottomOffset
+        leftFraction            leftOffset
+        topFraction             topOffset
+        rightFraction           rightOffset
+        leftAlignmentFraction   topAlignmentFraction
+    )
+
+    do:[:aKey||holder|
+        holder := ValueHolder new.
+        holder addDependent:self.
+        aspects at:aKey put:holder.
+    ].
+
+
+
+
+! !
+
+!UILayoutTool methodsFor:'selection'!
+
+selectedSlice
+    "returns slice assigned to selection or nil
+    "
+    selection notNil ifTrue:[
+        self class slices do:[:aSlice|
+            aSlice first = selection ifTrue:[
+                ^ aSlice
+            ]
+        ]
+    ].
+    ^ nil
+
+!
+
+selection
+    ^ selection
+!
+
+selection:aSelection
+    |appl view slice|
+
+    selection = aSelection ifFalse:[
+        (selection := aSelection) notNil ifTrue:[
+            slice := self selectedSlice.
+            appl  := slice last asString.
+            appl := Smalltalk classNamed:(self class name asString, '::', appl).
+            appl := appl new.
+            appl masterApplication:self.
+        ].
+        self noteBookView client:appl
+    ].
+    self update
+! !
+
+!UILayoutTool::LayoutOrigin class methodsFor:'interface specs'!
+
+windowSpec
+    "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:UILayoutTool::LayoutOrigin andSelector:#windowSpec
+     UILayoutTool::LayoutOrigin new openInterface:#windowSpec
+    "
+    "UILayoutTool::LayoutOrigin open"
+
+    <resource: #canvas>
+
+    ^
+     
+       #(#FullSpec
+          #'window:' 
+           #(#WindowSpec
+              #'name:' 'uIPainterView'
+              #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+              #'label:' 'unnamed'
+              #'bounds:' #(#Rectangle 0 0 258 93)
+          )
+          #'component:' 
+           #(#SpecCollection
+              #'collection:' 
+               #(
+                 #(#LabelSpec
+                    #'name:' 'labelRelative'
+                    #'layout:' #(#Point 57 12)
+                    #'label:' 'relative'
+                )
+                 #(#LabelSpec
+                    #'name:' 'labelAbsolute'
+                    #'layout:' #(#Point 154 13)
+                    #'label:' 'absolute'
+                )
+                 #(#LabelSpec
+                    #'name:' 'labelLeft'
+                    #'layout:' #(#AlignmentOrigin 52 0 44 0 1 0)
+                    #'label:' 'left'
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldLeftFraction'
+                    #'layout:' #(#LayoutFrame 57 0 44 0 114 0 62 0)
+                    #'tabable:' true
+                    #'model:' #leftFraction
+                    #'type:' #numberOrNil
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'actionRelativeLeft'
+                    #'layout:' #(#LayoutFrame 119 0 44 0 138 0 62 0)
+                    #'label:' ''
+                    #'model:' #relativeLeft
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldLeftOffset'
+                    #'layout:' #(#LayoutFrame 154 0 44 0 212 0 62 0)
+                    #'tabable:' true
+                    #'model:' #leftOffset
+                    #'type:' #numberOrNil
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'actionAbsoluteLeft'
+                    #'layout:' #(#LayoutFrame 216 0 44 0 235 0 62 0)
+                    #'label:' ''
+                    #'model:' #absoluteLeft
+                )
+                 #(#LabelSpec
+                    #'name:' 'labelTop'
+                    #'layout:' #(#AlignmentOrigin 52 0 71 0 1 0)
+                    #'label:' 'top'
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldTopFraction'
+                    #'layout:' #(#LayoutFrame 57 0 71 0 114 0 89 0)
+                    #'tabable:' true
+                    #'model:' #topFraction
+                    #'type:' #numberOrNil
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'actionRelativeTop'
+                    #'layout:' #(#LayoutFrame 119 0 71 0 138 0 89 0)
+                    #'label:' ''
+                    #'model:' #relativeTop
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldTopOffset'
+                    #'layout:' #(#LayoutFrame 154 0 71 0 212 0 89 0)
+                    #'tabable:' true
+                    #'model:' #topOffset
+                    #'type:' #numberOrNil
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'actionAbsoluteTop'
+                    #'layout:' #(#LayoutFrame 216 0 71 0 235 0 89 0)
+                    #'label:' ''
+                    #'model:' #absoluteTop
+                )
+              )
+          )
+      )
+! !
+
+!UILayoutTool::LayoutOrigin methodsFor:'accessing'!
+
+fetch:aView
+    "fetch layoutOrigin
+    "
+    |layout|
+
+    layout  := UIPainterView asLayoutFrameFromView:aView.
+
+    (self aspectFor:#leftOffset)   value:(layout leftOffset).
+    (self aspectFor:#leftFraction) value:(layout leftFraction).
+    (self aspectFor:#topOffset)    value:(layout topOffset).
+    (self aspectFor:#topFraction)  value:(layout topFraction).
+
+
+!
+
+layout
+    "returns current layout as layoutOrigin
+    "
+    |layout|
+
+    layout  := Smalltalk::LayoutOrigin new.
+
+    layout   leftOffset:((self aspectFor:#leftOffset)   value) ? 0.
+    layout    topOffset:((self aspectFor:#topOffset)    value) ? 0.
+    layout leftFraction:((self aspectFor:#leftFraction) value) ? 0.
+    layout  topFraction:((self aspectFor:#topFraction)  value) ? 0.
+
+  ^ layout
+
+! !
+
+!UILayoutTool::Rectangle class methodsFor:'interface specs'!
+
+windowSpec
+    "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:UILayoutTool::Rectangle andSelector:#windowSpec
+     UILayoutTool::Rectangle new openInterface:#windowSpec
+    "
+    "UILayoutTool::Rectangle open"
+
+    <resource: #canvas>
+
+    ^
+     
+       #(#FullSpec
+          #'window:' 
+           #(#WindowSpec
+              #'name:' 'uIPainterView'
+              #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+              #'label:' 'unnamed'
+              #'bounds:' #(#Rectangle 0 0 224 146)
+          )
+          #'component:' 
+           #(#SpecCollection
+              #'collection:' 
+               #(
+                 #(#UISubSpecification
+                    #'name:' 'subSpecification'
+                    #'layout:' #(#LayoutOrigin 0 0 0 0)
+                    #'majorKey:' #'UILayoutTool::Point'
+                    #'minorKey:' #windowSpec
+                )
+                 #(#LabelSpec
+                    #'name:' 'labelCornerX'
+                    #'layout:' #(#AlignmentOrigin 75 0 74 0 1 0)
+                    #'label:' 'corner x:'
+                    #'adjust:' #left
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldCornerX'
+                    #'layout:' #(#LayoutFrame 77 0 74 0 170 0 92 0)
+                    #'tabable:' true
+                    #'model:' #rightOffset
+                    #'type:' #numberOrNil
+                )
+                 #(#LabelSpec
+                    #'name:' 'labelCornerY'
+                    #'layout:' #(#AlignmentOrigin 75 0 101 0 1 0)
+                    #'label:' 'corner y:'
+                    #'adjust:' #left
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldCornerY'
+                    #'layout:' #(#LayoutFrame 77 0 101 0 170 0 119 0)
+                    #'tabable:' true
+                    #'model:' #bottomOffset
+                    #'type:' #numberOrNil
+                )
+              )
+          )
+      )
+! !
+
+!UILayoutTool::Rectangle methodsFor:'accessing'!
+
+fetch:aView
+    "fetch rectangle
+    "
+    |origin corner|
+
+    origin := aView computeOrigin.
+    corner := aView computeCorner.
+
+    (self aspectFor:#leftOffset)   value:(origin x).
+    (self aspectFor:#rightOffset)  value:(corner x).
+    (self aspectFor:#topOffset)    value:(origin y).
+    (self aspectFor:#bottomOffset) value:(corner y).
+
+
+!
+
+layout
+    "returns current layout as rectangle
+    "
+  ^ Smalltalk::Rectangle left:(((self aspectFor:#leftOffset)   value) ? 0)
+                          top:(((self aspectFor:#topOffset)    value) ? 0)
+                        right:(((self aspectFor:#rightOffset)  value) ? 0)
+                       bottom:(((self aspectFor:#bottomOffset) value) ? 0)
+
+
+! !
+
+!UILayoutTool::Point class methodsFor:'interface specs'!
+
+windowSpec
+    "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:UILayoutTool::Point andSelector:#windowSpec
+     UILayoutTool::Point new openInterface:#windowSpec
+    "
+    "UILayoutTool::Point open"
+
+    <resource: #canvas>
+
+    ^
+     
+       #(#FullSpec
+          #'window:' 
+           #(#WindowSpec
+              #'name:' 'uIPainterView'
+              #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+              #'label:' 'unnamed'
+              #'bounds:' #(#Rectangle 0 0 194 66)
+          )
+          #'component:' 
+           #(#SpecCollection
+              #'collection:' 
+               #(
+                 #(#LabelSpec
+                    #'name:' 'labelOriginX'
+                    #'layout:' #(#AlignmentOrigin 75 0 19 0 1 0)
+                    #'label:' 'origin x:'
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldOriginX'
+                    #'layout:' #(#LayoutFrame 77 0 19 0 170 0 37 0)
+                    #'tabable:' true
+                    #'model:' #leftOffset
+                    #'type:' #numberOrNil
+                )
+                 #(#LabelSpec
+                    #'name:' 'labelOriginY'
+                    #'layout:' #(#AlignmentOrigin 75 0 46 0 1 0)
+                    #'label:' 'origin y:'
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldOriginY'
+                    #'layout:' #(#LayoutFrame 77 0 46 0 170 0 64 0)
+                    #'tabable:' true
+                    #'model:' #topOffset
+                    #'type:' #numberOrNil
+                )
+              )
+          )
+      )
+! !
+
+!UILayoutTool::Point methodsFor:'accessing'!
+
+fetch:aView
+    "fetch point
+    "
+    |origin|
+
+    origin  := aView computeOrigin.
+
+    (self aspectFor:#leftOffset) value:(origin x).
+    (self aspectFor:#topOffset)  value:(origin y).
+
+
+!
+
+layout
+    "returns current layout as point
+    "
+  ^ Smalltalk::Point x:(((self aspectFor:#leftOffset) value) ? 0)
+                     y:(((self aspectFor:#topOffset)  value) ? 0)
+
+! !
+
+!UILayoutTool::LayoutFrame class methodsFor:'interface specs'!
+
+windowSpec
+    "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:UILayoutTool::LayoutFrame andSelector:#windowSpec
+     UILayoutTool::LayoutFrame new openInterface:#windowSpec
+    "
+    "UILayoutTool::LayoutFrame open"
+
+    <resource: #canvas>
+
+    ^
+     
+       #(#FullSpec
+          #'window:' 
+           #(#WindowSpec
+              #'name:' 'uIPainterView'
+              #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+              #'label:' 'unnamed'
+              #'bounds:' #(#Rectangle 0 0 250 193)
+          )
+          #'component:' 
+           #(#SpecCollection
+              #'collection:' 
+               #(
+                 #(#UISubSpecification
+                    #'name:' 'subLayoutSpec'
+                    #'layout:' #(#LayoutOrigin 0 0 0 0)
+                    #'majorKey:' #'UILayoutTool::LayoutOrigin'
+                    #'minorKey:' #windowSpec
+                )
+                 #(#LabelSpec
+                    #'name:' 'labelRight'
+                    #'layout:' #(#AlignmentOrigin 52 0 98 0 1 0)
+                    #'label:' 'right'
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldRightFraction'
+                    #'layout:' #(#LayoutFrame 57 0 98 0 114 0 116 0)
+                    #'model:' #rightFraction
+                    #'type:' #numberOrNil
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'actionRelativeRight'
+                    #'layout:' #(#LayoutFrame 119 0 98 0 138 0 116 0)
+                    #'label:' ''
+                    #'model:' #relativeRight
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldRightOffset'
+                    #'layout:' #(#LayoutFrame 154 0 98 0 212 0 116 0)
+                    #'model:' #rightOffset
+                    #'type:' #numberOrNil
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'actionAbsoluteRight'
+                    #'layout:' #(#LayoutFrame 216 0 98 0 235 0 116 0)
+                    #'label:' ''
+                    #'model:' #absoluteRight
+                )
+                 #(#LabelSpec
+                    #'name:' 'labelBottom'
+                    #'layout:' #(#AlignmentOrigin 52 0 126 0 1 0)
+                    #'label:' 'bottom'
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldBottomFraction'
+                    #'layout:' #(#LayoutFrame 57 0 126 0 114 0 144 0)
+                    #'model:' #bottomFraction
+                    #'type:' #numberOrNil
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'actionRelativeBottom'
+                    #'layout:' #(#LayoutFrame 119 0 126 0 138 0 144 0)
+                    #'label:' ''
+                    #'model:' #relativeBottom
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldBottomOffset'
+                    #'layout:' #(#LayoutFrame 154 0 126 0 211 0 144 0)
+                    #'model:' #bottomOffset
+                    #'type:' #numberOrNil
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'actionAbsoluteBottom'
+                    #'layout:' #(#LayoutFrame 216 0 126 0 235 0 144 0)
+                    #'label:' ''
+                    #'model:' #absoluteBottom
+                )
+              )
+          )
+      )
+! !
+
+!UILayoutTool::LayoutFrame methodsFor:'accessing'!
+
+fetch:aView
+    |layout|
+
+    layout  := UIPainterView asLayoutFrameFromView:aView.
+
+    (self aspectFor:#leftOffset)     value:(layout leftOffset).
+    (self aspectFor:#leftFraction)   value:(layout leftFraction).
+    (self aspectFor:#topOffset)      value:(layout topOffset).
+    (self aspectFor:#topFraction)    value:(layout topFraction).
+    (self aspectFor:#rightOffset)    value:(layout rightOffset).
+    (self aspectFor:#bottomOffset)   value:(layout bottomOffset).
+    (self aspectFor:#rightFraction)  value:(layout rightFraction).
+    (self aspectFor:#bottomFraction) value:(layout bottomFraction).
+
+!
+
+layout
+    "returns current layout as layoutFrame
+    "
+    |layout|
+
+    layout  := Smalltalk::LayoutFrame new.
+
+    layout     leftOffset:((self aspectFor:#leftOffset)     value) ? 0.
+    layout    rightOffset:((self aspectFor:#rightOffset)    value) ? 0.
+    layout      topOffset:((self aspectFor:#topOffset)      value) ? 0.
+    layout   bottomOffset:((self aspectFor:#bottomOffset)   value) ? 0.
+    layout   leftFraction:((self aspectFor:#leftFraction)   value) ? 0.
+    layout  rightFraction:((self aspectFor:#rightFraction)  value) ? 0.
+    layout    topFraction:((self aspectFor:#topFraction)    value) ? 0.
+    layout bottomFraction:((self aspectFor:#bottomFraction) value) ? 0.
+
+  ^ layout
+
+! !
+
+!UILayoutTool::AlignmentOrigin class methodsFor:'interface specs'!
+
+windowSpec
+    "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:UILayoutTool::AlignmentOrigin andSelector:#windowSpec
+     UILayoutTool::AlignmentOrigin new openInterface:#windowSpec
+    "
+    "UILayoutTool::AlignmentOrigin open"
+
+    <resource: #canvas>
+
+    ^
+     
+       #(#FullSpec
+          #'window:' 
+           #(#WindowSpec
+              #'name:' 'uIPainterView'
+              #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+              #'label:' 'AlignmentOrigin'
+              #'bounds:' #(#Rectangle 0 0 268 205)
+          )
+          #'component:' 
+           #(#SpecCollection
+              #'collection:' 
+               #(
+                 #(#UISubSpecification
+                    #'name:' 'subSpecification'
+                    #'layout:' #(#LayoutOrigin 0 0 0 0)
+                    #'majorKey:' #'UILayoutTool::LayoutOrigin'
+                    #'minorKey:' #windowSpec
+                )
+                 #(#LabelSpec
+                    #'name:' 'label5'
+                    #'layout:' #(#AlignmentOrigin 84 0 106 0 1 0)
+                    #'label:' 'align H'
+                    #'adjust:' #right
+                )
+                 #(#LabelSpec
+                    #'name:' 'label6'
+                    #'layout:' #(#AlignmentOrigin 84 0 132 0 1 0)
+                    #'label:' 'align V'
+                    #'adjust:' #right
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'editField5'
+                    #'layout:' #(#LayoutFrame 89 0 106 0 146 0 124 0)
+                    #'tabable:' true
+                    #'model:' #leftAlignmentFraction
+                    #'type:' #numberOrNil
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'editField6'
+                    #'layout:' #(#LayoutFrame 89 0 132 0 146 0 150 0)
+                    #'tabable:' true
+                    #'model:' #topAlignmentFraction
+                    #'type:' #numberOrNil
+                )
+                 #(#DividerSpec
+                    #'name:' 'separator1'
+                    #'layout:' #(#Rectangle 175 111 224 114)
+                    #'orientation:' #horizontal
+                )
+                 #(#DividerSpec
+                    #'name:' 'separator2'
+                    #'layout:' #(#Rectangle 175 143 224 146)
+                    #'orientation:' #horizontal
+                )
+                 #(#DividerSpec
+                    #'name:' 'separator3'
+                    #'layout:' #(#Rectangle 171 118 174 139)
+                    #'orientation:' #vertical
+                )
+                 #(#DividerSpec
+                    #'name:' 'separator4'
+                    #'layout:' #(#Rectangle 226 118 229 139)
+                    #'orientation:' #vertical
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'alignBottomRight'
+                    #'layout:' #(#Rectangle 222 138 234 150)
+                    #'label:' ''
+                    #'model:' #alignBottomRight
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'alignTopLeft'
+                    #'layout:' #(#Rectangle 166 107 178 119)
+                    #'label:' ''
+                    #'model:' #alignTopLeft
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'alignTopRight'
+                    #'layout:' #(#Rectangle 222 107 234 119)
+                    #'label:' ''
+                    #'model:' #alignTopRight
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'alignBottomLeft'
+                    #'layout:' #(#Rectangle 166 137 178 149)
+                    #'label:' ''
+                    #'model:' #alignBottomLeft
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'alignTopCenter'
+                    #'layout:' #(#Rectangle 194 107 206 119)
+                    #'label:' ''
+                    #'model:' #alignTopCenter
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'alignBottomCenter'
+                    #'layout:' #(#Rectangle 194 138 206 150)
+                    #'label:' ''
+                    #'model:' #alignBottomCenter
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'alignLeftCenter'
+                    #'layout:' #(#Rectangle 166 122 178 134)
+                    #'label:' ''
+                    #'model:' #alignLeftCenter
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'alignRightCenter'
+                    #'layout:' #(#Rectangle 222 122 234 134)
+                    #'label:' ''
+                    #'model:' #alignRightCenter
+                )
+                 #(#ActionButtonSpec
+                    #'name:' 'alignCenter'
+                    #'layout:' #(#Rectangle 194 122 206 134)
+                    #'label:' ''
+                    #'model:' #alignCenter
+                )
+              )
+          )
+      )
+! !
+
+!UILayoutTool::AlignmentOrigin methodsFor:'accessing'!
+
+fetch:aView
+    "fetch alignmentOrigin
+    "
+    |layout type extent|
+
+    type   := UIPainterView layoutType:aView.
+    layout := aView geometryLayout.
+
+    layout isLayout ifTrue:[
+        (self aspectFor:#leftOffset)   value:(layout leftOffset).
+        (self aspectFor:#leftFraction) value:(layout leftFraction).
+        (self aspectFor:#topOffset)    value:(layout topOffset).
+        (self aspectFor:#topFraction)  value:(layout topFraction).
+
+        type == #AlignmentOrigin ifTrue:[
+            (self aspectFor:#leftAlignmentFraction) value:(layout leftAlignmentFraction).
+            (self aspectFor:#topAlignmentFraction)  value:(layout topAlignmentFraction).
+          ^ self
+        ]
+    ] ifFalse:[
+        layout := aView computeOrigin.
+
+        (self aspectFor:#leftOffset)   value:(layout x).
+        (self aspectFor:#leftFraction) value:0.
+        (self aspectFor:#topOffset)    value:(layout y).
+        (self aspectFor:#topFraction)  value:0.
+    ].
+    (self aspectFor:#leftAlignmentFraction) value:0.
+    (self aspectFor:#topAlignmentFraction)  value:0.
+
+
+!
+
+layout
+    "returns current layout as alignmentOrigin
+    "
+    |layout|
+
+    layout  := Smalltalk::AlignmentOrigin new.
+
+    layout   leftOffset:((self aspectFor:#leftOffset)   value) ? 0.
+    layout    topOffset:((self aspectFor:#topOffset)    value) ? 0.
+    layout leftFraction:((self aspectFor:#leftFraction) value) ? 0.
+    layout  topFraction:((self aspectFor:#topFraction)  value) ? 0.
+
+    layout leftAlignmentFraction:((self aspectFor:#leftAlignmentFraction) value) ? 0.
+    layout  topAlignmentFraction:((self aspectFor:#topAlignmentFraction)  value) ? 0.
+
+  ^ layout
+! !
+
+!UILayoutTool::AlignmentOrigin methodsFor:'alignment'!
+
+alignBottomCenter
+    self makeAlignLeft:0.5 top:1
+
+
+!
+
+alignBottomLeft
+    self makeAlignLeft:0 top:1
+
+
+!
+
+alignBottomRight
+    self makeAlignLeft:1 top:1
+
+
+!
+
+alignCenter
+    self makeAlignLeft:0.5 top:0.5
+
+
+!
+
+alignLeftCenter
+    self makeAlignLeft:0 top:0.5
+
+
+!
+
+alignRightCenter
+    self makeAlignLeft:1 top:0.5
+
+
+!
+
+alignTopCenter
+    self makeAlignLeft:0.5 top:0
+
+
+!
+
+alignTopLeft
+    self makeAlignLeft:0 top:0
+
+
+!
+
+alignTopRight
+    self makeAlignLeft:1 top:0
+
+
+!
+
+makeAlignLeft:leftAlignmentFraction top:topAlignmentFraction
+    |lAF tAF lO tO ext|
+
+    lAF     := (self aspectFor:#leftAlignmentFraction) value ? 0.
+    tAF     := (self aspectFor:#topAlignmentFraction)  value ? 0.
+    ext     := (self aspectFor:#layoutView) computeExtent.
+
+    (self aspectFor:#leftAlignmentFraction) value:leftAlignmentFraction.
+    (self aspectFor:#topAlignmentFraction)  value:topAlignmentFraction.
+
+    lO := (self aspectFor:#leftOffset) value ? 0.
+    tO := (self aspectFor:#topOffset)  value ? 0.
+
+    lO := lO + (ext x * (leftAlignmentFraction - lAF)).
+    tO := tO + (ext y * (topAlignmentFraction  - tAF)).
+
+    (self aspectFor:#leftOffset) value:(lO rounded).
+    (self aspectFor:#topOffset)  value:(tO rounded).
+
+!
+
+makeAlignTopRight
+    self makeAlignLeft:1 top:0
+
+
+! !
+
+!UILayoutTool::Extent class methodsFor:'interface specs'!
+
+windowSpec
+    "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:UILayoutTool::Extent andSelector:#windowSpec
+     UILayoutTool::Extent new openInterface:#windowSpec
+    "
+    "UILayoutTool::Extent open"
+
+    <resource: #canvas>
+
+    ^
+     
+       #(#FullSpec
+          #'window:' 
+           #(#WindowSpec
+              #'name:' 'uIPainterView'
+              #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+              #'label:' 'unnamed'
+              #'bounds:' #(#Rectangle 0 0 226 86)
+          )
+          #'component:' 
+           #(#SpecCollection
+              #'collection:' 
+               #(
+                 #(#LabelSpec
+                    #'name:' 'labelHorizontal'
+                    #'layout:' #(#AlignmentOrigin 73 0 25 0 1 0)
+                    #'label:' 'horizontal:'
+                    #'adjust:' #left
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldLeftOffset'
+                    #'layout:' #(#LayoutFrame 78 0 25 0 171 0 43 0)
+                    #'tabable:' true
+                    #'model:' #leftOffset
+                    #'type:' #numberOrNil
+                )
+                 #(#LabelSpec
+                    #'name:' 'labelVertical'
+                    #'layout:' #(#AlignmentOrigin 73 0 52 0 1 0)
+                    #'label:' 'vertical:'
+                    #'adjust:' #left
+                )
+                 #(#InputFieldSpec
+                    #'name:' 'fieldRightOffset'
+                    #'layout:' #(#LayoutFrame 78 0 52 0 171 0 70 0)
+                    #'tabable:' true
+                    #'model:' #rightOffset
+                    #'type:' #numberOrNil
+                )
+              )
+          )
+      )
+! !
+
+!UILayoutTool::Extent methodsFor:'accessing'!
+
+fetch:aView
+    "fetch extent
+    "
+    |extent|
+
+    extent  := aView computeExtent.
+
+    (self aspectFor:#leftOffset)  value:(extent x).
+    (self aspectFor:#rightOffset) value:(extent y).
+
+
+!
+
+layout
+    "returns current extent
+    "
+  ^ Smalltalk::Point x:(((self aspectFor:#leftOffset)   value) ? 0)
+                     y:(((self aspectFor:#rightOffset)  value) ? 0)
+
+! !
+
+!UILayoutTool class methodsFor:'documentation'!
+
+version
+    ^ '$Header$'
+! !