UIHelpTool.st
author Claus Gittinger <cg@exept.de>
Tue, 14 May 2019 09:46:21 +0200
changeset 3663 9d49ecf8661a
parent 3560 8e0d01180c6e
permissions -rw-r--r--
#UI_ENHANCEMENT by cg
class: TabListEditor class
changed:
#canvasSpec
#menu
#windowSpec
     1 "{ Encoding: utf8 }"
     2 
     3 "
     4  COPYRIGHT (c) 1995 by eXept Software AG
     5 	      All Rights Reserved
     6 
     7  This software is furnished under a license and may be used
     8  only in accordance with the terms of that license and with the
     9  inclusion of the above copyright notice.   This software may not
    10  be provided or otherwise made available to, or used by, any
    11  other person.  No title to or ownership of the software is
    12  hereby transferred.
    13 "
    14 "{ Package: 'stx:libtool2' }"
    15 
    16 "{ NameSpace: Smalltalk }"
    17 
    18 ResourceSpecEditor subclass:#UIHelpTool
    19 	instanceVariableNames:'classItemList classItemModel keyItemModel helpTextView
    20 		modifiedHolder contentsModifiedChannel editModel'
    21 	classVariableNames:''
    22 	poolDictionaries:''
    23 	category:'Interface-UIPainter'
    24 !
    25 
    26 HierarchicalItem subclass:#ClassItem
    27 	instanceVariableNames:'theClass list modified'
    28 	classVariableNames:''
    29 	poolDictionaries:''
    30 	privateIn:UIHelpTool
    31 !
    32 
    33 HierarchicalItem subclass:#KeyItem
    34 	instanceVariableNames:'helpKey helpText flyByText modified icon'
    35 	classVariableNames:''
    36 	poolDictionaries:''
    37 	privateIn:UIHelpTool
    38 !
    39 
    40 !UIHelpTool class methodsFor:'documentation'!
    41 
    42 copyright
    43 "
    44  COPYRIGHT (c) 1995 by eXept Software AG
    45 	      All Rights Reserved
    46 
    47  This software is furnished under a license and may be used
    48  only in accordance with the terms of that license and with the
    49  inclusion of the above copyright notice.   This software may not
    50  be provided or otherwise made available to, or used by, any
    51  other person.  No title to or ownership of the software is
    52  hereby transferred.
    53 "
    54 !
    55 
    56 documentation
    57 "
    58     The Help Tool allows you to define help dictionaries for the widgets in
    59     window applications. The tool are able to run stand alone or in other master 
    60     applications like the GUI Painter and the Menu Editor.
    61     If the application responds to the selector #showHelp:aHelpText for:aView,
    62     this selector is called by the widget's view when the mouse cursor moves over. 
    63     If the application does not responds to that selector, and the activeHelp mode
    64     is enabled, an active help bubble is shown at the widget's view.
    65 
    66     [instance variables:]
    67 	specClass       <Symbol>        class implementing the help spec
    68 	specSelector    <Symbol>        selector returning the help spec
    69 	classItemList                   the list of classItems
    70 	classItemModel                  keeps the selected class
    71 	keyItemModel                    keeps the selected helpKey
    72 	modifiedHolder  <ValueHolder>   true if the editField or contents changed
    73 	editModel                       keeps the current helpKey
    74 	helpTextView                    the view which shows the helpText
    75 	contentsModifiedChannel         true if the helpText is modified
    76 
    77     [author:]
    78 	Claus Atzkern, eXept Software AG
    79 	Thomas Zwick,  eXept Software AG
    80 "
    81 ! !
    82 
    83 !UIHelpTool class methodsFor:'instance creation'!
    84 
    85 open
    86     ^ self openOnClass:nil.
    87 !
    88 
    89 openOnClass:aClass
    90     "opens a Help Tool on aClass
    91     "
    92     ^ self openOnClass:aClass andSelector:#helpSpec
    93 ! !
    94 
    95 !UIHelpTool class methodsFor:'constants'!
    96 
    97 label
    98     "returns the label; used if embedded as sub canvas in the GUI Painter or Menu Editor
    99     "
   100     ^'Help'
   101 ! !
   102 
   103 !UIHelpTool class methodsFor:'defaults'!
   104 
   105 resourceType
   106     "get the type of the resource of the method generated by the UIHelpTool"
   107 
   108     ^ #help
   109 ! !
   110 
   111 !UIHelpTool class methodsFor:'help specs'!
   112 
   113 helpSpec
   114     "This resource specification was automatically generated
   115      by the UIHelpTool of ST/X."
   116 
   117     "Do not manually edit this!! If it is corrupted,
   118      the UIHelpTool may not be able to read the specification."
   119 
   120     "
   121      UIHelpTool openOnClass:UIHelpTool    
   122     "
   123 
   124     <resource: #help>
   125 
   126     ^ super helpSpec addPairsFrom:#(
   127 
   128 #addHelpTextKey
   129 'Adds the key to the help spec.'
   130 
   131 #currentHelpTexts
   132 'Selected help text key.'
   133 
   134 #deleteHelpTextKey
   135 'Deletes the key from the help spec.'
   136 
   137 #fileLoad
   138 'Opens a dialog for selecting and loading a help spec from a class.'
   139 
   140 #fileSave
   141 'Saves the current help spec.'
   142 
   143 #fileUpdate
   144 'Reload the help spec.'
   145 
   146 #helpTextView
   147 'Shows the help text. Menu action ''Accept'' commits changes'
   148 
   149 #listOfClasses
   150 'Classes where help specs can be/are implemented.'
   151 
   152 #listOfHelpTexts
   153 'List of help text keys.'
   154 
   155 #removeHelpTextKey
   156 'Removes the help message from the widget.'
   157 
   158 #updateHelpTextKey
   159 'Refetch the help spec.'
   160 
   161 )
   162 ! !
   163 
   164 !UIHelpTool class methodsFor:'interface specs'!
   165 
   166 innerSpec
   167     "This resource specification was automatically generated
   168      by the UIPainter of ST/X."
   169 
   170     "Do not manually edit this!! If it is corrupted,
   171      the UIPainter may not be able to read the specification."
   172 
   173     "
   174      UIPainter new openOnClass:UIHelpTool andSelector:#innerSpec
   175      UIHelpTool new openInterface:#innerSpec
   176     "
   177 
   178     <resource: #canvas>
   179 
   180     ^ 
   181      #(FullSpec
   182         name: innerSpec
   183         window: 
   184        (WindowSpec
   185           label: 'UIHelpTool'
   186           name: 'UIHelpTool'
   187           min: (Point 10 10)
   188           bounds: (Rectangle 0 0 461 293)
   189         )
   190         component: 
   191        (SpecCollection
   192           collection: (
   193            (VariableVerticalPanelSpec
   194               name: 'PanelVrt'
   195               layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
   196               component: 
   197              (SpecCollection
   198                 collection: (
   199                  (VariableHorizontalPanelSpec
   200                     name: 'PanelHrz'
   201                     component: 
   202                    (SpecCollection
   203                       collection: (
   204                        (HierarchicalListViewSpec
   205                           name: 'keyItemModel'
   206                           model: keyItemModel
   207                           menu: keyItemMenu
   208                           hasHorizontalScrollBar: true
   209                           hasVerticalScrollBar: true
   210                           miniScrollerHorizontal: true
   211                           miniScrollerVertical: false
   212                           listModel: keyItemListHolder
   213                           useIndex: false
   214                           highlightMode: label
   215                           showLines: false
   216                           showIndicators: false
   217                           showLeftIndicators: false
   218                           useDefaultIcons: false
   219                           autoScrollHorizontal: false
   220                         )
   221                        (ViewSpec
   222                           name: 'classItemList'
   223                           component: 
   224                          (SpecCollection
   225                             collection: (
   226                              (InputFieldSpec
   227                                 name: 'editModel'
   228                                 layout: (LayoutFrame 0 0.0 2 0 -1 1.0 25 0)
   229                                 activeHelpKey: currentHelpTexts
   230                                 model: editModel
   231                                 immediateAccept: true
   232                                 acceptOnReturn: false
   233                                 acceptOnTab: false
   234                                 acceptOnLostFocus: false
   235                                 acceptOnPointerLeave: false
   236                               )
   237                              (SelectionInListModelViewSpec
   238                                 name: 'classItemModel'
   239                                 layout: (LayoutFrame 0 0.0 27 0.0 0 1.0 0 1.0)
   240                                 model: classItemModel
   241                                 hasHorizontalScrollBar: true
   242                                 hasVerticalScrollBar: true
   243                                 miniScrollerHorizontal: true
   244                                 miniScrollerVertical: true
   245                                 autoHideScrollBars: false
   246                                 listModel: classItemListHolder
   247                                 useIndex: false
   248                                 highlightMode: label
   249                               )
   250                              )
   251                            
   252                           )
   253                         )
   254                        )
   255                      
   256                     )
   257                     handles: (Any 0.607375 1.0)
   258                   )
   259                  (ArbitraryComponentSpec
   260                     name: 'helpTextView'
   261                     hasHorizontalScrollBar: true
   262                     hasVerticalScrollBar: true
   263                     miniScrollerHorizontal: true
   264                     miniScrollerVertical: true
   265                     hasBorder: false
   266                     component: helpTextView
   267                   )
   268                  )
   269                
   270               )
   271               handles: (Any 0.679181 1.0)
   272             )
   273            )
   274          
   275         )
   276       )
   277 !
   278 
   279 windowSpec
   280     "This resource specification was automatically generated
   281      by the UIPainter of ST/X."
   282 
   283     "Do not manually edit this!! If it is corrupted,
   284      the UIPainter may not be able to read the specification."
   285 
   286     "
   287      UIPainter new openOnClass:UIHelpTool andSelector:#windowSpec
   288      UIHelpTool new openInterface:#windowSpec
   289      UIHelpTool open
   290     "
   291 
   292     <resource: #canvas>
   293 
   294     ^ 
   295     #(FullSpec
   296        name: windowSpec
   297        window: 
   298       (WindowSpec
   299          label: 'Help Tool'
   300          name: 'Help Tool'
   301          min: (Point 300 300)
   302          bounds: (Rectangle 0 0 498 429)
   303          menu: menu
   304        )
   305        component: 
   306       (SpecCollection
   307          collection: (
   308           (ViewSpec
   309              name: 'mainPanel'
   310              layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 -24 1.0)
   311              component: 
   312             (SpecCollection
   313                collection: (
   314                 (UISubSpecification
   315                    name: 'innerSpec'
   316                    layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 -24 1.0)
   317                    minorKey: innerSpec
   318                  )
   319                 (UISubSpecification
   320                    name: 'windowSpecForCommit'
   321                    layout: (LayoutFrame 0 0.0 -30 1.0 0 1.0 0 1.0)
   322                    majorKey: ToolApplicationModel
   323                    minorKey: windowSpecForCommit
   324                  )
   325                 )
   326               
   327              )
   328            )
   329           (UISubSpecification
   330              name: 'infoBarSubSpec'
   331              layout: (LayoutFrame 0 0 -24 1 0 1 0 1)
   332              majorKey: ToolApplicationModel
   333              minorKey: windowSpecForInfoBar
   334            )
   335           )
   336         
   337        )
   338      )
   339 ! !
   340 
   341 !UIHelpTool class methodsFor:'menu specs'!
   342 
   343 helpTextMenu
   344     "This resource specification was automatically generated
   345      by the MenuEditor of ST/X."
   346 
   347     "Do not manually edit this!! If it is corrupted,
   348      the MenuEditor may not be able to read the specification."
   349 
   350 
   351     "
   352      MenuEditor new openOnClass:UIHelpTool andSelector:#helpTextMenu
   353      (Menu new fromLiteralArrayEncoding:(UIHelpTool helpTextMenu)) startUp
   354     "
   355 
   356     <resource: #menu>
   357 
   358     ^ 
   359      #(Menu
   360         (
   361          (MenuItem
   362             activeHelpKey: commitOK
   363             enabled: contentsModifiedChannel
   364             label: 'Accept'
   365             itemValue: accept
   366           )
   367          (MenuItem
   368             activeHelpKey: commitCancel
   369             enabled: contentsModifiedChannel
   370             label: 'Cancel'
   371             itemValue: cancel
   372           )
   373          )
   374         nil
   375         nil
   376       )
   377 !
   378 
   379 keyItemMenu
   380     "This resource specification was automatically generated
   381      by the MenuEditor of ST/X."
   382 
   383     "Do not manually edit this!! If it is corrupted,
   384      the MenuEditor may not be able to read the specification."
   385 
   386 
   387     "
   388      MenuEditor new openOnClass:UIHelpTool andSelector:#keyItemMenu
   389      (Menu new fromLiteralArrayEncoding:(UIHelpTool keyItemMenu)) startUp
   390     "
   391 
   392     <resource: #menu>
   393 
   394     ^ 
   395      #(Menu
   396         (
   397          (MenuItem
   398             activeHelpKey: deleteHelpTextKey
   399             enabled: hasKeyItemSelectedHolder
   400             label: 'Delete Key'
   401             itemValue: doDelete
   402           )
   403          (MenuItem
   404             label: '-'
   405           )
   406          (MenuItem
   407             activeHelpKey: extractHelpTextKeys
   408             label: 'Extract used Keys from Application'
   409             itemValue: doExtractUsedKeys
   410             enabled: hasSpecClassDefined
   411           )
   412          )
   413         nil
   414         nil
   415       )
   416 
   417     "Modified: / 24-05-2018 / 15:52:24 / Claus Gittinger"
   418 !
   419 
   420 listOfKeysMenu
   421     "This resource specification was automatically generated
   422      by the MenuEditor of ST/X."
   423 
   424     "Do not manually edit this!! If it is corrupted,
   425      the MenuEditor may not be able to read the specification."
   426 
   427 
   428     "
   429      MenuEditor new openOnClass:UIHelpTool andSelector:#listOfKeysMenu
   430      (Menu new fromLiteralArrayEncoding:(UIHelpTool listOfKeysMenu)) startUp
   431     "
   432 
   433     <resource: #menu>
   434 
   435     ^ 
   436      #(Menu
   437         (
   438          (MenuItem
   439             activeHelpKey: deleteHelpTextKey
   440             label: 'Delete'
   441             itemValue: doDelete
   442           )
   443          )
   444         nil
   445         nil
   446       )
   447 !
   448 
   449 menu
   450     "This resource specification was automatically generated
   451      by the MenuEditor of ST/X."
   452 
   453     "Do not manually edit this!! If it is corrupted,
   454      the MenuEditor may not be able to read the specification."
   455 
   456     "
   457      MenuEditor new openOnClass:UIHelpTool andSelector:#menu
   458      (Menu new fromLiteralArrayEncoding:(UIHelpTool menu)) startUp
   459     "
   460 
   461     <resource: #menu>
   462 
   463     ^ 
   464      #(Menu
   465         (
   466          (MenuItem
   467             label: 'File'
   468             translateLabel: true
   469             submenu: 
   470            (Menu
   471               (
   472                (MenuItem
   473                   label: 'New'
   474                   itemValue: doNew
   475                   translateLabel: true
   476                 )
   477                (MenuItem
   478                   label: '-'
   479                 )
   480                (MenuItem
   481                   activeHelpKey: fileLoad
   482                   label: 'Load...'
   483                   itemValue: doLoad
   484                   translateLabel: true
   485                 )
   486                (MenuItem
   487                   activeHelpKey: fileSave
   488                   label: 'Save'
   489                   itemValue: doSave
   490                   translateLabel: true
   491                 )
   492                (MenuItem
   493                   label: '-'
   494                   isVisible: isStandAlone
   495                 )
   496                (MenuItem
   497                   activeHelpKey: fileExit
   498                   label: 'Exit'
   499                   itemValue: closeRequest
   500                   translateLabel: true
   501                   isVisible: isStandAlone
   502                 )
   503                )
   504               nil
   505               nil
   506             )
   507           )
   508          (MenuItem
   509             label: 'Edit'
   510             translateLabel: true
   511             submenuChannel: keyItemMenu
   512             keepLinkedMenu: true
   513           )
   514          (MenuItem
   515             label: 'History'
   516             translateLabel: true
   517             isVisible: isStandAlone
   518             submenuChannel: menuHistory
   519           )
   520          (MenuItem
   521             label: 'MENU_Help'
   522             translateLabel: true
   523             startGroup: conditionalRight
   524             submenuChannel: menuHelp
   525           )
   526          )
   527         nil
   528         nil
   529       )
   530 ! !
   531 
   532 !UIHelpTool methodsFor:'accessing'!
   533 
   534 alternativeSpecSelectors
   535     "returns a set of alternative spec method selectors of the resource spec"
   536 
   537     ^ #( helpPairs helpSpec "flyByHelpSpec" tooltipSpec )
   538 
   539     "Modified: / 03-02-2017 / 13:05:02 / cg"
   540 !
   541 
   542 helpKey
   543     "returns the helpKey (symbol) or nil
   544     "
   545     |key|
   546 
   547     key := editModel value.
   548 
   549     key size ~~ 0 ifTrue:[
   550         key := key withoutSeparators.
   551         key notEmpty ifTrue:[ ^ key asSymbol ]
   552     ].
   553     ^ nil
   554 !
   555 
   556 helpKey:aKey
   557     "change the helpKey without any change notification (modifiedHolder).
   558     "
   559     |key|
   560 
   561     self withoutModifyDo:[
   562         aKey size ~~ 0 ifTrue:[
   563             key := aKey withoutSeparators asNilIfEmpty.
   564         ] ifFalse:[
   565             key := nil
   566         ].
   567         editModel value:key.
   568     ].
   569     self cancel.
   570 !
   571 
   572 modified
   573     "true if any items are added, deleted or modified
   574     "
   575     classItemList do:[:aClassItem|
   576 	aClassItem modified ifTrue:[^ true].
   577     ].
   578     ^ false
   579 !
   580 
   581 modified:aBoolean
   582     "true if any items are added, deleted or modified
   583     "
   584     classItemList do:[:aClassItem| aClassItem modified:aBoolean ].
   585 !
   586 
   587 modifiedHolder
   588     "boolean holder which is set to true if the helpKey or contents changed
   589     "
   590     ^ modifiedHolder
   591 !
   592 
   593 modifiedHolder:aValueHolder
   594     "boolean holder which is set to true if the helpKey or contents changed
   595     "
   596     modifiedHolder notNil ifTrue:[
   597 	modifiedHolder removeDependent:self. 
   598     ].
   599     modifiedHolder := aValueHolder.
   600 
   601     modifiedHolder notNil ifTrue:[
   602 	modifiedHolder addDependent:self.
   603     ].
   604 !
   605 
   606 specClass
   607     "returns the class on which the help tool works on
   608     "
   609     ^ specClass
   610 !
   611 
   612 specSelector
   613     "returns the selector of the edited helpSpec method
   614     "
   615     ^ specSelector ? #helpSpec
   616 ! !
   617 
   618 !UIHelpTool methodsFor:'aspects'!
   619 
   620 classItemListHolder
   621     "returns the holder which keeps the class items
   622     "
   623     |holder|
   624 
   625     holder := builder bindingAt:#classItemListHolder.
   626 
   627     holder isNil ifTrue:[
   628 	holder := nil asValue.
   629 	holder value:classItemList.
   630 	builder aspectAt:#classItemListHolder put:holder.
   631     ].
   632     ^ holder
   633 !
   634 
   635 classItemModel
   636     "returns the holder which keeps the current selected class
   637     "
   638     ^ classItemModel
   639 !
   640 
   641 contentsModifiedChannel
   642     "boolean holder, which is set to true if the contents assigned to the
   643      helpKey changed
   644     "
   645     ^ contentsModifiedChannel
   646 !
   647 
   648 editModel
   649     "string holder, which keeps the current editing helpKey as string
   650     "
   651     ^ editModel.
   652 !
   653 
   654 enablingCommitButtonsHolder
   655     "returns the enabling of the commit of this tool as value holder"
   656 
   657     masterApplication notNil ifTrue:[
   658         ^ masterApplication enablingCommitButtonsHolder
   659     ].
   660     ^ contentsModifiedChannel
   661 !
   662 
   663 hasKeyItemSelectedHolder
   664     ^ BlockValue 
   665         with:[:m | m notNil]
   666         argument:self keyItemModel
   667 
   668     "Created: / 24-05-2018 / 15:48:51 / Claus Gittinger"
   669 !
   670 
   671 hasSpecClassDefined
   672     ^ [ specClass notNil ]
   673 
   674     "Created: / 24-05-2018 / 15:52:09 / Claus Gittinger"
   675 !
   676 
   677 helpTextView
   678     "the editView which shows the current help contents assigned to the key
   679     "
   680     ^ helpTextView
   681 !
   682 
   683 infoLabelHolder
   684     "returns the info label as value holder"
   685 
   686     masterApplication notNil ifTrue:[
   687         builder aspectAt:#useAlienInfoLabel put:true.
   688         ^ masterApplication infoLabelHolder
   689     ].
   690     ^ super infoLabelHolder
   691 !
   692 
   693 keyItemListHolder
   694     "holder, which keeps the current hierarchical list
   695      assigned to the selected class item
   696     "
   697     |holder|
   698 
   699     holder := builder bindingAt:#keyItemListHolder.
   700 
   701     holder isNil ifTrue:[
   702 	holder := nil asValue.
   703 	holder value:(classItemList last list).
   704 	builder aspectAt:#keyItemListHolder put:holder.
   705     ].
   706     ^ holder
   707 !
   708 
   709 keyItemModel
   710     "model which keeps the current selected helpKey or nil
   711     "
   712     ^ keyItemModel.
   713 ! !
   714 
   715 !UIHelpTool methodsFor:'building'!
   716 
   717 buildAndMergeFromClass:aClassOrClassName
   718      "setup a new specClass, merge the current items into
   719      "
   720      |root mergeItems aClass|
   721 
   722      (aClass := aClassOrClassName) isBehavior ifFalse:[
   723          aClass := Smalltalk classNamed:aClassOrClassName
   724      ].
   725      
   726      root := classItemList first.
   727 
   728      root isUnspecified ifTrue:[ mergeItems := root children ]
   729                        ifFalse:[ mergeItems := nil ].
   730 
   731      self loadFromClass:aClass.
   732 
   733      mergeItems size ~~ 0 ifTrue:[
   734         root := classItemList first.
   735 
   736         mergeItems do:[:anItem| |item hkey|
   737             hkey := anItem helpKey.
   738             item := root detectItemWithKey:hkey.
   739 
   740             item isNil ifTrue:[
   741                 item := KeyItem helpKey:hkey helpText:(anItem helpText).
   742                 root add:item sortBlock:[:a :b| a label < b label ].
   743             ] ifFalse:[
   744                 item helpText:(anItem helpText).
   745             ]
   746         ]
   747     ].
   748 
   749     "Modified: / 01-11-2017 / 21:23:22 / cg"
   750 !
   751 
   752 loadFromClass:aClass
   753     "reads the help dictionary from aClass and find remaining classes 
   754      'between' aClass and ApplicationModel
   755     " 
   756     |lastContents root list helpSpecSelector alternativeSelector|
   757 
   758     (specClass notNil and:[specClass == aClass]) ifTrue:[
   759         ^ self.
   760     ].
   761 
   762     helpSpecSelector := self specSelector.
   763     specClass := self getHelpSpecClassFromClass:aClass.
   764 
   765     aClass notNil ifTrue:[
   766         ((aClass theMetaclass implements:helpSpecSelector)
   767         and:[(aClass theMetaclass compiledMethodAt:helpSpecSelector) hasResource:#help]) ifFalse:[
   768             alternativeSelector := (self alternativeSpecSelectors ? #()) 
   769                                         detect:[:sel | 
   770                                             (aClass theMetaclass implements:sel)
   771                                             and:[(aClass theMetaclass compiledMethodAt:sel) hasResource:#help]
   772                                         ] 
   773                                         ifNone:nil.
   774             alternativeSelector notNil ifTrue:[
   775                 helpSpecSelector := specSelector := alternativeSelector.
   776                 specClass := aClass.
   777             ].
   778         ].
   779     ].
   780     
   781     list := OrderedCollection new.
   782 
   783     (specClass isClass and:[specClass isLoaded]) ifTrue:[
   784         lastContents := nil.
   785 
   786         self addHistoryEntryForClass:specClass selector:helpSpecSelector.
   787 
   788         specClass withAllSuperclasses reverseDo:[:aClass| |value name|
   789             lastContents isNil ifTrue:[
   790                 aClass == ApplicationModel ifTrue:[ 
   791                     lastContents := IdentityDictionary new
   792                 ].
   793             ] ifFalse:[
   794                 root := ClassItem onClass:aClass.
   795 
   796                 (aClass respondsTo: helpSpecSelector) ifTrue:[ 
   797                     value := aClass perform: helpSpecSelector.
   798                 ].
   799 
   800                 value notNil ifTrue:[
   801                     (value isDictionary) ifTrue:[
   802                         value keysAndValuesDo:[:k :v| |cval|
   803                             cval := lastContents at:k ifAbsent:self.
   804                             cval = v ifFalse:[ root add:(KeyItem helpKey:k helpText:v) ].
   805                         ].
   806                         lastContents := value.
   807                     ] ifFalse:[
   808                         |dict|
   809                         dict := Dictionary new.
   810                         value pairWiseDo:[:k :v| |cval|
   811                             cval := lastContents at:k ifAbsent:self.
   812                             cval = v ifFalse:[ root add:(KeyItem helpKey:k helpText:v) ].
   813                             dict at:k put:v.
   814                         ].
   815                         lastContents := dict.
   816                     ].
   817                 ].
   818                 root sort:[:a :b| a label < b label ].
   819                 root modified:false.
   820                 list add:root.
   821             ]
   822         ]
   823     ].
   824     list isEmpty ifTrue:[
   825         list add:(ClassItem onClass:nil)
   826     ].
   827 
   828     self withoutModifyDo:[
   829         classItemList contents:list.
   830         self updateIcons.
   831         classItemModel value:(list last)
   832     ].
   833 
   834     "Modified: / 13-02-2017 / 17:47:02 / cg"
   835 !
   836 
   837 loadFromClass:aClass andSelector:aSelector
   838     "reads the help dictionary from aClass"
   839 
   840     self assert:(aClass isNil or:[aClass isClass]).
   841 
   842     specSelector := aSelector.
   843     self loadFromClass:aClass
   844 !
   845 
   846 loadFromHelpTool:aHelpTool
   847     "build from another helpTool
   848     "
   849     specClass     := aHelpTool specClass.
   850     specSelector  := aHelpTool specSelector.
   851     classItemList := aHelpTool classItemListHolder value.
   852 
   853     self classItemListHolder value:classItemList.
   854 
   855     classItemModel triggerValue:(classItemList last).
   856 ! !
   857 
   858 !UIHelpTool methodsFor:'change & update'!
   859 
   860 editModelChanged
   861     "called if the editModel changed
   862      cg: so does anyone think, that a comment like the above is useful?
   863      this is called when the text in the edit field (which selects the current key)
   864      is changed."
   865      
   866     |key|
   867 
   868     key := self helpKey.
   869 
   870     modifiedHolder notNil ifTrue:[
   871         modifiedHolder value:true
   872     ].
   873 
   874     contentsModifiedChannel value:false.
   875 
   876     key notNil ifTrue:[
   877         keyItemModel value = key ifTrue:[^ self].
   878 
   879         classItemList reverseDo:[:root| |item|
   880             item := root detectItemWithKey:key.
   881 
   882             item notNil ifTrue:[
   883                 classItemModel value:root.
   884                 keyItemModel   value:item.
   885                 ^ self.
   886             ].
   887         ].
   888 
   889         masterApplication isNil ifTrue:[
   890             "entered a new helpKey
   891             "
   892             self enablingCommitButtonsHolder value:true.
   893         ].
   894     ].
   895     keyItemModel value:nil.
   896 
   897     "Modified (comment): / 24-05-2018 / 16:17:16 / Claus Gittinger"
   898 !
   899 
   900 update:something with:aParameter from:changedObject
   901     "Invoked when an object that I depend upon sends a change notification.
   902     "
   903     |root item list|
   904 
   905     changedObject == keyItemModel ifTrue:[
   906 	item := keyItemModel value.
   907 
   908 	item notNil ifTrue:[
   909 	    editModel value:(item helpKey).
   910 	].
   911 	self cancel.
   912 	^ self
   913     ].
   914 
   915     changedObject == classItemModel ifTrue:[
   916 	root := classItemModel value.
   917 
   918 	root notNil ifTrue:[
   919 	    item := root detectItemWithKey:(self helpKey).
   920 	    list := root list.
   921 	] ifFalse:[
   922 	    list := item := nil.
   923 	].
   924 
   925 	item notNil ifTrue:[
   926 	    keyItemModel value:nil withoutNotifying:self.
   927 	].
   928 	self keyItemListHolder value:list.
   929 	keyItemModel value:item.
   930 	^ self
   931     ].
   932 
   933     changedObject == editModel ifTrue:[
   934 	self editModelChanged.
   935 	^ self
   936     ].
   937 
   938     changedObject == contentsModifiedChannel ifTrue:[
   939 	modifiedHolder notNil ifTrue:[
   940 	    modifiedHolder value:true
   941 	].
   942 	^ self
   943     ].
   944     super update:something with:aParameter from:changedObject
   945 !
   946 
   947 withoutModifyDo:aBlock
   948     "discard modifications; trigger not the modifiedHolder during
   949      the action is active"
   950 
   951     |holder|
   952 
   953     modifiedHolder isNil ifTrue:[
   954         ^ aBlock value
   955     ].
   956     holder := modifiedHolder.
   957     ^ aBlock ensure:[modifiedHolder := holder]
   958 ! !
   959 
   960 !UIHelpTool methodsFor:'private'!
   961 
   962 getHelpSpecClassFromClass:aClass
   963     |cls|
   964 
   965     aClass isNil ifTrue:[^ nil].
   966 
   967     cls := self resolveName:aClass.
   968     cls isNil ifTrue:[ ^ nil ].
   969 
   970     cls := cls perform:#helpSpecClass ifNotUnderstood:cls.
   971 
   972     (cls isBehavior and:[cls isLoaded]) ifTrue:[
   973         ^ cls
   974     ].
   975     ^ nil
   976 !
   977 
   978 loadFromMessage:classAndSelector
   979     "Set and rebuild the specClass and specSelector from a resource string.
   980      On success true is returned otherwise false. If the current spec is
   981      modified, a dialog is launched."
   982 
   983     self askForModification ifFalse:[ ^ false].
   984 
   985     classAndSelector notNil ifTrue:[
   986         self loadFromClass:(classAndSelector methodClass) andSelector:(classAndSelector methodSelector).
   987         ^ true
   988     ].
   989     ^ false
   990 !
   991 
   992 updateIcons
   993     "update all icons (redefinitions below above or both)
   994     "
   995     |iconBelow iconAbove iconAboveAndBelow isBehind redefinedAbove redefinedBelow icon|
   996 
   997     "/ if only one class exists, its not possible to have redefinitions
   998     classItemList size > 1 ifFalse:[ ^ self ].
   999 
  1000     iconBelow         := SystemBrowser medium_methodRedefinedBelowIcon.
  1001     iconAbove         := SystemBrowser medium_methodInheritedFromAboveIcon.
  1002     iconAboveAndBelow := SystemBrowser medium_methodInheritedFromAboveAndRedefinedBelowIcon.
  1003 
  1004     classItemList do:[:runClass|
  1005         runClass do:[:aKeyItem|
  1006             isBehind := redefinedBelow := redefinedAbove := false.
  1007 
  1008             classItemList do:[:testClass|
  1009                 testClass == runClass ifTrue:[
  1010                     isBehind := true
  1011                 ] ifFalse:[
  1012                     (testClass detectItemWithKey:(aKeyItem helpKey)) notNil ifTrue:[
  1013                         isBehind ifTrue:[ redefinedBelow := true ]
  1014                                 ifFalse:[ redefinedAbove := true ].
  1015                     ]
  1016                 ]
  1017             ].
  1018 
  1019             redefinedBelow ifTrue:[
  1020                 redefinedAbove ifTrue:[ icon := iconAboveAndBelow ]
  1021                               ifFalse:[ icon := iconBelow ]
  1022             ] ifFalse:[
  1023                 redefinedAbove ifTrue:[ icon := iconAbove ]
  1024                               ifFalse:[ icon := nil ]
  1025             ].
  1026             aKeyItem icon:icon.
  1027         ]
  1028     ].
  1029 ! !
  1030 
  1031 !UIHelpTool methodsFor:'startup & release'!
  1032 
  1033 closeRequest
  1034     "asks for permission before closing"
  1035 
  1036     masterApplication isNil ifTrue:[
  1037         super closeRequest.
  1038     ].
  1039 !
  1040 
  1041 commonPostBuild
  1042     "/ using masters infoHolder ?
  1043     self useAlienInfoLabel ifTrue:[
  1044         (builder componentAt:#mainPanel) layout bottomOffset:0.
  1045         (builder componentAt:#infoBarSubSpec) beInvisible
  1046     ]
  1047 
  1048     "Modified: / 20-02-2018 / 13:04:50 / stefan"
  1049 !
  1050 
  1051 initialize
  1052     "setup default attributes
  1053     "
  1054     super initialize.
  1055     self createBuilder.
  1056 
  1057     specSelector   := #helpSpec.
  1058 
  1059     classItemList  := List new.
  1060 
  1061     classItemModel := nil asValue.
  1062     classItemModel addDependent:self.
  1063 
  1064     keyItemModel := nil asValue.
  1065     keyItemModel addDependent:self.
  1066 
  1067     contentsModifiedChannel := false asValue.
  1068     contentsModifiedChannel addDependent:self.
  1069 
  1070     helpTextView := EditTextView new.
  1071     helpTextView acceptAction:[:dummy| self accept ].
  1072     helpTextView modifiedChannel:contentsModifiedChannel.
  1073 
  1074     editModel := nil asValue.
  1075     editModel addDependent:self.
  1076 
  1077     self loadFromClass:nil.
  1078 !
  1079 
  1080 openOnClass:aClass
  1081     "opens the UIHelpTool on aClass
  1082     "
  1083     self openOnClass:aClass andSelector:nil
  1084 !
  1085 
  1086 openOnClass:aClass andSelector: aSelector
  1087     "opens the UIHelpTool on aClass and aSelector"
  1088 
  1089     self openInterface:#windowSpec "ForStandAlone".
  1090 
  1091     builder window label:'Help Tool'.
  1092     self loadFromClass:aClass andSelector:aSelector
  1093 ! !
  1094 
  1095 !UIHelpTool methodsFor:'user actions'!
  1096 
  1097 accept
  1098     "accepts the help text;
  1099      take the contents of the helpTextView and store it under the current helpKey"
  1100 
  1101     |helpKey|
  1102 
  1103     helpKey := self helpKey.
  1104     helpKey isNil ifTrue:[^ self].
  1105 
  1106     self store:(helpTextView contents) forKey:helpKey
  1107 
  1108     "Modified: / 24-05-2018 / 16:31:25 / Claus Gittinger"
  1109 !
  1110 
  1111 cancel
  1112     "cancel modifications, reload helpText"
  1113 
  1114     |item contents modified|
  1115 
  1116     item := keyItemModel value.
  1117     modified := false.
  1118 
  1119     item notNil ifTrue:[
  1120         contents := item helpText.
  1121     ] ifFalse:[
  1122         contents := nil.
  1123 
  1124         modifiedHolder isNil ifTrue:[
  1125             modified := self helpKey notNil
  1126         ]
  1127     ].
  1128     helpTextView contents:contents.
  1129     contentsModifiedChannel value:modified.
  1130 
  1131     "Modified: / 29-08-2006 / 10:20:37 / cg"
  1132 !
  1133 
  1134 doDelete
  1135     "deletes the selected help key
  1136     "
  1137     |item|
  1138 
  1139     item := keyItemModel value.
  1140 
  1141     item notNil ifTrue:[
  1142         item remove.
  1143         item icon notNil ifTrue:[ self updateIcons ].
  1144     ].    
  1145     editModel value:nil.
  1146 !
  1147 
  1148 doExtractUsedKeys
  1149     "goes through the classes menu- and interface specs,
  1150      and extracts possible activeHelpKeys"
  1151 
  1152     |allHelpKeys existingKeys cls missingKeys|
  1153 
  1154     allHelpKeys := Set new.
  1155     
  1156     specClass theMetaclass methodsDo:[:mthd |
  1157         |spec bodyNode retVal specArray menu| 
  1158 
  1159         (mthd hasMenuResource or:[mthd hasCanvasResource]) ifTrue:[
  1160             bodyNode := mthd parseTree body.
  1161             bodyNode lastIsReturn ifTrue:[
  1162                 (retVal := bodyNode statements last value) isLiteralArray ifTrue:[
  1163                     specArray := retVal value.
  1164                     spec := specArray decodeAsLiteralArray.
  1165                     spec do:[:eachSpec |
  1166                         |k|
  1167 
  1168                         (k := eachSpec activeHelpKey) notNil ifTrue:[
  1169                             allHelpKeys add:k.
  1170                         ].
  1171                     ].
  1172                 ]
  1173             ].
  1174         ].    
  1175     ].
  1176 
  1177     existingKeys := Set new.
  1178     (cls := specClass theMetaclass whichClassImplements:self specSelector) notNil ifTrue:[
  1179         |specThere|
  1180         
  1181         specThere := cls theNonMetaclass perform:self specSelector.
  1182         specThere isDictionary ifFalse:[
  1183             Transcript showCR:('oops - helpSpec from ',cls name,'>>',self specSelector,' is not a dictionary').
  1184         ] ifTrue:[
  1185             existingKeys addAll:(specThere keys).    
  1186         ].
  1187     ].
  1188 
  1189     missingKeys := OrderedCollection new.
  1190     
  1191     allHelpKeys do:[:each |
  1192         (existingKeys includes:each) ifFalse:[
  1193             missingKeys add:each.
  1194         ].
  1195     ].
  1196     missingKeys do:[:eachKey |
  1197         self store:'no tooltip yet' forKey:eachKey
  1198     ].
  1199 
  1200     "Created: / 24-05-2018 / 16:00:08 / Claus Gittinger"
  1201 !
  1202 
  1203 doLoad
  1204     "opens a Resource Selection Browser in order to get a resource message"
  1205 
  1206     self loadFromMessage: 
  1207         (ResourceSelectionBrowser
  1208             request: 'Load Help Spec From Class'
  1209             onSuperclass: nil
  1210             andClass: specClass
  1211             andSelector: (self specSelector)
  1212             withResourceTypes: (Array with: #help)).
  1213 
  1214     self updateInfoLabel
  1215 !
  1216 
  1217 doNew
  1218     "reset all to empty
  1219     "
  1220     contentsModifiedChannel value:false.
  1221     self helpKey:nil.
  1222     self loadFromClass:nil.
  1223 !
  1224 
  1225 doSave
  1226     "save the help spec to the spec-class(es)"
  1227 
  1228     specClass isNil ifTrue:[
  1229         self information:'No class specified !!'.
  1230         ^ nil
  1231     ].
  1232     
  1233     "/ cg: the following test is rubbish !!
  1234     "/    (specClass isSubclassOf:ApplicationModel) ifFalse:[
  1235     "/        self information:(resources string:'Cannot save help into non-Application class').
  1236     "/        ^ nil
  1237     "/    ].
  1238 
  1239     classItemList do:[:aClassItem|
  1240         aClassItem theClass isNil ifTrue:[
  1241             aClassItem onClass:specClass
  1242         ].
  1243         aClassItem createHelpMethodNamed:(self specSelector) 
  1244     ].
  1245 
  1246     "Modified (format): / 24-05-2018 / 16:25:31 / Claus Gittinger"
  1247 !
  1248 
  1249 openDocumentation
  1250     "opens the documentation file of the Help Tool
  1251     "
  1252     self openHTMLDocument: 'tools/uipainter/HelpTool.html'
  1253 !
  1254 
  1255 store:helpText forKey:helpKey
  1256     "store helpText under helpKey"
  1257 
  1258     |helpItem root|
  1259 
  1260     root := classItemModel value.
  1261     root isNil ifTrue:[^ self].
  1262 
  1263     helpItem := root detectItemWithKey:helpKey.
  1264 
  1265     helpItem isNil ifTrue:[
  1266         helpItem := KeyItem helpKey:helpKey helpText:helpText.
  1267         root add:helpItem sortBlock:[:a :b| a label < b label ].
  1268         self updateIcons.
  1269     ] ifFalse:[
  1270         helpItem helpText:(helpTextView contents).
  1271     ].
  1272 
  1273     contentsModifiedChannel value:false.
  1274     keyItemModel triggerValue:helpItem.
  1275 
  1276     "Created: / 24-05-2018 / 16:31:08 / Claus Gittinger"
  1277 ! !
  1278 
  1279 !UIHelpTool::ClassItem class methodsFor:'instance creation'!
  1280 
  1281 onClass:aClass
  1282     |root|
  1283 
  1284     root := self new.
  1285     root onClass:aClass.
  1286     ^ root
  1287 ! !
  1288 
  1289 !UIHelpTool::ClassItem methodsFor:'accessing'!
  1290 
  1291 list
  1292     "returns the hierarchical list assigned to the classItem; the
  1293      list contains the keyItems
  1294     "
  1295     list isNil ifTrue:[
  1296 	list := HierarchicalList new.
  1297 	list showRoot:false.
  1298 	list root:self.
  1299     ].
  1300     ^ list
  1301 !
  1302 
  1303 theClass
  1304     "returns the class or nil if unspecified
  1305     "
  1306     ^ theClass
  1307 ! !
  1308 
  1309 !UIHelpTool::ClassItem methodsFor:'change & update'!
  1310 
  1311 helpTextChangedFor:anItem
  1312     "called if an helpKey changed its contents
  1313     "
  1314     self model notNil ifTrue:[
  1315 	self   modified:true.
  1316 	anItem modified:true.
  1317     ].
  1318 ! !
  1319 
  1320 !UIHelpTool::ClassItem methodsFor:'code generation'!
  1321 
  1322 createHelpMethodNamed:aMethodName
  1323     "cg: special case for helpPairs.
  1324      this returns a plain array, not invoking super"
  1325      
  1326     |stream|
  1327 
  1328     modified ifFalse:[
  1329         ^ self
  1330     ].
  1331     theClass isNil ifTrue:[
  1332         theClass := Dialog requestClass:'Save helpSpec in which class?' initialAnswer:''.
  1333         theClass isNil ifTrue:[
  1334             ^ self
  1335         ].
  1336     ].
  1337     stream := '' writeStream.
  1338 
  1339     aMethodName = 'helpPairs' ifTrue:[
  1340         stream nextPutAll:
  1341             aMethodName, '\' withCRs,
  1342             (ResourceSpecEditor codeGenerationCommentForClass:UIHelpTool) withCRs,
  1343     '\\' withCRs,
  1344     '    "\' withCRs,
  1345     '     UIHelpTool openOnClass:', theClass name asString ,'
  1346     "
  1347 
  1348     <resource: #help>
  1349 
  1350     ^ #(
  1351 
  1352 '.
  1353     ] ifFalse:[    
  1354         stream nextPutAll:
  1355             aMethodName, '\' withCRs,
  1356             (ResourceSpecEditor codeGenerationCommentForClass:UIHelpTool) withCRs,
  1357     '\\' withCRs,
  1358     '    "\' withCRs,
  1359     '     UIHelpTool openOnClass:', theClass name asString ,'
  1360     "
  1361 
  1362     <resource: #help>
  1363 
  1364     ^ super ', aMethodName, ' addPairsFrom:#(
  1365 
  1366 '.
  1367     ].
  1368     
  1369     self do:[:aKeyItem| |helpText|
  1370         helpText := aKeyItem helpText.
  1371         helpText isNil ifTrue:[ helpText := '' ].
  1372 
  1373         stream nextPutLine:(aKeyItem helpKey storeString).
  1374         stream nextPutLine:(helpText storeString); cr.
  1375     ].
  1376     stream nextPutLine:')'.
  1377 
  1378     Compiler
  1379         compile:(stream contents)
  1380         forClass:theClass class
  1381         inCategory:'help specs'.
  1382 
  1383     self modified:false.
  1384 
  1385     "Modified: / 13-02-2017 / 17:51:53 / cg"
  1386 ! !
  1387 
  1388 !UIHelpTool::ClassItem methodsFor:'displaying'!
  1389 
  1390 icon
  1391     "returns the display icon (always nil)
  1392     "
  1393     ^ nil
  1394 !
  1395 
  1396 label
  1397     "returns the display label
  1398     "
  1399     |label|
  1400 
  1401     theClass notNil ifTrue:[ label := theClass name ]
  1402 		   ifFalse:[ label := '** not yet defined **' ].
  1403 
  1404     modified ifTrue:[
  1405 	label := Text string:label color:(Color red).
  1406     ].
  1407     ^ label
  1408 ! !
  1409 
  1410 !UIHelpTool::ClassItem methodsFor:'instance creation'!
  1411 
  1412 initialize
  1413     "setup defaults"
  1414 
  1415     super initialize.
  1416 
  1417     children   := OrderedCollection new.
  1418     isExpanded := true.
  1419     modified   := false.
  1420 
  1421     "Modified: / 08-02-2017 / 01:02:14 / cg"
  1422 !
  1423 
  1424 onClass:aClass
  1425     "the class the ys are assigned to; if the class is nil,
  1426      the class is not yet specified.
  1427     "
  1428     theClass := aClass.
  1429 ! !
  1430 
  1431 !UIHelpTool::ClassItem methodsFor:'private'!
  1432 
  1433 basicAdd:aChild sortBlock:aBlock
  1434     "catch low-level add to update the modification flag
  1435     "
  1436     self   modified:true.
  1437     aChild modified:true.
  1438 
  1439     ^ super basicAdd:aChild sortBlock:aBlock.
  1440 !
  1441 
  1442 basicAddAll:aList beforeIndex:anIndex
  1443     "catch low-level add to update the modification flag
  1444     "
  1445     self modified:true.
  1446 
  1447     aList do:[:el| el modified:true ].
  1448     ^ super basicAddAll:aList beforeIndex:anIndex.
  1449 !
  1450 
  1451 basicRemoveFromIndex:startIndex toIndex:stopIndex
  1452     "catch low-level remove to update the modification flag
  1453     "
  1454     self isUnspecified ifFalse:[
  1455 	self modified:true.
  1456     ].
  1457     ^ super basicRemoveFromIndex:startIndex toIndex:stopIndex
  1458 ! !
  1459 
  1460 !UIHelpTool::ClassItem methodsFor:'queries'!
  1461 
  1462 isUnspecified
  1463     "true if the class is unspecified
  1464     "
  1465     ^ theClass isNil
  1466 !
  1467 
  1468 modified
  1469     "true, if any item is modified, created or deleted
  1470     "
  1471     ^ modified
  1472 !
  1473 
  1474 modified:aBoolean
  1475     "true, if any item is modified, created or deleted
  1476     "
  1477     modified ~~ aBoolean ifTrue:[
  1478 	modified := aBoolean.
  1479 
  1480 	modified ifFalse:[
  1481 	    self do:[:el| el modified:false ].
  1482 	].
  1483     ].
  1484 ! !
  1485 
  1486 !UIHelpTool::ClassItem methodsFor:'searching'!
  1487 
  1488 detectItemWithKey:aKey
  1489     "returns the item assigned to a helpKey or nil
  1490     "
  1491     |key|
  1492 
  1493     aKey isEmptyOrNil ifTrue:[ ^ nil ].
  1494     key := aKey asSymbol.
  1495 
  1496     self do:[:anItem|
  1497         anItem helpKey == key ifTrue:[ ^ anItem ].
  1498     ].
  1499     ^ nil
  1500 ! !
  1501 
  1502 !UIHelpTool::KeyItem class methodsFor:'instance creation'!
  1503 
  1504 helpKey:aKey helpText:aText 
  1505     |key|
  1506 
  1507     key := self new.
  1508     key helpKey:aKey helpText:aText.
  1509     ^ key
  1510 ! !
  1511 
  1512 !UIHelpTool::KeyItem methodsFor:'accessing'!
  1513 
  1514 helpKey
  1515     "returns the helpKey, a symbol"
  1516 
  1517     ^ helpKey
  1518 !
  1519 
  1520 helpText
  1521     "returns the contents assigned to the helpKey or nil
  1522     "
  1523     ^ helpText
  1524 !
  1525 
  1526 helpText:aText
  1527     "set the contents assigned to the helpKey; if the contents changes,
  1528      a notification is raised.
  1529     "
  1530     |text|
  1531 
  1532     text := self formatText:aText.
  1533 
  1534     text ~= helpText ifTrue:[
  1535         helpText := text.
  1536 
  1537         (modified or:[parent isNil]) ifFalse:[
  1538             parent helpTextChangedFor:self.
  1539         ]
  1540     ].
  1541 ! !
  1542 
  1543 !UIHelpTool::KeyItem methodsFor:'displaying'!
  1544 
  1545 icon
  1546     "returns the display icon (always nil)
  1547     "
  1548     ^ icon
  1549 !
  1550 
  1551 icon:anIcon
  1552 
  1553     icon ~= anIcon ifTrue:[
  1554         icon := anIcon.
  1555         self changed:#icon.
  1556     ].
  1557 !
  1558 
  1559 label
  1560     "returns the display label
  1561     "
  1562     modified ifTrue:[
  1563 	^ Text string:helpKey color:(Color red)
  1564     ].
  1565     ^ helpKey
  1566 ! !
  1567 
  1568 !UIHelpTool::KeyItem methodsFor:'instance creation'!
  1569 
  1570 helpKey:aKey helpText:aText
  1571     "set the key and contents without a change notification
  1572     "
  1573     helpKey  := aKey asSymbol.
  1574     helpText := self formatText:aText.
  1575 !
  1576 
  1577 initialize
  1578     "setup defaults"
  1579 
  1580     super initialize.
  1581     children := #().
  1582     modified := false.
  1583 
  1584     "Modified: / 08-02-2017 / 01:01:49 / cg"
  1585 ! !
  1586 
  1587 !UIHelpTool::KeyItem methodsFor:'private'!
  1588 
  1589 formatText:aText
  1590     "format the text, replace carriage return by spaces and compress spaces
  1591     "
  1592     |text result|
  1593 
  1594     aText size ~~ 0 ifTrue:[
  1595 	text := aText asString asCollectionOfWords.
  1596 
  1597 	text notEmpty ifTrue:[
  1598 	    result := text first.
  1599 
  1600 	    text from:2 do:[:t| result := result, ' ', t ].
  1601 	    ^ result
  1602        ].
  1603     ].
  1604     ^ nil
  1605 ! !
  1606 
  1607 !UIHelpTool::KeyItem methodsFor:'queries'!
  1608 
  1609 modified
  1610     "returns true if the helpText is modified
  1611     "
  1612     ^ modified
  1613 !
  1614 
  1615 modified:aBoolean
  1616     "set the modification flag
  1617     "
  1618     aBoolean == modified ifFalse:[
  1619 	modified := aBoolean.
  1620 	self changed:#redraw.
  1621     ].
  1622 ! !
  1623 
  1624 !UIHelpTool class methodsFor:'documentation'!
  1625 
  1626 version
  1627     ^ '$Header$'
  1628 !
  1629 
  1630 version_CVS
  1631     ^ '$Header$'
  1632 ! !
  1633