diff -r cc3413fc1afb -r e7362f3ab5e5 UIHelpTool.st --- a/UIHelpTool.st Fri Mar 20 19:11:50 1998 +0100 +++ b/UIHelpTool.st Fri Mar 20 19:25:20 1998 +0100 @@ -13,8 +13,8 @@ ApplicationModel subclass:#UIHelpTool - instanceVariableNames:'isModified specClass dictionary dictionaries listSelection - maxCharsPerLine modifiedHolder' + instanceVariableNames:'specClass dictionary dictionaries listSelection modified + modifiedHolder maxCharsPerLine' classVariableNames:'' poolDictionaries:'' category:'Interface-UIPainter' @@ -40,8 +40,13 @@ documentation " - used by the UIPainter to add help text to any component which will be shown - during runing an application with enabled activeHelp mode. + The UIHelpTool allows you to define help dictionaries for the widgets in + applications. The tool are able to run stand alone or in other master + applications like the GUI Painter and the Menu Editor. + If the application responds to the selector #showHelp:aHelpText for:aView, + this selector is called by the widget's view when the mouse cursor moves over. + If the application does not responds to that selector, and the activeHelp mode + is enabled, an active help bubble is shown at the widget's view. [author:] Claus Atzkern @@ -54,11 +59,8 @@ " UIHelpTool openOnClass:UIPainter " - |helpTool| - helpTool := UIHelpTool open. - helpTool helpSpecFrom:aClass. - helpTool dictionary: aClass helpSpec. + UIHelpTool open helpSpecFrom:aClass ! ! @@ -72,14 +74,19 @@ !UIHelpTool class methodsFor:'help specs'! helpSpec - "return a dictionary filled with helpKey -> helptext associations. - These are used by the activeHelp tool." + "This resource specification was automatically generated + by the UIHelpTool of ST/X." + + "Do not manually edit this!! If it is corrupted, + the UIHelpTool may not be able to read the specification." " - UIHelpTool openOnClass:UIHelpTool + UIHelpTool openOnClass:UIHelpTool " - ^ super helpSpec addPairsFrom:#( + + + ^super helpSpec addPairsFrom:#( #addHelpTextKey 'Adds help text key.' @@ -108,16 +115,17 @@ !UIHelpTool class methodsFor:'interface specs'! windowSpec - "this window spec was automatically generated by the ST/X UIPainter" + "This resource specification was automatically generated + by the UIPainter of ST/X." - "do not manually edit this - the painter/builder may not be able to - handle the specification if its corrupted." + "Do not manually edit this!! If it is corrupted, + the UIPainter may not be able to read the specification." " UIPainter new openOnClass:UIHelpTool andSelector:#windowSpec UIHelpTool new openInterface:#windowSpec + UIHelpTool open " - "UIHelpTool open" @@ -126,12 +134,12 @@ #(#FullSpec #window: #(#WindowSpec - #name: 'unnamed canvas' - #layout: #(#LayoutFrame 118 0 430 0 403 0 700 0) - #label: 'unnamed canvas' + #name: 'Help Tool' + #layout: #(#LayoutFrame 140 0 231 0 425 0 501 0) + #label: 'Help Tool' #min: #(#Point 10 10) #max: #(#Point 1160 870) - #bounds: #(#Rectangle 118 430 404 701) + #bounds: #(#Rectangle 140 231 426 502) #usePreferredExtent: false ) #component: @@ -150,52 +158,43 @@ #useIndex: false #sequenceList: #listChannel ) - #(#HorizontalPanelViewSpec - #name: 'HorizontalPanelView' - #layout: #(#LayoutFrame 1 0.5 2 0 -3 1 26 0) - #component: - #(#SpecCollection - #collection: - #( - #(#ActionButtonSpec - #name: 'AddButton' - #activeHelpKey: #addHelpTextKey - #label: 'Add' - #model: #add - #extent: #(#Point 44 24) - ) - #(#ActionButtonSpec - #name: 'RemoveButton' - #activeHelpKey: #removeHelpTextKey - #label: 'Remove' - #model: #remove - #extent: #(#Point 44 24) - ) - #(#ActionButtonSpec - #name: 'DeleteButton' - #activeHelpKey: #deleteHelpTextKey - #label: 'Delete' - #model: #delete - #extent: #(#Point 45 24) - ) - ) - ) - #horizontalLayout: #fit - #verticalLayout: #fit - #horizontalSpace: 3 - #verticalSpace: 3 + #(#ActionButtonSpec + #name: 'AddButton' + #layout: #(#LayoutFrame 2 0.5 2 0 -1 0.67 26 0) + #activeHelpKey: #addHelpTextKey + #label: 'Add' + #tabable: true + #model: #add + ) + #(#ActionButtonSpec + #name: 'RemoveButton' + #layout: #(#LayoutFrame 1 0.67 2 0 -1 0.83 26 0) + #activeHelpKey: #removeHelpTextKey + #label: 'Remove' + #tabable: true + #model: #remove + ) + #(#ActionButtonSpec + #name: 'DeleteButton' + #layout: #(#LayoutFrame 1 0.83 2 0 -2 1 26 0) + #activeHelpKey: #deleteHelpTextKey + #label: 'Delete' + #tabable: true + #model: #delete ) #(#InputFieldSpec #name: 'helpKeyInputField' #layout: #(#LayoutFrame 1 0.5 29 0 -3 1 51 0) #activeHelpKey: #currentHelpTexts + #tabable: true #model: #listModel #immediateAccept: false ) #(#SequenceViewSpec #name: 'listOfHelpSpecClassesView' - #layout: #(#LayoutFrame 1 0.5 53 0 -3 1 -1 0.5) + #layout: #(#LayoutFrame 1 0.5 54 0 -3 1 -1 0.5) #activeHelpKey: #listOfHelpSpecClasses + #tabable: true #model: #selectionOfHelpSpecClass #hasHorizontalScrollBar: true #hasVerticalScrollBar: true @@ -209,6 +208,7 @@ #name: 'helpTextView' #layout: #(#LayoutFrame 3 0.0 1 0.5 -1 1.0 -3 1.0) #activeHelpKey: #helpTextView + #tabable: true #hasHorizontalScrollBar: true #hasVerticalScrollBar: true #miniScrollerHorizontal: true @@ -220,10 +220,11 @@ ! windowSpecForStandAlone - "this window spec was automatically generated by the ST/X UIPainter" + "This resource specification was automatically generated + by the UIPainter of ST/X." - "do not manually edit this - the painter/builder may not be able to - handle the specification if its corrupted." + "Do not manually edit this!! If it is corrupted, + the UIPainter may not be able to read the specification." " UIPainter new openOnClass:UIHelpTool andSelector:#windowSpecForStandAlone @@ -238,11 +239,11 @@ #window: #(#WindowSpec #name: 'Help Tool' - #layout: #(#LayoutFrame 195 0 352 0 694 0 751 0) + #layout: #(#LayoutFrame 534 0 276 0 1033 0 675 0) #label: 'Help Tool' #min: #(#Point 10 10) #max: #(#Point 1160 870) - #bounds: #(#Rectangle 195 352 695 752) + #bounds: #(#Rectangle 534 276 1034 676) #menu: #menu #usePreferredExtent: false ) @@ -263,10 +264,11 @@ !UIHelpTool class methodsFor:'menu specs'! menu - "this window spec was automatically generated by the ST/X MenuEditor" + "This resource specification was automatically generated + by the MenuEditor of ST/X." - "do not manually edit this - the builder may not be able to - handle the specification if its corrupted." + "Do not manually edit this!! If it is corrupted, + the MenuEditor may not be able to read the specification." " MenuEditor new openOnClass:UIHelpTool andSelector:#menu @@ -378,7 +380,7 @@ " |help| - isModified := false. + modified := false. specClass notNil ifTrue: [ @@ -404,16 +406,16 @@ self updateList ! -isModified +modified "answer whether the help tool was modified " - ^isModified + ^modified ! -isModified: aBoolean +modified: aBoolean "set the help tool as modified " - isModified := aBoolean + modified := aBoolean ! modifiedHolder:aValueHolder @@ -446,157 +448,6 @@ ^specClass ! ! -!UIHelpTool methodsFor:'actions'! - -helpSpecClassSelected - "extract the help dictionary from the selected class and make it current - " - |clsName| - - clsName := self selectionOfHelpSpecClass value. - - (dictionary := dictionaries at: clsName ifAbsent: nil) isNil - ifTrue: - [ - dictionary := dictionaries at: clsName put: (self extractHelpSpecForClass: (Smalltalk at: clsName)) - ]. - - self updateList. - - listSelection notNil - ifTrue: - [ - (dictionary keys includes: listSelection asSymbol) - ifTrue: [(builder componentAt: #listOfHelpKeysView) selection: - (self listChannel value indexOf: (builder componentAt: #helpKeyInputField) contents)] - ifFalse: [(builder componentAt: #listOfHelpKeysView) selection: nil]. - ]. - listSelection notNil - ifTrue: - [ - self editTextView contents: (dictionary at: listSelection asSymbol ifAbsent: '') - ] - - -! - -installHelpSpecOnClass:aClass - "save the help dicts in aClass which is subclass of ApplicationModel" - - |cls src helpSpec| - - cls := self applicationClassAssociatedWith: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: [aClass = cls name asString ifTrue: [dictionary] ifFalse: [Dictionary new]]. - - (cls class implements: #helpSpec) - ifTrue: - [ - |superclassHelpKeys implementedHelpSpec hasChanged| - implementedHelpSpec := Dictionary new. - superclassHelpKeys := (cls superclass respondsTo: #helpSpec) - ifTrue: [cls superclass helpSpec keys] - ifFalse: [Array new]. - - cls helpSpec associationsDo: [:h| (superclassHelpKeys includes: h key) - ifFalse: [implementedHelpSpec at: h key put: h value]]. - - 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: #helpSpec) ifTrue: [cls class removeSelector: #helpSpec]. - ]. - - src := '' writeStream. - - src nextPutAll: - -'helpSpec - "return a dictionary filled with helpKey -> helptext associations. - These are used by the activeHelp tool." - - " - UIHelpTool openOnClass:', cls name asString ,' - " - - ^ super helpSpec addPairsFrom:#( - -'. - - helpSpec keys asSortedCollection - do:[:key | - |txt t| - - txt := helpSpec at:key. - src nextPutLine:key storeString. - - t := txt asString replaceAll:(Character cr) with:(Character space). - - (t endsWith:Character space) ifTrue:[ - t := t copyWithoutLast:1 - ]. - src nextPutLine:t storeString; cr. - ]. - src nextPutLine:')'. - - Compiler - compile:(src contents) - forClass:cls class - inCategory:'help specs'. - - - - -! - -installHelpSpecsOnClass:aClass - "save the help dicts on aClass and its superclasses which are subclasses of ApplicationModel - " - |cls helpSpecClasses| - - isModified ifFalse:[ - ^nil - ]. - - cls := aClass isClass ifTrue: [aClass name] ifFalse: [aClass]. - - (helpSpecClasses := self listOfHelpSpecClasses value) notNil - ifTrue: - [ - (helpSpecClasses includes: cls) ifFalse: [helpSpecClasses add: cls]. - helpSpecClasses do: [:clsName| (self installHelpSpecOnClass: clsName) isNil ifTrue: [^isModified := false]]. - ] - ifFalse: - [ - self installHelpSpecOnClass: cls - ]. - - isModified := false. - -! ! - !UIHelpTool methodsFor:'aspects'! listChannel @@ -643,21 +494,55 @@ ! ! -!UIHelpTool methodsFor:'initialization'! +!UIHelpTool methodsFor:'callbacks'! -initialize - "initialize instance variables +helpSpecClassSelected + "extract the help dictionary from the selected class and make it current " - super initialize. + |clsName| + + clsName := self selectionOfHelpSpecClass value. + + (dictionary := dictionaries at: clsName ifAbsent: nil) isNil + ifTrue: + [ + dictionary := dictionaries at: clsName put: (self extractHelpSpecForClass: (Smalltalk at: clsName)) + ]. + + self updateList. - dictionary := Dictionary new. - dictionaries := Dictionary new. - isModified := false. + listSelection notNil + ifTrue: + [ + (dictionary keys includes: listSelection asSymbol) + ifTrue: [(builder componentAt: #listOfHelpKeysView) selection: + (self listChannel value indexOf: (builder componentAt: #helpKeyInputField) contents)] + ifFalse: [(builder componentAt: #listOfHelpKeysView) selection: nil]. + ]. + listSelection notNil + ifTrue: + [ + self editTextView contents: (dictionary at: listSelection asSymbol ifAbsent: '') + ] + ! ! !UIHelpTool methodsFor:'private'! +applicationClassAssociatedWith:aClass + "get application class keeping the associated help text or nil + " + |cls| + + ((cls := self resolveName:aClass) notNil and:[cls includesBehavior:UISpecification]) ifTrue:[ + ^UISpecificationTool + ]. + ^cls + + +! + editTextView "get the editTextView or nil. " @@ -726,27 +611,128 @@ ! +installHelpSpecOnClass:aClass + "save the help dicts in aClass which is subclass of ApplicationModel" + + |cls src helpSpec| + + cls := self applicationClassAssociatedWith: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]]]. + + (cls class implements: #helpSpec) + ifTrue: + [ + |superclassHelpKeys implementedHelpSpec hasChanged| + implementedHelpSpec := Dictionary new. + superclassHelpKeys := (cls superclass respondsTo: #helpSpec) + ifTrue: [cls superclass helpSpec keys] + ifFalse: [Array new]. + + cls helpSpec associationsDo: [:h| (superclassHelpKeys includes: h key) + ifFalse: [implementedHelpSpec at: h key put: h value]]. + + 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: #helpSpec) ifTrue: [cls class removeSelector: #helpSpec]. + ]. + + src := '' writeStream. + + src nextPutAll: + 'helpSpec\' withCRs, + (ResourceSpecEditor codeGenerationCommentForClass: UIHelpTool) withCRs, + '\\' withCRs, + ' "\' withCRs, + ' UIHelpTool openOnClass:', cls name asString ,' + " + + + + ^super helpSpec addPairsFrom:#( + +'. + + helpSpec keys asSortedCollection + do:[:key | + |txt t| + + txt := helpSpec at:key. + src nextPutLine:key storeString. + + t := txt asString replaceAll:(Character cr) with:(Character space). + + (t endsWith:Character space) ifTrue:[ + t := t copyWithoutLast:1 + ]. + src nextPutLine:t storeString; cr. + ]. + src nextPutLine:')'. + + Compiler + compile:(src contents) + forClass:cls class + inCategory:'help specs'. +! + +installHelpSpecsOnClass:aClass + "save the help dicts on aClass and its superclasses which are subclasses of ApplicationModel + " + |cls helpSpecClasses| + + modified ifFalse:[ + ^nil + ]. + + cls := aClass isClass ifTrue: [aClass name] ifFalse: [aClass]. + + (helpSpecClasses := self listOfHelpSpecClasses value) notNil + ifTrue: + [ + (helpSpecClasses includes: cls) ifFalse: [helpSpecClasses add: cls]. + helpSpecClasses do: [:clsName| (self installHelpSpecOnClass: clsName) isNil ifTrue: [^modified := false]]. + ] + ifFalse: + [ + self installHelpSpecOnClass: cls + ]. + + modified := false. + +! + updateList "update the list channel from dictionary " self listChannel value: dictionary keys asSortedCollection ! ! -!UIHelpTool methodsFor:'queries'! - -applicationClassAssociatedWith:aClass - "get application class keeping the associated help text or nil - " - |cls| - - ((cls := self resolveName:aClass) notNil and:[cls includesBehavior:UISpecification]) ifTrue:[ - ^UISpecificationTool - ]. - ^cls - - -! ! - !UIHelpTool methodsFor:'selection'! listSelection @@ -804,12 +790,23 @@ closeRequest "before closing the help tool, ask for permission " - (isModified and:[self masterApplication isNil]) ifTrue:[ + (modified and:[self masterApplication isNil]) ifTrue:[ (self confirm:'Exit without saving your modifications?') ifFalse:[ ^ self ] ]. - ^ super closeRequest. + ^super closeRequest +! + +initialize + "initialize instance variables + " + super initialize. + + dictionary := Dictionary new. + dictionaries := Dictionary new. + modified := false. + ! openInterface:aSymbol @@ -818,7 +815,7 @@ super openInterface: #windowSpecForStandAlone ! ! -!UIHelpTool methodsFor:'user interactions'! +!UIHelpTool methodsFor:'user actions'! accept "accept the help text @@ -840,7 +837,7 @@ (builder componentAt: #listOfHelpKeysView) selection: (list indexOf: key). ]. - isModified := true. + modified := true. modifiedHolder notNil ifTrue: [modifiedHolder value:true] ] ! @@ -863,7 +860,7 @@ self updateList. - isModified := true. + modified := true. modifiedHolder notNil ifTrue: [modifiedHolder value:true] ] ! @@ -905,7 +902,7 @@ model value:nil. self helpSpecFrom:specClass. model value:oldSel. - isModified := false. + modified := false. ! @@ -921,6 +918,16 @@ self listModel value: nil. self updateList. modifiedHolder notNil ifTrue: [modifiedHolder value:true] +! + +reset + "reset the help tool + " + specClass := listSelection := nil. + self dictionary: nil. + self dictionaries: nil. + self listOfHelpSpecClasses removeAll. + modified := false. ! ! !UIHelpTool class methodsFor:'documentation'!