# HG changeset patch # User tz # Date 889047474 -3600 # Node ID e9140237290072eacd8303f675a8caec7d0f2d5a # Parent 0c8ba53ba791b96e481c5e39dff1059ae9ee8607 popup menu replaced by a list + supporting of help specs from different classes diff -r 0c8ba53ba791 -r e91402372900 UIHelpTool.st --- a/UIHelpTool.st Wed Mar 04 18:48:07 1998 +0100 +++ b/UIHelpTool.st Wed Mar 04 22:37:54 1998 +0100 @@ -13,8 +13,8 @@ ApplicationModel subclass:#UIHelpTool - instanceVariableNames:'isModified specClass dictionary listSelection maxCharsPerLine - modifiedHolder' + instanceVariableNames:'isModified specClass dictionary dictionaries listSelection + maxCharsPerLine modifiedHolder' classVariableNames:'' poolDictionaries:'' category:'Interface-UIPainter' @@ -56,17 +56,17 @@ " |helpTool| - helpTool := UIHelpTool new. - helpTool openInterface:#standAloneSpec. - helpTool helpSpecFrom:aClass - + helpTool := UIHelpTool open. + helpTool helpSpecFrom:aClass. + helpTool dictionary: aClass helpSpec. ! ! !UIHelpTool class methodsFor:'constants'! label - ^ 'Help' + + ^'Help' ! ! !UIHelpTool class methodsFor:'help specs'! @@ -81,184 +81,32 @@ ^ super helpSpec addPairsFrom:#( -#activeHelpAccessKey -'This ID is used to access an active help text for the selected component' +#addHelpTextKey +'Adds help text key.' + +#currentHelpTexts +'Selected help text key.' + +#deleteHelpTextKey +'Deletes the help text from the help spec.' + +#helpTextView +'Shows the help text.' + +#listOfHelpSpecClasses +'List of the classes where help specs can be/are implemented.' + +#listOfHelpTexts +'List of the help text keys.' + +#removeHelpTextKey +'Removes the help text key from the widget.' ) ! ! !UIHelpTool class methodsFor:'interface specs'! -keyMenu - "this window spec was automatically generated by the ST/X MenuEditor" - - "do not manually edit this - the builder may not be able to - handle the specification if its corrupted." - - " - MenuEditor new openOnClass:UIHelpTool andSelector:#keyMenu - (Menu new fromLiteralArrayEncoding:(UIHelpTool keyMenu)) startUp - " - - - - ^ - - #(#Menu - - #( - #(#MenuItem - #'label:' 'save as ...' - #'value:' #saveAs - ) - #(#MenuItem - #'label:' '-' - ) - #(#MenuItem - #'label:' 'remove' - #'value:' #removeKey - ) - ) nil - nil - ) - - "Created: / 27.10.1997 / 00:55:20 / cg" -! - -menuPanelStandAlone - "this window spec was automatically generated by the ST/X MenuEditor" - - "do not manually edit this - the builder may not be able to - handle the specification if its corrupted." - - " - MenuEditor new openOnClass:UIHelpTool andSelector:#menuPanelStandAlone - (Menu new fromLiteralArrayEncoding:(UIHelpTool menuPanelStandAlone)) startUp - " - - - - ^ - - #(#Menu - - #( - #(#MenuItem - #'label:' 'file' - #'submenu:' - #(#Menu - - #( - #(#MenuItem - #'label:' 'reload' - #'value:' #doReload - ) - #(#MenuItem - #'label:' '-' - ) - #(#MenuItem - #'label:' 'quit' - #'value:' #closeRequest - ) - ) nil - nil - ) - ) - #(#MenuItem - #'label:' 'code' - #'submenu:' - #(#Menu - - #( - #(#MenuItem - #'label:' 'class' - #'value:' #doFromClass - ) - #(#MenuItem - #'label:' '-' - ) - #(#MenuItem - #'label:' 'install help spec.' - #'value:' #doInstallHelpSpec - ) - ) nil - nil - ) - ) - ) nil - nil - ) -! - -standAloneSpec - "this window spec was automatically generated by the ST/X UIPainter" - - "do not manually edit this - the painter/builder may not be able to - handle the specification if its corrupted." - - " - UIPainter new openOnClass:UIHelpTool andSelector:#standAloneSpec - UIHelpTool new openInterface:#standAloneSpec - " - - - - ^ - - #(#FullSpec - #'window:' - #(#WindowSpec - #'name:' 'HelpTool' - #'layout:' #(#LayoutFrame 219 0 193 0 814 0 690 0) - #'label:' 'HelpTool' - #'min:' #(#Point 10 10) - #'max:' #(#Point 1160 870) - #'bounds:' #(#Rectangle 219 193 815 691) - #'usePreferredExtent:' false - ) - #'component:' - #(#SpecCollection - #'collection:' - #( - #(#MenuPanelSpec - #'name:' 'menuPanelStandAlone' - #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 25 0) - #'menu:' #menuPanelStandAlone - ) - #(#VariableHorizontalPanelSpec - #'name:' 'variableHorizontalPanel1' - #'layout:' #(#LayoutFrame 0 0.0 25 0.0 0 1.0 0 1.0) - #'component:' - #(#SpecCollection - #'collection:' - #( - #(#TextEditorSpec - #'name:' 'textView' - #'hasHorizontalScrollBar:' true - #'hasVerticalScrollBar:' true - #'miniScrollerHorizontal:' true - #'miniScrollerVertical:' true - ) - #(#SequenceViewSpec - #'name:' 'selectionList' - #'model:' #listModel - #'menu:' #keyMenu - #'hasHorizontalScrollBar:' true - #'hasVerticalScrollBar:' true - #'miniScrollerHorizontal:' true - #'miniScrollerVertical:' true - #'useIndex:' false - #'sequenceList:' #listChannel - ) - ) - ) - #'handles:' #(#Any 0.647651 1.0) - ) - ) - ) - ) -! - windowSpec "this window spec was automatically generated by the ST/X UIPainter" @@ -276,46 +124,196 @@ ^ #(#FullSpec - #'window:' + #window: #(#WindowSpec - #'name:' 'HelpTool' - #'layout:' #(#LayoutFrame 199 0 167 0 484 0 437 0) - #'label:' 'unnamed canvas' - #'min:' #(#Point 10 10) - #'max:' #(#Point 1160 870) - #'bounds:' #(#Rectangle 199 167 485 438) + #name: 'HelpTool' + #layout: #(#LayoutFrame 59 0 376 0 344 0 646 0) + #label: 'unnamed canvas' + #min: #(#Point 10 10) + #max: #(#Point 1160 870) + #bounds: #(#Rectangle 59 376 345 647) + #usePreferredExtent: false ) - #'component:' + #component: #(#SpecCollection - #'collection:' + #collection: #( - #(#LabelSpec - #'name:' 'keyLabel' - #'layout:' #(#AlignmentOrigin 3 0.0 42 0.0 0 1) - #'label:' 'Key:' - #'adjust:' #left - #'resizeForLabel:' true + #(#SequenceViewSpec + #name: 'listOfHelpKeysView' + #layout: #(#LayoutFrame 3 0 2 0 -1 0.5 -1 0.5) + #activeHelpKey: #listOfHelpTexts + #tabable: true + #model: #listModel + #hasHorizontalScrollBar: true + #hasVerticalScrollBar: true + #useIndex: false + #sequenceList: #listChannel ) - #(#ComboBoxSpec - #'name:' 'comboBox' - #'layout:' #(#LayoutFrame 48 0 22 0 -3 1.0 44 0) - #'activeHelpKey:' #activeHelpAccessKey - #'tabable:' true - #'model:' #listModel - #'type:' #symbolOrNil - #'comboList:' #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: #accept + #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 + ) + #(#InputFieldSpec + #name: 'helpKeyInputField' + #layout: #(#LayoutFrame 1 0.5 29 0 -3 1 51 0) + #activeHelpKey: #currentHelpTexts + #model: #listModel + ) + #(#SequenceViewSpec + #name: 'listOfHelpSpecClassesView' + #layout: #(#LayoutFrame 1 0.5 53 0 -3 1 -1 0.5) + #activeHelpKey: #listOfHelpSpecClasses + #model: #selectionOfHelpSpecClass + #hasHorizontalScrollBar: true + #hasVerticalScrollBar: true + #valueChangeSelector: #helpSpecClassSelected + #useIndex: false + #sequenceList: #listOfHelpSpecClasses ) #(#TextEditorSpec - #'name:' 'textView' - #'layout:' #(#LayoutFrame 3 0.0 45 0.0 -3 1.0 -3 1.0) - #'hasHorizontalScrollBar:' true - #'hasVerticalScrollBar:' true - #'miniScrollerHorizontal:' true - #'miniScrollerVertical:' true + #name: 'helpTextView' + #layout: #(#LayoutFrame 3 0.0 1 0.5 -1 1.0 -3 1.0) + #activeHelpKey: #helpTextView + #hasHorizontalScrollBar: true + #hasVerticalScrollBar: true + #miniScrollerHorizontal: true + #miniScrollerVertical: true ) ) ) ) +! + +windowSpecForStandAlone + "this window spec was automatically generated by the ST/X UIPainter" + + "do not manually edit this - the painter/builder may not be able to + handle the specification if its corrupted." + + " + UIPainter new openOnClass:UIHelpTool andSelector:#windowSpecForStandAlone + UIHelpTool new openInterface:#windowSpecForStandAlone + " + + + + ^ + + #(#FullSpec + #window: + #(#WindowSpec + #name: 'Help Tool' + #layout: #(#LayoutFrame 195 0 352 0 694 0 751 0) + #label: 'Help Tool' + #min: #(#Point 10 10) + #max: #(#Point 1160 870) + #bounds: #(#Rectangle 195 352 695 752) + #menu: #menu + #usePreferredExtent: false + ) + #component: + #(#SpecCollection + #collection: + #( + #(#UISubSpecification + #name: 'UISubSpecification1' + #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) + #minorKey: #windowSpec + ) + ) + ) + ) +! ! + +!UIHelpTool class methodsFor:'menu specs'! + +menu + "this window spec was automatically generated by the ST/X MenuEditor" + + "do not manually edit this - the builder may not be able to + handle the specification if its corrupted." + + " + MenuEditor new openOnClass:UIHelpTool andSelector:#menu + (Menu new fromLiteralArrayEncoding:(UIHelpTool menu)) startUp + " + + + + ^ + + #(#Menu + + #( + #(#MenuItem + #label: 'File' + #submenu: + #(#Menu + + #( + #(#MenuItem + #label: 'Reload' + #value: #doReload + ) + #(#MenuItem + #label: '-' + ) + #(#MenuItem + #label: 'Save' + #value: #doInstallHelpSpec + ) + #(#MenuItem + #label: '-' + ) + #(#MenuItem + #label: 'Define Class...' + #value: #doFromClass + ) + #(#MenuItem + #label: '-' + ) + #(#MenuItem + #label: 'Exit' + #value: #closeRequest + ) + ) nil + nil + ) + ) + ) nil + nil + ) ! ! !UIHelpTool methodsFor:'accessing'! @@ -356,15 +354,26 @@ " |help| + isModified := false. + dictionary := IdentityDictionary new. + dictionaries := IdentityDictionary new. specClass := self applicationClassAssociatedWith:aClass. - isModified := false. - + specClass isClass + ifTrue: + [ + self listOfHelpSpecClasses contents: (specClass withAllSuperclasses reverse collect: [:cls| cls name]). + self listOfHelpSpecClasses removeAll: (ApplicationModel withAllSuperclasses collect: [:cls| cls name]). + self selectionOfHelpSpecClass value: specClass name. + (builder componentAt: #listOfHelpSpecClassesView) selection: + (self listOfHelpSpecClasses value indexOf: specClass name). + self helpSpecClassSelected. + ]. (specClass respondsTo:#helpSpec) ifTrue:[ help := specClass helpSpec ] ifFalse:[ specClass := nil ]. - self dictionary:help + self updateList ! modifiedHolder:aValueHolder @@ -389,22 +398,6 @@ ] -! - -updateList - "update list from dictionary - " - self listChannel value:(dictionary keys asSortedCollection) -! ! - -!UIHelpTool methodsFor:'accessing menu'! - -keyMenu - "this window spec was automatically generated by the UI Builder" - - ^ self class keyMenu - - "Created: / 27.10.1997 / 00:55:20 / cg" ! ! !UIHelpTool methodsFor:'actions'! @@ -412,7 +405,7 @@ accept "accept the text " - |view key txt list listChgd| + |view key txt list listChgd| (listSelection size == 0 or:[(view := self editTextView) isNil]) ifFalse:[ txt := view contents asString. @@ -421,39 +414,79 @@ (listChgd := (dictionary at:key ifAbsent:nil) isNil) ifTrue:[ list add:key. - ]. + ]. dictionary at:key put:txt. - isModified := true. listChgd ifTrue:[ - self updateList - ]. + self updateList. + (builder componentAt: #listOfHelpKeysView) selection: (list indexOf: key). + ]. + + isModified := true. modifiedHolder notNil ifTrue: [modifiedHolder value:true] ] ! +delete + "delete selected help key + " + listSelection notNil + ifTrue: + [ + dictionary removeKey: listSelection asSymbol ifAbsent: nil. + self remove. + + self updateList. + + isModified := true. + modifiedHolder notNil ifTrue: [modifiedHolder value:true] + ] +! + +helpSpecClassSelected + + |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]]. + self editTextView contents: '' +! + installHelpSpecInto:aClass "install help text " - |cls src superHelpSpecKeys helpSpec| + |cls src superHelpSpecKeys helpSpec mayRemoveHelpSpecSelector| cls := self applicationClassAssociatedWith:aClass. cls isNil ifTrue:[ ^ self information:'No application class defined!!'. ]. + + aClass == cls name + ifTrue: [cls allSuperclasses value do: [:c| self installHelpSpecInto:c]. isModified := true]. + isModified not ifTrue:[ ^nil ]. - superHelpSpecKeys := cls superclass helpSpec keys. + (cls superclass respondsTo: #helpSpec) + ifTrue: [superHelpSpecKeys := cls superclass helpSpec keys. mayRemoveHelpSpecSelector := true] + ifFalse: [superHelpSpecKeys := IdentityDictionary new. mayRemoveHelpSpecSelector := false]. - helpSpec := IdentityDictionary new. - dictionary associationsDo: - [:asso| - (superHelpSpecKeys includes: asso key) ifFalse: [helpSpec at: asso key put: asso value] - ]. + helpSpec := dictionaries at: cls name ifAbsent: [^nil]. helpSpec isEmpty ifTrue:[ + mayRemoveHelpSpecSelector ifTrue: [cls class removeSelector: #helpSpec]. ^nil ]. @@ -495,12 +528,22 @@ isModified := false. +! + +remove + "remove selected help key + " + + self listModel value: nil. + + self updateList. + + modifiedHolder notNil ifTrue: [modifiedHolder value:true] ! ! !UIHelpTool methodsFor:'aspects'! listChannel - "automatically generated by UIPainter ..." |holder| @@ -508,12 +551,9 @@ builder aspectAt:#listChannel put:(holder := OrderedCollection new asValue). ]. ^ holder - - "Modified: / 27.10.1997 / 01:50:33 / cg" ! listModel - "automatically generated by UIPainter ..." |holder| @@ -522,6 +562,26 @@ builder aspectAt:#listModel put:holder. ]. ^ holder +! + +listOfHelpSpecClasses + + |holder| + (holder := builder bindingAt:#listOfHelpSpecClasses) isNil ifTrue:[ + builder aspectAt:#listOfHelpSpecClasses put: (holder := List new) + ]. + ^ holder + +! + +selectionOfHelpSpecClass + + |holder| + (holder := builder bindingAt:#selectionOfHelpSpecClass) isNil ifTrue:[ + builder aspectAt:#selectionOfHelpSpecClass put: (holder := ValueHolder new) + ]. + ^ holder + ! ! !UIHelpTool methodsFor:'initialization'! @@ -530,56 +590,12 @@ "setup instance attributes " super initialize. - dictionary := IdentityDictionary new. + dictionary := IdentityDictionary new. + dictionaries := IdentityDictionary new. isModified := false. ! ! -!UIHelpTool methodsFor:'menu actions'! - -removeKey - |k sym| - - k := Dialog request:'name of key to remove:' initialAnswer:listSelection. - k size > 0 ifTrue:[ - ((dictionary includesKey:k) - or:[(sym := k asSymbolIfInterned) notNil - and:[dictionary includesKey:sym]]) - ifFalse:[ - ^ self warn:'key is not present.'. - ]. - sym notNil ifTrue:[ - dictionary removeKey:sym ifAbsent:nil. - ]. - dictionary removeKey:k ifAbsent:nil. - isModified := true. - self updateList - ]. - - "Created: / 27.10.1997 / 01:48:48 / cg" - "Modified: / 27.10.1997 / 02:25:30 / cg" -! - -saveAs - |key new| - - key := Dialog request:'save under key:' initialAnswer:(listSelection ? ''). - key := key withoutSeparators. - - key size ~~ 0 ifTrue:[ - key := key asSymbol. - new := (dictionary at:key ifAbsent:nil) isNil. - - dictionary at:key put:(self editTextView contents asString). - - new ifTrue:[ - self updateList - ]. - isModified := true. - self listModel value:key. - ]. -! ! - !UIHelpTool methodsFor:'private'! editTextView @@ -587,7 +603,7 @@ " |view| - (view := builder componentAt:#textView) notNil ifTrue:[ + (view := builder componentAt:#helpTextView) notNil ifTrue:[ view := view scrolledView. view acceptAction isNil ifTrue:[ @@ -601,6 +617,57 @@ ]. ]. ^ view +! + +extractHelpSpecForClass: aClass + + |helpSpecSuperClass superHelpSpecKeys helpSpec| + + ((aClass class implements: #helpSpec) + and: [(helpSpecSuperClass := aClass allSuperclasses detect: [:cls| cls class implements: #helpSpec] ifNone: nil) notNil]) + ifTrue: + [ + superHelpSpecKeys := helpSpecSuperClass helpSpec keys. + helpSpec := IdentityDictionary new. + aClass helpSpec associationsDo: + [:asso| + (superHelpSpecKeys includes: asso key) ifFalse: [helpSpec at: asso key put: asso value] + ]. + ^dictionary := helpSpec + ]. + ^dictionary := IdentityDictionary new +! + +findHelpSpecForKey: aHelpKey + "update list from dictionary + " + |helpSpecClass superHelpSpecKeys helpSpec| + + aHelpKey isNil ifTrue: [^nil]. + + self listOfHelpSpecClasses value do: + [:clsName| + (dictionary := dictionaries at: clsName ifAbsent: nil) isNil + ifTrue: + [ + dictionary := dictionaries at: clsName put: (self extractHelpSpecForClass: (Smalltalk at: clsName)) + ]. + (dictionary includesKey: aHelpKey asSymbol) + ifTrue: + [ + self updateList. + ^(builder componentAt: #listOfHelpSpecClassesView) selection: + (self listOfHelpSpecClasses value indexOf: clsName). + ] + ]. + + +! + +updateList + "update list from dictionary + " + self listChannel value: dictionary keys asSortedCollection ! ! !UIHelpTool methodsFor:'queries'! @@ -637,6 +704,9 @@ " |txt view sel| + aSelection isNil ifTrue: [(builder componentAt: #listOfHelpKeysView) selection: nil]. + self findHelpSpecForKey: aSelection. + aSelection isNumber ifTrue:[ aSelection ~~ 0 ifTrue:[ sel := self listChannel value at:aSelection @@ -664,7 +734,7 @@ (txt isNil or:[maxCharsPerLine isNil]) ifFalse:[ txt := UIPainter convertString:(txt asString) maxLineSize:maxCharsPerLine skipLineFeed:false. ] - ]. + ]. view contents:txt. view modified:false. ] @@ -682,6 +752,12 @@ ] ]. ^ super closeRequest. +! + +openInterface:aSymbol + "open interface + " + super openInterface: #windowSpecForStandAlone ! ! !UIHelpTool methodsFor:'user interactions'! @@ -697,7 +773,7 @@ [true] whileTrue:[ accepted := (DialogBox new - addTextLabel:'Classes name:'; + addTextLabel:'Class name:'; addInputFieldOn:cls; addAbortButton; addOkButton; @@ -710,7 +786,7 @@ cls notNil ifTrue:[ ^ self helpSpecFrom:cls ]. - self warn:'no such class'. + self warn:'No such class!!'. ] !