reworked... to add/delete and modify keys
authorca
Mon, 04 Nov 2002 10:24:22 +0100
changeset 1646 4d2809c829e0
parent 1645 714b89cb8ff7
child 1647 caa90f350d18
reworked... to add/delete and modify keys
UIHelpTool.st
--- a/UIHelpTool.st	Mon Nov 04 10:23:48 2002 +0100
+++ b/UIHelpTool.st	Mon Nov 04 10:24:22 2002 +0100
@@ -15,8 +15,9 @@
 "{ Package: 'stx:libtool2' }"
 
 ToolApplicationModel subclass:#UIHelpTool
-	instanceVariableNames:'specClass specSelector dictionary dictionaries listSelection
-		maxCharsPerLine modifiedHolder modified'
+	instanceVariableNames:'specClass specSelector dictionary dictionaries modifiedHolder
+		modified listOfKeys listOfKeysModel listOfClasses
+		listOfClassesModel contentsModifiedChannel editModel editTextView'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'Interface-UIPainter'
@@ -91,7 +92,7 @@
 openOnClass:aClass
     "opens a Help Tool on aClass"
 
-    self new openOnClass:aClass
+    ^ self openOnClass:aClass andSelector:#helpSpec
 
     "
      UIHelpTool openOnClass:self
@@ -141,9 +142,6 @@
 #deleteHelpTextKey
 'Deletes the key from the help spec.'
 
-#updateHelpTextKey
-'Refetch the help spec.'
-
 #fileLoad
 'Opens a dialog for selecting and loading a help spec from a class.'
 
@@ -156,7 +154,7 @@
 #helpTextView
 'Shows the help text. Menu action ''Accept'' commits changes'
 
-#listOfHelpSpecClasses
+#listOfClasses
 'Classes where help specs can be/are implemented.'
 
 #listOfHelpTexts
@@ -165,6 +163,9 @@
 #removeHelpTextKey
 'Removes the help message from the widget.'
 
+#updateHelpTextKey
+'Refetch the help spec.'
+
 )
 ! !
 
@@ -194,7 +195,7 @@
           #name: 'Help Tool'
           #min: #(#Point 10 10)
           #max: #(#Point 1160 870)
-          #bounds: #(#Rectangle 218 175 504 446)
+          #bounds: #(#Rectangle 31 306 317 577)
         )
         #component: 
        #(#SpecCollection
@@ -205,128 +206,88 @@
               #component: 
              #(#SpecCollection
                 #collection: #(
-                 #(#ViewSpec
-                    #name: 'Box1'
+                 #(#VariableHorizontalPanelSpec
+                    #name: 'VariableHorizontalPanel'
                     #component: 
                    #(#SpecCollection
                       #collection: #(
-                       #(#HorizontalPanelViewSpec
-                          #name: 'HorizontalPanel1'
-                          #layout: #(#LayoutFrame 0 0 0 0 0 1 25 0)
-                          #horizontalLayout: #fit
-                          #verticalLayout: #fit
-                          #horizontalSpace: 3
-                          #verticalSpace: 3
+                       #(#SelectionInListModelViewSpec
+                          #name: 'listOfKeys'
+                          #activeHelpKey: #listOfHelpTexts
+                          #model: #listOfKeysModel
+                          #menu: #listOfKeysMenu
+                          #hasHorizontalScrollBar: true
+                          #hasVerticalScrollBar: true
+                          #miniScrollerHorizontal: true
+                          #listModel: #listOfKeys
+                          #useIndex: false
+                          #highlightMode: #line
+                        )
+                       #(#ViewSpec
+                          #name: 'Box'
                           #component: 
                          #(#SpecCollection
                             #collection: #(
-                             #(#ActionButtonSpec
-                                #label: 'Add'
-                                #name: 'AddButton'
-                                #activeHelpKey: #addHelpTextKey
-                                #translateLabel: true
+                             #(#InputFieldSpec
+                                #name: 'helpKeyInputField'
+                                #layout: #(#LayoutFrame 2 0.0 2 0 -2 1.0 25 0)
+                                #activeHelpKey: #currentHelpTexts
                                 #tabable: true
-                                #model: #doAdd
-                                #extent: #(#Point 69 25)
-                              )
-                             #(#ActionButtonSpec
-                                #label: 'Remove'
-                                #name: 'RemoveButton'
-                                #activeHelpKey: #removeHelpTextKey
-                                #translateLabel: true
-                                #tabable: true
-                                #model: #doRemove
-                                #extent: #(#Point 69 25)
+                                #model: #editModel
+                                #immediateAccept: true
+                                #acceptOnReturn: false
+                                #acceptOnTab: false
+                                #acceptOnPointerLeave: false
                               )
-                             #(#ActionButtonSpec
-                                #label: 'Update'
-                                #name: 'UpdateButton'
-                                #activeHelpKey: #updateHelpTextKey
-                                #translateLabel: true
-                                #tabable: true
-                                #model: #doUpdate
-                                #extent: #(#Point 69 25)
-                              )
-                             #(#ActionButtonSpec
-                                #label: 'Delete'
-                                #name: 'DeleteButton'
-                                #activeHelpKey: #deleteHelpTextKey
-                                #translateLabel: true
-                                #tabable: true
-                                #model: #doDelete
-                                #extent: #(#Point 70 25)
+                             #(#SelectionInListModelViewSpec
+                                #name: 'listOfClasses'
+                                #layout: #(#LayoutFrame 0 0.0 27 0 0 1.0 0 1.0)
+                                #activeHelpKey: #listOfClasses
+                                #model: #listOfClassesModel
+                                #hasHorizontalScrollBar: true
+                                #hasVerticalScrollBar: true
+                                #miniScrollerHorizontal: true
+                                #miniScrollerVertical: true
+                                #listModel: #listOfClasses
+                                #useIndex: false
+                                #highlightMode: #line
                               )
                              )
                            
                           )
                         )
-                       #(#VariableHorizontalPanelSpec
-                          #name: 'VariableHorizontalPanel'
-                          #layout: #(#LayoutFrame 0 0 25 0 0 1 0 1)
-                          #component: 
-                         #(#SpecCollection
-                            #collection: #(
-                             #(#SequenceViewSpec
-                                #name: 'listOfHelpKeysView'
-                                #activeHelpKey: #listOfHelpTexts
-                                #tabable: true
-                                #model: #listModel
-                                #hasHorizontalScrollBar: true
-                                #hasVerticalScrollBar: true
-                                #miniScrollerHorizontal: true
-                                #useIndex: false
-                                #sequenceList: #listChannel
-                              )
-                             #(#ViewSpec
-                                #name: 'Box'
-                                #component: 
-                               #(#SpecCollection
-                                  #collection: #(
-                                   #(#InputFieldSpec
-                                      #name: 'helpKeyInputField'
-                                      #layout: #(#LayoutFrame 2 0.0 2 0 -2 1.0 25 0)
-                                      #activeHelpKey: #currentHelpTexts
-                                      #tabable: true
-                                      #model: #listModel
-                                      #immediateAccept: false
-                                      #acceptOnPointerLeave: false
-                                    )
-                                   #(#SequenceViewSpec
-                                      #name: 'listOfHelpSpecClassesView'
-                                      #layout: #(#LayoutFrame 0 0.0 27 0 0 1.0 0 1.0)
-                                      #activeHelpKey: #listOfHelpSpecClasses
-                                      #tabable: true
-                                      #model: #selectionOfHelpSpecClass
-                                      #hasHorizontalScrollBar: true
-                                      #hasVerticalScrollBar: true
-                                      #miniScrollerHorizontal: true
-                                      #miniScrollerVertical: true
-                                      #valueChangeSelector: #helpSpecClassSelected
-                                      #useIndex: false
-                                      #sequenceList: #listOfHelpSpecClasses
-                                    )
-                                   )
-                                 
-                                )
-                              )
-                             )
-                           
-                          )
-                          #handles: #(#Any 0.5 1.0)
+                       )
+                     
+                    )
+                    #handles: #(#Any 0.5 1.0)
+                  )
+                 #(#ViewSpec
+                    #name: 'Box1'
+                    #component: 
+                   #(#SpecCollection
+                      #collection: #(
+                       #(#MenuPanelSpec
+                          #name: 'helpTextMenu'
+                          #layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 24 0)
+                          #menu: #helpTextMenu
+                          #textDefault: true
+                        )
+                       #(#TextEditorSpec
+                          #name: 'helpTextView'
+                          #layout: #(#LayoutFrame 0 0.0 24 0.0 0 1.0 0 1.0)
+                          #activeHelpKey: #helpTextView
+                          #tabable: true
+                          #hasHorizontalScrollBar: true
+                          #hasVerticalScrollBar: true
+                          #miniScrollerHorizontal: true
+                          #miniScrollerVertical: true
+                          #modifiedChannel: #contentsModifiedChannel
+                          #postBuildCallback: #postBuildTextView:
                         )
                        )
                      
                     )
                   )
-                 #(#TextEditorSpec
-                    #name: 'helpTextView'
-                    #activeHelpKey: #helpTextView
-                    #tabable: true
-                    #hasHorizontalScrollBar: true
-                    #hasVerticalScrollBar: true
-                    #miniScrollerHorizontal: true
-                    #miniScrollerVertical: true
-                  )
                  )
                
               )
@@ -352,42 +313,106 @@
 
     <resource: #canvas>
 
-    ^
-     
-       #(#FullSpec
-          #window: 
-           #(#WindowSpec
-              #name: 'Help Tool'
-              #layout: #(#LayoutFrame 191 0 334 0 660 0 663 0)
-              #label: 'Help Tool'
-              #min: #(#Point 300 300)
-              #max: #(#Point 1152 900)
-              #bounds: #(#Rectangle 191 334 661 664)
-              #menu: #menu
-              #usePreferredExtent: false
-          )
-          #component: 
-           #(#SpecCollection
-              #collection: 
-               #(
-                 #(#UISubSpecification
-                    #name: 'windowSpec'
-                    #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 -26 1.0)
-                    #minorKey: #windowSpec
-                )
-                 #(#UISubSpecification
-                    #name: 'windowSpecForInfoBar'
-                    #layout: #(#LayoutFrame 0 0 -24 1 0 1 0 1)
-                    #majorKey: #ToolApplicationModel
-                    #minorKey: #windowSpecForInfoBar
-                )
-              )
-          )
+    ^ 
+     #(#FullSpec
+        #name: #windowSpecForStandAlone
+        #window: 
+       #(#WindowSpec
+          #label: 'Help Tool'
+          #name: 'Help Tool'
+          #min: #(#Point 300 300)
+          #max: #(#Point 1152 900)
+          #bounds: #(#Rectangle 83 333 796 896)
+          #menu: #menu
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#UISubSpecification
+              #name: 'windowSpec'
+              #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 -26 1.0)
+              #minorKey: #windowSpec
+            )
+           #(#UISubSpecification
+              #name: 'windowSpecForInfoBar'
+              #layout: #(#LayoutFrame 0 0 -24 1 0 1 0 1)
+              #majorKey: #ToolApplicationModel
+              #minorKey: #windowSpecForInfoBar
+            )
+           )
+         
+        )
       )
 ! !
 
 !UIHelpTool class methodsFor:'menu specs'!
 
+helpTextMenu
+    "This resource specification was automatically generated
+     by the MenuEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the MenuEditor may not be able to read the specification."
+
+    "
+     MenuEditor new openOnClass:UIHelpTool andSelector:#helpTextMenu
+     (Menu new fromLiteralArrayEncoding:(UIHelpTool helpTextMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #activeHelpKey: #commitOK
+            #enabled: #contentsModifiedChannel
+            #label: 'Accept'
+            #itemValue: #accept
+            #translateLabel: true
+          )
+         #(#MenuItem
+            #activeHelpKey: #commitCancel
+            #enabled: #contentsModifiedChannel
+            #label: 'Cancel'
+            #itemValue: #cancel
+            #translateLabel: true
+          )
+         )
+        nil
+        nil
+      )
+!
+
+listOfKeysMenu
+    "This resource specification was automatically generated
+     by the MenuEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the MenuEditor may not be able to read the specification."
+
+    "
+     MenuEditor new openOnClass:UIHelpTool andSelector:#listOfKeysMenu
+     (Menu new fromLiteralArrayEncoding:(UIHelpTool listOfKeysMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #activeHelpKey: #deleteHelpTextKey
+            #label: 'Delete'
+            #itemValue: #doDelete
+            #translateLabel: true
+          )
+         )
+        nil
+        nil
+      )
+!
+
 menu
     "This resource specification was automatically generated
      by the MenuEditor of ST/X."
@@ -402,89 +427,69 @@
 
     <resource: #menu>
 
-    ^
-
-       #(#Menu
-
-           #(
-             #(#MenuItem
-                #label: 'File'
-                #translateLabel: true
-                #submenu: 
-                 #(#Menu
-
-                     #(
-                       #(#MenuItem
-                          #label: 'Load...'
-                          #translateLabel: true
-                          #value: #doLoad
-                          #activeHelpKey: #fileLoad
-                      )
-                       #(#MenuItem
-                          #label: 'Update'
-                          #translateLabel: true
-                          #value: #doUpdate
-                          #activeHelpKey: #fileUpdate
-                      )
-                       #(#MenuItem
-                          #label: '-'
-                      )
-                       #(#MenuItem
-                          #label: 'Save'
-                          #translateLabel: true
-                          #value: #doSave
-                          #activeHelpKey: #fileSave
-                      )
-                       #(#MenuItem
-                          #label: '-'
-                      )
-                       #(#MenuItem
-                          #label: 'Exit'
-                          #translateLabel: true
-                          #value: #closeRequest
-                          #activeHelpKey: #fileExit
-                      )
-                    ) nil
-                    nil
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'File'
+            #translateLabel: true
+            #submenu: 
+           #(#Menu
+              #(
+               #(#MenuItem
+                  #activeHelpKey: #fileLoad
+                  #label: 'Load...'
+                  #itemValue: #doLoad
+                  #translateLabel: true
+                )
+               #(#MenuItem
+                  #activeHelpKey: #fileSave
+                  #label: 'Save'
+                  #itemValue: #doSave
+                  #translateLabel: true
+                )
+               #(#MenuItem
+                  #label: '-'
+                )
+               #(#MenuItem
+                  #activeHelpKey: #fileExit
+                  #label: 'Exit'
+                  #itemValue: #closeRequest
+                  #translateLabel: true
                 )
+               )
+              nil
+              nil
             )
-             #(#MenuItem
-                #label: 'Edit'
-                #translateLabel: true
-                #submenu: 
-                 #(#Menu
-
-                     #(
-                       #(#MenuItem
-                          #label: 'Add'
-                          #translateLabel: true
-                          #value: #doAdd
-                          #activeHelpKey: #addHelpTextKey
-                      )
-                       #(#MenuItem
-                          #label: '-'
-                      )
-                       #(#MenuItem
-                          #label: 'Delete'
-                          #translateLabel: true
-                          #value: #doDelete
-                          #activeHelpKey: #deleteHelpTextKey
-                      )
-                    ) nil
-                    nil
+          )
+         #(#MenuItem
+            #label: 'Edit'
+            #translateLabel: true
+            #submenu: 
+           #(#Menu
+              #(
+               #(#MenuItem
+                  #activeHelpKey: #deleteHelpTextKey
+                  #label: 'Delete'
+                  #itemValue: #doDelete
+                  #translateLabel: true
                 )
+               )
+              nil
+              nil
             )
-             #(#MenuItem
-                #label: 'Help'
-                #translateLabel: true
-                #startGroup: #right
-                #activeHelpKey: #help
-                #submenuChannel: #menuHelp
-            )
-          ) nil
-          nil
+          )
+         #(#MenuItem
+            #activeHelpKey: #help
+            #label: 'Help'
+            #translateLabel: true
+            #startGroup: #right
+            #submenuChannel: #menuHelp
+          )
+         )
+        nil
+        nil
       )
-
 ! !
 
 !UIHelpTool methodsFor:'accessing'!
@@ -510,20 +515,16 @@
     ^dictionary
 !
 
-dictionary:aDictionary
-    "sets dictionary of the selected class"
+helpKey
+    "returns the help key as symbol or nil
+    "
+    |value|
 
-    (dictionary := aDictionary) isNil ifTrue:[
-        dictionary := Dictionary new.
-    ].
-    self updateList
-!
+    value := editModel value.
 
-helpKey
-    "returns the help key of selected help text"
-
-    listSelection size ~~ 0 ifTrue:[
-        ^ listSelection asSymbol
+    value notNil ifTrue:[
+        value := value withoutSeparators.
+        value notEmpty ifTrue:[ ^ value asSymbol ]
     ].
     ^ nil
 !
@@ -532,50 +533,45 @@
     "sets the help key into the selection channel in order to show the help text"
 
     |key|
+
     aKey size ~~ 0 ifTrue:[
-        key := aKey asString
+        aKey isSymbol ifTrue:[
+            key := aKey
+        ] ifFalse:[
+            key := aKey withoutSeparators.
+            key notEmpty ifTrue:[ key := key asSymbol ]
+                        ifFalse:[ key := nil ].
+        ]
+    ] ifFalse:[
+        key := nil
     ].
-    self listModel value:key
-
+    editModel value:key.            
+    self cancel.
 !
 
 modified
-    "returns whether the help tool was modified"
-
-    ^modified
+    "true if the helpSpec is modified, items are added, deleted or modified
+    "
+    ^ modified
 !
 
 modified: aBoolean
-    "sets the help tool as modified"
-
-    modified := aBoolean
+    "true if the helpSpec is modified, items are added, deleted or modified
+    "
+    modified := aBoolean.
 !
 
 modifiedHolder:aValueHolder
     "sets the value holder to true in case of modifying attributes"
 
-    |eTxtView modChannel|
-
     modifiedHolder notNil ifTrue:[
         modifiedHolder removeDependent:self. 
     ].
-
-    (modifiedHolder := aValueHolder) notNil ifTrue:[
-        modifiedHolder addDependent:self.
+    modifiedHolder := aValueHolder.
 
-        (eTxtView := self editTextView) notNil ifTrue: [
-            modChannel := eTxtView modifiedChannel.
-            modChannel onChangeEvaluate:[
-                modifiedHolder notNil ifTrue:[
-                    modChannel value ifTrue:[
-                        modifiedHolder value:true
-                    ]
-                ]
-            ]
-        ]
+    modifiedHolder notNil ifTrue:[
+        modifiedHolder addDependent:self.
     ]
-
-    "Modified: / 16.7.1998 / 18:12:09 / cg"
 !
 
 setHelpKey:aKey
@@ -590,51 +586,55 @@
 !
 
 specClass
-    "returns the class on which the help tool works"
+    "returns the class on which the help tool works
+    "
+    ^ specClass
+!
 
-    ^specClass
+specSelector
+    "returns the selector on which the class is opened
+    "
+    ^ specSelector
 ! !
 
 !UIHelpTool methodsFor:'aspects'!
 
-listChannel
-    "returns the value holder of the help texts"
+contentsModifiedChannel
+    "returns the model which indicates whether the current helpText is modified
+    "
+    ^ contentsModifiedChannel
+!
 
-    |holder|
-    (holder := builder bindingAt:#listChannel) isNil ifTrue:[
-        builder aspectAt:#listChannel put:(holder :=  OrderedCollection new asValue).
-    ].
-    ^ holder
+editModel
+    "returns the model which keeps the current editing key
+    "
+    ^ editModel
+!
+
+listOfClasses
+    "returns the list which keeps the classes
+    "
+    ^ listOfClasses
 !
 
-listModel
-    "returns the value holder of the help key"
-
-    |holder|
-    (holder := builder bindingAt:#listModel) isNil ifTrue:[
-        holder := AspectAdaptor new subject:self; forAspect:#listSelection.
-        builder aspectAt:#listModel put:holder.
-    ].
-    ^ holder
+listOfClassesModel
+    "returns the model which keeps the current class selection
+     or nil
+    "
+    ^ listOfClassesModel
 !
 
-listOfHelpSpecClasses
-    "returns the value holder of the specClass and its superclasses 
-     which are subclasses of ApplicationModel"
-
-    ^ builder listAspectFor:#listOfHelpSpecClasses
-
+listOfKeys
+    "returns the list which keeps the current keys
+    "
+    ^ listOfKeys
 !
 
-selectionOfHelpSpecClass
-    "returns the value holder of the selected help spec class"
-
-    |holder|
-    (holder := builder bindingAt:#selectionOfHelpSpecClass) isNil ifTrue:[
-        builder aspectAt:#selectionOfHelpSpecClass put: (holder := ValueHolder new)
-    ].
-    ^ holder
-
+listOfKeysModel
+    "returns the model which keeps the current list selection
+     or nil
+    "
+    ^ listOfKeysModel
 !
 
 valueOfInfoLabel
@@ -651,9 +651,31 @@
     "reads the help dictionary from aClass and find remaining classes 
      'between' aClass and ApplicationModel" 
 
-    modified := false.
-    specClass  := self getHelpSpecClassFromClass:aClass.
-    self rebuild.
+    |list|
+
+    modified  := false.
+    specClass := self getHelpSpecClassFromClass:aClass.
+
+    specClass notNil ifTrue:[   
+        dictionary   := Dictionary new.
+        dictionaries removeAll.
+    ].
+
+    (specClass isClass and:[specClass isLoaded]) ifFalse:[
+        self updateList.
+        ^ self
+    ].
+    (specClass class includesSelector:specSelector) ifFalse:[
+        dictionaries at:(specClass name) put:dictionary. 
+    ].
+    list := specClass withAllSuperclasses reverse collect:[:cls| cls name ].
+
+    (list includes: #ApplicationModel) ifTrue:[
+        list := list asOrderedCollection.
+        list removeAll:(ApplicationModel withAllSuperclasses collect:[:cls| cls name])
+    ].
+    listOfClasses contents:list.
+    listOfClassesModel triggerValue:(specClass name).
 !
 
 buildFromClass: aClass andSelector: aSelector
@@ -664,92 +686,114 @@
 
 !
 
-rebuild
-    "reads the help dictionary from aClass and find remaining classes 
-     'between' aClass and ApplicationModel" 
+buildFromHelpTool:aHelpTool
+
+    self doNew.
+
+    dictionaries := aHelpTool dictionaries.
+    dictionary   := aHelpTool dictionary.
+
+    specSelector := aHelpTool specSelector.
+    specClass    := aHelpTool specClass.
+
+    listOfClasses contents:(aHelpTool listOfClasses).
+    listOfClassesModel triggerValue:(listOfClasses at:1 ifAbsent:nil).
+! !
 
-    |list listOfHelpSpecClassesView|
+!UIHelpTool methodsFor:'change & update'!
+
+editModelChanged
+    "called if the edit model changed
+    "
+    |key|
 
-    specClass notNil ifTrue:[   
-        dictionary   := Dictionary new.
-        dictionaries := Dictionary new.
-    ].
+    key := self helpKey.
+    modifiedHolder notNil ifTrue:[ modifiedHolder value:true ].
+
+    (key notNil and:[(dictionary at:key ifAbsent:nil) isNil]) ifTrue:[
+        listOfClasses do:[:name| |dir|
+            dir := self dictionaryForClassNamed:name.
 
-    (specClass isClass and: [specClass isLoaded])
-    ifTrue: 
-    [                                               
-        (specClass class includesSelector:specSelector) ifFalse:[
-            dictionaries at: specClass name put: dictionary 
+            (dir includesKey:key) ifTrue:[
+                "/ setup new class
+                listOfKeysModel setValue:key.
+                listOfClassesModel value:name.
+                ^ self
+            ].
         ].
-        list := self listOfHelpSpecClasses.
+        key := nil.
+    ].
+    listOfKeysModel value:key.
+!
+
+listOfClassesModelChanged
+    "called if the class selection changed
+    "
+    |clsName|
+
+    clsName := listOfClassesModel value.
+    clsName isNil ifTrue:[^ self].
 
-        list contents:  (specClass withAllSuperclasses reverse collect: [:cls| cls name]).
-        (list includes: #ApplicationModel)
-            ifTrue: [list removeAll: (ApplicationModel withAllSuperclasses collect: [:cls| cls name])].
-        self selectionOfHelpSpecClass value: specClass name.  
+    dictionary := self dictionaryForClassNamed:clsName.
+    self updateList.
+!
+
+listOfKeysModelChanged
+    "called if the selection of the key list changed
+    "
+    |key txt|
+
+    key := listOfKeysModel value.
 
-        listOfHelpSpecClassesView := self componentAt: #listOfHelpSpecClassesView.
-        listOfHelpSpecClassesView notNil ifTrue:[
-            listOfHelpSpecClassesView selection: 
-                    (list value indexOf: specClass name).
+    key notNil ifTrue:[
+        key := key asSymbol.
+        txt := dictionary at:key ifAbsent:nil.
+
+        txt isNil ifTrue:[
+            listOfKeysModel value:nil.
+            ^ self
         ].
-        self helpSpecClassSelected.
+        editModel value ~= key ifTrue:[
+            editModel value:key withoutNotifying:self.
+            modifiedHolder notNil ifTrue:[ modifiedHolder value:true ].
+        ].
     ].
 
-    self updateList
-! !
-
-!UIHelpTool methodsFor:'callbacks'!
-
-helpSpecClassSelected
-    "extracts the help dictionary from the selected class and make it current"
+    contentsModifiedChannel value ifFalse:[
+        self cancel
+    ].
+!
 
-    |clsName listOfHelpKeysView newSelection|
-
-    clsName := self selectionOfHelpSpecClass value.
+update:something with:aParameter from:changedObject
+    "Invoked when an object that I depend upon sends a change notification."
 
-    dictionary := self dictionaryForClassNamed:clsName.
-
-    self updateList.
+    editModel == changedObject ifTrue:[
+        self editModelChanged.
+        ^ self
+    ].
 
-    listSelection notNil ifTrue: [
-        listOfHelpKeysView := self componentAt: #listOfHelpKeysView.
+    listOfKeysModel == changedObject ifTrue:[
+        self listOfKeysModelChanged.
+        ^ self
+    ].
 
-        (dictionary keys includes: listSelection asSymbol)
-        ifTrue: [
-            newSelection := 
-                 (self listChannel value indexOf: (self componentAt: #helpKeyInputField) contents)
-        ] ifFalse: [
-            newSelection := nil
+    listOfClassesModel == changedObject ifTrue:[
+        self listOfClassesModelChanged.
+        ^ self
+    ].
+
+    contentsModifiedChannel == changedObject ifTrue:[
+        contentsModifiedChannel value ifTrue:[
+            modifiedHolder notNil ifTrue:[modifiedHolder value:true].
         ].
-
-        listOfHelpKeysView selection:newSelection.
+        ^ self
     ].
-    listSelection notNil ifTrue: [
-        self editTextView contents: (dictionary at: listSelection asSymbol ifAbsent: '')
-    ]
+
+    super update:something with:aParameter from:changedObject
 ! !
 
 !UIHelpTool methodsFor:'help'!
 
-defaultInfoLabel
-    "returns the default label for the info bar"
-
-    specClass isClass
-    ifTrue:
-    [
-        (specClass class includesSelector: specSelector)
-        ifFalse: 
-        [
-            ^specSelector isNil 
-                ifTrue:  [specClass name, ' >> ? (no selector defined)']
-                ifFalse: [specClass name, ' >> ', specSelector, ' (not implemented)']
-        ].
-        ^specClass name, ' >> ', specSelector
-    ].
-    ^'No class and selector defined.'
-!
-
 openDocumentation
     "opens the documentation file of the Help Tool"
 
@@ -761,51 +805,25 @@
 askForModification
     "asks for modification"
 
-    modified
-    ifTrue:
-    [
-        ((YesNoBox title: 'List was modified!!')        
-            noText:'Cancel';
-            yesText:'Waste it and proceed';
+    modified ifTrue:[
+        ( (YesNoBox title: 'List was modified!!')        
+                   noText:'Cancel';
+                  yesText:'Waste it and proceed';
             showAtPointer;
-            accepted) ifFalse: [^false].
+            accepted
+        ) ifFalse:[
+            ^ false
+        ].
         modified := false
     ].
-    ^true
-
-
-
+    ^ true
 !
 
 dictionaryForClassNamed:clsName
-    |dictionary|
-
-    dictionary := dictionaries at:clsName ifAbsent:nil.
-    dictionary isNil ifTrue: [        
-        dictionary := dictionaries at:clsName put:(self extractHelpSpecForClass: (Smalltalk at:clsName))
-    ].
-    ^ dictionary
-!
-
-editTextView
-    "returns the editTextView or nil"
-
-    |view|
-
-    (view := self componentAt:#helpTextView) notNil ifTrue:[
-        view := view scrolledView.
-
-        view acceptAction isNil ifTrue:[
-            view acceptAction:[:aList| self accept ].
-        ].
-
-        view left ~~ 0 ifTrue:[
-            (maxCharsPerLine := view extent x // view font width) < 10 ifTrue:[
-                maxCharsPerLine := nil
-            ]
-        ].
-    ].       
-    ^ view
+    "returns the directory assigned to a class name
+    "
+    ^ dictionaries at:clsName
+          ifAbsentPut:[ self extractHelpSpecForClass: (Smalltalk at:clsName) ].
 !
 
 extractHelpSpecForClass: aClass
@@ -813,39 +831,20 @@
 
     |helpSpecSuperClass superHelpSpecKeys helpSpec|
 
+    helpSpec := Dictionary new.
+
     ((aClass class includesSelector: specSelector)
     and: [(helpSpecSuperClass := aClass allSuperclasses detect: [:cls| cls class includesSelector: specSelector] ifNone: nil) notNil])
     ifTrue:[                  
         superHelpSpecKeys := helpSpecSuperClass helpSpec keys.
-        helpSpec := Dictionary new.
+
         aClass helpSpec keysAndValuesDo:[:key :value |
             (superHelpSpecKeys includes:key) ifFalse: [
                 helpSpec at:key put:value
             ]
         ].          
-        ^ dictionary := helpSpec
     ].
-    ^ dictionary := Dictionary new 
-!
-
-findHelpSpecForKey: aHelpKey
-    "finds the help spec class including aHelpKey in its help dictionary and make it current"
-
-    |dictTemp listOfHelpSpecClasses|
-
-    aHelpKey isNil ifTrue: [^nil].
-
-    dictTemp := dictionary.
-    listOfHelpSpecClasses := self listOfHelpSpecClasses.
-    listOfHelpSpecClasses value do:[:clsName|            
-        dictionary := self dictionaryForClassNamed:clsName.
-        (dictionary includesKey: aHelpKey asSymbol) ifTrue:[            
-            self updateList.
-            ^(self componentAt: #listOfHelpSpecClassesView) selection: 
-                (listOfHelpSpecClasses value indexOf: clsName).
-        ]
-    ].
-    dictionary := dictTemp
+    ^ helpSpec 
 !
 
 getHelpSpecClassFromClass:aClass
@@ -967,18 +966,27 @@
     |cls helpSpecClasses|
 
     cls := self getHelpSpecClassFromClass:aClass.
-    cls isNil ifTrue: [^self information:'No application class defined!!'].
+
+    cls isNil ifTrue: [
+        self information:'No application class defined!!'.
+        ^ self  
+    ].
 
     modified ifFalse:[
         masterApplication isNil ifTrue: [self information:'Nothing was modified!!'].
-        ^nil
+        ^ self
     ].
+    helpSpecClasses := listOfClasses copy.
+
+    helpSpecClasses notEmpty ifTrue:[
+        (helpSpecClasses includes: cls name) ifFalse: [helpSpecClasses add: cls name].
 
-    (helpSpecClasses := self listOfHelpSpecClasses value) notNil
-    ifTrue:
-    [        
-        (helpSpecClasses includes: cls name) ifFalse: [helpSpecClasses add: cls name].
-        helpSpecClasses do: [:clsName| (self installHelpSpecOnClass: clsName) isNil ifTrue: [^modified := false]].
+        helpSpecClasses do:[:clsName|
+            (self installHelpSpecOnClass: clsName) isNil ifTrue:[
+                modified := false.
+                ^ self
+            ]
+        ].
     ]
     ifFalse:
     [      
@@ -986,7 +994,6 @@
     ].
 
     modified := false.
-
 !
 
 resourceMessage: aString
@@ -1011,65 +1018,19 @@
 !
 
 updateList
-    "updates the list channel from dictionary"
-
-    self listChannel value: dictionary keys asSortedCollection
-! !
-
-!UIHelpTool methodsFor:'selection'!
-
-listSelection
-    "returns current selection"
-
-    ^ listSelection
-!
+    "updates the list of keys
+    "
+    |key|
 
-listSelection:aSelection
-    "sets current selection"
-
-    |txt view selection|
-
-    aSelection notNil ifTrue:[
-        aSelection isNumber ifTrue:[
-            aSelection ~~ 0 ifTrue:[
-                selection := self listChannel value at:aSelection ifAbsent:nil
-            ]
-        ] ifFalse:[
-            selection := aSelection withoutSeparators.
+    listOfKeysModel setValue:nil.
+    listOfKeys contents:(dictionary keys asSortedCollection).
 
-            selection size == 0 ifTrue:[
-                selection := nil
-            ]
-        ]
-    ].
+    key := self helpKey.
 
-    selection isNil ifTrue:[
-        (self componentAt:#listOfHelpKeysView) selection:nil
-    ] ifFalse:[
-        (dictionary includesKey:selection asSymbol) ifFalse:[
-            self findHelpSpecForKey:selection
-        ]
-    ].
-    listSelection == selection ifTrue:[
-        ^ self
+    (key notNil and:[listOfKeys includes:key]) ifFalse:[
+        key := nil.
     ].
-    listSelection := selection.
-
-    modifiedHolder notNil ifTrue:[
-        modifiedHolder value:true.
-    ].
-
-    (view := self editTextView) notNil ifTrue:[
-        listSelection notNil ifTrue:[
-            txt := dictionary at:(listSelection asSymbol) ifAbsent:nil.
-
-            (txt isNil or:[maxCharsPerLine isNil]) ifFalse:[
-                txt := UIPainter convertString:(txt asString) maxLineSize:maxCharsPerLine skipLineFeed:false.
-            ]
-        ]. 
-        view contents:txt.
-        view modified:false.
-    ]
+    listOfKeysModel triggerValue:key
 ! !
 
 !UIHelpTool methodsFor:'startup / release'!
@@ -1090,8 +1051,21 @@
     specSelector := #helpSpec.
     dictionary   := Dictionary new.
     dictionaries := Dictionary new.
-    modified   := false.
+    modified     := false.
+
+    editModel := nil asValue.
+    editModel addDependent:self.
 
+    listOfKeys   := List new.
+    listOfKeysModel := nil asValue.
+    listOfKeysModel addDependent:self.
+
+    listOfClasses := List new.
+    listOfClassesModel := nil asValue.
+    listOfClassesModel addDependent:self.
+
+    contentsModifiedChannel := false asValue.
+    contentsModifiedChannel addDependent:self.
 !
 
 loadFromMessage:aString
@@ -1136,9 +1110,14 @@
 
     super openInterface: #windowSpecForStandAlone.
 
-    self masterApplication isNil ifTrue: [(self componentAt: #RemoveButton) beInvisible].
     builder window label: 'Help Tool'.
     self buildFromClass:aClass andSelector:aSelector
+!
+
+postBuildTextView:aView
+
+    editTextView := aView scrolledView.
+    editTextView acceptAction:[:dummy| self accept ].
 ! !
 
 !UIHelpTool methodsFor:'user actions'!
@@ -1146,64 +1125,68 @@
 accept
     "accepts the help text"
 
-    |view key txt list listChgd|   
+    |key txt|   
+
+    contentsModifiedChannel value ifFalse:[^ self].
+    contentsModifiedChannel value:false.
 
-    (listSelection size == 0 or:[(view := self editTextView) isNil]) ifFalse:[
-        txt    := view contents asString.
-        key    := listSelection asSymbol.
-        list   := self listChannel value.
+    key := self helpKey.
+    key isNil ifTrue:[^ self].
+
+    txt := editTextView contents ? ''.
+    txt := txt asString.
 
-        (listChgd := (dictionary at:key ifAbsent:nil) isNil) ifTrue:[
-            list add:key.
-        ].             
-        dictionary at:key put:txt.
+    dictionary at:key put:txt.
 
-        listChgd ifTrue:[
-            self updateList.
-            (self componentAt: #listOfHelpKeysView) selection: (list indexOf: key).
-        ]. 
+    listOfKeys detect:[:el| el = key ] ifNone:[ |idx|
+        idx := listOfKeys findFirst:[:el| el > key ].
+        idx == 0 ifTrue:[ listOfKeys add:key ]
+                ifFalse:[ listOfKeys add:key beforeIndex:idx]
+    ].
 
-        modified := true.
-        modifiedHolder notNil ifTrue: [modifiedHolder value:true]
-    ]
+    listOfKeysModel value:key withoutNotifying:self.
+
+    modified := true.
+    modifiedHolder notNil ifTrue:[ modifiedHolder value:true ].
 !
 
-doAdd
-    "adds a help key"
+cancel
+    |key txt|
+
+    editTextView notNil ifTrue:[
+        key := listOfKeysModel value.
 
-    |helpKey|
-    (helpKey := (self componentAt: #helpKeyInputField asSymbol) contents) size > 0
-    ifTrue:
-    [
-        self listModel value: helpKey.
-        self accept
-    ]
-    ifFalse:
-    [
-        self warn:'No key was entered !!'
-    ]
-
-    "Modified: / 20.5.1998 / 01:15:06 / cg"
+        key notNil ifTrue:[
+            txt := dictionary at:key ifAbsent:nil.
+        ] ifFalse:[
+            txt := nil
+        ].
+        editTextView contents:txt.
+    ].
+    contentsModifiedChannel value:false.
 !
 
 doDelete
-    "deletes the selected help key"
+    "deletes the selected help key
+    "
+    |key|
+
+    key := listOfKeysModel value.
 
-    listSelection notNil
-    ifTrue:
-    [
-        dictionary removeKey: listSelection asSymbol ifAbsent: nil.
-        self doRemove.
-        self updateList.
+    key isNil ifTrue:[
+        self warn:'No key selected !!'.
+        ^ self
+    ].
+
+    listOfKeysModel value:nil.
+
+    key := key asSymbol.
+    listOfKeys remove:key ifAbsent:nil.
+
+    (dictionary removeKey:key ifAbsent:nil) notNil ifTrue:[
         modified := true.
-        modifiedHolder notNil ifTrue: [modifiedHolder value:true]
-    ]
-    ifFalse:
-    [
-        self warn:'No key selected !!'
-    ]
-
-    "Modified: / 20.5.1998 / 01:15:00 / cg"
+        modifiedHolder notNil ifTrue: [modifiedHolder value:true].
+    ].
 !
 
 doLoad
@@ -1224,61 +1207,24 @@
 doNew
     "resets the help tool"
 
-    specClass := listSelection := nil.
-    self dictionary: nil.
-    self dictionaries: nil.
-    self listOfHelpSpecClasses removeAll.
-    modified := false.
-!
+    specClass := nil.
 
-doReload
-    "reloads the help dictionaries"
-
-    |oldSel model|
-
-    model  := self listModel.
-    oldSel := model value.
-    model value:nil.
-    self helpSpecFrom:specClass.
-    model value:oldSel.
-    modified := false.
+    editModel          value:nil withoutNotifying:self.
+    listOfKeysModel    value:nil.
+    listOfClassesModel value:nil.
 
-!
-
-doRemove
-    "removes the selected help key"
+    listOfKeys    removeAll.
+    listOfClasses removeAll.
+    dictionaries  removeAll.
 
-    listSelection notNil
-    ifTrue:
-    [
-        self listModel value: nil.
-        self updateList.
-        modifiedHolder notNil ifTrue: [modifiedHolder value:true]
-    ]
-    ifFalse:
-    [
-        self warn:'No key selected !!'
-    ]
-
-    "Modified: / 20.5.1998 / 01:15:11 / cg"
+    dictionary   := Dictionary new.
+    modified     := false.
 !
 
 doSave
     "saves the help dictionaries on specClass"
 
     self installHelpSpecsOnClass:specClass
-!
-
-doUpdate
-    "reread the helpspecs and update my lists"
-
-    specClass isNil ifTrue:[
-        ^ self warn:'No spec loaded'.
-    ].
-
-    (self askForModification) ifTrue:[
-        self rebuild
-    ]
 ! !
 
 !UIHelpTool class methodsFor:'documentation'!