james@1522: "{ Package: 'stx:libtool2' }" james@1522: james@1522: ApplicationModel subclass:#MethodFinderWindow james@1522: instanceVariableNames:'argumentsEditor messageAnswerEditor receiverEditor receiver james@1522: resultSelectors arg2BoxVisible arg1BoxVisible arg4BoxVisible james@1522: arg3BoxVisible argCountHolder argCountList argument1Editor james@1522: argument2Editor argument3Editor argument4Editor resultSelected cg@1532: lookAtResultEditor codeHolder' james@1522: classVariableNames:'' james@1522: poolDictionaries:'' cg@1538: category:'Interface-MethodFinder' james@1522: ! james@1522: cg@1530: !MethodFinderWindow class methodsFor:'documentation'! cg@1530: cg@1530: documentation cg@1530: " cg@1531: [author:] cg@1531: ported from Squeak and GUI enhanced by James Hayes james@exept.de cg@1530: " cg@1530: ! ! james@1522: cg@1532: !MethodFinderWindow class methodsFor:'constants'! cg@1532: cg@1532: markerForImplementingClass cg@1532: ^ '=> '. cg@1532: ^ '*' cg@1532: cg@1532: "Created: / 13.11.2001 / 12:09:52 / cg" cg@1532: "Modified: / 13.11.2001 / 12:11:57 / cg" cg@1532: ! ! cg@1532: james@1522: !MethodFinderWindow class methodsFor:'interface specs'! james@1522: james@1522: windowSpec james@1522: "This resource specification was automatically generated james@1522: by the UIPainter of ST/X." james@1522: james@1522: "Do not manually edit this!! If it is corrupted, james@1522: the UIPainter may not be able to read the specification." james@1522: james@1522: " james@1522: UIPainter new openOnClass:MethodFinderWindow andSelector:#windowSpec james@1522: MethodFinderWindow new openInterface:#windowSpec james@1522: MethodFinderWindow open james@1522: " james@1522: james@1522: james@1522: james@1522: ^ james@1522: #(#FullSpec james@1522: #name: #windowSpec james@1522: #window: james@1522: #(#WindowSpec james@1522: #label: 'MethodFinder' james@1522: #name: 'MethodFinder' james@1525: #min: #(#Point nil nil) james@1525: #max: #(#Point nil nil) cg@1530: #bounds: #(#Rectangle 13 23 563 423) james@1525: #menu: #menu james@1525: #forceRecursiveBackground: false james@1522: ) james@1522: #component: james@1522: #(#SpecCollection james@1522: #collection: #( cg@1532: #(#VariableHorizontalPanelSpec cg@1532: #name: 'VariableHorizontalPanel1' cg@1530: #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) cg@1532: #snapMode: #both james@1522: #component: james@1522: #(#SpecCollection james@1522: #collection: #( cg@1530: #(#ViewSpec cg@1532: #name: 'Box6' cg@1532: #level: 1 james@1522: #component: james@1522: #(#SpecCollection james@1522: #collection: #( cg@1532: #(#SequenceViewSpec cg@1532: #name: 'List1' cg@1532: #layout: #(#LayoutFrame 0 0 0 0.5 0 1 0 1) cg@1532: #hasHorizontalScrollBar: true cg@1532: #hasVerticalScrollBar: true cg@1532: #autoHideScrollBars: true cg@1532: #valueChangeSelector: #updateImplementorsOf: cg@1530: #useIndex: true cg@1532: #sequenceList: #resultHolder cg@1530: ) cg@1532: #(#ViewSpec cg@1532: #name: 'Box4' cg@1532: #layout: #(#LayoutFrame 0 0 0 0 0 1 -25 0.5) james@1522: #component: james@1522: #(#SpecCollection james@1522: #collection: #( cg@1532: #(#LabelSpec cg@1532: #label: 'Receiver' cg@1532: #name: 'ReceiverLabel' cg@1532: #layout: #(#LayoutFrame -4 0.0162791 0 0 -4 0.293023 24 0) cg@1532: #translateLabel: true cg@1532: #adjust: #center cg@1530: ) cg@1532: #(#ComboListSpec cg@1532: #name: 'allowedArgments' cg@1532: #layout: #(#LayoutFrame 0 0.339535 1 0 0 0.653488 23 0) cg@1532: #model: #argCountHolder cg@1532: #comboList: #argCountList cg@1532: #useIndex: true cg@1532: ) cg@1532: #(#LabelSpec cg@1532: #label: 'Answer' cg@1532: #name: 'MessageAnswerLabel' cg@1532: #layout: #(#LayoutFrame 0 0.6693 0 0 0 0.99023 24 0) cg@1532: #translateLabel: true cg@1532: #adjust: #center cg@1532: ) cg@1532: #(#HorizontalPanelViewSpec cg@1532: #name: 'HorizontalPanel1' cg@1532: #layout: #(#LayoutFrame 0 0 25 0 0 1 0 1) cg@1530: #horizontalLayout: #fit cg@1530: #verticalLayout: #fit cg@1530: #horizontalSpace: 3 cg@1530: #verticalSpace: 3 james@1525: #component: james@1525: #(#SpecCollection james@1525: #collection: #( cg@1532: #(#WorkspaceSpec cg@1532: #name: 'ReceiverEditor' cg@1532: #tabable: true cg@1532: #hasHorizontalScrollBar: true cg@1532: #hasVerticalScrollBar: true cg@1532: #miniScrollerHorizontal: true cg@1532: #miniScrollerVertical: true cg@1532: #autoHideScrollBars: true cg@1532: #extent: #(#Point 87 149) cg@1532: #postBuildCallback: #receiverWidgetCreated: cg@1532: ) cg@1532: #(#VerticalPanelViewSpec cg@1532: #name: 'VerticalPanel1' cg@1532: #horizontalLayout: #fit cg@1532: #verticalLayout: #fit cg@1532: #horizontalSpace: 3 cg@1532: #verticalSpace: 3 cg@1530: #component: cg@1530: #(#SpecCollection cg@1530: #collection: #( cg@1532: #(#ViewSpec cg@1532: #name: 'Box1' cg@1532: #visibilityChannel: #arg1BoxVisible cg@1532: #component: cg@1532: #(#SpecCollection cg@1532: #collection: #( cg@1532: #(#WorkspaceSpec cg@1532: #name: 'Arg1Editor' cg@1532: #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) cg@1532: #tabable: true cg@1532: #hasHorizontalScrollBar: true cg@1532: #hasVerticalScrollBar: true cg@1532: #miniScrollerHorizontal: true cg@1532: #miniScrollerVertical: true cg@1532: #autoHideScrollBars: true cg@1532: #postBuildCallback: #argument1WidgetCreated: cg@1532: ) cg@1532: ) cg@1532: cg@1532: ) cg@1532: #extent: #(#Point 87 48) cg@1532: ) cg@1532: #(#ViewSpec cg@1532: #name: 'Box2' cg@1532: #visibilityChannel: #arg2BoxVisible cg@1532: #component: cg@1532: #(#SpecCollection cg@1532: #collection: #( cg@1532: #(#WorkspaceSpec cg@1532: #name: 'TextEditor5' cg@1532: #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) cg@1532: #tabable: true cg@1532: #hasHorizontalScrollBar: true cg@1532: #hasVerticalScrollBar: true cg@1532: #miniScrollerHorizontal: true cg@1532: #miniScrollerVertical: true cg@1532: #autoHideScrollBars: true cg@1532: #postBuildCallback: #argument2WidgetCreated: cg@1532: ) cg@1532: ) cg@1532: cg@1532: ) cg@1532: #extent: #(#Point 87 47) cg@1532: ) cg@1532: #(#ViewSpec cg@1532: #name: 'Box3' cg@1532: #visibilityChannel: #arg3BoxVisible cg@1532: #component: cg@1532: #(#SpecCollection cg@1532: #collection: #( cg@1532: #(#WorkspaceSpec cg@1532: #name: 'TextEditor6' cg@1532: #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) cg@1532: #tabable: true cg@1532: #hasHorizontalScrollBar: true cg@1532: #hasVerticalScrollBar: true cg@1532: #miniScrollerHorizontal: true cg@1532: #miniScrollerVertical: true cg@1532: #autoHideScrollBars: true cg@1532: #postBuildCallback: #argument3WidgetCreated: cg@1532: ) cg@1532: ) cg@1532: cg@1532: ) cg@1532: #extent: #(#Point 87 48) cg@1530: ) cg@1530: ) cg@1530: cg@1530: ) cg@1532: #extent: #(#Point 87 149) cg@1530: ) cg@1532: #(#WorkspaceSpec cg@1532: #name: 'AnswerEditor' cg@1532: #tabable: true cg@1532: #hasHorizontalScrollBar: true cg@1532: #hasVerticalScrollBar: true cg@1532: #miniScrollerHorizontal: true cg@1532: #miniScrollerVertical: true cg@1532: #autoHideScrollBars: true cg@1532: #extent: #(#Point 88 149) cg@1532: #postBuildCallback: #messageAnswerWidgetCreated: james@1525: ) james@1525: ) james@1525: james@1525: ) james@1525: ) cg@1532: ) cg@1532: cg@1532: ) cg@1532: ) cg@1532: #(#ViewSpec cg@1532: #name: 'Box5' cg@1532: #layout: #(#LayoutFrame 53 0.224737 -23 0.5 0 1 0 0.5) cg@1532: #component: cg@1532: #(#SpecCollection cg@1532: #collection: #( cg@1532: #(#ActionButtonSpec cg@1532: #label: 'Clear' cg@1532: #name: 'Button2' cg@1532: #layout: #(#LayoutFrame 0 0 0 0 -5 0.5 0 1) cg@1532: #translateLabel: true cg@1532: #model: #clear cg@1532: ) cg@1532: #(#ActionButtonSpec cg@1532: #label: 'Search' cg@1532: #name: 'Button1' cg@1532: #layout: #(#LayoutFrame 5 0.5 0 0 0 1 0 1) cg@1532: #translateLabel: true cg@1530: #tabable: true cg@1532: #model: #search james@1522: ) james@1522: ) james@1522: james@1522: ) james@1522: ) cg@1530: ) cg@1530: cg@1530: ) cg@1530: ) cg@1532: #(#VariableVerticalPanelSpec cg@1532: #name: 'VariableVerticalPanel1' cg@1530: #component: cg@1530: #(#SpecCollection cg@1530: #collection: #( cg@1532: #(#SequenceViewSpec cg@1532: #name: 'List2' cg@1532: #model: #selectedClassOfResultHolder cg@1532: #menu: #implementorListMenu cg@1532: #hasHorizontalScrollBar: true cg@1532: #hasVerticalScrollBar: true cg@1532: #autoHideScrollBars: true cg@1532: #doubleClickSelector: #openBrowserOn: cg@1532: #valueChangeSelector: #selectedClassOfResultHolderChanged cg@1532: #useIndex: false cg@1532: #sequenceList: #classOfResultHolder cg@1530: ) cg@1532: #(#CodeViewSpec cg@1532: #name: 'CodeView' cg@1532: #model: #codeHolder cg@1532: #hasHorizontalScrollBar: true cg@1532: #hasVerticalScrollBar: true cg@1532: #autoHideScrollBars: true cg@1532: #postBuildCallback: #sourceCodeWidgetCreated: james@1522: ) james@1522: ) james@1522: james@1522: ) cg@1532: #handles: #(#Any 0.5 1.0) james@1522: ) james@1522: ) james@1522: james@1522: ) cg@1532: #handles: #(#Any 0.5 1.0) james@1522: ) james@1522: ) james@1522: james@1522: ) james@1522: ) cg@1530: cg@1532: "Modified: / 13.11.2001 / 12:53:50 / cg" james@1522: ! ! james@1522: james@1525: !MethodFinderWindow class methodsFor:'menu specs'! james@1525: cg@1529: implementorListMenu cg@1529: "This resource specification was automatically generated cg@1529: by the MenuEditor of ST/X." cg@1529: cg@1529: "Do not manually edit this!! If it is corrupted, cg@1529: the MenuEditor may not be able to read the specification." cg@1529: cg@1529: " cg@1529: MenuEditor new openOnClass:MethodFinderWindow andSelector:#implementorListMenu cg@1529: (Menu new fromLiteralArrayEncoding:(MethodFinderWindow implementorListMenu)) startUp cg@1529: " cg@1529: cg@1529: cg@1529: cg@1529: ^ cg@1529: #(#Menu cg@1529: #( cg@1529: #(#MenuItem cg@1529: #label: 'Browse' cg@1529: #translateLabel: true cg@1529: #value: #openBrowserOnSelectedItem cg@1529: ) cg@1529: ) cg@1529: nil cg@1529: nil cg@1529: ) cg@1529: ! cg@1529: james@1525: menu james@1525: "This resource specification was automatically generated james@1525: by the MenuEditor of ST/X." james@1525: james@1525: "Do not manually edit this!! If it is corrupted, james@1525: the MenuEditor may not be able to read the specification." james@1525: james@1525: " james@1525: MenuEditor new openOnClass:MethodFinderWindow andSelector:#menu james@1525: (Menu new fromLiteralArrayEncoding:(MethodFinderWindow menu)) startUp james@1525: " james@1525: james@1525: james@1525: james@1525: ^ james@1525: #(#Menu james@1525: #( james@1525: #(#MenuItem james@1525: #label: '&File' james@1525: #activeHelpKey: #file james@1525: #submenu: james@1525: #(#Menu james@1525: #( james@1525: #(#MenuItem james@1525: #label: 'Exit' james@1525: #value: #closeRequest james@1525: #activeHelpKey: #fileExit james@1525: ) james@1525: ) james@1525: nil james@1525: nil james@1525: ) james@1525: ) james@1525: #(#MenuItem james@1525: #label: 'Help' james@1525: #startGroup: #right james@1525: #submenu: james@1525: #(#Menu james@1525: #( james@1525: #(#MenuItem james@1525: #label: 'Documentation' james@1525: #value: #openHTMLDocumentation james@1525: #activeHelpKey: #helpTutorial james@1525: ) james@1525: #(#MenuItem cg@1532: #label: 'About MethodFinder...' james@1525: #value: #openAboutThisApplication james@1525: #activeHelpKey: #aboutThisAppliaction james@1525: ) james@1525: ) james@1525: nil james@1525: nil james@1525: ) james@1525: ) james@1525: ) james@1525: nil james@1525: nil james@1525: ) cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:36:39 / cg" james@1525: ! ! james@1525: james@1522: !MethodFinderWindow methodsFor:'accessing'! james@1522: james@1522: receiver james@1525: "Return a copy of the value of the instance variable 'receiver' " james@1522: james@1522: ^ receiver copy james@1522: ! ! james@1522: james@1522: !MethodFinderWindow methodsFor:'actions'! james@1522: james@1522: argumentEditorsContents james@1525: james@1525: "Determine how many text editors of the arguments are used and store the result james@1525: as argCounter. The result being the minimum between how many editors have james@1525: expressions in and how many are displayed. james@1525: james@1525: Add each argument string (key)and the evaluated version (value) to an Ordered Dictionary james@1525: from each of the text editors. james@1525: james@1525: Return the OrderedDictionary with the expressions from all the text editors. " james@1525: sr@2165: | tempArguments argCounter tempArgument1Editor tempArgument2Editor tempArgument3Editor james@1522: associationKey associationValue| james@1522: james@1522: argCounter:=0. james@1522: james@1522: tempArgument1Editor:= (self cleanInputs: argument1Editor contents). james@1522: tempArgument2Editor:= (self cleanInputs: argument2Editor contents). james@1522: tempArgument3Editor:= (self cleanInputs: argument3Editor contents). james@1522: james@1522: tempArgument1Editor = '' ifFalse:[argCounter:=argCounter +1]. james@1522: tempArgument2Editor = '' ifFalse:[argCounter:=argCounter +1]. james@1522: tempArgument3Editor = '' ifFalse:[argCounter:=argCounter +1]. james@1522: james@1522: james@1522: argCounter:= (argCounter min: (self argCountHolder value -1)). james@1522: tempArguments:= OrderedDictionary new:argCounter. james@1522: james@1522: (argCounter value >= 1) james@1522: ifTrue:[associationValue:= (Compiler evaluate: tempArgument1Editor). james@1522: ((self isExpression:tempArgument1Editor) or:[ associationValue isNil]) ifTrue:[ "looks if an expression is typed in" james@1522: associationKey:=associationValue printString] james@1522: ifFalse:[ james@1522: associationKey:=tempArgument1Editor]. james@1522: james@1522: tempArguments add: associationKey-> associationValue. james@1522: ]. james@1522: (argCounter value >= 2) james@1522: ifTrue:[ associationValue:= (Compiler evaluate: tempArgument2Editor). james@1522: (((self isExpression:tempArgument2Editor) or:[ associationValue isNil])) ifTrue:[ "looks if an expression is typed in" james@1522: associationKey:=associationValue printString] james@1522: ifFalse:[ james@1522: associationKey:=tempArgument2Editor]. james@1522: james@1522: tempArguments add: associationKey-> associationValue]. james@1522: james@1522: (argCounter value >= 3) james@1522: ifTrue:[ associationValue:= (Compiler evaluate: tempArgument3Editor). james@1522: ((self isExpression:tempArgument3Editor) or:[ associationValue isNil]) ifTrue:[ "looks if an expression is typed in" james@1522: associationKey:=associationValue printString] james@1522: ifFalse:[ james@1522: associationKey:=tempArgument3Editor]. james@1522: james@1522: tempArguments add: associationKey-> associationValue]. james@1522: james@1522: james@1522: ^tempArguments james@1522: ! james@1522: james@1522: clear james@1525: "Reset the contents of all the outputs. Return the receiver." james@1522: james@1522: receiverEditor contents:nil. james@1522: argument1Editor contents:nil. james@1522: argument2Editor contents:nil. james@1522: argument3Editor contents:nil. james@1522: messageAnswerEditor contents:nil. james@1522: self resultHolder value:nil. james@1525: self classOfResultHolder value: nil. james@1522: ! james@1522: cg@1532: extractClassAndSelectorFrom:anArgument cg@1532: "Opens browser on theArgument of a specific class. anArgument being a string with the cg@1532: Class and the selector upon which the browser is to be opened. Return the receiver." cg@1532: cg@1532: |aClass aSelector x theArgument marker| cg@1532: cg@1532: anArgument isNil ifTrue:[ cg@1532: ^ nil cg@1532: ]. cg@1532: marker := self class markerForImplementingClass. cg@1532: cg@1532: theArgument := anArgument string. cg@1532: (theArgument startsWith:marker) ifTrue:[ cg@1532: theArgument := theArgument copyFrom:marker size+1 cg@1532: ]. cg@1532: aClass := theArgument copyUpTo:(Character space). cg@1532: x := aClass size + 2. cg@1532: aSelector := theArgument copyFrom:x. cg@1532: aClass := Smalltalk classNamed:aClass. cg@1532: ^ aClass -> aSelector asSymbol cg@1532: cg@1532: " cg@1532: MethodFinderWindow new extractClassAndSelectorFrom: '*SmallInteger +' cg@1532: MethodFinderWindow new extractClassAndSelectorFrom: 'String ,' cg@1532: MethodFinderWindow new extractClassAndSelectorFrom: 'Number detentBy:atMultiplesOf:snap:' cg@1532: cg@1532: cg@1532: " cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:45:43 / cg" cg@1532: ! cg@1532: james@1522: isExpression: aString james@1525: "Return true or false depending on if the subString includes certain characters" james@1522: (aString includesSubString:': ') ifTrue:[^true]. james@1522: (aString includesSubString:'+') ifTrue:[^true]. james@1522: (aString includesSubString:'-') ifTrue:[^true]. james@1522: (aString includesSubString:'*') ifTrue:[^true]. james@1522: (aString includesSubString:'/') ifTrue:[^true]. james@1522: (aString includesSubString:'>') ifTrue:[^true]. james@1522: (aString includesSubString:'<') ifTrue:[^true]. james@1522: (aString includesSubString:' new') ifTrue:[^true]. james@1522: (aString includesSubString:'[') & (aString includesSubString:']') & (aString includesSubString:'.') james@1522: ifTrue:[^false]. james@1522: (aString includesSubString:'.') ifTrue:[^true]. james@1522: james@1522: ^false james@1522: ! james@1522: james@1522: messageAnswerEditorContents james@1525: "Return a cleaned up version of message answer taken from the messageAnswerEditor james@1525: as an association. The association has cleanedAnswerString as a key and the james@1525: compiledAnswer as value." james@1522: james@1522: | aCleanedAnswerString compiledAnswer | james@1522: james@1522: aCleanedAnswerString:=self cleanInputs: (messageAnswerEditor contents). james@1522: compiledAnswer:=Compiler evaluate: aCleanedAnswerString. james@1522: ((self isExpression:aCleanedAnswerString) or:[compiledAnswer isNil]) ifTrue:[ james@1522: aCleanedAnswerString:=compiledAnswer printString]. james@1522: james@1522: ^aCleanedAnswerString->compiledAnswer. james@1522: ! james@1522: james@1522: openBrowserOn:anArgument james@1522: "Opens browser on theArgument of a specific class. anArgument being a string with the james@1525: Class and the selector upon which the browser is to be opened. Return the receiver." james@1522: cg@1532: |classAndSelector| james@1522: cg@1532: classAndSelector := self extractClassAndSelectorFrom:anArgument. cg@1532: classAndSelector isNil ifTrue:[ james@1525: ^ self james@1522: ]. cg@2459: UserPreferences current systemBrowserClass cg@2459: openInClass:classAndSelector key cg@2459: selector:classAndSelector value james@1525: james@1525: " james@1525: MethodFinderWindow new openBrowserOn: '*SmallInteger +' james@1525: MethodFinderWindow new openBrowserOn: 'String ,' james@1525: MethodFinderWindow new openBrowserOn: 'Number detentBy:atMultiplesOf:snap:' james@1525: james@1525: james@1525: " cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:46:17 / cg" james@1522: ! james@1522: cg@1529: openBrowserOnSelectedItem cg@1529: |sel| cg@1529: cg@1529: sel := self selectedClassOfResultHolder value. cg@1529: self openBrowserOn:sel cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:47:39 / cg" cg@1529: ! cg@1529: james@1522: receiverEditorContents james@1525: "Return a cleaned up version of receiver taken from the receiverEditor james@1525: as an association. The association has aCleanedRecieverString as a key and the james@1525: compiledReceiver as value." james@1525: james@1522: | aCleanedRecieverString compiledReceiver | james@1522: james@1522: aCleanedRecieverString:=self cleanInputs: (receiverEditor contents). james@1522: james@1522: compiledReceiver:=Compiler evaluate: aCleanedRecieverString. james@1522: james@1522: ((self isExpression:aCleanedRecieverString) or:[compiledReceiver isNil]) ifTrue:[ james@1522: aCleanedRecieverString:=compiledReceiver printString]. james@1522: ^aCleanedRecieverString->compiledReceiver. james@1522: ! james@1522: james@1522: search james@1525: "Do a search based on the input in the various text editors. Return the receiver." james@1522: | tempReceiver tempAnswer tempArguments anArray resultArray receiverWithArgument mf| cg@1534: cg@1534: self resultHolder value: nil. "reset the result list" james@1522: self classOfResultHolder value: nil. "reset the implementorOf list" cg@1534: self codeHolder value: nil. "reset the source" james@1522: james@1522: tempArguments:=self argumentEditorsContents. james@1522: tempReceiver :=self receiverEditorContents . james@1522: tempAnswer:= self messageAnswerEditorContents. james@1522: james@1522: "self cleanInputRec:tempReceiver arg:tempArguments ans:tempAnswer." james@1522: james@1522: james@1522: anArray:=Array new:2. "creates an array which is to be used as input for the method finder." james@1522: james@1522: receiverWithArgument:=self mergReciever: (tempReceiver value) WithArgument: (tempArguments values). james@1522: james@1522: anArray at:1 put:receiverWithArgument; james@1522: at:2 put: tempAnswer value. james@1522: james@1522: "an array now holds the following array #(#(receiver argument) answer) or #(#(reciever) answer). which should james@1522: be suitable input for the method finder." cg@1534: self withCursor:Cursor execute do:[ cg@1534: mf:= MethodFinder new. cg@1534: resultArray:= mf load: anArray; findMessage. cg@1534: ]. james@1522: james@1522: ((resultArray at: 1 )includesSubString: 'no single') ifTrue:[ james@1522: self warn: (resultArray at: 1 ). james@1522: ^self james@1522: ]. james@1522: "the following then replaces data1 and data2 created by the method finder to the appropriate arguments" james@1522: resultArray keysAndValuesDo:[:key :value | | newValue | james@1522: newValue:= value replString: 'data1' withString:(tempReceiver key). james@1522: (tempArguments size) >= 1 ifTrue:[ james@1522: newValue:= newValue replString: 'data2' withString:(tempArguments keyAt:1)]. james@1522: james@1522: (tempArguments size) > 1 ifTrue:[ james@1522: newValue:= newValue replString: 'data3' withString:(tempArguments keyAt:2).]. james@1522: james@1522: (tempArguments size) > 2 ifTrue:[ james@1522: newValue:= newValue replString: 'data4' withString:(tempArguments keyAt:3).]. james@1522: cg@1532: (tempArguments size) > 3 ifTrue:[ self halt. ]. cg@1532: james@1522: james@1522: " newValue:= value replString: 'data3' withString:(self messageAnswer key). " james@1522: james@1522: newValue:=newValue, ' --> ', (tempAnswer key). cg@1532: newValue replaceAll:Character cr with:Character space. james@1522: james@1522: resultArray at: key put: newValue. james@1522: james@1522: ]. james@1522: james@1522: self resultHolder value: resultArray. james@1522: resultSelectors:= mf selectors. "used to find implementors so we do not have to " james@1522: receiver:=tempReceiver "search the string for the selector found. Stored as an ordered collection" cg@1532: cg@1534: "Modified: / 13.11.2001 / 18:52:35 / cg" cg@1532: ! cg@1532: cg@1532: selectedClassOfResultHolderChanged cg@1532: |sel classAndSelector mthd| cg@1532: cg@1532: sel := self selectedClassOfResultHolder value. cg@1532: cg@1532: classAndSelector := self extractClassAndSelectorFrom:sel. cg@1532: classAndSelector isNil ifTrue:[ cg@1532: ^ self cg@1532: ]. cg@1532: mthd := classAndSelector key >> classAndSelector value. cg@1532: mthd notNil ifTrue:[ cg@1532: self withWaitCursorDo:[ cg@1532: self codeHolder value:mthd source cg@1532: ] cg@1532: ] ifFalse:[ cg@1532: self codeHolder value:nil cg@1532: ]. cg@1532: cg@1532: "Created: / 13.11.2001 / 12:43:43 / cg" cg@1532: "Modified: / 13.11.2001 / 12:48:56 / cg" james@1522: ! james@1522: james@1522: updateImplementorsOf:anInteger james@1525: "Request the implementors of the selected argument provided by aNumber. james@1525: Return the receiver. " james@1522: |methods classList aNumber| james@1522: james@1525: james@1522: (anInteger isNil) ifTrue:[^self]. james@1522: anInteger isNil ifTrue:[aNumber:=1] james@1522: ifFalse:[aNumber:=anInteger]. james@1525: methods:=SystemBrowser findImplementorsOf: (resultSelectors at:aNumber) in:Smalltalk allClasses ignoreCase:false. james@1525: classList:=methods asOrderedCollection collect:[:m | m mclass name , ' ' , m selector]. james@1522: james@1522: classList:=(self markMatchingClasses:(resultSelectors at:aNumber) classesWithSelector:classList). james@1522: james@1522: self classOfResultHolder value: classList. cg@1532: self selectedClassOfResultHolder value:nil. cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:07:31 / cg" james@1522: ! ! james@1522: james@1522: !MethodFinderWindow methodsFor:'aspects'! james@1522: james@1522: arg1BoxVisible james@1525: "Determines if the box should be visble or not. Return true or false" james@1522: arg1BoxVisible isNil ifTrue:[ james@1522: arg1BoxVisible := BlockValue james@1522: with:[:vh | vh value >= 2 ] james@1522: argument:(self argCountHolder) james@1522: ]. james@1522: ^ arg1BoxVisible. james@1522: ! james@1522: james@1522: arg2BoxVisible james@1525: "Determines if the box should be visble or not. Return true or false" james@1522: arg2BoxVisible isNil ifTrue:[ james@1522: arg2BoxVisible := BlockValue james@1522: with:[:vh | vh value >= 3 ] james@1522: argument:(self argCountHolder) james@1522: ]. james@1522: ^ arg2BoxVisible. james@1522: ! james@1522: james@1522: arg3BoxVisible james@1525: "Determines if the box should be visble or not. Return true or false" james@1522: arg3BoxVisible isNil ifTrue:[ james@1522: arg3BoxVisible := BlockValue james@1522: with:[:vh | vh value >= 4 ] james@1522: argument:(self argCountHolder) james@1522: ]. james@1522: ^ arg3BoxVisible. james@1522: ! james@1522: james@1522: arg4BoxVisible james@1525: "Determines if the box should be visble or not. Return true or false" james@1522: arg4BoxVisible isNil ifTrue:[ james@1522: arg4BoxVisible := BlockValue james@1522: with:[:vh | vh value >= 5 ] james@1522: argument:(self argCountHolder) james@1522: ]. james@1522: ^ arg4BoxVisible. james@1522: ! james@1522: james@1522: argCountHolder james@1525: "Return the value of argCounterHolder which is initialized at 2." james@1522: argCountHolder isNil ifTrue:[ james@1522: argCountHolder := 2 asValue. james@1522: ]. james@1522: ^ argCountHolder. james@1522: ! james@1522: james@1522: argCountList james@1525: "Return the argCountList" james@1522: argCountList isNil ifTrue:[ james@1522: argCountList := #('0 arguments' '1 argument' '2 arguments' '3 arguments') asValue james@1522: ]. james@1522: ^ argCountList. james@1522: ! james@1522: james@1522: classOfResultHolder james@1525: "Return a valueHolder which contains a collection with the names of the james@1525: implementors of a specific message. " james@1522: james@1522: |holder| james@1522: (holder := builder bindingAt:#classOfResultHolder) isNil ifTrue:[ james@1525: holder := ValueHolder new. james@1525: builder aspectAt:#classOfResultHolder put:holder james@1522: ]. james@1522: ^ holder james@1522: ! james@1522: cg@1532: codeHolder cg@1532: codeHolder isNil ifTrue:[ cg@1532: codeHolder := '' asValue. cg@1532: ]. cg@1532: ^ codeHolder. cg@1532: cg@1532: "Created: / 13.11.2001 / 12:44:11 / cg" cg@1532: ! cg@1532: james@1522: resultHolder james@1525: "Return a value holder which contains the results of a search as a collection." james@1522: james@1522: |holder| james@1522: (holder := builder bindingAt:#resultHolder) isNil ifTrue:[ james@1525: holder := ValueHolder new. james@1525: builder aspectAt:#resultHolder put:holder. james@1522: ]. james@1522: ^ holder. cg@1529: ! cg@1529: cg@1529: selectedClassOfResultHolder cg@1529: "Return a valueHolder which contains the index of the selected result class cg@1529: (right list)" cg@1529: cg@1529: |holder| cg@1529: (holder := builder bindingAt:#selectedClassOfResultHolder) isNil ifTrue:[ cg@1529: holder := ValueHolder new. cg@1529: builder aspectAt:#selectedClassOfResultHolder put:holder cg@1529: ]. cg@1529: ^ holder james@1522: ! ! james@1522: james@1522: !MethodFinderWindow methodsFor:'callBacks'! james@1522: james@1522: argument1WidgetCreated: aWidget james@1525: "Store the widget as an instance variable. Return the receiver" james@1525: james@1525: james@1522: argument1Editor := aWidget scrolledView. cg@1532: aWidget tabMeansNextField:true. cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:21:41 / cg" james@1522: ! james@1522: james@1522: argument2WidgetCreated: aWidget james@1525: "Store the widget as an instance variable. Return the receiver" james@1525: james@1522: james@1522: argument2Editor := aWidget scrolledView. cg@1532: aWidget tabMeansNextField:true. cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:21:45 / cg" james@1522: ! james@1522: james@1522: argument3WidgetCreated: aWidget james@1525: "Store the widget as an instance variable. Return the receiver" james@1525: james@1522: james@1522: argument3Editor := aWidget scrolledView. cg@1532: aWidget tabMeansNextField:true. cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:21:49 / cg" james@1522: ! james@1522: james@1525: messageAnswerWidgetCreated: aWidget james@1525: "Store the widget as an instance variable. Return the receiver" james@1522: james@1525: messageAnswerEditor := aWidget scrolledView. cg@1532: aWidget tabMeansNextField:true. cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:24:55 / cg" james@1522: ! james@1522: james@1525: openHTMLDocumentation james@1525: HTMLDocumentView openFullOnDocumentationFile:'tools/misc/TOP.html#METHODFINDER' james@1522: ! james@1522: james@1522: receiverWidgetCreated: aWidget james@1525: "Store the widget as an instance variable. Return the receiver" james@1522: james@1522: receiverEditor := aWidget scrolledView. cg@1532: aWidget tabMeansNextField:true. cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:24:49 / cg" cg@1532: ! cg@1532: cg@1532: sourceCodeWidgetCreated: aWidget cg@1532: aWidget acceptAction:nil. cg@1532: aWidget readOnly:true cg@1532: cg@1532: "Created: / 13.11.2001 / 12:50:27 / cg" cg@1532: "Modified: / 13.11.2001 / 12:51:23 / cg" james@1522: ! ! james@1522: james@1522: !MethodFinderWindow methodsFor:'controlInput'! james@1522: james@1522: cleanInputs: aDirtyString james@1525: "Find and remove common mistakes made by the user. Return the james@1525: 'aStringToBeCleaned' variable" james@1522: | aStringToBeCleaned rs position| james@1522: james@1522: aStringToBeCleaned:=aDirtyString. james@1522: james@1522: (aStringToBeCleaned endsWith:(Character cr)) ifTrue:[ james@1522: aStringToBeCleaned:=aStringToBeCleaned copyFrom:1 to: (aStringToBeCleaned size -1).]. james@1522: aStringToBeCleaned:= aStringToBeCleaned withoutSeparators. james@1522: james@1522: james@1522: rs:=ReadStream on: aStringToBeCleaned. james@1522: [rs upToAll: '#true'. rs atEnd] whileFalse: [ james@1522: position:= rs position. james@1522: aStringToBeCleaned:=aStringToBeCleaned copyReplaceFrom: position to: position with: ''. "remove #" james@1522: rs:=ReadStream on: aStringToBeCleaned. james@1522: ]. james@1522: james@1522: rs:=ReadStream on: aStringToBeCleaned. james@1522: [rs upToAll: '#false'. rs atEnd] whileFalse: [ james@1522: position:= rs position. james@1522: aStringToBeCleaned:=aStringToBeCleaned copyReplaceFrom: position to: position with: ''. "remove #" james@1522: rs:=ReadStream on: aStringToBeCleaned. james@1522: rs:=ReadStream on: aStringToBeCleaned. ]. james@1522: james@1522: [rs upToAll: '#nil'. rs atEnd] whileFalse: [ james@1522: position:= rs position. james@1522: aStringToBeCleaned:=aStringToBeCleaned copyReplaceFrom: position to: position with: ''. "remove #" james@1522: rs:=ReadStream on: aStringToBeCleaned. ]. james@1522: ^aStringToBeCleaned james@1522: ! james@1522: james@1525: markMatchingClasses: aSelector classesWithSelector:anOrderedCollection james@1525: " Matches the class of the receiver with all the elements in anOrderedCollection james@1525: (which are classes with selectors). If a match is found it is marked with an asterisk. james@1525: The classes are then sorted so the the asterisk appears first. Return the james@1525: markedClassList." james@1522: sr@2165: | marker recClass unmarkedClassList markedClassList| james@1522: cg@1532: marker := self class markerForImplementingClass. cg@1532: cg@1532: recClass := receiver value class. james@1525: unmarkedClassList:=anOrderedCollection copy. james@1525: unmarkedClassList do: james@1525: [:classAndMethod | | class | james@1525: class:=Compiler evaluate: james@1525: ((ReadStream on: classAndMethod) upToAll: aSelector). cg@1532: "/ (recClass == class) cg@1532: (recClass whichClassImplements:aSelector) == class cg@1532: ifTrue: cg@1532: ["/ unmarkedClassList add: marker, classAndMethod. cg@1532: unmarkedClassList add: classAndMethod allBold. cg@1532: unmarkedClassList remove: classAndMethod. cg@1532: ]. cg@1532: ]. james@1522: james@1522: unmarkedClassList sort:[:a :b | |rawA rawB| cg@1532: rawA := a string. cg@1532: (rawA startsWith:marker) ifTrue:[rawA := rawA copyFrom:marker size+1]. cg@1532: rawB := b string. cg@1532: (rawB startsWith:marker) ifTrue:[rawB := rawB copyFrom:marker size+1]. cg@1532: rawA < rawB. ]. james@1525: markedClassList:= unmarkedClassList. james@1525: james@1525: ^markedClassList cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:16:05 / cg" james@1522: ! james@1522: james@1522: mergReciever: aReceiver WithArgument: arguments james@1522: james@1525: "Puts the receiver and arguments into an array so it can be of a suitable input for the james@1525: MethodFinder. Return an array." james@1525: james@1522: | tempReceiver tempArguments receiverWithArgument| james@1522: james@1522: tempReceiver:= aReceiver. james@1522: tempArguments := arguments. james@1522: james@1522: (tempArguments isEmpty or:[(tempArguments) isNil]) james@1522: ifTrue:[ receiverWithArgument:=Array new:1."no argument" james@1522: receiverWithArgument at:1 put: tempReceiver. james@1522: ] james@1522: ifFalse:[ james@1522: (tempArguments size = 1) james@1522: ifTrue:[ receiverWithArgument:=Array new:2. james@1522: receiverWithArgument at:1 put: tempReceiver. james@1522: receiverWithArgument at:2 put: (tempArguments at:1) james@1522: ]. "a receiver with an argument" james@1522: james@1522: (tempArguments size = 2) james@1522: ifTrue:[ receiverWithArgument:=Array new:3. james@1522: receiverWithArgument at:1 put: tempReceiver. james@1522: (receiverWithArgument at:2 put: (tempArguments at:1)). james@1522: (receiverWithArgument at:3 put: (tempArguments at:2)) james@1522: ]. "a receiver with an argument" james@1522: (tempArguments size = 3) james@1522: ifTrue:[ receiverWithArgument:=Array new:4. james@1522: receiverWithArgument at:1 put: tempReceiver. james@1522: (receiverWithArgument at:2 put: (tempArguments at:1)). james@1522: (receiverWithArgument at:3 put: (tempArguments at:2)). james@1522: (receiverWithArgument at:4 put: (tempArguments at:3)). james@1522: james@1522: ]. "a receiver with an argument" james@1522: james@1522: ]. james@1522: ^receiverWithArgument james@1522: ! ! james@1522: cg@1532: !MethodFinderWindow methodsFor:'misc'! cg@1532: cg@1532: aboutThisApplicationText cg@1532: |msg| cg@1532: cg@1532: msg := super aboutThisApplicationText. cg@2412: msg := msg , '\\Ported from Squeak to ST/X by James Hayes (james@exept.de). cg@2412: Original written by Ted Kaehler, Scott Wallace and Dan Ingalls.'. cg@1532: ^msg withCRs. cg@1532: cg@1532: "Modified: / 13.11.2001 / 12:56:44 / cg" cg@1532: ! ! cg@1532: james@1522: !MethodFinderWindow class methodsFor:'documentation'! james@1522: james@1522: version james@1522: ^ '$Header$' james@1522: ! !