cg@156: " cg@156: COPYRIGHT (c) 1995 by eXept Software AG ca@1669: All Rights Reserved cg@156: cg@156: This software is furnished under a license and may be used cg@156: only in accordance with the terms of that license and with the cg@156: inclusion of the above copyright notice. This software may not cg@156: be provided or otherwise made available to, or used by, any cg@156: other person. No title to or ownership of the software is cg@156: hereby transferred. cg@156: " cg@1554: "{ Package: 'stx:libtool2' }" cg@1554: sv@1772: ResourceSpecEditor subclass:#UIHelpTool sv@1772: instanceVariableNames:'classItemList classItemModel keyItemModel helpTextView sv@1772: modifiedHolder contentsModifiedChannel editModel' ca@148: classVariableNames:'' ca@148: poolDictionaries:'' ca@148: category:'Interface-UIPainter' ca@148: ! ca@148: ca@1669: HierarchicalItem subclass:#ClassItem ca@1669: instanceVariableNames:'theClass list modified' ca@1669: classVariableNames:'' ca@1669: poolDictionaries:'' ca@1669: privateIn:UIHelpTool ca@1669: ! ca@1669: ca@1669: HierarchicalItem subclass:#KeyItem cg@1681: instanceVariableNames:'helpKey helpText flyByText modified icon' ca@1669: classVariableNames:'' ca@1669: poolDictionaries:'' ca@1669: privateIn:UIHelpTool ca@1669: ! ca@1669: ca@148: !UIHelpTool class methodsFor:'documentation'! ca@148: cg@156: copyright cg@156: " cg@156: COPYRIGHT (c) 1995 by eXept Software AG ca@1669: All Rights Reserved cg@156: cg@156: This software is furnished under a license and may be used cg@156: only in accordance with the terms of that license and with the cg@156: inclusion of the above copyright notice. This software may not cg@156: be provided or otherwise made available to, or used by, any cg@156: other person. No title to or ownership of the software is cg@156: hereby transferred. cg@156: " cg@156: ! cg@156: ca@148: documentation ca@148: " tz@779: The Help Tool allows you to define help dictionaries for the widgets in tz@761: window applications. The tool are able to run stand alone or in other master tz@740: applications like the GUI Painter and the Menu Editor. tz@740: If the application responds to the selector #showHelp:aHelpText for:aView, tz@740: this selector is called by the widget's view when the mouse cursor moves over. tz@740: If the application does not responds to that selector, and the activeHelp mode tz@740: is enabled, an active help bubble is shown at the widget's view. cg@156: tz@779: [instance variables:] ca@1669: specClass class implementing the help spec ca@1669: specSelector selector returning the help spec ca@1669: classItemList the list of classItems ca@1669: classItemModel keeps the selected class ca@1669: keyItemModel keeps the selected helpKey ca@1669: modifiedHolder true if the editField or contents changed ca@1669: editModel keeps the current helpKey ca@1669: helpTextView the view which shows the helpText ca@1669: contentsModifiedChannel true if the helpText is modified tz@779: cg@156: [author:] ca@1669: Claus Atzkern, eXept Software AG ca@1669: Thomas Zwick, eXept Software AG ca@148: " ca@148: ! ! ca@148: ca@286: !UIHelpTool class methodsFor:'instance creation'! ca@286: cg@832: open cg@833: ^ self openOnClass:nil. cg@832: ! cg@832: ca@286: openOnClass:aClass ca@1669: "opens a Help Tool on aClass ca@286: " ca@1669: ^ self openOnClass:aClass andSelector:#helpSpec tz@750: ! ! tz@750: ca@286: !UIHelpTool class methodsFor:'constants'! ca@286: ca@286: label ca@1669: "returns the label; used if embedded as sub canvas in the GUI Painter or Menu Editor ca@1669: " tz@696: ^'Help' ca@286: ! ! ca@286: sv@1772: !UIHelpTool class methodsFor:'defaults'! sv@1772: sv@1772: resourceType sv@1772: "get the type of the resource of the method generated by the UIHelpTool" sv@1772: sv@1772: ^ #help sv@1772: ! ! sv@1772: ca@151: !UIHelpTool class methodsFor:'help specs'! ca@151: ca@151: helpSpec tz@740: "This resource specification was automatically generated tz@740: by the UIHelpTool of ST/X." tz@740: tz@740: "Do not manually edit this!! If it is corrupted, tz@740: the UIHelpTool may not be able to read the specification." ca@292: ca@172: " tz@740: UIHelpTool openOnClass:UIHelpTool ca@292: " ca@292: tz@740: tz@740: ca@1669: ^ super helpSpec addPairsFrom:#( ca@151: tz@696: #addHelpTextKey cg@1340: 'Adds the key to the help spec.' tz@696: tz@696: #currentHelpTexts tz@696: 'Selected help text key.' tz@696: tz@696: #deleteHelpTextKey cg@1340: 'Deletes the key from the help spec.' cg@1340: tz@750: #fileLoad tz@750: 'Opens a dialog for selecting and loading a help spec from a class.' tz@750: tz@750: #fileSave cg@1340: 'Saves the current help spec.' cg@1340: cg@1340: #fileUpdate cg@1340: 'Reload the help spec.' tz@696: tz@696: #helpTextView sv@1622: 'Shows the help text. Menu action ''Accept'' commits changes' tz@696: ca@1646: #listOfClasses cg@1340: 'Classes where help specs can be/are implemented.' tz@696: tz@696: #listOfHelpTexts cg@1340: 'List of help text keys.' tz@696: tz@696: #removeHelpTextKey cg@1340: 'Removes the help message from the widget.' ca@172: ca@1646: #updateHelpTextKey ca@1646: 'Refetch the help spec.' ca@1646: ca@172: ) ca@151: ! ! ca@151: ca@148: !UIHelpTool class methodsFor:'interface specs'! ca@148: cg@1982: innerSpec tz@740: "This resource specification was automatically generated tz@740: by the UIPainter of ST/X." ca@148: tz@740: "Do not manually edit this!! If it is corrupted, tz@740: the UIPainter may not be able to read the specification." ca@148: ca@148: " cg@1982: UIPainter new openOnClass:UIHelpTool andSelector:#innerSpec cg@1982: UIHelpTool new openInterface:#innerSpec ca@148: " ca@148: ca@148: ca@148: ca@1302: ^ sv@1737: #(FullSpec cg@1982: name: innerSpec sv@1737: window: sv@1737: (WindowSpec sv@1737: label: 'UIHelpTool' sv@1737: name: 'UIHelpTool' sv@1737: min: (Point 10 10) cg@1973: bounds: (Rectangle 0 0 461 293) sv@1737: ) sv@1737: component: sv@1737: (SpecCollection sv@1737: collection: ( sv@1737: (VariableVerticalPanelSpec sv@1737: name: 'PanelVrt' sv@1737: layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) sv@1737: component: sv@1737: (SpecCollection sv@1737: collection: ( sv@1737: (VariableHorizontalPanelSpec sv@1737: name: 'PanelHrz' sv@1737: component: sv@1737: (SpecCollection sv@1737: collection: ( sv@1737: (HierarchicalListViewSpec sv@1737: name: 'keyItemModel' sv@1737: model: keyItemModel sv@1737: menu: keyItemMenu sv@1737: hasHorizontalScrollBar: true sv@1737: hasVerticalScrollBar: true sv@1737: miniScrollerHorizontal: true sv@1737: miniScrollerVertical: false sv@1737: listModel: keyItemListHolder sv@1737: useIndex: false sv@1737: highlightMode: label sv@1737: showLines: false sv@1737: showIndicators: false sv@1737: showLeftIndicators: false sv@1737: useDefaultIcons: false sv@1737: autoScrollHorizontal: false sv@1737: ) sv@1737: (ViewSpec sv@1737: name: 'classItemList' sv@1737: component: sv@1737: (SpecCollection sv@1737: collection: ( sv@1737: (InputFieldSpec sv@1737: name: 'editModel' sv@1737: layout: (LayoutFrame 0 0.0 2 0 -1 1.0 25 0) sv@1737: activeHelpKey: currentHelpTexts sv@1737: model: editModel sv@1737: immediateAccept: true sv@1737: acceptOnReturn: false sv@1737: acceptOnTab: false sv@1737: acceptOnLostFocus: false sv@1737: acceptOnPointerLeave: false sv@1737: ) sv@1737: (SelectionInListModelViewSpec sv@1737: name: 'classItemModel' sv@1737: layout: (LayoutFrame 0 0.0 27 0.0 0 1.0 0 1.0) sv@1737: model: classItemModel sv@1737: hasHorizontalScrollBar: true sv@1737: hasVerticalScrollBar: true sv@1737: miniScrollerHorizontal: true sv@1737: miniScrollerVertical: true sv@1737: autoHideScrollBars: false sv@1737: listModel: classItemListHolder sv@1737: useIndex: false sv@1737: highlightMode: label sv@1737: ) sv@1737: ) cg@1340: sv@1737: ) sv@1737: ) sv@1737: ) ca@1646: sv@1737: ) sv@1737: handles: (Any 0.607375 1.0) sv@1737: ) sv@1737: (ArbitraryComponentSpec sv@1737: name: 'helpTextView' sv@1737: hasHorizontalScrollBar: true sv@1737: hasVerticalScrollBar: true sv@1737: miniScrollerHorizontal: true sv@1737: miniScrollerVertical: true sv@1737: hasBorder: false sv@1737: component: helpTextView sv@1737: ) sv@1737: ) ca@1302: sv@1737: ) sv@1737: handles: (Any 0.679181 1.0) sv@1737: ) sv@1737: ) ca@1302: sv@1737: ) ca@148: ) tz@696: ! tz@696: cg@1982: windowSpec tz@740: "This resource specification was automatically generated tz@740: by the UIPainter of ST/X." tz@696: tz@740: "Do not manually edit this!! If it is corrupted, tz@740: the UIPainter may not be able to read the specification." tz@696: tz@696: " cg@1982: UIPainter new openOnClass:UIHelpTool andSelector:#windowSpec cg@1982: UIHelpTool new openInterface:#windowSpec cg@1982: UIHelpTool open tz@696: " tz@696: tz@696: tz@696: ca@1646: ^ sv@1737: #(FullSpec cg@1982: name: windowSpec sv@1737: window: sv@1737: (WindowSpec sv@1737: label: 'Help Tool' sv@1737: name: 'Help Tool' sv@1737: min: (Point 300 300) cg@1982: bounds: (Rectangle 0 0 498 429) sv@1737: menu: menu sv@1737: ) sv@1737: component: sv@1737: (SpecCollection sv@1737: collection: ( cg@2002: (ViewSpec cg@2002: name: 'mainPanel' cg@2002: layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 -24 1.0) cg@2002: component: cg@2002: (SpecCollection cg@2002: collection: ( cg@2002: (UISubSpecification cg@2002: name: 'innerSpec' cg@2002: layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 -24 1.0) cg@2002: minorKey: innerSpec cg@2002: ) cg@2002: (UISubSpecification cg@2002: name: 'windowSpecForCommit' cg@2002: layout: (LayoutFrame 0 0.0 -24 1.0 0 1.0 0 1.0) cg@2002: majorKey: ToolApplicationModel cg@2002: minorKey: windowSpecForCommit cg@2002: ) cg@2002: ) cg@2002: cg@2002: ) sv@1737: ) sv@1737: (UISubSpecification cg@2002: name: 'infoBarSubSpec' sv@1737: layout: (LayoutFrame 0 0 -24 1 0 1 0 1) sv@1737: majorKey: ToolApplicationModel sv@1737: minorKey: windowSpecForInfoBar sv@1737: ) sv@1737: ) ca@1646: sv@1737: ) tz@696: ) tz@696: ! ! tz@696: tz@696: !UIHelpTool class methodsFor:'menu specs'! tz@696: ca@1646: helpTextMenu ca@1646: "This resource specification was automatically generated ca@1646: by the MenuEditor of ST/X." ca@1646: ca@1646: "Do not manually edit this!! If it is corrupted, ca@1646: the MenuEditor may not be able to read the specification." ca@1646: ca@1646: " ca@1646: MenuEditor new openOnClass:UIHelpTool andSelector:#helpTextMenu ca@1646: (Menu new fromLiteralArrayEncoding:(UIHelpTool helpTextMenu)) startUp ca@1646: " ca@1646: ca@1646: ca@1646: ca@1646: ^ ca@1646: #(#Menu ca@1669: #( ca@1669: #(#MenuItem ca@1669: #activeHelpKey: #commitOK ca@1669: #enabled: #contentsModifiedChannel ca@1669: #label: 'Accept' ca@1669: #itemValue: #accept ca@1669: #translateLabel: true ca@1669: ) ca@1669: #(#MenuItem ca@1669: #activeHelpKey: #commitCancel ca@1669: #enabled: #contentsModifiedChannel ca@1669: #label: 'Cancel' ca@1669: #itemValue: #cancel ca@1669: #translateLabel: true ca@1669: ) ca@1669: ) ca@1669: nil ca@1669: nil ca@1669: ) ca@1669: ! ca@1669: ca@1669: keyItemMenu ca@1669: "This resource specification was automatically generated ca@1669: by the MenuEditor of ST/X." ca@1669: ca@1669: "Do not manually edit this!! If it is corrupted, ca@1669: the MenuEditor may not be able to read the specification." ca@1669: ca@1669: " ca@1669: MenuEditor new openOnClass:UIHelpTool andSelector:#keyItemMenu ca@1669: (Menu new fromLiteralArrayEncoding:(UIHelpTool keyItemMenu)) startUp ca@1669: " ca@1669: ca@1669: ca@1669: ca@1669: ^ ca@1669: #(#Menu ca@1669: #( ca@1669: #(#MenuItem ca@1669: #activeHelpKey: #deleteHelpTextKey ca@1669: #label: 'Delete' ca@1669: #itemValue: #doDelete ca@1669: #translateLabel: true ca@1669: ) ca@1669: ) ca@1669: nil ca@1669: nil ca@1646: ) ca@1646: ! ca@1646: ca@1646: listOfKeysMenu ca@1646: "This resource specification was automatically generated ca@1646: by the MenuEditor of ST/X." ca@1646: ca@1646: "Do not manually edit this!! If it is corrupted, ca@1646: the MenuEditor may not be able to read the specification." ca@1646: ca@1646: " ca@1646: MenuEditor new openOnClass:UIHelpTool andSelector:#listOfKeysMenu ca@1646: (Menu new fromLiteralArrayEncoding:(UIHelpTool listOfKeysMenu)) startUp ca@1646: " ca@1646: ca@1646: ca@1646: ca@1646: ^ ca@1646: #(#Menu ca@1669: #( ca@1669: #(#MenuItem ca@1669: #activeHelpKey: #deleteHelpTextKey ca@1669: #label: 'Delete' ca@1669: #itemValue: #doDelete ca@1669: #translateLabel: true ca@1669: ) ca@1669: ) ca@1669: nil ca@1669: nil ca@1646: ) ca@1646: ! ca@1646: tz@696: menu tz@740: "This resource specification was automatically generated tz@740: by the MenuEditor of ST/X." tz@696: tz@740: "Do not manually edit this!! If it is corrupted, tz@740: the MenuEditor may not be able to read the specification." tz@696: tz@696: " tz@696: MenuEditor new openOnClass:UIHelpTool andSelector:#menu tz@696: (Menu new fromLiteralArrayEncoding:(UIHelpTool menu)) startUp tz@696: " tz@696: tz@696: tz@696: ca@1646: ^ ca@1775: #(Menu ca@1775: ( ca@1775: (MenuItem ca@1775: label: 'File' ca@1775: translateLabel: true ca@1775: submenu: ca@1775: (Menu ca@1775: ( ca@1775: (MenuItem cg@1973: label: 'New' cg@1973: itemValue: doNew cg@1973: translateLabel: true cg@1973: ) cg@1973: (MenuItem cg@1973: label: '-' cg@1973: ) cg@1973: (MenuItem ca@1775: activeHelpKey: fileLoad ca@1775: label: 'Load...' ca@1775: itemValue: doLoad ca@1775: translateLabel: true ca@1775: ) ca@1775: (MenuItem ca@1775: activeHelpKey: fileSave ca@1775: label: 'Save' ca@1775: itemValue: doSave ca@1775: translateLabel: true ca@1775: ) ca@1775: (MenuItem ca@1775: label: '-' cg@1982: isVisible: isStandAlone ca@1775: ) ca@1775: (MenuItem ca@1775: activeHelpKey: fileExit ca@1775: label: 'Exit' ca@1775: itemValue: closeRequest ca@1775: translateLabel: true cg@1982: isVisible: isStandAlone ca@1775: ) ca@1775: ) ca@1775: nil ca@1775: nil ca@1775: ) ca@1775: ) ca@1775: (MenuItem ca@1775: label: 'Edit' ca@1775: translateLabel: true ca@1775: submenuChannel: keyItemMenu ca@1775: keepLinkedMenu: true ca@1775: ) ca@1775: (MenuItem cg@1973: label: 'History' cg@1973: translateLabel: true cg@1982: isVisible: isStandAlone cg@1973: submenuChannel: menuHistory cg@1973: ) cg@1973: (MenuItem cg@2665: label: 'MENU_Help' ca@1775: translateLabel: true cg@2127: startGroup: conditionalRight ca@1775: submenuChannel: menuHelp ca@1775: ) ca@1775: ) ca@1775: nil ca@1775: nil tz@696: ) ca@148: ! ! ca@148: ca@148: !UIHelpTool methodsFor:'accessing'! ca@148: ca@1669: helpKey ca@1669: "returns the helpKey as symbol or nil ca@1669: " ca@1669: |key| tz@710: ca@1669: key := editModel value. ca@151: ca@1669: key size ~~ 0 ifTrue:[ ca@1669: key := key withoutSeparators. ca@1669: key notEmpty ifTrue:[ ^ key asSymbol ] ca@151: ]. ca@286: ^ nil ca@286: ! ca@286: ca@286: helpKey:aKey ca@1669: "change the helpKey without any change notification (modifiedHolder). ca@1669: " ca@286: |key| ca@1646: ca@1669: self withoutModifyDo:[ ca@1669: aKey size ~~ 0 ifTrue:[ ca@1669: key := aKey withoutSeparators. ca@1669: key isEmpty ifTrue:[ key := nil ] ca@1669: ] ifFalse:[ ca@1669: key := nil ca@1669: ]. ca@1669: editModel value:key. ca@286: ]. ca@1646: self cancel. ca@151: ! ca@151: tz@740: modified cg@2020: "true if any items are added, deleted or modified cg@2020: " cg@2020: classItemList do:[:aClassItem| cg@2020: aClassItem modified ifTrue:[^ true]. cg@2020: ]. cg@2020: ^ false tz@700: ! tz@700: ca@1669: modified:aBoolean ca@1669: "true if any items are added, deleted or modified ca@1646: " ca@1669: classItemList do:[:aClassItem| aClassItem modified:aBoolean ]. ca@1669: ! ca@1669: ca@1669: modifiedHolder ca@1669: "boolean holder which is set to true if the helpKey or contents changed ca@1669: " ca@1669: ^ modifiedHolder tz@700: ! tz@700: ca@286: modifiedHolder:aValueHolder ca@1669: "boolean holder which is set to true if the helpKey or contents changed ca@1669: " ca@286: modifiedHolder notNil ifTrue:[ ca@1669: modifiedHolder removeDependent:self. ca@286: ]. ca@1646: modifiedHolder := aValueHolder. tz@459: ca@1646: modifiedHolder notNil ifTrue:[ ca@1669: modifiedHolder addDependent:self. ca@1669: ]. ca@1604: ! ca@1604: tz@715: specClass ca@1669: "returns the class on which the help tool works on ca@1646: " ca@1646: ^ specClass ca@1646: ! tz@779: ca@1646: specSelector cg@1681: "returns the selector of the edited helpSpec method ca@1646: " cg@1681: ^ specSelector ? #helpSpec cg@354: ! ! cg@354: ca@148: !UIHelpTool methodsFor:'aspects'! ca@148: ca@1669: classItemListHolder ca@1669: "returns the holder which keeps the class items ca@1669: " ca@1669: |holder| ca@1669: ca@1669: holder := builder bindingAt:#classItemListHolder. ca@1669: ca@1669: holder isNil ifTrue:[ ca@1669: holder := nil asValue. ca@1669: holder value:classItemList. ca@1669: builder aspectAt:#classItemListHolder put:holder. ca@1669: ]. ca@1669: ^ holder ca@1669: ! ca@1669: ca@1669: classItemModel ca@1669: "returns the holder which keeps the current selected class ca@1669: " ca@1669: ^ classItemModel ca@1669: ! ca@1669: ca@1646: contentsModifiedChannel ca@1669: "boolean holder, which is set to true if the contents assigned to the ca@1669: helpKey changed ca@1646: " ca@1646: ^ contentsModifiedChannel ca@1646: ! tz@779: ca@1646: editModel ca@1669: "string holder, which keeps the current editing helpKey as string ca@1646: " ca@1669: ^ editModel. ca@1646: ! ca@1646: cg@1989: enablingCommitButtonsHolder cg@1989: "returns the enabling of the commit of this tool as value holder" cg@1989: cg@1989: masterApplication notNil ifTrue:[ cg@1989: ^ masterApplication enablingCommitButtonsHolder cg@1989: ]. cg@1989: ^ contentsModifiedChannel cg@1989: ! cg@1989: ca@1669: helpTextView ca@1669: "the editView which keeps the current help contents assigned to the key ca@1646: " ca@1669: ^ helpTextView ca@148: ! ca@148: cg@1989: infoLabelHolder cg@1989: "returns the info label as value holder" cg@1989: cg@1989: masterApplication notNil ifTrue:[ cg@2037: builder aspectAt:#useAlienInfoLabelHolder put:true. cg@1989: ^ masterApplication infoLabelHolder cg@1989: ]. cg@1989: ^ super infoLabelHolder cg@1989: ! cg@1989: ca@1669: keyItemListHolder ca@1669: "holder, which keeps the current hierarchical list ca@1669: assigned to the selected class item ca@1646: " ca@1669: |holder| ca@1669: ca@1669: holder := builder bindingAt:#keyItemListHolder. ca@1669: ca@1669: holder isNil ifTrue:[ ca@1669: holder := nil asValue. ca@1669: holder value:(classItemList last list). ca@1669: builder aspectAt:#keyItemListHolder put:holder. ca@1669: ]. ca@1669: ^ holder tz@696: ! tz@696: ca@1669: keyItemModel ca@1669: "model which keeps the current selected helpKey or nil ca@1646: " ca@1669: ^ keyItemModel. ca@148: ! ! ca@148: tz@750: !UIHelpTool methodsFor:'building'! tz@750: ca@1663: buildAndMergeFromClass:aClass ca@1669: "setup a new specClass, merge the current items into ca@1669: " ca@1669: |root mergeItems| ca@1663: ca@1669: root := classItemList first. ca@1669: ca@1669: root isUnspecified ifTrue:[ mergeItems := root children ] cg@1973: ifFalse:[ mergeItems := nil ]. ca@1669: cg@1973: self loadFromClass:aClass. ca@1663: ca@1669: mergeItems size ~~ 0 ifTrue:[ cg@1973: root := classItemList first. ca@1669: cg@1973: mergeItems do:[:anItem| |item hkey| cg@1973: hkey := anItem helpKey. cg@1973: item := root detectItemWithKey:hkey. ca@1663: cg@1973: item isNil ifTrue:[ cg@1973: item := KeyItem helpKey:hkey helpText:(anItem helpText). cg@1973: root add:item sortBlock:[:a :b| a label < b label ]. cg@1973: ] ifFalse:[ cg@1973: item helpText:(anItem helpText). cg@1973: ] cg@1973: ] ca@1663: ]. ca@1663: ! ca@1663: cg@1973: loadFromClass:aClass tz@779: "reads the help dictionary from aClass and find remaining classes ca@1669: 'between' aClass and ApplicationModel ca@1669: " cg@1973: |lastContents root list helpSpecSelector| tz@779: cg@1681: helpSpecSelector := self specSelector. ca@1646: specClass := self getHelpSpecClassFromClass:aClass. ca@1646: ca@1669: list := OrderedCollection new. ca@1669: ca@1669: (specClass isClass and:[specClass isLoaded]) ifTrue:[ ca@1670: lastContents := nil. cg@1973: cg@1973: self addHistoryEntryForClass:specClass selector:helpSpecSelector. ca@1669: ca@1670: specClass withAllSuperclasses reverse do:[:aClass| |value name| ca@1670: lastContents isNil ifTrue:[ ca@1670: aClass == ApplicationModel ifTrue:[ ca@1670: lastContents := IdentityDictionary new ca@1670: ]. ca@1670: ] ifFalse:[ ca@1670: root := ClassItem onClass:aClass. ca@1669: cg@1973: (aClass respondsTo: helpSpecSelector) ifTrue:[ cg@1973: value := aClass perform: helpSpecSelector. cg@1973: ]. ca@1669: cg@1973: value notNil ifTrue:[ ca@1670: value keysAndValuesDo:[:k :v| |cval| ca@1670: cval := lastContents at:k ifAbsent:self. ca@1670: cval = v ifFalse:[ root add:(KeyItem helpKey:k helpText:v) ]. ca@1670: ]. ca@1670: lastContents := value. ca@1670: ]. ca@1670: root sort:[:a :b| a label < b label ]. ca@1670: root modified:false. ca@1670: list add:root. ca@1670: ] ca@1670: ] ca@1669: ]. ca@1669: list isEmpty ifTrue:[ ca@1670: list add:(ClassItem onClass:nil) ca@1646: ]. ca@1646: ca@1669: self withoutModifyDo:[ ca@1670: classItemList contents:list. ca@1670: self updateIcons. ca@1670: classItemModel value:(list last) ca@1646: ]. cg@1340: ! cg@1340: cg@1973: loadFromClass:aClass andSelector:aSelector cg@1973: "reads the help dictionary from aClass" cg@1973: cg@1973: self assert:(aClass isNil or:[aClass isClass]). cg@1973: cg@1340: specSelector := aSelector. cg@1973: self loadFromClass:aClass cg@1340: ! cg@1340: cg@1973: loadFromHelpTool:aHelpTool ca@1669: "build from another helpTool ca@1669: " ca@1669: specClass := aHelpTool specClass. ca@1669: specSelector := aHelpTool specSelector. ca@1669: classItemList := aHelpTool classItemListHolder value. ca@1646: ca@1669: self classItemListHolder value:classItemList. ca@1646: ca@1669: classItemModel triggerValue:(classItemList last). ca@1646: ! ! cg@1340: ca@1646: !UIHelpTool methodsFor:'change & update'! ca@1646: ca@1646: editModelChanged ca@1669: "called if the editModel changed ca@1646: " ca@1646: |key| cg@1340: ca@1646: key := self helpKey. ca@1646: ca@1669: modifiedHolder notNil ifTrue:[ cg@1989: modifiedHolder value:true ca@1669: ]. cg@963: ca@1669: contentsModifiedChannel value:false. cg@963: ca@1646: key notNil ifTrue:[ cg@1989: keyItemModel value = key ifTrue:[^ self]. ca@1669: cg@1989: classItemList reverseDo:[:root| |item| cg@1989: item := root detectItemWithKey:key. ca@1646: cg@1989: item notNil ifTrue:[ cg@1989: classItemModel value:root. cg@1989: keyItemModel value:item. cg@1989: ^ self. cg@1989: ]. cg@1989: ]. ca@1669: cg@1989: masterApplication isNil ifTrue:[ cg@1989: "entered a new helpKey cg@1989: " cg@1989: self enablingCommitButtonsHolder value:true. cg@1989: ]. tz@750: ]. ca@1669: keyItemModel value:nil. ca@1646: ! tz@779: ca@1646: update:something with:aParameter from:changedObject ca@1669: "Invoked when an object that I depend upon sends a change notification. ca@1669: " ca@1669: |root item list| tz@722: ca@1669: changedObject == keyItemModel ifTrue:[ ca@1669: item := keyItemModel value. cg@1597: ca@1669: item notNil ifTrue:[ ca@1669: editModel value:(item helpKey). ca@1669: ]. ca@1669: self cancel. ca@1669: ^ self ca@1646: ]. ca@1646: ca@1669: changedObject == classItemModel ifTrue:[ ca@1669: root := classItemModel value. ca@1669: ca@1669: root notNil ifTrue:[ ca@1669: item := root detectItemWithKey:(self helpKey). ca@1669: list := root list. ca@1669: ] ifFalse:[ ca@1669: list := item := nil. ca@1669: ]. ca@1669: ca@1669: item notNil ifTrue:[ ca@1669: keyItemModel value:nil withoutNotifying:self. ca@1669: ]. ca@1669: self keyItemListHolder value:list. ca@1669: keyItemModel value:item. ca@1669: ^ self tz@740: ]. ca@1646: ca@1669: changedObject == editModel ifTrue:[ ca@1669: self editModelChanged. ca@1669: ^ self ca@1669: ]. tz@750: ca@1669: changedObject == contentsModifiedChannel ifTrue:[ ca@1669: modifiedHolder notNil ifTrue:[ ca@1669: modifiedHolder value:true ca@1669: ]. ca@1669: ^ self ca@1669: ]. ca@1669: super update:something with:aParameter from:changedObject ca@1669: ! tz@904: ca@1669: withoutModifyDo:aBlock ca@1669: "discard modifications; trigger not the modifiedHolder during sv@1723: the action is active" sv@1723: ca@1669: |holder| ca@1669: sv@1723: modifiedHolder isNil ifTrue:[ sv@1723: ^ aBlock value sv@1723: ]. ca@1669: holder := modifiedHolder. sv@1723: ^ aBlock ensure:[modifiedHolder := holder] tz@750: ! ! tz@750: ca@286: !UIHelpTool methodsFor:'private'! ca@286: cg@1973: getHelpSpecClassFromClass:aClass cg@1973: |cls| tz@696: cg@1973: aClass isNil ifTrue:[^ nil]. tz@696: cg@1973: cls := self resolveName:aClass. cg@1973: cls isNil ifTrue:[ ^ nil ]. ca@1646: cg@1973: cls := cls perform:#helpSpecClass ifNotUnderstood:cls. cg@1973: cg@1973: (cls isBehavior and:[cls isLoaded]) ifTrue:[ cg@1973: ^ cls tz@696: ]. ca@1669: ^ nil tz@696: ! tz@696: cg@1973: loadFromMessage:classAndSelector ca@1669: "Set and rebuild the specClass and specSelector from a resource string. ca@1669: On success true is returned otherwise false. If the current spec is cg@1973: modified, a dialog is launched." tz@740: cg@1973: self askForModification ifFalse:[ ^ false]. tz@740: cg@1973: classAndSelector notNil ifTrue:[ cg@1973: self loadFromClass:(classAndSelector methodClass) andSelector:(classAndSelector methodSelector). cg@1973: ^ true tz@750: ]. ca@1669: ^ false ca@1670: ! ca@1670: ca@1670: updateIcons ca@1670: "update all icons (redefinitions below above or both) ca@1670: " ca@1670: |iconBelow iconAbove iconAboveAndBelow isBehind redefinedAbove redefinedBelow icon| ca@1670: ca@1670: "/ if only one class exists, its not possible to have redefinitions ca@1670: classItemList size > 1 ifFalse:[ ^ self ]. ca@1670: ca@1670: iconBelow := SystemBrowser medium_methodRedefinedBelowIcon. ca@1670: iconAbove := SystemBrowser medium_methodInheritedFromAboveIcon. ca@1670: iconAboveAndBelow := SystemBrowser medium_methodInheritedFromAboveAndRedefinedBelowIcon. ca@1670: ca@1670: classItemList do:[:runClass| ca@1670: runClass do:[:aKeyItem| ca@1670: isBehind := redefinedBelow := redefinedAbove := false. ca@1670: ca@1670: classItemList do:[:testClass| ca@1670: testClass == runClass ifTrue:[ ca@1670: isBehind := true ca@1670: ] ifFalse:[ ca@1670: (testClass detectItemWithKey:(aKeyItem helpKey)) notNil ifTrue:[ ca@1670: isBehind ifTrue:[ redefinedBelow := true ] ca@1670: ifFalse:[ redefinedAbove := true ]. ca@1670: ] ca@1670: ] ca@1670: ]. ca@1670: ca@1670: redefinedBelow ifTrue:[ ca@1670: redefinedAbove ifTrue:[ icon := iconAboveAndBelow ] ca@1670: ifFalse:[ icon := iconBelow ] ca@1670: ] ifFalse:[ ca@1670: redefinedAbove ifTrue:[ icon := iconAbove ] ca@1670: ifFalse:[ icon := nil ] ca@1670: ]. ca@1670: aKeyItem icon:icon. ca@1670: ] ca@1670: ]. ca@286: ! ! ca@286: ca@1669: !UIHelpTool methodsFor:'startup & release'! ca@369: ca@369: closeRequest sv@1772: "asks for permission before closing" sv@1772: sv@1772: masterApplication isNil ifTrue:[ sv@1772: super closeRequest. ca@1669: ]. tz@740: ! tz@740: cg@2002: commonPostBuild cg@2002: "/ using masters infoHolder ? cg@2002: (builder aspectAt:#useAlienInfoLabelHolder) == true ifTrue:[ cg@2002: (builder componentAt:#mainPanel) layout bottomOffset:0. cg@2002: (builder componentAt:#infoBarSubSpec) beInvisible cg@2002: ] cg@2002: ! cg@2002: tz@740: initialize ca@1669: "setup default attributes ca@1669: " ca@1669: super initialize. ca@1669: self createBuilder. tz@779: ca@1669: specSelector := #helpSpec. ca@1669: ca@1669: classItemList := List new. tz@740: ca@1669: classItemModel := nil asValue. ca@1669: classItemModel addDependent:self. ca@1669: ca@1669: keyItemModel := nil asValue. ca@1669: keyItemModel addDependent:self. ca@1669: ca@1669: contentsModifiedChannel := false asValue. ca@1669: contentsModifiedChannel addDependent:self. ca@1669: ca@1669: helpTextView := EditTextView new. ca@1669: helpTextView acceptAction:[:dummy| self accept ]. ca@1669: helpTextView modifiedChannel:contentsModifiedChannel. ca@1646: ca@1646: editModel := nil asValue. ca@1646: editModel addDependent:self. tz@740: cg@1973: self loadFromClass:nil. tz@750: ! tz@750: tz@750: openOnClass:aClass ca@1669: "opens the UIHelpTool on aClass ca@1669: " cg@1597: self openOnClass:aClass andSelector:nil tz@940: ! tz@940: tz@940: openOnClass:aClass andSelector: aSelector tz@940: "opens the UIHelpTool on aClass and aSelector" tz@940: cg@1982: self openInterface:#windowSpec "ForStandAlone". cg@1597: cg@1973: builder window label:'Help Tool'. cg@1973: self loadFromClass:aClass andSelector:aSelector ca@369: ! ! ca@369: tz@740: !UIHelpTool methodsFor:'user actions'! ca@286: tz@722: accept ca@1669: "accepts the help text ca@1669: " ca@1669: |helpKey helpItem root| tz@779: ca@1669: helpKey := self helpKey. ca@1669: helpKey isNil ifTrue:[^ self]. ca@1646: ca@1669: root := classItemModel value. ca@1669: root isNil ifTrue:[^ self]. ca@1669: ca@1669: helpItem := root detectItemWithKey:helpKey. cg@1648: ca@1669: helpItem isNil ifTrue:[ ca@1670: helpItem := KeyItem helpKey:helpKey helpText:(helpTextView contents). ca@1670: root add:helpItem sortBlock:[:a :b| a label < b label ]. ca@1670: self updateIcons. ca@1669: ] ifFalse:[ ca@1670: helpItem helpText:(helpTextView contents). ca@1646: ]. tz@722: ca@1669: contentsModifiedChannel value:false. ca@1669: keyItemModel triggerValue:helpItem. tz@722: ! tz@722: ca@1646: cancel cg@2069: "cancel modifications, reload helpText" cg@2069: ca@1669: |item contents modified| ca@1646: ca@1669: item := keyItemModel value. ca@1669: modified := false. tz@779: ca@1669: item notNil ifTrue:[ cg@2069: contents := item helpText. ca@1669: ] ifFalse:[ cg@2069: contents := nil. ca@1669: cg@2069: modifiedHolder isNil ifTrue:[ cg@2069: modified := self helpKey notNil cg@2069: ] ca@1646: ]. ca@1669: helpTextView contents:contents. ca@1669: contentsModifiedChannel value:modified. cg@2069: cg@2069: "Modified: / 29-08-2006 / 10:20:37 / cg" tz@722: ! tz@722: tz@750: doDelete ca@1646: "deletes the selected help key ca@1646: " ca@1669: |item| ca@1646: ca@1669: item := keyItemModel value. ca@1670: ca@1670: item notNil ifTrue:[ ca@1670: item remove. ca@1670: item icon notNil ifTrue:[ self updateIcons ]. ca@1670: ]. ca@1669: editModel value:nil. tz@722: ! tz@722: tz@750: doLoad cg@1973: "opens a Resource Selection Browser in order to get a resource message" cg@1973: tz@750: self loadFromMessage: cg@1681: (ResourceSelectionBrowser cg@1681: request: 'Load Help Spec From Class' cg@1681: onSuperclass: nil cg@1681: andClass: specClass cg@1681: andSelector: (self specSelector) cg@1681: withResourceTypes: (Array with: #help)). tz@779: tz@779: self updateInfoLabel tz@750: ! ca@286: tz@750: doNew ca@1669: "reset all to empty ca@1669: " ca@1669: contentsModifiedChannel value:false. ca@1669: self helpKey:nil. cg@1973: self loadFromClass:nil. tz@750: ! tz@750: tz@722: doSave cg@1973: "save the help spec to the spec-class(es)" cg@1973: ca@1669: specClass isNil ifTrue:[ ca@1669: self information:(resources string:'No class specified !!'). ca@1669: ^ nil ca@1669: ]. cg@1777: "/ cg: the following test is rubbish !! cg@1777: "/ (specClass isSubclassOf:ApplicationModel) ifFalse:[ cg@1777: "/ self information:(resources string:'Cannot save help into non-Application class'). cg@1777: "/ ^ nil cg@1777: "/ ]. ca@1669: cg@1681: classItemList do:[:aClassItem| cg@1681: aClassItem createHelpMethodNamed:(self specSelector) cg@1681: ]. ca@1669: ! ca@1669: cg@2020: openDocumentation cg@2020: "opens the documentation file of the Help Tool cg@2020: " cg@2020: self openHTMLDocument: 'tools/uipainter/HelpTool.html' cg@2020: ! ! ca@1669: cg@2020: !UIHelpTool::ClassItem class methodsFor:'instance creation'! cg@2020: cg@2020: onClass:aClass cg@2020: |root| cg@2020: cg@2020: root := self new. cg@2020: root onClass:aClass. cg@2020: ^ root cg@2020: ! ! cg@2020: cg@2020: !UIHelpTool::ClassItem methodsFor:'accessing'! ca@1669: ca@1669: list ca@1669: "returns the hierarchical list assigned to the classItem; the ca@1669: list contains the keyItems ca@1669: " ca@1669: list isNil ifTrue:[ ca@1669: list := HierarchicalList new. ca@1669: list showRoot:false. ca@1669: list root:self. ca@1669: ]. ca@1669: ^ list ca@1669: ! ca@1669: ca@1669: theClass ca@1669: "returns the class or nil if unspecified ca@1669: " ca@1669: ^ theClass ca@1669: ! ! ca@1669: cg@2020: !UIHelpTool::ClassItem methodsFor:'change & update'! ca@1669: ca@1669: helpTextChangedFor:anItem ca@1669: "called if an helpKey changed its contents ca@1669: " ca@1669: self model notNil ifTrue:[ ca@1669: self modified:true. ca@1669: anItem modified:true. ca@1669: ]. ca@1669: ! ! ca@1669: ca@1669: !UIHelpTool::ClassItem methodsFor:'code generation'! ca@1669: ca@1669: createHelpMethodNamed:aMethodName ca@1669: |stream| ca@1669: ca@1669: (modified and:[theClass notNil]) ifFalse:[ ca@1669: ^ self ca@1669: ]. ca@1669: stream := '' writeStream. ca@1669: ca@1669: stream nextPutAll: ca@1669: aMethodName, '\' withCRs, ca@1669: (ResourceSpecEditor codeGenerationCommentForClass:UIHelpTool) withCRs, ca@1669: '\\' withCRs, ca@1669: ' "\' withCRs, ca@1669: ' UIHelpTool openOnClass:', theClass name asString ,' ca@1669: " ca@1669: ca@1669: ca@1669: ca@1669: ^ super ', aMethodName, ' addPairsFrom:#( ca@1669: ca@1669: '. ca@1669: ca@1669: self do:[:aKeyItem| |helpText| ca@1669: helpText := aKeyItem helpText. ca@1669: helpText isNil ifTrue:[ helpText := '' ]. ca@1669: ca@1669: stream nextPutLine:(aKeyItem helpKey storeString). ca@1669: stream nextPutLine:(helpText storeString); cr. ca@1669: ]. ca@1669: stream nextPutLine:')'. ca@1669: ca@1669: Compiler ca@1669: compile:(stream contents) ca@1669: forClass:theClass class ca@1669: inCategory:'help specs'. ca@1669: ca@1669: self modified:false. cg@2020: ! ! ca@1669: cg@2020: !UIHelpTool::ClassItem methodsFor:'displaying'! cg@2020: cg@2020: icon cg@2020: "returns the display icon (always nil) cg@2020: " cg@2020: ^ nil cg@2020: ! cg@2020: cg@2020: label cg@2020: "returns the display label cg@2020: " cg@2020: |label| cg@2020: cg@2020: theClass notNil ifTrue:[ label := theClass name ] cg@2020: ifFalse:[ label := '** not yet defined **' ]. cg@2020: cg@2020: modified ifTrue:[ cg@2020: label := Text string:label color:(Color red). cg@2020: ]. cg@2020: ^ label cg@2020: ! ! cg@2020: cg@2020: !UIHelpTool::ClassItem methodsFor:'instance creation'! ca@1669: ca@1669: initialize ca@1669: "setup defaults ca@1669: " ca@1669: super initialize. ca@1669: ca@1669: children := OrderedCollection new. ca@1669: isExpanded := true. ca@1669: modified := false. ca@1669: ! ca@1669: ca@1669: onClass:aClass ca@1669: "the class the ys are assigned to; if the class is nil, ca@1669: the class is not yet specified. ca@1669: " ca@1669: theClass := aClass. ca@1669: ! ! ca@1669: ca@1669: !UIHelpTool::ClassItem methodsFor:'private'! ca@1669: ca@1669: basicAdd:aChild sortBlock:aBlock ca@1669: "catch low-level add to update the modification flag ca@1669: " ca@1669: self modified:true. ca@1669: aChild modified:true. ca@1669: ca@1669: ^ super basicAdd:aChild sortBlock:aBlock. ca@1669: ! ca@1669: ca@1669: basicAddAll:aList beforeIndex:anIndex ca@1669: "catch low-level add to update the modification flag ca@1669: " ca@1669: self modified:true. ca@1669: cg@2020: aList do:[:el| el modified:true ]. cg@2020: ^ super basicAddAll:aList beforeIndex:anIndex. cg@2020: ! tz@779: ca@1669: basicRemoveFromIndex:startIndex toIndex:stopIndex ca@1669: "catch low-level remove to update the modification flag ca@1669: " ca@1669: self isUnspecified ifFalse:[ ca@1669: self modified:true. ca@1669: ]. ca@1669: ^ super basicRemoveFromIndex:startIndex toIndex:stopIndex ca@1669: ! ! ca@1669: ca@1669: !UIHelpTool::ClassItem methodsFor:'queries'! ca@1669: ca@1669: isUnspecified ca@1669: "true if the class is unspecified ca@1669: " ca@1669: ^ theClass isNil ca@1669: ! ca@1669: ca@1669: modified cg@2020: "true, if any item is modified, created or deleted cg@2020: " cg@2020: ^ modified cg@2020: ! ca@1669: ca@1669: modified:aBoolean ca@1669: "true, if any item is modified, created or deleted ca@1669: " ca@1669: modified ~~ aBoolean ifTrue:[ ca@1669: modified := aBoolean. ca@1669: ca@1669: modified ifFalse:[ ca@1669: self do:[:el| el modified:false ]. ca@1669: ]. ca@1669: ]. ca@1669: ! ! ca@1669: ca@1669: !UIHelpTool::ClassItem methodsFor:'searching'! ca@1669: ca@1669: detectItemWithKey:aKey ca@1669: "returns the item assigned to a helpKey or nil ca@1669: " ca@1669: |key| ca@1669: cg@2037: aKey isEmptyOrNil ifTrue:[ ^ nil ]. cg@2037: key := aKey asSymbol. ca@1669: cg@2037: self do:[:anItem| cg@2037: anItem helpKey == key ifTrue:[ ^ anItem ]. ca@1669: ]. cg@2020: ^ nil ca@1669: ! ! ca@1669: cg@2020: !UIHelpTool::KeyItem class methodsFor:'instance creation'! cg@2020: cg@2020: helpKey:aKey helpText:aText cg@2020: |key| ca@1669: cg@2020: key := self new. cg@2020: key helpKey:aKey helpText:aText. cg@2020: ^ key cg@2020: ! ! ca@1669: cg@2020: !UIHelpTool::KeyItem methodsFor:'accessing'! ca@1669: ca@1669: helpKey ca@1669: "returns the helpKey, a symbol ca@1669: " ca@1669: ^ helpKey ca@1669: ! ca@1669: ca@1669: helpText ca@1669: "returns the contents assigned to the helpKey or nil ca@1669: " ca@1669: ^ helpText ca@1669: ! ca@1669: ca@1669: helpText:aText cg@1681: "set the contents assigned to the helpKey; if the contents changes, ca@1669: a notification is raised. ca@1669: " ca@1669: |text| ca@1669: ca@1669: text := self formatText:aText. ca@1669: ca@1669: text ~= helpText ifTrue:[ cg@1681: helpText := text. ca@1669: cg@1681: (modified or:[parent isNil]) ifFalse:[ cg@1681: parent helpTextChangedFor:self. cg@1681: ] ca@1669: ]. ca@1669: ! ! ca@1669: cg@2020: !UIHelpTool::KeyItem methodsFor:'displaying'! cg@2020: cg@2020: icon cg@2020: "returns the display icon (always nil) cg@2020: " cg@2020: ^ icon ca@1670: ! ca@1670: cg@2020: icon:anIcon cg@2020: cg@2020: icon ~= anIcon ifTrue:[ cg@2020: icon := anIcon. cg@2020: self changed:#icon. cg@2020: ]. cg@2020: ! cg@2020: cg@2020: label cg@2020: "returns the display label cg@2020: " cg@2020: modified ifTrue:[ cg@2020: ^ Text string:helpKey color:(Color red) cg@2020: ]. cg@2020: ^ helpKey cg@2020: ! ! cg@2020: cg@2020: !UIHelpTool::KeyItem methodsFor:'instance creation'! cg@2020: ca@1669: helpKey:aKey helpText:aText ca@1669: "set the key and contents without a change notification ca@1669: " ca@1669: helpKey := aKey asSymbol. ca@1669: helpText := self formatText:aText. ca@1669: ! ca@1669: ca@1669: initialize ca@1669: "setup defaults ca@1669: " ca@1669: super initialize. ca@1669: children := #(). ca@1669: modified := false. ca@1669: ! ! ca@1669: ca@1669: !UIHelpTool::KeyItem methodsFor:'private'! ca@1669: ca@1669: formatText:aText ca@1669: "format the text, replace carriage return by spaces and compress spaces ca@1669: " ca@1669: |text result| ca@1669: ca@1669: aText size ~~ 0 ifTrue:[ ca@1669: text := aText asString asCollectionOfWords. ca@1669: ca@1669: text notEmpty ifTrue:[ ca@1669: result := text first. ca@1669: ca@1669: text from:2 do:[:t| result := result, ' ', t ]. cg@2020: ^ result cg@2020: ]. cg@2020: ]. cg@2020: ^ nil cg@2020: ! ! cg@2020: cg@2020: !UIHelpTool::KeyItem methodsFor:'queries'! cg@2020: cg@2020: modified cg@2020: "returns true if the helpText is modified cg@2020: " cg@2020: ^ modified cg@2020: ! ca@1669: ca@1669: modified:aBoolean ca@1669: "set the modification flag ca@1669: " ca@1669: aBoolean == modified ifFalse:[ ca@1669: modified := aBoolean. ca@1669: self changed:#redraw. ca@1669: ]. ca@148: ! ! ca@148: ca@148: !UIHelpTool class methodsFor:'documentation'! ca@148: ca@148: version ca@148: ^ '$Header$' cg@2665: ! cg@2665: cg@2665: version_CVS cg@2665: ^ '$Header$' ca@148: ! !