MethodFinderWindow.st
author Claus Gittinger <cg@exept.de>
Wed, 18 Dec 2019 19:07:20 +0100
changeset 3829 7a5b398e1316
parent 3816 70c345c11145
child 3839 b37f9731ec27
permissions -rw-r--r--
regenerated

"
 Copyright (C) Original Authors (Kaehler, Scott Wallace and Dan Ingalls)
 Copyright (C) 2001 eXept Software AG

 Permission is hereby granted, free of charge, to any 
 person obtaining a copy of this software and associated 
 documentation files (the 'Software'), to deal in the 
 Software without restriction, including without limitation 
 the rights to use, copy, modify, merge, publish, distribute, 
 sublicense, and/or sell copies of the Software, and to 
 permit persons to whom the Software is furnished to do so, 
 subject to the following conditions:

 The above copyright notice and this permission notice shall 
 be included in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"
"{ Package: 'stx:libtool2' }"

"{ NameSpace: Smalltalk }"

ApplicationModel subclass:#MethodFinderWindow
	instanceVariableNames:'resultHolder selectorPatternHolder classOfResultHolder
		selectedImplementorsHolder argumentsEditor messageAnswerEditor
		receiverEditor receiver resultSelectors arg2BoxVisible
		arg1BoxVisible arg4BoxVisible arg3BoxVisible argCountHolder
		argCountList argument1Editor argument2Editor argument3Editor
		argument4Editor resultSelected lookAtResultEditor codeHolder
		searchProcess classOfResultNameListHolder
		selectedClassOfResultIndexHolder classOfResultListHolder'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-Tools'
!

!MethodFinderWindow class methodsFor:'documentation'!

copyright
"
 Copyright (C) Original Authors (Kaehler, Scott Wallace and Dan Ingalls)
 Copyright (C) 2001 eXept Software AG

 Permission is hereby granted, free of charge, to any 
 person obtaining a copy of this software and associated 
 documentation files (the 'Software'), to deal in the 
 Software without restriction, including without limitation 
 the rights to use, copy, modify, merge, publish, distribute, 
 sublicense, and/or sell copies of the Software, and to 
 permit persons to whom the Software is furnished to do so, 
 subject to the following conditions:

 The above copyright notice and this permission notice shall 
 be included in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"
!

documentation
"
  a tool to find implementing methods by example.
  Give it values for a receiver, optional arguments and a desired result,
  and it will find methods which do that for you.
  Please read the online documentation for details (open via the tool's help menu).

  [author:]
    original squeak version by Ted Kaehler, Scott Wallace and Dan Ingalls.
    ported from Squeak and GUI enhanced 2001 by James Hayes james@exept.de.
    improved by Claus Gittinger.
"
! !

!MethodFinderWindow class methodsFor:'constants'!

defaultIcon
    <resource: #programImage>

    ^ ToolbarIconLibrary methodFinder24x24Icon

    "Created: / 01-06-2012 / 13:05:11 / cg"
!

markerForImplementingClass
    ^ '=> '.
    ^ '*'

    "Created: / 13.11.2001 / 12:09:52 / cg"
    "Modified: / 13.11.2001 / 12:11:57 / cg"
! !

!MethodFinderWindow class methodsFor:'help specs'!

helpSpec
    "This resource specification was automatically generated
     by the UIHelpTool of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIHelpTool may not be able to read the specification."

    "
     UIHelpTool openOnClass:MethodFinderWindow
    "

    <resource: #help>

    ^ super helpSpec addPairsFrom:#(

#'*'
'as in GLOB patterns (i.e. like filename patterns)'

#answerValue
'Enter the desired result value here.\Can be a constant like $a or ''hello'' or #(10 20 30)\or a Smalltalk expression, such as "10@20" or "Rectangle new".'

#arg1Value
'Enter a value for the first argument here.\Can be a constant like $a or ''hello'' or #(10 20 30)\or a Smalltalk expression, such as "10@20" or "Rectangle new".'

#arg2Value
'Enter a value for the second argument here.\Can be a constant or a Smalltalk expression.'

#arg3Value
'Enter a value for the third argument here.\Can be a constant or a Smalltalk expression.'

#argumentCount
'Specify the number of arguments here.'

#clearButton
'Clear all sample value fields.'

#implementorsFound
'Shows a list of messages which deliver the result or match the selector pattern'

#receiverValue
'Enter a receiver value here.\Can be a constant (like ''hello'')\or a Smalltalk expression, such as "Rectangle basicNew".'

#selectorPattern
'Enter a pattern to search by message name'

#selectorPatternSearch
'Search by name.\You can use match characters'

#startSearchButton
'Search for methods which answer the desired value,\given the concrete arguments'

#startSearchPatternButton
'Search for methods whose name matches the pattern'

)

    "Modified: / 08-06-2019 / 16:06:17 / Claus Gittinger"
! !

!MethodFinderWindow class methodsFor:'interface specs'!

windowSpec
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIPainter may not be able to read the specification."

    "
     UIPainter new openOnClass:MethodFinderWindow andSelector:#windowSpec
     MethodFinderWindow new openInterface:#windowSpec
     MethodFinderWindow open
    "

    <resource: #canvas>

    ^ 
    #(FullSpec
       name: windowSpec
       uuid: '7da03570-e499-11e9-8918-10ddb1cc5928'
       window: 
      (WindowSpec
         label: 'MethodFinder'
         name: 'MethodFinder'
         uuid: '5fb0c87a-89f6-11e9-8df0-b8f6b1108e05'
         bounds: (Rectangle 0 0 816 738) menu: menu
         icon: defaultIcon
      ) component: 
      (SpecCollection
         collection: (
          (VariableHorizontalPanelSpec
             name: 'VariableHorizontalPanel1'
             layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) uuid: '5fb0cd98-89f6-11e9-8df0-b8f6b1108e05'
             showHandle: true
             snapMode: both
             component: 
            (SpecCollection
               collection: (
                (VariableVerticalPanelSpec
                   name: 'LeftBox'
                   uuid: '5fb0d1a8-89f6-11e9-8df0-b8f6b1108e05'
                   showHandle: true
                   component: 
                  (SpecCollection
                     collection: (
                      (ViewSpec
                         name: 'MethodFinderBox'
                         uuid: '5fb0d36a-89f6-11e9-8df0-b8f6b1108e05'
                         component: 
                        (SpecCollection
                           collection: (
                            (ViewSpec
                               name: 'ReceiverArgBox'
                               layout: (LayoutFrame 0 0 0 0 0 1 -30 1) uuid: '5fb0d4f0-89f6-11e9-8df0-b8f6b1108e05'
                               component: 
                              (SpecCollection
                                 collection: (
                                  (LabelSpec
                                     label: 'Receiver'
                                     name: 'ReceiverLabel'
                                     layout: (LayoutFrame 0 0 0 0 0 0.34000000000000002 28 0) uuid: '5fb0d6b2-89f6-11e9-8df0-b8f6b1108e05'
                                     translateLabel: true
                                  )
                                  (ComboListSpec
                                     name: 'AllowedArguments'
                                     layout: (LayoutFrame 0 0.34000000000000002 1 0 0 0.64000000000000135 28 0) activeHelpKey: argumentCount
                                     uuid: '5fb0da9a-89f6-11e9-8df0-b8f6b1108e05'
                                     model: argCountHolder
                                     comboList: argCountList
                                     useIndex: true
                                  )
                                  (LabelSpec
                                     label: 'Answer'
                                     name: 'MessageAnswerLabel'
                                     layout: (LayoutFrame 0 0.64000000000000135 0 0 0 1 28 0) activeHelpKey: arg1Value
                                     uuid: '5fb0dd60-89f6-11e9-8df0-b8f6b1108e05'
                                     translateLabel: true
                                  )
                                  (HorizontalPanelViewSpec
                                     name: 'HorizontalPanel1'
                                     layout: (LayoutFrame 0 0 30 0 0 1 0 1) uuid: '5fb0dee6-89f6-11e9-8df0-b8f6b1108e05'
                                     horizontalLayout: fit
                                     verticalLayout: fit
                                     horizontalSpace: 3
                                     verticalSpace: 3
                                     component: 
                                    (SpecCollection
                                       collection: (
                                        (WorkspaceSpec
                                           name: 'ReceiverEditor'
                                           activeHelpKey: receiverValue
                                           uuid: '5fb0e152-89f6-11e9-8df0-b8f6b1108e05'
                                           tabable: true
                                           hasHorizontalScrollBar: true
                                           hasVerticalScrollBar: true
                                           miniScrollerHorizontal: true
                                           miniScrollerVertical: true
                                           autoHideScrollBars: true
                                           hasKeyboardFocusInitially: false
                                           extent: (Point 86 142) postBuildCallback: receiverWidgetCreated:
                                        )
                                        (VerticalPanelViewSpec
                                           name: 'VerticalPanel1'
                                           uuid: '5fb0e51c-89f6-11e9-8df0-b8f6b1108e05'
                                           horizontalLayout: fit
                                           verticalLayout: fit
                                           horizontalSpace: 3
                                           verticalSpace: 3
                                           component: 
                                          (SpecCollection
                                             collection: (
                                              (ViewSpec
                                                 name: 'Arg1Box'
                                                 uuid: '5fb0e6d4-89f6-11e9-8df0-b8f6b1108e05'
                                                 visibilityChannel: arg1BoxVisible
                                                 component: 
                                                (SpecCollection
                                                   collection: (
                                                    (WorkspaceSpec
                                                       name: 'Arg1Editor'
                                                       layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) activeHelpKey: arg1Value
                                                       uuid: '5fb0e7ce-89f6-11e9-8df0-b8f6b1108e05'
                                                       tabable: true
                                                       hasHorizontalScrollBar: true
                                                       hasVerticalScrollBar: true
                                                       miniScrollerHorizontal: true
                                                       miniScrollerVertical: true
                                                       autoHideScrollBars: true
                                                       hasKeyboardFocusInitially: false
                                                       postBuildCallback: argument1WidgetCreated:
                                                    )
                                                  )
                                                ) extent: (Point 87 45)
                                              )
                                              (ViewSpec
                                                 name: 'Arg2Box'
                                                 uuid: '5fb0e9b8-89f6-11e9-8df0-b8f6b1108e05'
                                                 visibilityChannel: arg2BoxVisible
                                                 component: 
                                                (SpecCollection
                                                   collection: (
                                                    (WorkspaceSpec
                                                       name: 'Arg2Editor'
                                                       layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) activeHelpKey: arg2Value
                                                       uuid: '5fb0eabc-89f6-11e9-8df0-b8f6b1108e05'
                                                       tabable: true
                                                       hasHorizontalScrollBar: true
                                                       hasVerticalScrollBar: true
                                                       miniScrollerHorizontal: true
                                                       miniScrollerVertical: true
                                                       autoHideScrollBars: true
                                                       hasKeyboardFocusInitially: false
                                                       postBuildCallback: argument2WidgetCreated:
                                                    )
                                                  )
                                                ) extent: (Point 87 46)
                                              )
                                              (ViewSpec
                                                 name: 'Arg3Box'
                                                 uuid: '5fb0ec74-89f6-11e9-8df0-b8f6b1108e05'
                                                 visibilityChannel: arg3BoxVisible
                                                 component: 
                                                (SpecCollection
                                                   collection: (
                                                    (WorkspaceSpec
                                                       name: 'Arg3Editor'
                                                       layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) activeHelpKey: arg3Value
                                                       uuid: '5fb0ed64-89f6-11e9-8df0-b8f6b1108e05'
                                                       tabable: true
                                                       hasHorizontalScrollBar: true
                                                       hasVerticalScrollBar: true
                                                       miniScrollerHorizontal: true
                                                       miniScrollerVertical: true
                                                       autoHideScrollBars: true
                                                       hasKeyboardFocusInitially: false
                                                       postBuildCallback: argument3WidgetCreated:
                                                    )
                                                  )
                                                ) extent: (Point 87 45)
                                              )
                                            )
                                          ) extent: (Point 87 142)
                                        )
                                        (WorkspaceSpec
                                           name: 'AnswerEditor'
                                           activeHelpKey: answerValue
                                           uuid: '5fb0ef30-89f6-11e9-8df0-b8f6b1108e05'
                                           tabable: true
                                           hasHorizontalScrollBar: true
                                           hasVerticalScrollBar: true
                                           miniScrollerHorizontal: true
                                           miniScrollerVertical: true
                                           autoHideScrollBars: true
                                           hasKeyboardFocusInitially: false
                                           extent: (Point 87 142) postBuildCallback: messageAnswerWidgetCreated:
                                        )
                                      )
                                    )
                                  )
                                )
                              )
                            )
                            (ViewSpec
                               name: 'ReceiverArgBoxActionBox'
                               layout: (LayoutFrame 0 0 -30 1 0 1 0 1) uuid: '5fb0f0fc-89f6-11e9-8df0-b8f6b1108e05'
                               component: 
                              (SpecCollection
                                 collection: (
                                  (ActionButtonSpec
                                     label: 'Clear'
                                     name: 'ClearButton'
                                     layout: (LayoutFrame 5 0 0 0 -5 0.5 0 1) activeHelpKey: clearButton
                                     uuid: '5fb0f214-89f6-11e9-8df0-b8f6b1108e05'
                                     translateLabel: true
                                     model: clear
                                  )
                                  (ActionButtonSpec
                                     label: 'Search'
                                     name: 'SearchButton'
                                     layout: (LayoutFrame 5 0.5 0 0 -5 1 0 1) activeHelpKey: startSearchButton
                                     uuid: '5fb0f52a-89f6-11e9-8df0-b8f6b1108e05'
                                     translateLabel: true
                                     tabable: true
                                     model: search
                                  )
                                )
                              )
                            )
                          )
                        )
                      )
                      (ViewSpec
                         name: 'SelectorFinderBox'
                         uuid: '5fb0f714-89f6-11e9-8df0-b8f6b1108e05'
                         component: 
                        (SpecCollection
                           collection: (
                            (ViewSpec
                               name: 'MatchActionBox'
                               layout: (LayoutFrame 0 0 0 0 0 1 90 0) uuid: '5fb0f818-89f6-11e9-8df0-b8f6b1108e05'
                               component: 
                              (SpecCollection
                                 collection: (
                                  (LabelSpec
                                     label: 'Selector Pattern:'
                                     name: 'SelectorPatternLabel'
                                     layout: (LayoutFrame 0 0 0 0 0 1 25 0) uuid: '5fb0f908-89f6-11e9-8df0-b8f6b1108e05'
                                     translateLabel: true
                                     adjust: left
                                  )
                                  (InputFieldSpec
                                     name: 'SelectorPattern'
                                     layout: (LayoutFrame 2 0 -54 1 -2 1 -29 1) activeHelpKey: selectorPattern
                                     uuid: '5fb0fa70-89f6-11e9-8df0-b8f6b1108e05'
                                     model: selectorPatternHolder
                                     immediateAccept: true
                                     acceptOnReturn: true
                                     acceptOnTab: true
                                     acceptOnPointerLeave: true
                                  )
                                  (ActionButtonSpec
                                     label: 'Search'
                                     name: 'SearchPatternButton'
                                     layout: (LayoutFrame 5 0.5 -25 1 -5 1 0 1) activeHelpKey: startSearchPatternButton
                                     uuid: '5fb0fea8-89f6-11e9-8df0-b8f6b1108e05'
                                     translateLabel: true
                                     tabable: true
                                     model: searchPatternMatchesInBackground
                                  )
                                )
                              )
                            )
                            (SequenceViewSpec
                               name: 'ResultList'
                               layout: (LayoutFrame 0 0 94 0 0 1 0 1) activeHelpKey: implementorsFound
                               uuid: '5fb1009c-89f6-11e9-8df0-b8f6b1108e05'
                               model: selectedImplementorsHolder
                               menu: resultListMenu
                               hasHorizontalScrollBar: true
                               hasVerticalScrollBar: true
                               autoHideScrollBars: true
                               useIndex: true
                               sequenceList: resultHolder
                            )
                          )
                        )
                      )
                    )
                  ) handles: (Any 0.28000000000000003 1.0)
                )
                (VariableVerticalPanelSpec
                   name: 'RightBox'
                   uuid: '5fb103c6-89f6-11e9-8df0-b8f6b1108e05'
                   component: 
                  (SpecCollection
                     collection: (
                      (SequenceViewSpec
                         name: 'ImplementorsList'
                         uuid: '5fb10524-89f6-11e9-8df0-b8f6b1108e05'
                         model: selectedClassOfResultIndexHolder
                         menu: implementorListMenu
                         hasHorizontalScrollBar: true
                         hasVerticalScrollBar: true
                         autoHideScrollBars: true
                         doubleClickSelector: openBrowserOn:
                         valueChangeSelector: selectedClassOfResultIndexHolderChanged
                         useIndex: true
                         sequenceList: classOfResultNameListHolder
                      )
                      (ViewSpec
                         name: 'Box4'
                         uuid: '4698d744-a993-11e9-b8a4-b8f6b1108e05'
                         component: 
                        (SpecCollection
                           collection: (
                            (CodeViewSpec
                               name: 'CodeView'
                               layout: (LayoutFrame 0 0 0 0 0 1 0 1) uuid: '5fb106dc-89f6-11e9-8df0-b8f6b1108e05'
                               model: codeHolder
                               hasHorizontalScrollBar: true
                               hasVerticalScrollBar: true
                               autoHideScrollBars: true
                               hasKeyboardFocusInitially: false
                               viewClassName: 'codeViewClass'
                               postBuildCallback: sourceCodeWidgetCreated:
                            )
                          )
                        )
                      )
                    )
                  ) handles: (Any 0.5 1.0)
                )
              )
            ) handles: (Any 0.33000000000000002 1.0)
          )
        )
      )
    )
!

windowSpec_old
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIPainter may not be able to read the specification."

    "
     UIPainter new openOnClass:MethodFinderWindow andSelector:#windowSpec_old
     MethodFinderWindow new openInterface:#windowSpec_old
    "

    <resource: #canvas>

    ^ 
    #(FullSpec
       name: #'windowSpec_old'
       uuid: '92a85286-e499-11e9-8918-10ddb1cc5928'
       window: 
      (WindowSpec
         label: 'MethodFinder'
         name: 'MethodFinder'
         uuid: '92a85542-e499-11e9-8918-10ddb1cc5928'
         bounds: (Rectangle 0 0 920 690) menu: menu
         icon: defaultIcon
      ) component: 
      (SpecCollection
         collection: (
          (VariableHorizontalPanelSpec
             name: 'VariableHorizontalPanel1'
             layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) uuid: '92a857b8-e499-11e9-8918-10ddb1cc5928'
             snapMode: both
             component: 
            (SpecCollection
               collection: (
                (ViewSpec
                   name: 'LeftBox'
                   uuid: '92a85998-e499-11e9-8918-10ddb1cc5928'
                   level: 1
                   component: 
                  (SpecCollection
                     collection: (
                      (ViewSpec
                         name: 'ReceiverArgBox'
                         layout: (LayoutFrame 0 0 0 0 0 1 -100 0.5) uuid: '92a85ad8-e499-11e9-8918-10ddb1cc5928'
                         component: 
                        (SpecCollection
                           collection: (
                            (LabelSpec
                               label: 'Receiver'
                               name: 'ReceiverLabel'
                               layout: (LayoutFrame 0 0 0 0 0 0.34000000000000002 28 0) uuid: '92a85bd2-e499-11e9-8918-10ddb1cc5928'
                               translateLabel: true
                            )
                            (ComboListSpec
                               name: 'AllowedArguments'
                               layout: (LayoutFrame 0 0.34000000000000002 1 0 0 0.64000000000000046 28 0) activeHelpKey: argumentCount
                               uuid: '92a85d8a-e499-11e9-8918-10ddb1cc5928'
                               model: argCountHolder
                               comboList: argCountList
                               useIndex: true
                            )
                            (LabelSpec
                               label: 'Answer'
                               name: 'MessageAnswerLabel'
                               layout: (LayoutFrame 0 0.64000000000000046 0 0 0 1 28 0) activeHelpKey: arg1Value
                               uuid: '92a85f4c-e499-11e9-8918-10ddb1cc5928'
                               translateLabel: true
                            )
                            (HorizontalPanelViewSpec
                               name: 'HorizontalPanel1'
                               layout: (LayoutFrame 0 0 30 0 0 1 0 1) uuid: '92a860aa-e499-11e9-8918-10ddb1cc5928'
                               horizontalLayout: fit
                               verticalLayout: fit
                               horizontalSpace: 3
                               verticalSpace: 3
                               component: 
                              (SpecCollection
                                 collection: (
                                  (WorkspaceSpec
                                     name: 'ReceiverEditor'
                                     activeHelpKey: receiverValue
                                     uuid: '92a8626c-e499-11e9-8918-10ddb1cc5928'
                                     tabable: true
                                     hasHorizontalScrollBar: true
                                     hasVerticalScrollBar: true
                                     miniScrollerHorizontal: true
                                     miniScrollerVertical: true
                                     autoHideScrollBars: true
                                     hasKeyboardFocusInitially: false
                                     extent: (Point 111 214) postBuildCallback: receiverWidgetCreated:
                                  )
                                  (VerticalPanelViewSpec
                                     name: 'VerticalPanel1'
                                     uuid: '92a864f6-e499-11e9-8918-10ddb1cc5928'
                                     horizontalLayout: fit
                                     verticalLayout: fit
                                     horizontalSpace: 3
                                     verticalSpace: 3
                                     component: 
                                    (SpecCollection
                                       collection: (
                                        (ViewSpec
                                           name: 'Arg1Box'
                                           uuid: '92a8667c-e499-11e9-8918-10ddb1cc5928'
                                           visibilityChannel: arg1BoxVisible
                                           component: 
                                          (SpecCollection
                                             collection: (
                                              (WorkspaceSpec
                                                 name: 'Arg1Editor'
                                                 layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) activeHelpKey: arg1Value
                                                 uuid: '92a8678a-e499-11e9-8918-10ddb1cc5928'
                                                 tabable: true
                                                 hasHorizontalScrollBar: true
                                                 hasVerticalScrollBar: true
                                                 miniScrollerHorizontal: true
                                                 miniScrollerVertical: true
                                                 autoHideScrollBars: true
                                                 hasKeyboardFocusInitially: false
                                                 postBuildCallback: argument1WidgetCreated:
                                              )
                                            )
                                          ) extent: (Point 111 69)
                                        )
                                        (ViewSpec
                                           name: 'Arg2Box'
                                           uuid: '92a86974-e499-11e9-8918-10ddb1cc5928'
                                           visibilityChannel: arg2BoxVisible
                                           component: 
                                          (SpecCollection
                                             collection: (
                                              (WorkspaceSpec
                                                 name: 'Arg2Editor'
                                                 layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) activeHelpKey: arg2Value
                                                 uuid: '92a86a6e-e499-11e9-8918-10ddb1cc5928'
                                                 tabable: true
                                                 hasHorizontalScrollBar: true
                                                 hasVerticalScrollBar: true
                                                 miniScrollerHorizontal: true
                                                 miniScrollerVertical: true
                                                 autoHideScrollBars: true
                                                 hasKeyboardFocusInitially: false
                                                 postBuildCallback: argument2WidgetCreated:
                                              )
                                            )
                                          ) extent: (Point 111 70)
                                        )
                                        (ViewSpec
                                           name: 'Arg3Box'
                                           uuid: '92a86c30-e499-11e9-8918-10ddb1cc5928'
                                           visibilityChannel: arg3BoxVisible
                                           component: 
                                          (SpecCollection
                                             collection: (
                                              (WorkspaceSpec
                                                 name: 'Arg3Editor'
                                                 layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) activeHelpKey: arg3Value
                                                 uuid: '92a86d20-e499-11e9-8918-10ddb1cc5928'
                                                 tabable: true
                                                 hasHorizontalScrollBar: true
                                                 hasVerticalScrollBar: true
                                                 miniScrollerHorizontal: true
                                                 miniScrollerVertical: true
                                                 autoHideScrollBars: true
                                                 hasKeyboardFocusInitially: false
                                                 postBuildCallback: argument3WidgetCreated:
                                              )
                                            )
                                          ) extent: (Point 111 69)
                                        )
                                      )
                                    ) extent: (Point 111 214)
                                  )
                                  (WorkspaceSpec
                                     name: 'AnswerEditor'
                                     activeHelpKey: answerValue
                                     uuid: '92a86ef6-e499-11e9-8918-10ddb1cc5928'
                                     tabable: true
                                     hasHorizontalScrollBar: true
                                     hasVerticalScrollBar: true
                                     miniScrollerHorizontal: true
                                     miniScrollerVertical: true
                                     autoHideScrollBars: true
                                     hasKeyboardFocusInitially: false
                                     extent: (Point 111 214) postBuildCallback: messageAnswerWidgetCreated:
                                  )
                                )
                              )
                            )
                          )
                        )
                      )
                      (ViewSpec
                         name: 'ReceiverArgBoxActionBox'
                         layout: (LayoutFrame 0 0 -98 0.5 0 1 -75 0.5) uuid: '92a870cc-e499-11e9-8918-10ddb1cc5928'
                         component: 
                        (SpecCollection
                           collection: (
                            (ActionButtonSpec
                               label: 'Clear'
                               name: 'Button2'
                               layout: (LayoutFrame 5 0 0 0 -5 0.5 0 1) activeHelpKey: clearButton
                               uuid: '92a871d0-e499-11e9-8918-10ddb1cc5928'
                               translateLabel: true
                               model: clear
                            )
                            (ActionButtonSpec
                               label: 'Search'
                               name: 'Button1'
                               layout: (LayoutFrame 5 0.5 0 0 -5 1 0 1) activeHelpKey: startSearchButton
                               uuid: '92a8740a-e499-11e9-8918-10ddb1cc5928'
                               translateLabel: true
                               tabable: true
                               model: search
                            )
                          )
                        )
                      )
                      (ViewSpec
                         name: 'MatchActionBox'
                         layout: (LayoutFrame 0 0 -70 0.5 0 1 10 0.5) uuid: '92a875e0-e499-11e9-8918-10ddb1cc5928'
                         component: 
                        (SpecCollection
                           collection: (
                            (LabelSpec
                               label: 'Selector Pattern:'
                               name: 'Label1'
                               layout: (LayoutFrame 0 0 0 0 0 0.5 25 0) uuid: '92a876e4-e499-11e9-8918-10ddb1cc5928'
                               translateLabel: true
                               adjust: left
                            )
                            (InputFieldSpec
                               name: 'EntryField1'
                               layout: (LayoutFrame 2 0 -54 1 -2 1 -29 1) uuid: '92a87838-e499-11e9-8918-10ddb1cc5928'
                               model: selectorPatternHolder
                               immediateAccept: true
                               acceptOnReturn: true
                               acceptOnTab: true
                               acceptOnPointerLeave: true
                            )
                            (ActionButtonSpec
                               label: 'Search'
                               name: 'Button4'
                               layout: (LayoutFrame 5 0.5 -25 1 -5 1 0 1) uuid: '92a87a9a-e499-11e9-8918-10ddb1cc5928'
                               translateLabel: true
                               tabable: true
                               model: searchPatternMatchesInBackground
                            )
                          )
                        )
                      )
                      (SequenceViewSpec
                         name: 'ResultList'
                         layout: (LayoutFrame 0 0 15 0.5 0 1 0 1) uuid: '92a87c66-e499-11e9-8918-10ddb1cc5928'
                         model: selectedImplementorsHolder
                         menu: resultListMenu
                         hasHorizontalScrollBar: true
                         hasVerticalScrollBar: true
                         autoHideScrollBars: true
                         useIndex: true
                         sequenceList: resultHolder
                      )
                    )
                  )
                )
                (VariableVerticalPanelSpec
                   name: 'VariableVerticalPanel1'
                   uuid: '92a87e78-e499-11e9-8918-10ddb1cc5928'
                   component: 
                  (SpecCollection
                     collection: (
                      (SequenceViewSpec
                         name: 'List2'
                         uuid: '92a87fd6-e499-11e9-8918-10ddb1cc5928'
                         model: selectedClassOfResultIndexHolder
                         menu: implementorListMenu
                         hasHorizontalScrollBar: true
                         hasVerticalScrollBar: true
                         autoHideScrollBars: true
                         doubleClickSelector: openBrowserOn:
                         valueChangeSelector: selectedClassOfResultIndexHolderChanged
                         useIndex: true
                         sequenceList: classOfResultNameListHolder
                      )
                      (CodeViewSpec
                         name: 'CodeView'
                         uuid: '92a88184-e499-11e9-8918-10ddb1cc5928'
                         model: codeHolder
                         hasHorizontalScrollBar: true
                         hasVerticalScrollBar: true
                         autoHideScrollBars: true
                         hasKeyboardFocusInitially: false
                         viewClassName: 'codeViewClass'
                         postBuildCallback: sourceCodeWidgetCreated:
                      )
                    )
                  ) handles: (Any 0.5 1.0)
                )
              )
            ) handles: (Any 0.37 1.0)
          )
        )
      )
    )
! !

!MethodFinderWindow class methodsFor:'menu specs'!

helpMenu
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the MenuEditor may not be able to read the specification."


    "
     MenuEditor new openOnClass:MethodFinderWindow andSelector:#helpMenu
     (Menu new fromLiteralArrayEncoding:(MethodFinderWindow helpMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(Menu 
       (MenuItem
          activeHelpKey: helpTutorial
          label: 'Documentation'
          itemValue: openHTMLDocumentation
       ) 
       (MenuItem
          label: '-'
       ) 
       (MenuItem
          label: 'Show Me How it Works'
          itemValue: showMeHowItWorks
          labelImage: (ResourceRetriever ToolbarIconLibrary presentationIcon 'Show Me How it Works')
       ) 
       (MenuItem
          label: '-'
       ) 
       (MenuItem
          activeHelpKey: aboutThisAppliaction
          label: 'About MethodFinder...'
          itemValue: openAboutThisApplication
       )
     )
!

implementorListMenu
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the MenuEditor may not be able to read the specification."


    "
     MenuEditor new openOnClass:MethodFinderWindow andSelector:#implementorListMenu
     (Menu new fromLiteralArrayEncoding:(MethodFinderWindow implementorListMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(Menu 
       (MenuItem
          label: 'Browse'
          itemValue: openBrowserOnSelectedItem
       )
     )
!

menu
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the MenuEditor may not be able to read the specification."


    "
     MenuEditor new openOnClass:MethodFinderWindow andSelector:#menu
     (Menu new fromLiteralArrayEncoding:(MethodFinderWindow menu)) startUp
    "

    <resource: #menu>

    ^ 
     #(Menu 
       (MenuItem
          activeHelpKey: file
          label: '&File'
          submenu: 
         (Menu 
           (MenuItem
              activeHelpKey: fileExit
              label: 'Exit'
              itemValue: closeRequest
           )
         )
       ) 
       (MenuItem
          label: 'MENU_Help'
          startGroup: conditionalRight
          submenuChannel: helpMenu
       )
     )
!

resultListMenu
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the MenuEditor may not be able to read the specification."


    "
     MenuEditor new openOnClass:MethodFinderWindow andSelector:#resultListMenu
     (Menu new fromLiteralArrayEncoding:(MethodFinderWindow resultListMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(Menu 
       (MenuItem
          label: 'Browse Senders'
          itemValue: openBrowserOnSenderOfSelectedResultItem
       ) 
       (MenuItem
          label: 'Browse Implementors'
          itemValue: openBrowserOnSelectedResultItem
       )
     )
! !

!MethodFinderWindow class methodsFor:'startup'!

openOnSelectorPattern:selector
    |app|

    app := self new.
    app allButOpen.
    app selectorPatternHolder value:selector.
    app openWindow.
    "/ app waitForBackgroundSearchFinished.
    
    ^ app

    "
     self openOnSelectorPattern:'asLowercase'
    "
! !

!MethodFinderWindow methodsFor:'accessing'!

receiver
    "Return a copy of the value of the instance variable 'receiver' "

    ^ receiver copy
! !

!MethodFinderWindow methodsFor:'actions'!

clear
    "Reset the contents of all the outputs."

    receiverEditor notNil ifTrue:[
        receiverEditor contents:nil.
    ].
    argument1Editor contents:nil.
    argument2Editor contents:nil.
    argument3Editor contents:nil.
    messageAnswerEditor contents:nil.
    self resultHolder value:nil.
    self classOfResultListHolder value: nil.
    codeHolder notNil ifTrue:[
        codeHolder value:nil.
    ].
!

messageAnswerEditorContents
    "Return a cleaned up version of message answer taken from the messageAnswerEditor
     as an association. The association has cleanedAnswerString as a key and the
     compiledAnswer as value."
    
    |aCleanedAnswerString compiledAnswer|

    aCleanedAnswerString := self cleanInputs:(messageAnswerEditor contents).
    compiledAnswer := Compiler evaluate:aCleanedAnswerString 
                               ifFail:[
                                    Dialog information:'Bad value in the answer field'.
                                    AbortOperationRequest raise.
                                ].
    ((self isExpression:aCleanedAnswerString) or:[ compiledAnswer isNil ]) ifTrue:[
        aCleanedAnswerString := compiledAnswer printString
    ].
    ^ aCleanedAnswerString -> compiledAnswer.
!

openBrowserOn:indexInList
    "Opens browser on theArgument of a specific class. 
     anArgument being the index of the selected list entry,
     which is a string with the class and the selector 
     upon which the browser is to be opened. 
     Return the receiver."

    |sel classAndSelector|

    sel := classOfResultListHolder value at:indexInList.
    classAndSelector := self extractClassAndSelectorFrom:sel.
    classAndSelector isNil ifTrue:[
        ^ self
    ].
    SystemBrowser default
        openInClass:classAndSelector key 
        selector:classAndSelector value   

"
MethodFinderWindow new openBrowserOn: '*SmallInteger +'
MethodFinderWindow new openBrowserOn: 'String ,'
MethodFinderWindow new openBrowserOn: 'Number detentBy:atMultiplesOf:snap:' 


"

    "Modified: / 01-09-2017 / 14:21:18 / cg"
!

openBrowserOnSelectedItem 
    "on the selected implementor"

    |sel|

    sel := self selectedClassOfResultHolder value.
    self openBrowserOn:sel

    "Modified: / 13-11-2001 / 12:47:39 / cg"
    "Modified (comment): / 21-09-2012 / 11:08:33 / cg"
!

openBrowserOnSelectedResultItem 
    "on an item in the lower left list,
     on all implementors of that message"

    |selIndex selector|

    selIndex := self selectedImplementorsHolder value.
    selIndex isNil ifTrue:[^ self].

    selector := resultSelectors at:selIndex.
    UserPreferences browserClass browseImplementorsOf:selector.

    "Created: / 21-09-2012 / 11:05:46 / cg"
!

openBrowserOnSenderOfSelectedResultItem
    "on an item in the lower left list,
     on all implementors of that message"

    |selIndex selector|

    selIndex := self selectedImplementorsHolder value.
    selIndex isNil ifTrue:[^ self].

    selector := resultSelectors at:selIndex.
    UserPreferences browserClass browseSendersOf:selector.
!

search
    "Do a search based on the input in the various text editors. Return the receiver."

    |tempReceiver tempAnswer tempArguments numArgs
     anArray resultArrayOrErrorString receiverWithArgument mf|

    self resultHolder value:nil.
    self classOfResultListHolder value:nil.
    self codeHolder value:nil.
    tempArguments := self argumentEditorsContents.
    numArgs := tempArguments size.
    tempReceiver := self receiverEditorContents.
    tempAnswer := self messageAnswerEditorContents.

    "self cleanInputRec:tempReceiver arg:tempArguments ans:tempAnswer."
    receiverWithArgument := self mergeReceiver:(tempReceiver value) withArgument:(tempArguments values).
    anArray := Array
        with:receiverWithArgument
        with:tempAnswer value.

    "an array now holds the following array #(#(receiver argument) answer) or #(#(receiver) answer). 
     which should be suitable input for the method finder."
    self withCursor:(Cursor execute) do:[
        mf := MethodFinder new.
        mf load:anArray.
        resultArrayOrErrorString := mf findMessage.
    ].

    (resultArrayOrErrorString isString "(resultArray at:1) includesSubString:'no single'") ifTrue:[
        false ifTrue:[
            (self confirm:(c'%1\nTry a more exhaustive search (may take long)?' 
                            bindWith:resultArrayOrErrorString))
            ifTrue:[
                self search2Levels.
            ]. 
        ] ifFalse:[
            self warn:resultArrayOrErrorString.
        ].    
        ^ self
    ].
    
    "the following then replaces data1 and data2 created by the method finder to the appropriate arguments"
    resultArrayOrErrorString keysAndValuesDo:[:key :value |
        |newValue|

        newValue := value copyReplaceString:'data1' 
                          withString:(tempReceiver value storeString). "/ was: "tempReceiver key" 

        numArgs > 0 ifTrue:[
            newValue := newValue copyReplaceString:'data2'
                                 withString:(tempArguments valueAt:1) storeString. "/ was "keyAt:1" 
            numArgs > 1 ifTrue:[
                newValue := newValue copyReplaceString:'data3'
                                     withString:(tempArguments valueAt:2) storeString. "/ was "keyAt:2" 

                numArgs > 2 ifTrue:[
                    newValue := newValue copyReplaceString:'data4'
                                         withString:(tempArguments valueAt:3) storeString. "/ was: keyAt:3

                    numArgs > 3 ifTrue:[
                        self halt:'unimplemented'.
                    ].
                ].
            ].
        ].
         "    newValue:= value copyReplaceString: 'data3' withString:(self messageAnswer key). "
        newValue := newValue , ' --> ' , (tempAnswer key).
        newValue replaceAll:Character cr with:Character space.
        resultArrayOrErrorString at:key put:newValue.
    ].
    self resultHolder value:resultArrayOrErrorString.
    resultSelectors := mf selectors.
    receiver := tempReceiver

    "Modified: / 26-09-2011 / 12:42:28 / cg"
    "Modified: / 27-02-2018 / 11:37:58 / stefan"
    "Modified: / 18-07-2019 / 21:57:12 / Claus Gittinger"
!

search2Levels
    "Do an exhaustive search.
     Given the original message,
     try applying all unary messages first to the receiver,
     then to each argument.
     This takes O(Nē) time - so be prepared"

    |tempReceiver tempAnswer tempArguments numArgs
     anArray resultArray receiverWithArgument mf|

    tempArguments := self argumentEditorsContents.
    numArgs := tempArguments size.
    tempReceiver := self receiverEditorContents.
    tempAnswer := self messageAnswerEditorContents.

    receiverWithArgument := self mergeReceiver:(tempReceiver value)
                                 withArgument:(tempArguments values).
    anArray := Array
        with:receiverWithArgument;
        with:tempAnswer value.

    "an array now holds the following array #(#(receiver argument) answer) or #(#(receiver) answer). 
     which should be suitable input for the method finder."
    self withCursor:Cursor execute do:[
        mf := MethodFinder new.
        mf load:anArray.
        resultArray := mf findMessage.
    ].
        
    (resultArray isString "(resultArray at:1) includesSubString:'no single'") ifTrue:[
        (self confirm:(c'%1\nTry a more exhaustive search (may take long)?' bindWith:(resultArray at:1)))
        ifTrue:[
            self search2Levels.
        ].    
        ^ self
    ].
    
    "the following then replaces data1 and data2 created by the method finder to the appropriate arguments"
    resultArray
        keysAndValuesDo:[:key :value |
            |newValue|

            newValue := value copyReplaceString:'data1' 
                              withString:(tempReceiver value storeString). "/ was: "tempReceiver key" 
            numArgs > 0 ifTrue:[
                newValue := newValue copyReplaceString:'data2'
                                     withString:(tempArguments valueAt:1) storeString. "/ was "keyAt:1" 

                numArgs > 1 ifTrue:[
                    newValue := newValue copyReplaceString:'data3'
                                         withString:(tempArguments valueAt:2) storeString. "/ was "keyAt:2" 

                    numArgs > 2 ifTrue:[
                        newValue := newValue copyReplaceString:'data4'
                                             withString:(tempArguments valueAt:3) storeString. "/ was: keyAt:3

                        numArgs > 3 ifTrue:[
                            self halt:'unimplemented'.
                        ].
                    ]
                ]
            ].
             "    newValue:= value copyReplaceString: 'data3' withString:(self messageAnswer key). "
            newValue := newValue , ' --> ' , (tempAnswer key).
            newValue replaceAll:Character cr with:Character space.
            resultArray at:key put:newValue.
        ].
    self resultHolder value:resultArray.
    resultSelectors := mf selectors.
    receiver := tempReceiver

    "Created: / 18-07-2019 / 21:22:47 / Claus Gittinger"
!

searchPatternMatches:pattern
    "Do a search based on the pattern match"

    |list counts firsts seconds selectors resultList idx match|

    self withCursor:Cursor execute do:[
        pattern includesMatchCharacters ifFalse:[   
            list := SystemBrowser findImplementorsOf:pattern in:Smalltalk allClasses ignoreCase:true.
            list isEmptyOrNil ifTrue:[
                match := pattern,'*'.
                list := SystemBrowser findImplementorsMatching:match in:Smalltalk allClasses ignoreCase:true.
            ].
        ] ifTrue:[
            match := pattern.
            list := SystemBrowser findImplementorsMatching:match in:Smalltalk allClasses ignoreCase:true.
        ].
    ].

    counts := IdentityDictionary new.
    firsts := IdentityDictionary new.
    seconds := IdentityDictionary new.
    selectors := IdentitySet new.
    list do:[:eachMethod |
        |msel|

        msel := eachMethod selector.
        selectors add:msel.
        (counts at:msel ifAbsentPut:[ 0 asValue ]) increment.
        (firsts includesKey:msel) ifTrue:[
            (seconds includesKey:msel) ifFalse:[
                seconds at:msel ifAbsentPut:[ eachMethod mclass ].
            ].
        ] ifFalse:[
            firsts at:msel ifAbsentPut:[ eachMethod mclass ].
        ].
    ].
    resultSelectors := selectors asOrderedCollection sort.
    resultList := resultSelectors 
                    collect:[:sel | 
                        |cnt s|

                        s := sel allBold , ' --> '.
                        cnt := (counts at:sel) value.
                        cnt == 1 ifTrue:[
                            s , (firsts at:sel) name
                        ] ifFalse:[
                            cnt == 2 ifTrue:[
                                s , (firsts at:sel) name , ' and ' , (seconds at:sel) name
                            ] ifFalse:[
                                s , cnt printString , ' implementor(s)'
                            ]
                        ].
                    ].

    self enqueueDelayedAction:[ self updateListAfterPatternSearch: resultList ].

    "Created: / 01-06-2012 / 13:16:54 / cg"
!

searchPatternMatchesInBackground
    "Do a search based on the pattern match as a background task"

    | p pattern|

    (p := searchProcess) notNil ifTrue:[
        searchProcess := nil.
        p terminate.
    ].

    pattern := self selectorPatternHolder value.
    pattern isEmptyOrNil ifTrue:[
        self resultHolder value:self resultInfoText.
        self classOfResultListHolder value:nil.
        self codeHolder value:nil.
        ^ self
    ].

    searchProcess := 
        [
            self searchPatternMatches:pattern.
        ] fork.

    "Created: / 01-06-2012 / 13:16:54 / cg"
!

selectedImplementorChanged
    self updateImplementorsOf:selectedImplementorsHolder value
!

updateImplementorsOf:anInteger 
    "Request the implementors of the selected argument provided by aNumber (index in list).
     Return the receiver."
    
    |methods classList classNameList aNumber|

    (anInteger isNil or:[anInteger == 0]) ifTrue:[
        ^ self
    ].

    aNumber := anInteger ? 1.
    methods := SystemBrowser 
                findImplementorsOf:(resultSelectors at:aNumber)
                in:Smalltalk allClasses
                ignoreCase:false.
    methods := methods asOrderedCollection. 
    classList := methods collect:[:m | m mclass name , ' ' , m selector ].
    classList := self markMatchingClasses:(resultSelectors at:aNumber) classesWithSelector:classList.

    classNameList := classList with:methods collect:[:s1 :m | s1 , ' ' , ('{' , m category , '}') allGray ].

    "/ now classList contains a list of <className> <selector>,
    "/ where the one which is responsible for the selected result is marked (bold)
    self classOfResultListHolder value:classList.
    self classOfResultNameListHolder value:classNameList.

    "/ initially select the bold one
    classList notEmptyOrNil ifTrue:[
        |idx receiversMethodEntryInClass|

        idx := classList findFirst:#isText.
        idx == 0 ifTrue:[
            "/ not found; select the first
            idx := 1.
        ].
        receiversMethodEntryInClass := classList detect:#isText ifNone:nil.
        self selectedClassOfResultIndexHolder value:idx.
        self selectedClassOfResultIndexHolderChanged.
    ] ifFalse:[
        self selectedClassOfResultIndexHolder value:nil.
    ].

    "Modified (comment): / 24-06-2012 / 18:41:45 / cg"
    "Modified: / 08-06-2019 / 15:39:49 / Claus Gittinger"
!

updateListAfterPatternSearch:resultList
    |searchPattern idx|
    
    self classOfResultListHolder value:nil.
    self codeHolder value:nil.
    self resultHolder value:resultList.

    searchPattern := self selectorPatternHolder value.
    "/ is the search pattern in the list (i.e. a perfect match)?
    "/ Then select it.
    idx := resultSelectors indexOf:searchPattern.
    idx ~~ 0 ifTrue:[
        self selectedImplementorsHolder setValue:idx; changed
    ].    
! !

!MethodFinderWindow methodsFor:'aspects'!

arg1BoxVisible
    "Determines if the box should be visible or not. 
     Return a holder providing true or false"

    arg1BoxVisible isNil ifTrue:[
        arg1BoxVisible := BlockValue
                              with:[:vh | vh >= 2 ]
                              argument:(self argCountHolder)
    ].
    ^ arg1BoxVisible.

    "Modified: / 17-05-2019 / 16:16:59 / Stefan Vogel"
!

arg2BoxVisible
    "Determines if the box should be visible or not. 
     Return a holder providing true or false"

    arg2BoxVisible isNil ifTrue:[
        arg2BoxVisible := BlockValue
                              with:[:vh | vh >= 3 ]
                              argument:(self argCountHolder)
    ].
    ^ arg2BoxVisible.

    "Modified: / 17-05-2019 / 16:16:54 / Stefan Vogel"
!

arg3BoxVisible
    "Determines if the box should be visible or not. 
     Return a holder providing true or false"

    arg3BoxVisible isNil ifTrue:[
        arg3BoxVisible := BlockValue
                              with:[:vh | vh >= 4 ]
                              argument:(self argCountHolder)
    ].
    ^ arg3BoxVisible.

    "Modified: / 17-05-2019 / 16:16:48 / Stefan Vogel"
!

arg4BoxVisible
    "Determines if the box should be visible or not. 
     Return a holder providing true or false"

    arg4BoxVisible isNil ifTrue:[
        arg4BoxVisible := BlockValue
                              with:[:vh | vh >= 5 ]
                              argument:(self argCountHolder)
    ].
    ^ arg4BoxVisible.

    "Modified: / 17-05-2019 / 16:16:43 / Stefan Vogel"
!

argCountHolder
    "Return an argCounterHolder which is initialized at 2."
    
    argCountHolder isNil ifTrue:[
        argCountHolder := 2 asValue.
    ].     
    ^ argCountHolder.
!

argCountList
    "Return the argCountList (shown in the combo)"

    argCountList isNil ifTrue:[
        argCountList := #('0 arguments' '1 argument' '2 arguments' '3 arguments') asValue  
    ].
    ^ argCountList.
!

classOfResultListHolder
    "Return a valueHolder which contains a collection with the names of the 
     implementors of a specific message.   "

    classOfResultListHolder isNil ifTrue:[
        classOfResultListHolder := ValueHolder new.
    ].
    ^ classOfResultListHolder
!

classOfResultNameListHolder
    "Return a valueHolder which contains a collection with the names of the 
     implementors of a specific message with cateogy.
     This is shown in the list view"

    classOfResultNameListHolder isNil ifTrue:[
        classOfResultNameListHolder := ValueHolder new.
    ].
    ^ classOfResultNameListHolder
!

codeHolder
    codeHolder isNil ifTrue:[
        codeHolder := '' asValue.
    ].
    ^ codeHolder.

    "Created: / 13.11.2001 / 12:44:11 / cg"
!

codeViewClass
    "the species of view to be created as codeview"
    
    ^ Tools::CodeView2 ? CodeView
!

resultHolder
    "Return a value holder which contains the results of a search as a collection."

    resultHolder isNil ifTrue:[
        resultHolder := ValueHolder new.
        resultHolder value:(self resultInfoText collect:[:l | l withColor:Color darkGrey]).
    ].
    ^ resultHolder.

    "Modified: / 01-06-2012 / 13:06:02 / cg"
!

resultInfoText
    ^  {
          'Please enter combination of' .
          '    ',('receiver, arg and result' allBold) .
          'or a'.
          '    ',('selector search pattern' allBold) .
          'into the above fields.' .
          'Then click on either ',('"search"' allBold),'-button.'
       }
!

selectedClassOfResultIndexHolder
    "valueHolder which contains the index of the selected result class (right list)"

    selectedClassOfResultIndexHolder isNil ifTrue:[
        selectedClassOfResultIndexHolder := ValueHolder new.
    ].
    ^ selectedClassOfResultIndexHolder

    "Modified (comment): / 21-09-2012 / 11:10:29 / cg"
!

selectedImplementorsHolder
    "valueHolder which contains the index of the selected implementors list (left list)"

    selectedImplementorsHolder isNil ifTrue:[
        selectedImplementorsHolder := ValueHolder new.
        selectedImplementorsHolder onChangeSend:#selectedImplementorChanged to:self.
    ].
    ^ selectedImplementorsHolder

    "Created: / 21-09-2012 / 11:10:13 / cg"
!

selectorPatternHolder
    selectorPatternHolder isNil ifTrue:[
        selectorPatternHolder := ValueHolder new.
        selectorPatternHolder onChangeSend:#selectorPatternChanged to:self.
    ].
    ^ selectorPatternHolder

    "Created: / 27-04-2012 / 14:44:01 / cg"
! !

!MethodFinderWindow methodsFor:'controlInput'!

cleanInputs:aDirtyString 
    "Find and remove common mistakes made by the user. 
     Return the 'aStringToBeCleaned' variable"
    
    |aStringToBeCleaned rs position|

    aStringToBeCleaned := aDirtyString.
    (aStringToBeCleaned endsWith:(Character cr)) ifTrue:[
        aStringToBeCleaned := aStringToBeCleaned copyFrom:1 to:(aStringToBeCleaned size - 1).
    ].
    aStringToBeCleaned := aStringToBeCleaned withoutSeparators.
    rs := ReadStream on:aStringToBeCleaned.
    [
        rs upToAll_positionBefore:'#true'.
        rs atEnd
    ] whileFalse:[
        position := rs position.
        aStringToBeCleaned := aStringToBeCleaned 
                copyReplaceFrom:position
                to:position
                with:''.
        rs := ReadStream on:aStringToBeCleaned.
    ].
    rs := ReadStream on:aStringToBeCleaned.
    [
        rs upToAll_positionBefore:'#false'.
        rs atEnd
    ] whileFalse:[
        position := rs position.
        aStringToBeCleaned := aStringToBeCleaned 
                copyReplaceFrom:position
                to:position
                with:''.
        rs := ReadStream on:aStringToBeCleaned.
    ].
    [
        rs upToAll_positionBefore:'#nil'.
        rs atEnd
    ] whileFalse:[
        position := rs position.
        aStringToBeCleaned := aStringToBeCleaned 
                copyReplaceFrom:position
                to:position
                with:''.
        rs := ReadStream on:aStringToBeCleaned.
    ].
    ^ aStringToBeCleaned
!

markMatchingClasses:aSelector classesWithSelector:anOrderedCollection
    " Matches the class of the receiver with all the elements in anOrderedCollection
     (which are classes with selectors). If a match is found it is marked with an asterisk.
     The classes are then sorted so the asterisk appears first. Return the
     markedClassList."
    
    |marker recClass unmarkedClassList markedClassList toMark|

    marker := self class markerForImplementingClass.
    recClass := receiver value class.

    toMark := OrderedCollection new.
    
    unmarkedClassList := anOrderedCollection copy.
    unmarkedClassList do:[:classAndMethod |
        |className class sel|

        className := (classAndMethod copyButLast:aSelector size) withoutSeparators.
        class := Smalltalk classNamed:className. "/ Compiler evaluate:className.

        "/ (recClass == class)

        (recClass whichClassImplements:aSelector) == class ifTrue:[
            toMark add:classAndMethod.
        ].
    ].
    unmarkedClassList removeAll:toMark.
    unmarkedClassList addAll:(toMark collect:#allBold).

    unmarkedClassList
        sort:[:a :b |
            |rawA rawB|

            rawA := a string withoutPrefix:marker.
            rawB := b string withoutPrefix:marker.
            rawA < rawB.
        ].
    markedClassList := unmarkedClassList.
    ^ markedClassList

    "Modified: / 13-11-2001 / 12:16:05 / cg"
    "Modified: / 08-06-2019 / 15:36:30 / Claus Gittinger"
!

mergeReceiver: aReceiver withArgument: arguments

    "Puts the receiver and arguments into an array so it can be of a suitable input for the
     MethodFinder. Return an array."

    | tempReceiver tempArguments nTempArgs |

    tempReceiver:= aReceiver.
    tempArguments := arguments.
    nTempArgs := tempArguments size.

    nTempArgs == 0 ifTrue:[  
        ^ { tempReceiver }
    ].
    (nTempArgs == 1) ifTrue:[ 
        ^ { tempReceiver . (tempArguments at:1) }  "a receiver with an argument"
    ].
    (nTempArgs == 2) ifTrue:[  
        ^ { tempReceiver . (tempArguments at:1) . (tempArguments at:2) }  "a receiver with 2 arguments"
    ].
    (nTempArgs == 3) ifTrue:[ 
        ^ { tempReceiver .  (tempArguments at:1) . (tempArguments at:2) . (tempArguments at:3) } " 3 args"
    ].
    ^ nil
! !

!MethodFinderWindow methodsFor:'initialization'!

argument1WidgetCreated: aWidget
    "UI post creation hook. remember the widget as an instance variable."

    argument1Editor := aWidget scrolledView.
    aWidget tabMeansNextField:true.

    "Modified: / 13.11.2001 / 12:21:41 / cg"
!

argument2WidgetCreated: aWidget
    "UI post creation hook. remember the widget as an instance variable."

    argument2Editor := aWidget scrolledView.
    aWidget tabMeansNextField:true.

    "Modified: / 13.11.2001 / 12:21:45 / cg"
!

argument3WidgetCreated: aWidget
    "UI post creation hook. remember the widget as an instance variable"

    argument3Editor := aWidget scrolledView.
    aWidget tabMeansNextField:true.

    "Modified: / 13.11.2001 / 12:21:49 / cg"
!

messageAnswerWidgetCreated: aWidget
    "UI post creation hook. remember the widget as an instance variable."

    messageAnswerEditor := aWidget scrolledView.
    aWidget tabMeansNextField:true.

    "Modified: / 13.11.2001 / 12:24:55 / cg"
!

receiverWidgetCreated: aWidget
    "UI post creation hook. remember the widget as an instance variable."

    receiverEditor := aWidget scrolledView.
    aWidget tabMeansNextField:true.

    "Modified: / 13.11.2001 / 12:24:49 / cg"
!

sourceCodeWidgetCreated: aWidget
    "UI post creation hook. make the codeView readonly"
    
    aWidget acceptAction:nil.
    aWidget readOnly:true

    "Created: / 13.11.2001 / 12:50:27 / cg"
    "Modified: / 13.11.2001 / 12:51:23 / cg"
! !

!MethodFinderWindow methodsFor:'menu actions - help'!

aboutThisApplicationText
    |msg|

    msg := super aboutThisApplicationText.
    msg := msg , self aboutThisApplicationText2.
    ^msg withCRs.

    "Modified: / 13.11.2001 / 12:56:44 / cg"
!

aboutThisApplicationText2
    ^ '\\Original written by Ted Kaehler, Scott Wallace and Dan Ingalls.
Ported from Squeak to ST/X by James Hayes (2001 james@exept.de).
Improved by Claus Gittinger.    
'.
    
!

openHTMLDocumentation
    "about/help menu action"
    
    HTMLDocumentView openFullOnDocumentationFile:'tools/misc/TOP.html#METHODFINDER'
! !

!MethodFinderWindow methodsFor:'private'!

argStringAndValueFromEditorContents:editorContents
    |associationKey associationValue|

    associationValue := Compiler 
                                evaluate:editorContents
                                ifFail:[
                                    Dialog information:'Bad value in the answer field'.
                                    AbortOperationRequest raise.
                                ].
    ((self isExpression:editorContents) or:[ associationValue isNil]) ifTrue:[
        "looks if an expression is typed in"
        associationKey := associationValue printString
    ] ifFalse:[
        associationKey := editorContents
    ].
    ^ (associationKey -> associationValue).
!

argumentEditorsContents
    "Determine how many text editors of the arguments are used and store the result
     as argCounter. The result being the minimum between how many editors have
     expressions in and how many are displayed.

     Add each argument string (key)and the evaluated version (value) to an Ordered Dictionary
     from each of the text editors.

     Return the OrderedDictionary with the expressions from all the text editors. "

     | tempArguments argCounter 
       tempArgument1EditorContents tempArgument2EditorContents tempArgument3EditorContents |

    argCounter:=0.

    tempArgument1EditorContents := (self cleanInputs: argument1Editor contents).
    tempArgument2EditorContents := (self cleanInputs: argument2Editor contents).
    tempArgument3EditorContents := (self cleanInputs: argument3Editor contents).

    tempArgument1EditorContents = '' ifFalse:[argCounter := argCounter +1].
    tempArgument2EditorContents = '' ifFalse:[argCounter := argCounter +1].
    tempArgument3EditorContents = '' ifFalse:[argCounter := argCounter +1].

    argCounter:= (argCounter min: (self argCountHolder value -1)).
    tempArguments:= OrderedDictionary new:argCounter. 

    (argCounter value >= 1) ifTrue:[
        tempArguments add:(self argStringAndValueFromEditorContents:tempArgument1EditorContents)
    ].
    (argCounter value >= 2) ifTrue:[ 
        tempArguments add:(self argStringAndValueFromEditorContents:tempArgument2EditorContents)
    ].
    (argCounter value >= 3) ifTrue:[ 
        tempArguments add:(self argStringAndValueFromEditorContents:tempArgument3EditorContents)
    ].


    ^tempArguments
!

extractClassAndSelectorFrom:anArgument 
    "extracts the class and selector from a list entry,
     which contains the classname and selector sep'd by a space.
     Return an association"

    |aClass aSelector x theArgument marker|

    anArgument isNil ifTrue:[
        ^ nil
    ].
    marker := self class markerForImplementingClass.

    theArgument := anArgument string withoutPrefix:marker.
    aClass := theArgument copyUpTo:(Character space).
    x := aClass size + 2.
    aSelector := theArgument copyFrom:x.
    aClass := Smalltalk classNamed:aClass.
    (aSelector startsWith:'class ') ifTrue:[
        aSelector := aSelector withoutPrefix:'class '.
        aClass := aClass class.
    ].
    ^ aClass -> aSelector asSymbol

    "
     MethodFinderWindow new extractClassAndSelectorFrom: '*SmallInteger +'
     MethodFinderWindow new extractClassAndSelectorFrom: 'String ,'       
     MethodFinderWindow new extractClassAndSelectorFrom: 'Number detentBy:atMultiplesOf:snap:' 
    "

    "Modified: / 27-04-2012 / 15:05:53 / cg"
!

isExpression:aString 
    "Return true or false depending on if the subString includes certain characters"

    |tree|

    Error ignoreIn:[
        tree := Parser parseExpression:aString.
        ^ tree isMessage
    ].

    "/ cg: this is naive - why not ask the parser, if it is a literal?
    (aString includesSubString:': ') ifTrue:[
        ^ true
    ].
    (aString includes:$+) ifTrue:[
        ^ true
    ].
    (aString includes:$-) ifTrue:[
        ^ true
    ].
    (aString includes:$*) ifTrue:[
        ^ true
    ].
    (aString includes:$/) ifTrue:[
        ^ true
    ].
    (aString includes:$>) ifTrue:[
        ^ true
    ].
    (aString includes:$<) ifTrue:[
        ^ true
    ].
    (aString includesSubString:' new') ifTrue:[
        ^ true
    ].
    (aString includes:$[) 
        & (aString includes:$]) 
        & (aString includes:$.) ifTrue:[ ^ false ].

    (aString includes:$.) ifTrue:[
        ^ true
    ].
    ^ false
!

receiverEditorContents
    "Return a cleaned up version of receiver taken from the receiverEditor
     as an association. The association has aCleanedReceiverString as a key and the
     compiledReceiver as value."

    |aCleanedReceiverString compiledReceiver|

    aCleanedReceiverString := self cleanInputs:(receiverEditor contents).

    "/ allow C-style integers 
"/ (now supported by compiler)
"/    (aCleanedReceiverString startsWith:'0b') ifTrue:[
"/        aCleanedReceiverString := '2r',(aCleanedReceiverString withoutPrefix:'0b')
"/    ] ifFalse:[
"/        (aCleanedReceiverString startsWith:'0x') ifTrue:[
"/            aCleanedReceiverString := '16r',(aCleanedReceiverString withoutPrefix:'0x')
"/        ] ifFalse:[
"/            (aCleanedReceiverString startsWith:'0o') ifTrue:[
"/                aCleanedReceiverString := '8r',(aCleanedReceiverString withoutPrefix:'0o')
"/            ].
"/        ].
"/    ].
    compiledReceiver := Compiler evaluate:aCleanedReceiverString.
    ((self isExpression:aCleanedReceiverString) or:[ compiledReceiver isNil ]) ifTrue:[
        aCleanedReceiverString := compiledReceiver printString
    ].
    ^ aCleanedReceiverString -> compiledReceiver.
!

waitForBackgroundSearchFinished
    | p |

    (p := searchProcess) isNil ifTrue:[^ self].
    p isDead ifTrue:[^ self].
    p waitUntilTerminated 
! !

!MethodFinderWindow methodsFor:'user actions'!

selectedClassOfResultIndexHolderChanged
    |selIdx sel classAndSelector mthd|

    selIdx := self selectedClassOfResultIndexHolder value.
    selIdx isNil ifTrue:[^ self].

    sel := classOfResultListHolder value at:selIdx.

    classAndSelector := self extractClassAndSelectorFrom:sel.
    classAndSelector isNil ifTrue:[
        ^ self
    ].

    mthd := classAndSelector key >> classAndSelector value.   
    mthd notNil ifTrue:[
        self withWaitCursorDo:[
            self codeHolder value:mthd source
        ]
    ] ifFalse:[
        self codeHolder value:nil
    ].

    "Created: / 13.11.2001 / 12:43:43 / cg"
    "Modified: / 13.11.2001 / 12:48:56 / cg"
!

selectorPatternChanged
    self searchPatternMatchesInBackground

    "Created: / 01-06-2012 / 13:18:16 / cg"
! !

!MethodFinderWindow class methodsFor:'documentation'!

version
    ^ '$Header$'
!

version_CVS
    ^ '$Header$'
! !