--- a/UIHelpTool.st Sat Dec 21 14:11:41 2002 +0100
+++ b/UIHelpTool.st Wed Jan 08 13:16:05 2003 +0100
@@ -1,6 +1,6 @@
"
COPYRIGHT (c) 1995 by eXept Software AG
- All Rights Reserved
+ 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
@@ -10,25 +10,36 @@
hereby transferred.
"
-
-
"{ Package: 'stx:libtool2' }"
ToolApplicationModel subclass:#UIHelpTool
- instanceVariableNames:'specClass specSelector dictionary dictionaries modifiedHolder
- modified listOfKeys listOfKeysModel listOfClasses
- listOfClassesModel contentsModifiedChannel editModel editTextView'
+ instanceVariableNames:'specClass specSelector classItemList classItemModel keyItemModel
+ helpTextView modifiedHolder contentsModifiedChannel editModel'
classVariableNames:''
poolDictionaries:''
category:'Interface-UIPainter'
!
+HierarchicalItem subclass:#ClassItem
+ instanceVariableNames:'theClass list modified'
+ classVariableNames:''
+ poolDictionaries:''
+ privateIn:UIHelpTool
+!
+
+HierarchicalItem subclass:#KeyItem
+ instanceVariableNames:'helpKey helpText modified'
+ classVariableNames:''
+ poolDictionaries:''
+ privateIn:UIHelpTool
+!
+
!UIHelpTool class methodsFor:'documentation'!
copyright
"
COPYRIGHT (c) 1995 by eXept Software AG
- All Rights Reserved
+ 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
@@ -37,8 +48,6 @@
other person. No title to or ownership of the software is
hereby transferred.
"
-
-
!
documentation
@@ -52,18 +61,19 @@
is enabled, an active help bubble is shown at the widget's view.
[instance variables:]
- specClass <Symbol> class implementing the help spec
- specSelector <Symbol> selector returning the help spec
- dictionary <Dictionary> dictionary containing pairs of help keys/texts
- dictionaries <Dictionary> dictionary containing pairs of help spec classes/help dictionaries
- listSelection <String> current selected help key
- maxCharsPerLine <Integer> maximum number of allowed characters per text line
- modifiedHolder <ValueHolder> value holder for setting as modified
- modified <Boolean> flag whether the help spec was modified
+ specClass <Symbol> class implementing the help spec
+ specSelector <Symbol> selector returning the help spec
+ classItemList the list of classItems
+ classItemModel keeps the selected class
+ keyItemModel keeps the selected helpKey
+ modifiedHolder <ValueHolder> true if the editField or contents changed
+ editModel keeps the current helpKey
+ helpTextView the view which shows the helpText
+ contentsModifiedChannel true if the helpText is modified
[author:]
- Claus Atzkern, eXept Software AG
- Thomas Zwick, eXept Software AG
+ Claus Atzkern, eXept Software AG
+ Thomas Zwick, eXept Software AG
"
! !
@@ -71,48 +81,25 @@
open
^ self openOnClass:nil.
-
-"/ |className cls|
-"/
-"/ className := Dialog request:(ClassResources string:'Open on which class ?').
-"/ className size > 0 ifTrue:[
-"/ cls := Smalltalk at:className asSymbol.
-"/ cls notNil ifTrue:[
-"/ ^ self openOnClass:cls.
-"/ ].
-"/ self warn:(ClassResources string:'No such class').
-"/ ].
-"/
-"/ "Created: / 20.5.1998 / 00:55:05 / cg"
-"/
-
- "Modified: / 20.5.1998 / 01:06:07 / cg"
!
openOnClass:aClass
- "opens a Help Tool on aClass"
-
- ^ self openOnClass:aClass andSelector:#helpSpec
-
+ "opens a Help Tool on aClass
"
- UIHelpTool openOnClass:self
- "
-
- "Modified: / 20.5.1998 / 01:06:14 / cg"
+ ^ self openOnClass:aClass andSelector:#helpSpec
!
openOnClass:aClass andSelector: aSelector
- "opens a Help Tool on aClass and aSelector"
-
- ^self new openOnClass:aClass andSelector: aSelector
-
+ "opens a Help Tool on aClass and aSelector
+ "
+ ^ self new openOnClass:aClass andSelector:aSelector
! !
!UIHelpTool class methodsFor:'constants'!
label
- "returns the label; used if embedded as sub canvas in the GUI Painter or Menu Editor"
-
+ "returns the label; used if embedded as sub canvas in the GUI Painter or Menu Editor
+ "
^'Help'
! !
@@ -131,7 +118,7 @@
<resource: #help>
- ^super helpSpec addPairsFrom:#(
+ ^ super helpSpec addPairsFrom:#(
#addHelpTextKey
'Adds the key to the help spec.'
@@ -188,114 +175,101 @@
^
#(#FullSpec
- #name: #windowSpec
- #window:
+ #name: #windowSpec
+ #window:
#(#WindowSpec
- #label: 'Help Tool'
- #name: 'Help Tool'
- #min: #(#Point 10 10)
- #max: #(#Point 1160 870)
- #bounds: #(#Rectangle 31 306 317 577)
- )
- #component:
+ #label: 'UIHelpTool'
+ #name: 'UIHelpTool'
+ #min: #(#Point 10 10)
+ #max: #(#Point 1024 768)
+ #bounds: #(#Rectangle 30 292 491 585)
+ )
+ #component:
#(#SpecCollection
- #collection: #(
- #(#VariableVerticalPanelSpec
- #name: 'VariableVerticalPanel'
- #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
- #component:
- #(#SpecCollection
- #collection: #(
- #(#VariableHorizontalPanelSpec
- #name: 'VariableHorizontalPanel'
- #component:
- #(#SpecCollection
- #collection: #(
- #(#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: #(
- #(#InputFieldSpec
- #name: 'helpKeyInputField'
- #layout: #(#LayoutFrame 2 0.0 2 0 -2 1.0 25 0)
- #activeHelpKey: #currentHelpTexts
- #tabable: true
- #model: #editModel
- #immediateAccept: true
- #acceptOnReturn: false
- #acceptOnTab: false
- #acceptOnPointerLeave: false
- )
- #(#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
- )
- )
+ #collection: #(
+ #(#VariableVerticalPanelSpec
+ #name: 'PanelVrt'
+ #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+ #component:
+ #(#SpecCollection
+ #collection: #(
+ #(#VariableHorizontalPanelSpec
+ #name: 'PanelHrz'
+ #component:
+ #(#SpecCollection
+ #collection: #(
+ #(#HierarchicalListViewSpec
+ #name: 'keyItemModel'
+ #model: #keyItemModel
+ #menu: #keyItemMenu
+ #hasHorizontalScrollBar: true
+ #hasVerticalScrollBar: true
+ #miniScrollerHorizontal: true
+ #miniScrollerVertical: false
+ #listModel: #keyItemListHolder
+ #useIndex: false
+ #highlightMode: #label
+ #showLines: false
+ #showIndicators: false
+ #showLeftIndicators: false
+ #useDefaultIcons: false
+ #autoScrollHorizontal: false
+ )
+ #(#ViewSpec
+ #name: 'classItemList'
+ #component:
+ #(#SpecCollection
+ #collection: #(
+ #(#InputFieldSpec
+ #name: 'editModel'
+ #layout: #(#LayoutFrame 0 0.0 2 0 -1 1.0 25 0)
+ #activeHelpKey: #currentHelpTexts
+ #model: #editModel
+ #immediateAccept: true
+ #acceptOnReturn: false
+ #acceptOnTab: false
+ #acceptOnLostFocus: false
+ #acceptOnPointerLeave: false
+ )
+ #(#SelectionInListModelViewSpec
+ #name: 'classItemModel'
+ #layout: #(#LayoutFrame 0 0.0 27 0.0 0 1.0 0 1.0)
+ #model: #classItemModel
+ #hasHorizontalScrollBar: true
+ #hasVerticalScrollBar: true
+ #miniScrollerHorizontal: true
+ #miniScrollerVertical: true
+ #autoHideScrollBars: false
+ #listModel: #classItemListHolder
+ #useIndex: false
+ #highlightMode: #label
+ )
+ )
- )
- )
- )
+ )
+ )
+ )
- )
- #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:
- )
- )
-
- )
- )
- )
+ )
+ #handles: #(#Any 0.607375 1.0)
+ )
+ #(#ArbitraryComponentSpec
+ #name: 'helpTextView'
+ #hasHorizontalScrollBar: true
+ #hasVerticalScrollBar: true
+ #miniScrollerHorizontal: true
+ #miniScrollerVertical: true
+ #hasBorder: false
+ #component: #helpTextView
+ )
+ )
- )
- #handles: #(#Any 0.5 1.0)
- )
- )
+ )
+ #handles: #(#Any 0.679181 1.0)
+ )
+ )
- )
+ )
)
!
@@ -315,33 +289,39 @@
^
#(#FullSpec
- #name: #windowSpecForStandAlone
- #window:
+ #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:
+ #label: 'Help Tool'
+ #name: 'Help Tool'
+ #min: #(#Point 300 300)
+ #max: #(#Point 1152 900)
+ #bounds: #(#Rectangle 11 332 509 761)
+ #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
- )
- )
+ #collection: #(
+ #(#UISubSpecification
+ #name: 'windowSpec'
+ #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 -50 1.0)
+ #minorKey: #windowSpec
+ )
+ #(#UISubSpecification
+ #name: 'windowSpecForCommit'
+ #layout: #(#LayoutFrame 0 0.0 -50 1.0 0 1.0 -24 1.0)
+ #majorKey: #ToolApplicationModel
+ #minorKey: #windowSpecForCommit
+ )
+ #(#UISubSpecification
+ #name: 'windowSpecForInfoBar'
+ #layout: #(#LayoutFrame 0 0 -24 1 0 1 0 1)
+ #majorKey: #ToolApplicationModel
+ #minorKey: #windowSpecForInfoBar
+ )
+ )
- )
+ )
)
! !
@@ -363,24 +343,53 @@
^
#(#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
+ #(
+ #(#MenuItem
+ #activeHelpKey: #commitOK
+ #enabled: #contentsModifiedChannel
+ #label: 'Accept'
+ #itemValue: #accept
+ #translateLabel: true
+ )
+ #(#MenuItem
+ #activeHelpKey: #commitCancel
+ #enabled: #contentsModifiedChannel
+ #label: 'Cancel'
+ #itemValue: #cancel
+ #translateLabel: true
+ )
+ )
+ nil
+ nil
+ )
+!
+
+keyItemMenu
+ "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:#keyItemMenu
+ (Menu new fromLiteralArrayEncoding:(UIHelpTool keyItemMenu)) startUp
+ "
+
+ <resource: #menu>
+
+ ^
+ #(#Menu
+ #(
+ #(#MenuItem
+ #activeHelpKey: #deleteHelpTextKey
+ #label: 'Delete'
+ #itemValue: #doDelete
+ #translateLabel: true
+ )
+ )
+ nil
+ nil
)
!
@@ -400,16 +409,16 @@
^
#(#Menu
- #(
- #(#MenuItem
- #activeHelpKey: #deleteHelpTextKey
- #label: 'Delete'
- #itemValue: #doDelete
- #translateLabel: true
- )
- )
- nil
- nil
+ #(
+ #(#MenuItem
+ #activeHelpKey: #deleteHelpTextKey
+ #label: 'Delete'
+ #itemValue: #doDelete
+ #translateLabel: true
+ )
+ )
+ nil
+ nil
)
!
@@ -429,164 +438,138 @@
^
#(#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
- #activeHelpKey: #deleteHelpTextKey
- #label: 'Delete'
- #itemValue: #doDelete
- #translateLabel: true
- )
- )
- nil
- nil
- )
- )
- #(#MenuItem
- #activeHelpKey: #help
- #label: 'Help'
- #translateLabel: true
- #startGroup: #right
- #submenuChannel: #menuHelp
- )
- )
- nil
- nil
+ #(
+ #(#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: 'New'
+ #itemValue: #doNew
+ #translateLabel: true
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #activeHelpKey: #fileExit
+ #label: 'Exit'
+ #itemValue: #closeRequest
+ #translateLabel: true
+ )
+ )
+ nil
+ nil
+ )
+ )
+ #(#MenuItem
+ #activeHelpKey: #history
+ #label: 'History'
+ #translateLabel: true
+ #submenuChannel: #menuHistory
+ )
+ #(#MenuItem
+ #label: 'Edit'
+ #translateLabel: true
+ #submenuChannel: #keyItemMenu
+ #keepLinkedMenu: true
+ )
+ #(#MenuItem
+ #activeHelpKey: #help
+ #label: 'Help'
+ #translateLabel: true
+ #startGroup: #right
+ #submenuChannel: #menuHelp
+ )
+ )
+ nil
+ nil
)
! !
!UIHelpTool methodsFor:'accessing'!
-dictionaries
- "returns the dictionary of the help dictionaries of the classes having help specs"
-
- ^dictionaries
-!
-
-dictionaries:aDictionaryOfDictionaries
- "sets a dictionary of the help dictionaries of the classes having help specs"
-
- (dictionaries := aDictionaryOfDictionaries) isNil ifTrue:[
- dictionaries := Dictionary new.
- ].
- self updateList.
-!
+helpKey
+ "returns the helpKey as symbol or nil
+ "
+ |key|
-dictionary
- "returns the dictionary of the selected class"
-
- ^dictionary
-!
+ key := editModel value.
-helpKey
- "returns the help key as symbol or nil
- "
- |value|
-
- value := editModel value.
-
- value notNil ifTrue:[
- value := value withoutSeparators.
- value notEmpty ifTrue:[ ^ value asSymbol ]
+ key size ~~ 0 ifTrue:[
+ key := key withoutSeparators.
+ key notEmpty ifTrue:[ ^ key asSymbol ]
].
^ nil
!
helpKey:aKey
- "sets the help key into the selection channel in order to show the help text"
-
+ "change the helpKey without any change notification (modifiedHolder).
+ "
|key|
- aKey size ~~ 0 ifTrue:[
- aKey isSymbol ifTrue:[
- key := aKey
- ] ifFalse:[
- key := aKey withoutSeparators.
- key notEmpty ifTrue:[ key := key asSymbol ]
- ifFalse:[ key := nil ].
- ]
- ] ifFalse:[
- key := nil
+ self withoutModifyDo:[
+ aKey size ~~ 0 ifTrue:[
+ key := aKey withoutSeparators.
+ key isEmpty ifTrue:[ key := nil ]
+ ] ifFalse:[
+ key := nil
+ ].
+ editModel value:key.
].
- editModel value:key.
self cancel.
!
modified
- "true if the helpSpec is modified, items are added, deleted or modified
+ "true if any items are added, deleted or modified
"
- ^ modified
+ classItemList do:[:aClassItem|
+ aClassItem modified ifTrue:[^ true].
+ ].
+ ^ false
!
-modified: aBoolean
- "true if the helpSpec is modified, items are added, deleted or modified
+modified:aBoolean
+ "true if any items are added, deleted or modified
"
- modified := aBoolean.
+ classItemList do:[:aClassItem| aClassItem modified:aBoolean ].
+!
+
+modifiedHolder
+ "boolean holder which is set to true if the helpKey or contents changed
+ "
+ ^ modifiedHolder
!
modifiedHolder:aValueHolder
- "sets the value holder to true in case of modifying attributes"
-
+ "boolean holder which is set to true if the helpKey or contents changed
+ "
modifiedHolder notNil ifTrue:[
- modifiedHolder removeDependent:self.
+ modifiedHolder removeDependent:self.
].
modifiedHolder := aValueHolder.
modifiedHolder notNil ifTrue:[
- modifiedHolder addDependent:self.
- ]
-!
-
-setHelpKey:aKey
- "set the helpKey without notification
- "
- |model|
-
- model := modifiedHolder.
- modifiedHolder := nil.
- self helpKey:aKey.
- modifiedHolder := model.
+ modifiedHolder addDependent:self.
+ ].
!
specClass
- "returns the class on which the help tool works
+ "returns the class on which the help tool works on
"
^ specClass
!
@@ -599,48 +582,82 @@
!UIHelpTool methodsFor:'aspects'!
+classItemListHolder
+ "returns the holder which keeps the class items
+ "
+ |holder|
+
+ holder := builder bindingAt:#classItemListHolder.
+
+ holder isNil ifTrue:[
+ holder := nil asValue.
+ holder value:classItemList.
+ builder aspectAt:#classItemListHolder put:holder.
+ ].
+ ^ holder
+!
+
+classItemModel
+ "returns the holder which keeps the current selected class
+ "
+ ^ classItemModel
+!
+
contentsModifiedChannel
- "returns the model which indicates whether the current helpText is modified
+ "boolean holder, which is set to true if the contents assigned to the
+ helpKey changed
"
^ contentsModifiedChannel
!
editModel
- "returns the model which keeps the current editing key
+ "string holder, which keeps the current editing helpKey as string
"
- ^ editModel
+ ^ editModel.
!
-listOfClasses
- "returns the list which keeps the classes
+helpTextView
+ "the editView which keeps the current help contents assigned to the key
"
- ^ listOfClasses
+ ^ helpTextView
!
-listOfClassesModel
- "returns the model which keeps the current class selection
- or nil
+keyItemListHolder
+ "holder, which keeps the current hierarchical list
+ assigned to the selected class item
"
- ^ listOfClassesModel
+ |holder|
+
+ holder := builder bindingAt:#keyItemListHolder.
+
+ holder isNil ifTrue:[
+ holder := nil asValue.
+ holder value:(classItemList last list).
+ builder aspectAt:#keyItemListHolder put:holder.
+ ].
+ ^ holder
!
-listOfKeys
- "returns the list which keeps the current keys
+keyItemModel
+ "model which keeps the current selected helpKey or nil
"
- ^ listOfKeys
+ ^ keyItemModel.
!
-listOfKeysModel
- "returns the model which keeps the current list selection
- or nil
+valueOfEnablingCommitButtons
+ "returns the enabling of the commit of this tool as value holder
"
- ^ listOfKeysModel
+ masterApplication notNil ifTrue:[
+ ^ masterApplication valueOfEnablingCommitButtons
+ ].
+ ^ contentsModifiedChannel
!
valueOfInfoLabel
-
+ "returns the info label as value holder
+ "
masterApplication notNil ifTrue:[
- ^ masterApplication valueOfInfoLabel
+ ^ masterApplication valueOfInfoLabel
].
^ super valueOfInfoLabel
! !
@@ -648,604 +665,763 @@
!UIHelpTool methodsFor:'building'!
buildAndMergeFromClass:aClass
- "class and selector changed; merge old definitions
- into definitions loaded from a class
- "
- |saveDictionary saveHelpKey|
+ "setup a new specClass, merge the current items into
+ "
+ |root mergeItems|
- saveDictionary := dictionary.
- saveHelpKey := self helpKey.
+ root := classItemList first.
+
+ root isUnspecified ifTrue:[ mergeItems := root children ]
+ ifFalse:[ mergeItems := nil ].
+
+ self buildFromClass:aClass.
- self buildFromClass:aClass.
+ mergeItems size ~~ 0 ifTrue:[
+ root := classItemList first.
+
+ mergeItems do:[:anItem| |item hkey|
+ hkey := anItem helpKey.
+ item := root detectItemWithKey:hkey.
- saveDictionary notEmpty ifTrue:[
- dictionary declareAllFrom:saveDictionary.
- self updateList.
+ item isNil ifTrue:[
+ item := KeyItem helpKey:hkey helpText:(anItem helpText).
+ root add:item sortBlock:[:a :b| a label < b label ].
+ ] ifFalse:[
+ item helpText:(anItem helpText).
+ ]
+ ]
].
- self helpKey:saveHelpKey.
- self modified:true.
!
buildFromClass:aClass
"reads the help dictionary from aClass and find remaining classes
- 'between' aClass and ApplicationModel"
+ 'between' aClass and ApplicationModel
+ "
+ |lastContents root list resource|
- |list|
-
- modified := false.
+ specSelector isNil ifTrue:[ specSelector := #helpSpec ].
specClass := self getHelpSpecClassFromClass:aClass.
- specClass notNil ifTrue:[
- dictionary := Dictionary new.
- dictionaries removeAll.
+ list := OrderedCollection new.
+
+ (specClass isClass and:[specClass isLoaded]) ifTrue:[
+ lastContents := nil.
+ resource := specClass name, ' ', specSelector.
+ self addToHistory:(Association key:resource value:#'loadFromMessage:').
+
+ specClass withAllSuperclasses reverse do:[:aClass| |value name|
+ lastContents isNil ifTrue:[
+ aClass == ApplicationModel ifTrue:[
+ lastContents := IdentityDictionary new
+ ].
+ ] ifFalse:[
+ root := ClassItem onClass:aClass.
+
+ (aClass class includesSelector:specSelector) ifTrue:[
+ value := aClass perform:specSelector.
+
+ value keysAndValuesDo:[:k :v| |cval|
+ cval := lastContents at:k ifAbsent:self.
+ cval = v ifFalse:[ root add:(KeyItem helpKey:k helpText:v) ].
+ ].
+ lastContents := value.
+ ].
+ root sort:[:a :b| a label < b label ].
+ root modified:false.
+ list add:root.
+ ]
+ ]
+ ].
+ list isEmpty ifTrue:[
+ list add:(ClassItem onClass:nil)
].
- (specClass isClass and:[specClass isLoaded]) ifFalse:[
- self updateList.
- ^ self
- ].
- (specClass class includesSelector:specSelector) ifFalse:[
- dictionaries at:(specClass name) put:dictionary.
+ self withoutModifyDo:[
+ classItemList contents:list.
+ classItemModel value:(list last)
].
- 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
- "sets aSelector and reads the help dictionary from aClass"
-
+ "sets aSelector and reads the help dictionary from aClass
+ "
specSelector := aSelector.
self buildFromClass:aClass
-
!
buildFromHelpTool:aHelpTool
-
- self doNew.
-
- dictionaries := aHelpTool dictionaries.
- dictionary := aHelpTool dictionary.
+ "build from another helpTool
+ "
+ specClass := aHelpTool specClass.
+ specSelector := aHelpTool specSelector.
+ classItemList := aHelpTool classItemListHolder value.
- specSelector := aHelpTool specSelector.
- specClass := aHelpTool specClass.
+ self classItemListHolder value:classItemList.
- listOfClasses contents:(aHelpTool listOfClasses).
- listOfClassesModel triggerValue:(listOfClasses at:1 ifAbsent:nil).
+ classItemModel triggerValue:(classItemList last).
! !
!UIHelpTool methodsFor:'change & update'!
editModelChanged
- "called if the edit model changed
+ "called if the editModel changed
"
|key|
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.
-
- (dir includesKey:key) ifTrue:[
- "/ setup new class
- listOfKeysModel setValue:key.
- listOfClassesModel value:name.
- ^ self
- ].
- ].
- key := nil.
- ].
- listOfKeysModel value:key.
-!
-listOfClassesModelChanged
- "called if the class selection changed
- "
- |clsName|
-
- clsName := listOfClassesModel value.
- clsName isNil ifTrue:[^ self].
+ modifiedHolder notNil ifTrue:[
+ modifiedHolder value:true
+ ].
- dictionary := self dictionaryForClassNamed:clsName.
- self updateList.
-!
-
-listOfKeysModelChanged
- "called if the selection of the key list changed
- "
- |key txt|
-
- key := listOfKeysModel value.
+ contentsModifiedChannel value:false.
key notNil ifTrue:[
- key := key asSymbol.
- txt := dictionary at:key ifAbsent:nil.
+ keyItemModel value = key ifTrue:[^ self].
+
+ classItemList reverseDo:[:root| |item|
+ item := root detectItemWithKey:key.
- txt isNil ifTrue:[
- listOfKeysModel value:nil.
- ^ self
- ].
- editModel value ~= key ifTrue:[
- editModel value:key withoutNotifying:self.
- modifiedHolder notNil ifTrue:[ modifiedHolder value:true ].
- ].
+ item notNil ifTrue:[
+ classItemModel value:root.
+ keyItemModel value:item.
+ ^ self.
+ ].
+ ].
+
+ masterApplication isNil ifTrue:[
+ "entered a new helpKey
+ "
+ self valueOfEnablingCommitButtons value:true.
+ ].
].
-
- contentsModifiedChannel value ifFalse:[
- self cancel
- ].
+ keyItemModel value:nil.
!
update:something with:aParameter from:changedObject
- "Invoked when an object that I depend upon sends a change notification."
-
- editModel == changedObject ifTrue:[
- self editModelChanged.
- ^ self
- ].
+ "Invoked when an object that I depend upon sends a change notification.
+ "
+ |root item list|
- listOfKeysModel == changedObject ifTrue:[
- self listOfKeysModelChanged.
- ^ self
- ].
+ changedObject == keyItemModel ifTrue:[
+ item := keyItemModel value.
- listOfClassesModel == changedObject ifTrue:[
- self listOfClassesModelChanged.
- ^ self
+ item notNil ifTrue:[
+ editModel value:(item helpKey).
+ ].
+ self cancel.
+ ^ self
].
- contentsModifiedChannel == changedObject ifTrue:[
- contentsModifiedChannel value ifTrue:[
- modifiedHolder notNil ifTrue:[modifiedHolder value:true].
- ].
- ^ self
+ changedObject == classItemModel ifTrue:[
+ root := classItemModel value.
+
+ root notNil ifTrue:[
+ item := root detectItemWithKey:(self helpKey).
+ list := root list.
+ ] ifFalse:[
+ list := item := nil.
+ ].
+
+ item notNil ifTrue:[
+ keyItemModel value:nil withoutNotifying:self.
+ ].
+ self keyItemListHolder value:list.
+ keyItemModel value:item.
+ ^ self
].
- super update:something with:aParameter from:changedObject
-! !
-
-!UIHelpTool methodsFor:'help'!
+ changedObject == editModel ifTrue:[
+ self editModelChanged.
+ ^ self
+ ].
-openDocumentation
- "opens the documentation file of the Help Tool"
+ changedObject == contentsModifiedChannel ifTrue:[
+ modifiedHolder notNil ifTrue:[
+ modifiedHolder value:true
+ ].
+ ^ self
+ ].
+ super update:something with:aParameter from:changedObject
+!
- self openHTMLDocument: 'tools/uipainter/HelpTool.html'
+withoutModifyDo:aBlock
+ "discard modifications; trigger not the modifiedHolder during
+ the action is active.
+ "
+ |holder|
+
+ holder := modifiedHolder.
+
+ holder isNil ifTrue:[
+ ^ aBlock value
+ ].
+ ^ aBlock valueNowOrOnUnwindDo:[ modifiedHolder := holder ]
! !
!UIHelpTool methodsFor:'private'!
askForModification
- "asks for modification"
+ "asks for modification; launch a dialog if something is modified;
+ returns true if the modifications are accepted by user otherwise
+ false.
+ "
+ |dialog|
- modified ifTrue:[
- ( (YesNoBox title: 'List was modified!!')
- noText:'Cancel';
- yesText:'Waste it and proceed';
- showAtPointer;
- accepted
- ) ifFalse:[
- ^ false
- ].
- modified := false
+ self modified ifTrue:[
+ dialog := YesNoBox title:(resources string:'List was modified !!')
+ yesText:(resources string:'Forget it and proceed')
+ noText:(resources string:'Cancel').
+
+ dialog showAtPointer.
+ dialog accepted ifFalse:[^ false].
+ self modified:false.
].
^ true
!
-dictionaryForClassNamed:clsName
- "returns the directory assigned to a class name
+extractResourceFrom:aString
+ "extracts class and selector from a resource string. On success
+ an association with the key a class and the selector as value
+ is returned. Otherwise nil is returned
"
- ^ dictionaries at:clsName
- ifAbsentPut:[ self extractHelpSpecForClass: (Smalltalk at:clsName) ].
-!
+ |words newClass newSel|
-extractHelpSpecForClass: aClass
- "extracts the help dictionary of aClass, it current and return it"
-
- |helpSpecSuperClass superHelpSpecKeys helpSpec|
+ aString size ~~ 0 ifTrue:[
+ words := aString asCollectionOfWords.
- helpSpec := Dictionary new.
+ words size == 2 ifTrue:[
+ newClass := self resolveName:(words first).
- ((aClass class includesSelector: specSelector)
- and: [(helpSpecSuperClass := aClass allSuperclasses detect: [:cls| cls class includesSelector: specSelector] ifNone: nil) notNil])
- ifTrue:[
- superHelpSpecKeys := (helpSpecSuperClass perform:specSelector) keys.
+ (newClass isClass and:[newClass isLoaded]) ifTrue:[
+ newSel := words last asSymbol.
- (aClass perform:specSelector) keysAndValuesDo:[:key :value |
- (superHelpSpecKeys includes:key) ifFalse: [
- helpSpec at:key put:value
- ]
- ].
+ (newClass class includesSelector:newSel) ifTrue:[
+ ^ Association key:newClass value:newSel
+ ].
+ ].
+ ].
].
- ^ helpSpec
+ ^ nil
!
getHelpSpecClassFromClass:aClass
- "returns application class keeping the associated help text or nil"
-
+ "oops
+ "
|cls|
- ((cls := self resolveName:aClass) notNil and:[cls respondsTo: #helpSpecClass]) ifTrue:[
- ^cls helpSpecClass
- ].
- ^cls
+ aClass notNil ifTrue:[
+ cls := self resolveName:aClass.
-
-!
+ cls notNil ifTrue:[
+ cls := cls perform:#helpSpecClass ifNotUnderstood:cls.
-getUnformattedHelpText: aHelpText
- "unformats aHelpText and returns it"
-
- |helpText|
-
- helpText := aHelpText asString copyReplaceAll:(Character cr) with:(Character space).
- (helpText endsWith:(Character space)) ifTrue:[
- helpText := helpText copyWithoutLast:1
+ (cls isClass and:[cls isLoaded]) ifTrue:[
+ ^ cls
+ ].
+ ].
].
- ^ helpText
-
- "Modified: / 20.7.1998 / 13:17:52 / cg"
+ ^ nil
!
-installHelpSpecOnClass:aClass
- "saves the help dicts in aClass which is subclass of ApplicationModel"
-
- |cls src helpSpec|
-
- cls := self getHelpSpecClassFromClass: aClass.
-
- cls isNil ifTrue:[
- self information:'No application class defined!!'.
- ^nil
- ].
-
- (cls isSubclassOf: ApplicationModel) ifFalse:[
- self information: 'Cannot save help spec into class ', cls name asBoldText, ',\because it is not a subclass of ApplicationModel!!' withCRs.
- ^nil
- ].
-
- helpSpec := dictionaries
- at: cls name
- ifAbsent: [specClass notNil
- ifTrue: [dictionaries at: aClass put: (self extractHelpSpecForClass: (Smalltalk at: aClass))]
- ifFalse: [dictionary size > 0 ifTrue: [dictionary] ifFalse: [Dictionary new]]].
-
- helpSpec associationsDo:
- [:h|
- helpSpec at: h key put: (self getUnformattedHelpText: h value)
- ].
-
- (cls class includesSelector: specSelector)
- ifTrue:
- [
- |superclassHelpKeys implementedHelpSpec hasChanged|
- implementedHelpSpec := Dictionary new.
- superclassHelpKeys := (cls superclass respondsTo: specSelector)
- ifTrue: [(cls superclass perform:specSelector) keys]
- ifFalse: [Array new].
-
- (cls perform:specSelector) associationsDo: [:h| (superclassHelpKeys includes: h key)
- ifFalse: [implementedHelpSpec at: h key put: h value]].
+loadFromMessage:aString
+ "Set and rebuild the specClass and specSelector from a resource string.
+ On success true is returned otherwise false. If the current spec is
+ modified, a dialog is launched.
+ "
+ |association|
- hasChanged := false.
- implementedHelpSpec associationsDo: [:h| (helpSpec includesAssociation: h) ifFalse: [hasChanged := true]].
- helpSpec associationsDo: [:h| (implementedHelpSpec includesAssociation: h) ifFalse: [hasChanged := true]].
-
- (implementedHelpSpec notEmpty and: [hasChanged and:
- [DialogBox confirm: 'Class ', cls name asBoldText, ' already implements\a help spec!!\\Do only replace, if you have removed\help keys in an existing help spec.\' withCRs yesLabel: ' Merge ' noLabel: ' Replace ']])
- ifTrue:
- [
- implementedHelpSpec associationsDo: [:h| (helpSpec includesKey: h key)
- ifFalse: [helpSpec at: h key put: h value]].
- ]
- ].
-
- helpSpec isEmpty ifTrue:[
- ^(cls superclass respondsTo: specSelector) ifTrue: [cls class removeSelector: specSelector].
- ].
-
- src := '' writeStream.
+ association := self extractResourceFrom:aString.
- src nextPutAll:
- specSelector, '\' withCRs,
- (ResourceSpecEditor codeGenerationCommentForClass: UIHelpTool) withCRs,
- '\\' withCRs,
- ' "\' withCRs,
- ' UIHelpTool openOnClass:', cls name asString ,'
- "
-
- <resource: #help>
-
- ^super ', specSelector, ' addPairsFrom:#(
-
-'.
-
- helpSpec keys asSortedCollection do:
- [:key|
- src nextPutLine: key storeString.
- src nextPutLine: (helpSpec at: key) storeString; cr.
+ association notNil ifTrue:[
+ self askForModification ifTrue:[
+ self buildFromClass:(association key) andSelector:(association value).
+ ^ true
+ ].
].
- src nextPutLine:')'.
-
- Compiler
- compile:(src contents)
- forClass:cls class
- inCategory:'help specs'.
+ ^ false
!
-installHelpSpecsOnClass:aClass
- "saves the help dicts on aClass and its superclasses which are subclasses of ApplicationModel"
-
- |cls helpSpecClasses|
-
- cls := self getHelpSpecClassFromClass:aClass.
-
- cls isNil ifTrue: [
- self information:'No application class defined!!'.
- ^ self
- ].
-
- modified ifFalse:[
- masterApplication isNil ifTrue: [self information:'Nothing was modified!!'].
- ^ self
- ].
- helpSpecClasses := listOfClasses copy.
-
- helpSpecClasses notEmpty ifTrue:[
- (helpSpecClasses includes: cls name) ifFalse: [helpSpecClasses add: cls name].
-
- helpSpecClasses do:[:clsName|
- (self installHelpSpecOnClass: clsName) isNil ifTrue:[
- modified := false.
- ^ self
- ]
- ].
- ]
- ifFalse:
- [
- self installHelpSpecOnClass: cls
- ].
-
- modified := false.
-!
+resourceMessage:aString
+ "Set the specClass and specSelector from a resource string. On
+ success true is returned otherwise false.
+ "
+ |association|
-resourceMessage: aString
- "extracts from aString the specClass and the specSelector"
+ association := self extractResourceFrom:aString.
- (aString notNil and: [self askForModification])
- ifTrue:
- [
- |msg cls sel|
- msg := aString asCollectionOfWords.
- (msg size == 2 and:
- [(cls := self resolveName:(msg at:1)) notNil])
- ifTrue:
- [
- specClass := cls name.
- specSelector := (msg at: 2) asSymbol.
- ^true
- ]
+ association notNil ifTrue:[
+ specClass := association key.
+ specSelector := association value.
+ ^ true
].
- ^false
-
-!
-
-updateList
- "updates the list of keys
- "
- |key|
-
- listOfKeysModel setValue:nil.
- listOfKeys contents:(dictionary keys asSortedCollection).
-
- key := self helpKey.
-
- (key notNil and:[listOfKeys includes:key]) ifFalse:[
- key := nil.
- ].
- listOfKeysModel triggerValue:key
+ ^ false
! !
-!UIHelpTool methodsFor:'startup / release'!
+!UIHelpTool methodsFor:'startup & release'!
closeRequest
- "asks for permission before closing"
-
- (self masterApplication isNil and:[self askForModification]) ifTrue:[
- super closeRequest
- ]
+ "asks for permission before closing
+ "
+ (masterApplication isNil and:[self askForModification]) ifTrue:[
+ super closeRequest.
+ ].
!
initialize
- "initializes instance variables"
+ "setup default attributes
+ "
+ super initialize.
+ self createBuilder.
- super initialize.
+ specSelector := #helpSpec.
+
+ classItemList := List new.
- specSelector := #helpSpec.
- dictionary := Dictionary new.
- dictionaries := Dictionary new.
- modified := false.
+ classItemModel := nil asValue.
+ classItemModel addDependent:self.
+
+ keyItemModel := nil asValue.
+ keyItemModel addDependent:self.
+
+ contentsModifiedChannel := false asValue.
+ contentsModifiedChannel addDependent:self.
+
+ helpTextView := EditTextView new.
+ helpTextView acceptAction:[:dummy| self accept ].
+ helpTextView modifiedChannel:contentsModifiedChannel.
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
- "loads a help spec by evaluating aString"
-
- (aString notNil and: [self askForModification])
- ifTrue:
- [
- |msg cls sel|
- msg := aString asCollectionOfWords.
- (msg size == 2 and:
- [(cls := self resolveName:(msg at:1)) notNil and:
- [cls class includesSelector: (sel := (msg at: 2) asSymbol)]])
- ifTrue:
- [
- self buildFromClass: (specClass := cls name) andSelector: (specSelector := sel).
- ^true
- ]
- ].
- ^false
+ self buildFromClass:nil.
!
openInterface:aSymbol
- "do not open as stand alone"
-
-
-
+ "do not open as stand alone
+ "
!
openOnClass:aClass
- "opens the UIHelpTool on aClass"
-
+ "opens the UIHelpTool on aClass
+ "
self openOnClass:aClass andSelector:nil
-
- "
- self openOnClass:NewLauncher
- "
!
openOnClass:aClass andSelector: aSelector
"opens the UIHelpTool on aClass and aSelector"
- super openInterface: #windowSpecForStandAlone.
+ super openInterface:#windowSpecForStandAlone.
builder window label: 'Help Tool'.
self buildFromClass:aClass andSelector:aSelector
-!
-
-postBuildTextView:aView
-
- editTextView := aView scrolledView.
- editTextView acceptAction:[:dummy| self accept ].
! !
!UIHelpTool methodsFor:'user actions'!
accept
- "accepts the help text"
+ "accepts the help text
+ "
+ |helpKey helpItem root|
- |key txt|
-
- key := self helpKey.
- key isNil ifTrue:[^ self].
+ helpKey := self helpKey.
+ helpKey isNil ifTrue:[^ self].
- contentsModifiedChannel value ifFalse:[
- (dictionary includes:key) ifTrue:[^ self].
- ].
- contentsModifiedChannel value:false.
+ root := classItemModel value.
+ root isNil ifTrue:[^ self].
+
+ helpItem := root detectItemWithKey:helpKey.
- txt := editTextView contents ? ''.
- txt := txt asString.
-
- dictionary at:key put:txt.
-
- 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]
+ helpItem isNil ifTrue:[
+ helpItem := KeyItem helpKey:helpKey helpText:(helpTextView contents).
+ root add:helpItem sortBlock:[:a :b| a label < b label ].
+ ] ifFalse:[
+ helpItem helpText:(helpTextView contents).
].
- listOfKeysModel value:key withoutNotifying:self.
-
- modified := true.
- modifiedHolder notNil ifTrue:[ modifiedHolder value:true ].
+ contentsModifiedChannel value:false.
+ keyItemModel triggerValue:helpItem.
!
cancel
- |key txt|
+ "cancel modifications, reload helpText
+ "
+ |item contents modified|
- editTextView notNil ifTrue:[
- key := listOfKeysModel value.
+ item := keyItemModel value.
+ modified := false.
- key notNil ifTrue:[
- txt := dictionary at:key ifAbsent:nil.
- ] ifFalse:[
- txt := nil
- ].
- editTextView contents:txt.
+ item notNil ifTrue:[
+ contents := item helpText.
+ ] ifFalse:[
+ contents := nil.
+
+ modifiedHolder isNil ifTrue:[
+ modified := self helpKey notNil
+ ]
].
- contentsModifiedChannel value:false.
+ helpTextView contents:contents.
+ contentsModifiedChannel value:modified.
!
doDelete
"deletes the selected help key
"
- |key|
-
- key := listOfKeysModel value.
-
- key isNil ifTrue:[
- self warn:'No key selected !!'.
- ^ self
- ].
+ |item|
- 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].
- ].
+ item := keyItemModel value.
+ item notNil ifTrue:[ item remove ].
+ editModel value:nil.
!
doLoad
- "opens a Resource Selection Browser in order to get a resource message"
-
+ "opens a Resource Selection Browser in order to get a resource message
+ "
self loadFromMessage:
- (ResourceSelectionBrowser
- request: 'Load Help Spec From Class'
- onSuperclass: nil
- andClass: specClass
- andSelector: specSelector ? #help
- withResourceTypes: (Array with: #help)).
+ (ResourceSelectionBrowser
+ request: 'Load Help Spec From Class'
+ onSuperclass: nil
+ andClass: specClass
+ andSelector: specSelector ? #help
+ withResourceTypes: (Array with: #help)).
self updateInfoLabel
-
!
doNew
- "resets the help tool"
-
- specClass := nil.
-
- editModel value:nil withoutNotifying:self.
- listOfKeysModel value:nil.
- listOfClassesModel value:nil.
-
- listOfKeys removeAll.
- listOfClasses removeAll.
- dictionaries removeAll.
-
- dictionary := Dictionary new.
- modified := false.
+ "reset all to empty
+ "
+ contentsModifiedChannel value:false.
+ self helpKey:nil.
+ self buildFromClass:nil.
!
doSave
- "saves the help dictionaries on specClass"
+ "save the help spec to the spec-class(es)
+ "
+ specClass isNil ifTrue:[
+ self information:(resources string:'No class specified !!').
+ ^ nil
+ ].
+ (specClass isSubclassOf:ApplicationModel) ifFalse:[
+ self information:(resources string:'Cannot save help into none Application class').
+ ^ nil
+ ].
+
+ classItemList do:[:aClassItem| aClassItem createHelpMethodNamed:specSelector ].
+!
+
+openDocumentation
+ "opens the documentation file of the Help Tool
+ "
+ self openHTMLDocument: 'tools/uipainter/HelpTool.html'
+! !
+
+!UIHelpTool::ClassItem class methodsFor:'instance creation'!
+
+onClass:aClass
+ |root|
+
+ root := self new.
+ root onClass:aClass.
+ ^ root
+! !
+
+!UIHelpTool::ClassItem methodsFor:'accessing'!
+
+list
+ "returns the hierarchical list assigned to the classItem; the
+ list contains the keyItems
+ "
+ list isNil ifTrue:[
+ list := HierarchicalList new.
+ list showRoot:false.
+ list root:self.
+ ].
+ ^ list
+!
+
+theClass
+ "returns the class or nil if unspecified
+ "
+ ^ theClass
+! !
+
+!UIHelpTool::ClassItem methodsFor:'change & update'!
+
+helpTextChangedFor:anItem
+ "called if an helpKey changed its contents
+ "
+ self model notNil ifTrue:[
+ self modified:true.
+ anItem modified:true.
+ ].
+! !
+
+!UIHelpTool::ClassItem methodsFor:'code generation'!
+
+createHelpMethodNamed:aMethodName
+ |stream|
+
+ (modified and:[theClass notNil]) ifFalse:[
+ ^ self
+ ].
+ stream := '' writeStream.
+
+ stream nextPutAll:
+ aMethodName, '\' withCRs,
+ (ResourceSpecEditor codeGenerationCommentForClass:UIHelpTool) withCRs,
+ '\\' withCRs,
+ ' "\' withCRs,
+ ' UIHelpTool openOnClass:', theClass name asString ,'
+ "
+
+ <resource: #help>
+
+ ^ super ', aMethodName, ' addPairsFrom:#(
+
+'.
+
+ self do:[:aKeyItem| |helpText|
+ helpText := aKeyItem helpText.
+ helpText isNil ifTrue:[ helpText := '' ].
+
+ stream nextPutLine:(aKeyItem helpKey storeString).
+ stream nextPutLine:(helpText storeString); cr.
+ ].
+ stream nextPutLine:')'.
+
+ Compiler
+ compile:(stream contents)
+ forClass:theClass class
+ inCategory:'help specs'.
+
+ self modified:false.
+! !
+
+!UIHelpTool::ClassItem methodsFor:'displaying'!
+
+icon
+ "returns the display icon (always nil)
+ "
+ ^ nil
+!
+
+label
+ "returns the display label
+ "
+ |label|
+
+ theClass notNil ifTrue:[ label := theClass name ]
+ ifFalse:[ label := '** not yet defined **' ].
+
+ modified ifTrue:[
+ label := Text string:label color:(Color red).
+ ].
+ ^ label
+! !
+
+!UIHelpTool::ClassItem methodsFor:'instance creation'!
+
+initialize
+ "setup defaults
+ "
+ super initialize.
+
+ children := OrderedCollection new.
+ isExpanded := true.
+ modified := false.
+!
+
+onClass:aClass
+ "the class the ys are assigned to; if the class is nil,
+ the class is not yet specified.
+ "
+ theClass := aClass.
+! !
+
+!UIHelpTool::ClassItem methodsFor:'private'!
+
+basicAdd:aChild sortBlock:aBlock
+ "catch low-level add to update the modification flag
+ "
+ self modified:true.
+ aChild modified:true.
+
+ ^ super basicAdd:aChild sortBlock:aBlock.
+!
+
+basicAddAll:aList beforeIndex:anIndex
+ "catch low-level add to update the modification flag
+ "
+ self modified:true.
+
+ aList do:[:el| el modified:true ].
+ ^ super basicAddAll:aList beforeIndex:anIndex.
+!
- self installHelpSpecsOnClass:specClass
+basicRemoveFromIndex:startIndex toIndex:stopIndex
+ "catch low-level remove to update the modification flag
+ "
+ self isUnspecified ifFalse:[
+ self modified:true.
+ ].
+ ^ super basicRemoveFromIndex:startIndex toIndex:stopIndex
+! !
+
+!UIHelpTool::ClassItem methodsFor:'queries'!
+
+isUnspecified
+ "true if the class is unspecified
+ "
+ ^ theClass isNil
+!
+
+modified
+ "true, if any item is modified, created or deleted
+ "
+ ^ modified
+!
+
+modified:aBoolean
+ "true, if any item is modified, created or deleted
+ "
+ modified ~~ aBoolean ifTrue:[
+ modified := aBoolean.
+
+ modified ifFalse:[
+ self do:[:el| el modified:false ].
+ ].
+ ].
+! !
+
+!UIHelpTool::ClassItem methodsFor:'searching'!
+
+detectItemWithKey:aKey
+ "returns the item assigned to a helpKey or nil
+ "
+ |key|
+
+ aKey size ~~ 0 ifTrue:[
+ key := aKey asSymbol.
+
+ self do:[:anItem|
+ anItem helpKey == key ifTrue:[ ^ anItem ].
+ ]
+ ].
+ ^ nil
+! !
+
+!UIHelpTool::KeyItem class methodsFor:'instance creation'!
+
+helpKey:aKey helpText:aText
+ |key|
+
+ key := self new.
+ key helpKey:aKey helpText:aText.
+ ^ key
+! !
+
+!UIHelpTool::KeyItem methodsFor:'accessing'!
+
+helpKey
+ "returns the helpKey, a symbol
+ "
+ ^ helpKey
+!
+
+helpText
+ "returns the contents assigned to the helpKey or nil
+ "
+ ^ helpText
+!
+
+helpText:aText
+ "set the contents assigned to the helpKey; if the cxontents changed,
+ a notification is raised.
+ "
+ |text|
+
+ text := self formatText:aText.
+
+ text ~= helpText ifTrue:[
+ helpText := text.
+
+ (modified or:[parent isNil]) ifFalse:[
+ parent helpTextChangedFor:self.
+ ]
+ ].
+! !
+
+!UIHelpTool::KeyItem methodsFor:'displaying'!
+
+icon
+ "returns the display icon (always nil)
+ "
+ ^ nil
+!
+
+label
+ "returns the display label
+ "
+ modified ifTrue:[
+ ^ Text string:helpKey color:(Color red)
+ ].
+ ^ helpKey
+! !
+
+!UIHelpTool::KeyItem methodsFor:'instance creation'!
+
+helpKey:aKey helpText:aText
+ "set the key and contents without a change notification
+ "
+ helpKey := aKey asSymbol.
+ helpText := self formatText:aText.
+!
+
+initialize
+ "setup defaults
+ "
+ super initialize.
+ children := #().
+ modified := false.
+! !
+
+!UIHelpTool::KeyItem methodsFor:'private'!
+
+formatText:aText
+ "format the text, replace carriage return by spaces and compress spaces
+ "
+ |text result|
+
+ aText size ~~ 0 ifTrue:[
+ text := aText asString asCollectionOfWords.
+
+ text notEmpty ifTrue:[
+ result := text first.
+
+ text from:2 do:[:t| result := result, ' ', t ].
+ ^ result
+ ].
+ ].
+ ^ nil
+! !
+
+!UIHelpTool::KeyItem methodsFor:'queries'!
+
+modified
+ "returns true if the helpText is modified
+ "
+ ^ modified
+!
+
+modified:aBoolean
+ "set the modification flag
+ "
+ aBoolean == modified ifFalse:[
+ modified := aBoolean.
+ self changed:#redraw.
+ ].
! !
!UIHelpTool class methodsFor:'documentation'!