UIPainterView.st
changeset 211 45f193f4e870
parent 210 e49d831bb81f
child 212 1836a16763cc
--- a/UIPainterView.st	Fri Jul 04 23:39:10 1997 +0200
+++ b/UIPainterView.st	Fri Jul 04 23:47:35 1997 +0200
@@ -17,6 +17,20 @@
 	category:'Interface-UIPainter'
 !
 
+MultiSelectionInList subclass:#ListHolder
+	instanceVariableNames:'painter propertyList masterElement disabledChanged'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:UIPainterView
+!
+
+Object subclass:#ViewProperty
+	instanceVariableNames:'view spec identifier'
+	classVariableNames:'Identifier'
+	poolDictionaries:''
+	privateIn:UIPainterView
+!
+
 !UIPainterView class methodsFor:'documentation'!
 
 copyright
@@ -1019,7 +1033,6 @@
         self withSelectionHiddenDo:[
             self transaction:#specification selectionDo:[:aView|
                 builder := UIBuilder new.
-                builder applicationClass:(Smalltalk classNamed:className).
                 props   := self propertyOfView:aView.
                 name    := (aSpec name) withoutSeparators.
 
@@ -1047,8 +1060,6 @@
             ]
         ]
     ]
-
-    "Modified: 4.7.1997 / 23:37:27 / cg"
 ! !
 
 !UIPainterView methodsFor:'transaction'!
@@ -1191,7 +1202,6 @@
         view    := props view.
         spec    := args at:1.
         builder := UIBuilder new.
-        builder applicationClass:(Smalltalk classNamed:className).
         props spec:spec.
 
         spec needsRebuildForAttributes ifTrue:[
@@ -1206,7 +1216,6 @@
         listHolder propertyChanged:props.
     ]
 
-    "Modified: 4.7.1997 / 23:37:20 / cg"
 ! !
 
 !UIPainterView methodsFor:'user actions - arrange'!
@@ -1241,6 +1250,465 @@
 
 ! !
 
+!UIPainterView::ListHolder class methodsFor:'instance creation'!
+
+for:aPainter
+    ^ self new for:aPainter
+! !
+
+!UIPainterView::ListHolder methodsFor:'accessing'!
+
+painter
+    "returns painter
+    "
+    ^ painter
+!
+
+propertyAt:anIndex
+    "returns property at an index
+    "
+    ^ propertyList at:anIndex
+! !
+
+!UIPainterView::ListHolder methodsFor:'adding & removing'!
+
+add:aProperty
+    "add property and update list
+    "
+    |idx list name last|
+
+    list := self list.
+    idx  := self findParentProperty:aProperty.
+    name := aProperty name.
+
+    idx == 0 ifTrue:[
+        last := list size
+    ] ifFalse:[
+        last := self lastInGroupStartingAt:idx.
+        name := (String new:(4+((list at:idx) leftIndent))), name.
+    ].
+    propertyList add:aProperty afterIndex:last.
+    list         add:name      afterIndex:last.
+    self changed:#size
+
+
+!
+
+remove:aView
+    "remove all view relevant resources
+    "
+    |start|
+
+    aView notNil ifTrue:[
+        start := self findProperty:[:p| p view == aView ].
+
+        start ~~ 0 ifTrue:[
+            self basicRemove:start.
+            self changed:#size.
+        ]
+    ]
+!
+
+removeAll
+    masterElement := nil.
+    self selection:#().
+
+    [propertyList notEmpty] whileTrue:[
+        self basicRemove:1
+    ].
+    self changed:#size.
+
+! !
+
+!UIPainterView::ListHolder methodsFor:'change & update'!
+
+changed:aParameter
+    "notify all dependents that the receiver has changed somehow.
+     Each dependent gets a '#update:'-message with aParameter
+     as argument. In case of disabled no notifications are raised
+    "
+    disabledChanged ifFalse:[
+        super changed:aParameter
+    ]
+!
+
+disableNotificationsWhileEvaluating:aBlock
+    "perform block without notification; after evaluation of block,
+     a #size changed notification is raised
+    "
+    |oldState|
+
+    oldState := disabledChanged.
+    disabledChanged := true.
+    aBlock value.
+    disabledChanged := oldState.
+    self changed:#size.
+!
+
+propertyChanged:aProperty
+    "property list changed; update list names
+    "
+    |list idx oldName newName wspName view indent mid|
+
+    view := aProperty view.
+    idx  := self findProperty:[:p| p view == view ].
+
+    idx == 0 ifTrue:[
+        ^ self error
+    ].
+
+    list    := self list.
+    oldName := list at:idx.
+    wspName := oldName string withoutSeparators.
+    newName := aProperty name.
+
+    wspName = newName ifFalse:[
+        mid := self masterElement.
+        list at:idx put:((String new:(oldName leftIndent)), newName).
+
+        idx == mid ifTrue:[
+            masterElement := nil.
+            self masterElement:idx
+        ].
+    ].
+    self changed:#property
+
+! !
+
+!UIPainterView::ListHolder methodsFor:'enumerating'!
+
+propertiesDo:aBlock
+    "evaluate a block for each property
+    "
+    propertyList do:aBlock
+! !
+
+!UIPainterView::ListHolder methodsFor:'initialization'!
+
+for:aPainter
+    "initialize for a painter
+    "
+    painter := aPainter.
+    disabledChanged := false.
+    self list:(OrderedCollection new).
+    propertyList := OrderedCollection new.
+    self selection:#().
+    self addDependent:painter.
+
+! !
+
+!UIPainterView::ListHolder methodsFor:'private'!
+
+basicRemove:start
+    "remove all resources assigned to a group starting at start;
+     no notifications are raised
+    "
+    |end view superView|
+
+    end  := self lastInGroupStartingAt:start.
+    view := (propertyList at:start) view.
+
+    view notNil ifTrue:[
+        superView := view superView.
+        view destroy.
+        superView sizeChanged:nil.
+    ].
+
+    propertyList removeFromIndex:start toIndex:end.
+    self list    removeFromIndex:start toIndex:end.
+!
+
+masterElement
+    "returns index of master
+    "
+    ^ self indexOfName:masterElement.
+!
+
+masterElement:newIndex
+    "change master of selection
+    "
+    |name list oldIdx|
+
+    (oldIdx := self masterElement) ~~ newIndex ifTrue:[
+        list := self list.
+        
+        oldIdx ~~ 0 ifTrue:[
+            list at:oldIdx put:masterElement
+        ].
+        newIndex ~~ 0 ifTrue:[
+            masterElement := list at:newIndex.
+            name := Text string:masterElement.
+            name emphasizeFrom:(1+(name leftIndent)) with:#(#bold #underline).
+            list at:newIndex put:name.
+        ] ifFalse:[
+            masterElement := nil
+        ].
+        self changed:#list.
+    ]
+! !
+
+!UIPainterView::ListHolder methodsFor:'recomputing'!
+
+recompute
+    |list prop size osel|
+
+    osel := self selection copy.
+    size := self list size.
+    list := OrderedCollection new:size.
+    prop := OrderedCollection new:size.
+
+    painter allSubViewsDo:[:v|
+        size := self indexOfView:v.
+
+        size ~~ 0 ifTrue:[
+            list add:(self list at:size).
+            prop add:(propertyList at:size)
+        ]
+    ].
+    propertyList := prop.
+    self list:list.
+    self selection:osel.
+! !
+
+!UIPainterView::ListHolder methodsFor:'searching'!
+
+detectProperty:aBlock
+    "find the property, for which evaluation of the argument, aBlock
+     returns true; return the property or nil if none detected
+    "
+    |idx|
+
+    idx := self findProperty:aBlock.
+    idx ~~ 0 ifTrue:[ ^ propertyList at:idx ].
+  ^ nil
+!
+
+findParentProperty:aChildProp
+    "returns index of parent or 0
+    "
+    |view index|
+
+    view := aChildProp view.
+
+    view notNil ifTrue:[
+        [ (view := view superView) notNil ] whileTrue:[
+            index := self findProperty:[:aProp| aProp view == view ].
+            index ~~ 0 ifTrue:[
+                ^ index
+            ]
+        ]
+    ].
+    ^ 0
+
+
+!
+
+findProperty:aBlock
+    "find the first property, for which evaluation of the argument, aBlock
+     returns true; return its index or 0 if none detected
+    "
+    ^ propertyList findFirst:aBlock
+!
+
+indexOfName:aString
+    "returns index assigned to a string or 0
+    "
+    |name list size|
+
+    aString notNil ifTrue:[
+        name := aString string withoutSeparators.
+        size := name size.
+        list := self list.
+
+        list keysAndValuesDo:[:anIndex :aName|
+            |el|
+
+            el := aName string.
+            (el endsWith:name) ifTrue:[
+                (el size - el leftIndent) == name size ifTrue:[
+                    ^ anIndex
+                ]
+            ]
+        ]
+    ].
+    ^ 0
+
+!
+
+indexOfView:aView
+    "returns index assigned to a view or 0
+    "
+    aView notNil ifTrue:[
+        ^ propertyList findFirst:[:p| p view == aView ]
+    ].
+    ^ 0
+
+!
+
+lastInGroupStartingAt:start
+    "returns last index of a group
+    "
+    |end list idt|
+
+    list := self list.
+
+    start < list size ifTrue:[
+        idt := (list at:start) leftIndent.
+        end := list findFirst:[:el|(el leftIndent) <= idt] startingAt:(start+1).
+        end ~~ 0 ifTrue:[
+            ^ end - 1
+        ]
+    ].
+    ^ list size
+! !
+
+!UIPainterView::ListHolder methodsFor:'selection'!
+
+selectGroup
+    "select all elements assigned to master
+    "
+    |start end sel size|
+
+    painter enabled ifTrue:[
+        (start := self masterElement) ~~ 0 ifTrue:[
+            end  := self lastInGroupStartingAt:start.
+            size := end - start + 1.
+            sel  := Array new:size.
+
+            1 to:size do:[:i|
+                sel at:i put:start.
+                start := start + 1
+            ].
+            self selectionIndex:sel.
+        ] ifFalse:[
+            (self selectionIndex) size == 0 ifFalse:[
+                self selectionIndex:#()
+            ].
+        ]
+    ]
+!
+
+selectedProperty
+    "returns current selected instance; in case of multiple selection
+     or no selection nil is returned
+    "
+    |selection|
+    selection := self selectionIndex.
+
+    selection size == 1 ifTrue:[
+        propertyList size ~~ 0 ifTrue:[
+            ^ propertyList at:(selection first)
+        ]
+    ].
+    ^ nil
+!
+
+selectionIndex:aList
+    |masterIndex aSel|
+
+    painter enabled ifTrue:[aSel := aList]
+                   ifFalse:[aSel := nil].
+
+    aSel size ~~ 0 ifTrue:[masterIndex := aSel at:1]
+                  ifFalse:[masterIndex := 0].
+
+    self masterElement:masterIndex.
+    super selectionIndex:aSel
+! !
+
+!UIPainterView::ViewProperty class methodsFor:'instance creation'!
+
+new
+    Identifier notNil ifTrue:[Identifier := Identifier + 1]
+                     ifFalse:[Identifier := 1].
+
+  ^ self basicNew initialize
+! !
+
+!UIPainterView::ViewProperty methodsFor:'accessing'!
+
+identifier
+    "return the unique identifier assigned to property
+    "
+    ^ identifier
+!
+
+identifier:anIdentifier
+    "set the unique identifier assigned to property; called after an restore of
+     a deleted instance
+    "
+    identifier := anIdentifier
+!
+
+spec
+    "return the value of the instance variable 'spec' (automatically generated)"
+
+    ^ spec!
+
+spec:something
+    "set the value of the instance variable 'spec' (automatically generated)"
+
+    spec := something.!
+
+view
+    "return the value of the instance variable 'view' (automatically generated)"
+
+    ^ view!
+
+view:something
+    "set the value of the instance variable 'view' (automatically generated)"
+
+    view := something.! !
+
+!UIPainterView::ViewProperty methodsFor:'initialization'!
+
+initialize
+    super initialize.
+    identifier := Identifier
+! !
+
+!UIPainterView::ViewProperty methodsFor:'misc'!
+
+extractNumberStartingAt:anIndex
+    "return the number from the name starting at anIndex or 0.
+    "
+    |val|
+
+    val := 0.
+
+    self name from:anIndex do:[:c|
+        c isDigit ifTrue:[val := val * 10 + c digitValue]
+                 ifFalse:[^ 0]
+    ].
+    ^ val
+        
+! !
+
+!UIPainterView::ViewProperty methodsFor:'spec messages'!
+
+doesNotUnderstand:aMessage
+    spec notNil ifTrue:[
+        (spec respondsTo:(aMessage selector)) ifTrue:[^ aMessage sendTo:spec]
+    ].
+    ^ nil
+!
+
+layout
+    spec layout
+!
+
+layout:aLayout
+    spec layout:aLayout
+!
+
+name
+    ^ spec name
+!
+
+name:aName
+    spec name:aName
+! !
+
 !UIPainterView class methodsFor:'documentation'!
 
 version