diff -r 4c863461e5a2 -r 00b306851c88 Tools__CodeNavigationService.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Tools__CodeNavigationService.st Fri Jul 01 15:20:03 2011 +0200 @@ -0,0 +1,542 @@ +" + COPYRIGHT (c) 2006 by eXept Software AG + All Rights Reserved + + This software is furnished under a license and may be used + only in accordance with the terms of that license and with the + inclusion of the above copyright notice. This software may not + be provided or otherwise made available to, or used by, any + other person. No title to or ownership of the software is + hereby transferred. +" +"{ Package: 'stx:libtool' }" + +"{ NameSpace: Tools }" + +CodeViewService subclass:#CodeNavigationService + instanceVariableNames:'selectorEmphasis variableEmphasis currentEmphasis' + classVariableNames:'' + poolDictionaries:'' + category:'Interface-CodeView' +! + +!CodeNavigationService class methodsFor:'documentation'! + +copyright +" + COPYRIGHT (c) 2006 by eXept Software AG + All Rights Reserved + + This software is furnished under a license and may be used + only in accordance with the terms of that license and with the + inclusion of the above copyright notice. This software may not + be provided or otherwise made available to, or used by, any + other person. No title to or ownership of the software is + hereby transferred. +" +! ! + +!CodeNavigationService class methodsFor:'accessing'! + +label + + "Answers short label - for UI" + + ^'Semi-modal Code Navigation' + + "Created: / 07-03-2010 / 14:00:43 / Jan Vrany " +! ! + +!CodeNavigationService class methodsFor:'accessing - defaults'! + +defaultSelectorEmphasis + ^ Array with:#backgroundColor + -> (Color white blendWith:(Color + redByte:100 + greenByte:180 + blueByte:255)) +! + +defaultVariableEmphasis + ^ Array with:#backgroundColor + -> (Color gray: 90) + + "Created: / 25-06-2010 / 13:56:43 / Jan Vrany " +! ! + +!CodeNavigationService methodsFor:'code services'! + +browseClass: class + + self browser ifNil: [^NewSystemBrowser browseClass:class]. + (UserPreferences current alwaysOpenNewTabWhenCtrlClick + or:[self browser navigationState modified]) + ifTrue: + [self browser + spawnFullBrowserInClass: class selector:nil in:#newBuffer] + ifFalse: + [self browser + switchToClass: class] + + "Created: / 15-02-2010 / 09:36:50 / Jan Vrany " + "Modified: / 25-07-2010 / 11:00:26 / Jan Vrany " +! + +browseMethod: method + + self browseMethod: method label: nil. + + "Created: / 14-02-2010 / 19:41:46 / Jan Vrany " +! + +browseMethod: method label: label + + self browser ifNil: [^NewSystemBrowser openInMethod:method]. + (UserPreferences current alwaysOpenNewTabWhenCtrlClick + or:[self browser navigationState modified]) + ifTrue: + [self browser + spawnFullBrowserInClass: method mclass + selector:method selector + in:#newBuffer] + ifFalse: + [self browser + switchToClass: method containingClass + selector: method selector]. + + "Modified: / 19-02-2008 / 10:15:17 / janfrog" + "Created: / 19-10-2008 / 08:16:17 / Jan Vrany " + "Modified: / 25-07-2010 / 13:34:27 / Jan Vrany " +! + +browseMethods: methods label: label + + methods size = 1 ifTrue: + [^self browseMethod: methods anyOne label: label]. + + self browser + ifNil: [NewSystemBrowser browseMethods: methods title: label] + ifNotNil:[self browser spawnMethodBrowserFor:methods in:#newBuffer label:label] + + "Created: / 26-12-2007 / 11:32:04 / janfrog" + "Modified: / 19-10-2008 / 08:17:28 / Jan Vrany " +! + +browser + + ^codeView browserHolder value + + "Created: / 06-03-2010 / 21:14:51 / Jan Vrany " +! + +implementorsOf: selector + + selector ifNil:[^#()]. + ^SystemBrowser + findImplementorsOf: selector + in: Smalltalk allClasses + ignoreCase: false + + "Created: / 26-12-2007 / 11:37:11 / janfrog" +! + +sendersOf: selector + + ^SystemBrowser + findSendersOf: selector + in: Smalltalk allClasses + ignoreCase: false + + "Created: / 26-12-2007 / 11:37:22 / janfrog" +! ! + +!CodeNavigationService methodsFor:'event handling'! + +button1Press + + codeView syntaxElementSelection ifNil:[^self]. + + codeView syntaxElementSelection type == #selector ifTrue:[^self button1PressForSelector: codeView syntaxElementSelection value]. + codeView syntaxElementSelection type == #class ifTrue:[^self browseClass:codeView syntaxElementSelection value]. + + "Created: / 14-02-2010 / 18:43:03 / Jan Vrany " + "Modified: / 06-03-2010 / 21:11:30 / Jan Vrany " +! + +button1PressForSelector: selector + + | impls menu | + impls := self implementorsOf: selector. + impls size = 1 ifTrue:[^self browseMethod: impls anyOne]. + menu := self implementorsMenu: impls selector: selector. + self highlightClear. + menu showAtPointer. + + "Created: / 14-02-2010 / 18:50:13 / Jan Vrany " +! + +button2Press + + | sel | + sel := codeView syntaxElementSelection. + (sel notNil and:[sel type == #selector]) ifTrue:[^self button2PressForSelector: sel value]. + + "Created: / 14-02-2010 / 18:43:04 / Jan Vrany " + "Modified: / 17-06-2011 / 08:58:34 / Jan Vrany " +! + +button2PressForSelector: selector + + | senders menu | + senders := self implementorsOf: selector. + senders size = 1 ifTrue:[^self browseMethod: senders anyOne]. + menu := self sendersMenu: senders selector: selector. + self highlightClear. + menu showAtPointer. + + "Created: / 14-02-2010 / 18:50:13 / Jan Vrany " +! + +buttonMotion: button x:x y:y in: view + + "Handles an event in given view (a subview of codeView). + If the method returns true, the event will not be processed + by the view." + + (view == textView and:[textView sensor ctrlDown]) ifTrue: + [self highlightElementAtX:x y:y. ^true]. + ^false + + "Created: / 06-03-2010 / 20:40:37 / Jan Vrany " +! + +buttonPress: button x:x y:y in: view + + "Handles an event in given view (a subview of codeView). + If the method returns true, the event will not be processed + by the view." + + (view == textView) ifTrue: + [codeView sensor ctrlDown ifTrue: + [button == 1 ifTrue: [self button1Press.^true]. + button == #paste ifTrue: [self button2Press.^true]. + button == 2 ifTrue: [self button2Press.^true]]. + button == 1 ifTrue:[ + self highlightVariableAtX:x y:y. + ] + ]. + ^false + + "Created: / 06-03-2010 / 21:12:26 / Jan Vrany " + "Modified: / 25-06-2010 / 14:53:36 / Jan Vrany " +! + +keyPress:key x:x y:y in:view + "Handles an event in given view (a subview of codeView). + If the method returns true, the event will not be processed + by the view." + + (view == textView) ifTrue:[ + (key == #'Control_L' or:[ key == #Ctrl ]) ifTrue:[ + self highlightElementAtX:x y:y. + ^ true + ]. + self highlightVariableAtCursor. + ^ false + ]. + ^ false + + "Created: / 06-03-2010 / 20:50:45 / Jan Vrany " + "Modified: / 25-06-2010 / 14:46:10 / Jan Vrany " +! + +keyRelease: key x:x y:y in: view + + "Handles an event in given view (a subview of codeView). + If the method returns true, the event will not be processed + by the view." + + (view == textView and:[key == #'Control_L' or:[key == #Ctrl]]) ifTrue: + [self highlightClear. textView redraw. ^true]. + ^false + + "Created: / 06-03-2010 / 21:03:59 / Jan Vrany " +! ! + +!CodeNavigationService methodsFor:'initialization'! + +initialize + + super initialize. + selectorEmphasis := self class defaultSelectorEmphasis. + variableEmphasis := self class defaultVariableEmphasis. + + "Created: / 25-06-2010 / 14:05:09 / Jan Vrany " +! ! + +!CodeNavigationService methodsFor:'menus-dynamic'! + +implementorsMenu: implementors selector: selector + | menu| + + menu := Menu new. + implementors isNilOrEmptyCollection ifTrue:[ + menu addItem:(MenuItem label:'No implementors found') disable + ] ifFalse:[ + menu addItem:(MenuItem + label:(selector storeString , (' (all implementors) ') asText allItalic) + value:[ + self browseMethods:implementors + label:'Implementors of ' , selector storeString + ]). + menu addSeparator. + implementors do:[:mth | + menu + addItem:(MenuItem label:(selector storeString + , (' in ' , mth containingClass name asText allBold)) + value:[ self browseMethod:mth label: 'Implementor of ' , selector storeString ]) + ] + ]. + ^ menu + + "Modified: / 19-10-2008 / 08:16:50 / Jan Vrany " + "Created: / 14-02-2010 / 19:39:37 / Jan Vrany " +! + +sendersMenu: senders selector: selector + | menu| + + menu := Menu new. + senders isNilOrEmptyCollection ifTrue:[ + menu addItem:(MenuItem label:'No senders found') disable + ] ifFalse:[ + menu addItem:(MenuItem + label:(selector storeString , (' (all senders)') asText allItalic) + value:[ + self browseMethods:senders + label:'Senders of ' , selector storeString + ]). + menu addSeparator. + senders do:[:mth | + menu + addItem:(MenuItem label:(mth selector storeString + , (' in ' , mth containingClass name asText allBold)) + value:[ self browseMethod:mth label: 'Sender of ' , selector storeString ]) + ] + ]. + ^ menu + + "Modified: / 19-10-2008 / 08:17:00 / Jan Vrany " + "Created: / 14-02-2010 / 19:40:10 / Jan Vrany " + "Modified: / 01-08-2010 / 11:09:59 / Jan Vrany " +! ! + +!CodeNavigationService methodsFor:'private'! + +elementAtCursor + ^self elementAtLine: textView cursorLine col: textView cursorCol - 1 + + "Created: / 25-06-2010 / 14:39:14 / Jan Vrany " +! + +elementAtLine:line col:col + |characterPosition index element | + + characterPosition := textView characterPositionOfLine:line col:col. + index := SortedCollection binarySearch: (codeView syntaxElements) forIndexOf: characterPosition. + index > (codeView syntaxElements) size ifTrue:[^nil]. + element := (codeView syntaxElements) at: index. + (characterPosition between: element start and: element stop) ifFalse:[^nil]. + ^element + + "Created: / 25-06-2010 / 14:40:03 / Jan Vrany " +! + +elementAtX:x y:y + |visibleLine line col| + + codeView syntaxElements ifNil:[^nil]. + visibleLine := textView visibleLineOfY:y. + col := textView colOfX:x inVisibleLine:visibleLine. + line := textView visibleLineToAbsoluteLine:visibleLine. + ^self elementAtLine:line col:col + + "Created: / 25-06-2010 / 14:52:39 / Jan Vrany " + "Modified: / 01-08-2010 / 08:50:18 / Jan Vrany " +! + +highlighEmphasisFor: element + + element ifNil:[^nil]. + + element type == #selector ifTrue:[^selectorEmphasis]. + element type == #variable ifTrue:[^variableEmphasis]. + + ^nil + + "Created: / 25-06-2010 / 13:54:42 / Jan Vrany " +! + +highlightClear + |textView| + + codeView syntaxElementSelection == nil ifTrue:[^ self]. + + textView := codeView textView. + textView list ifNil:[ ^ self ]. + textView list do:[:line | + line isText ifTrue:[ + line emphasisAllRemove: currentEmphasis + ] + ]. + textView redraw. + codeView syntaxElementSelection:nil. + + "Modified: / 26-12-2007 / 12:28:05 / janfrog" + "Created: / 25-06-2010 / 14:15:58 / Jan Vrany " + "Modified: / 30-06-2011 / 11:07:05 / cg" +! + +highlightElement: element + codeView syntaxElementSelection == element ifTrue:[^ self]. + + self highlightClear. + currentEmphasis := self highlighEmphasisFor: element. + element + ifNotNil: + [|e| + codeView syntaxElementSelection: element. + e := element. + [e isNil] whileFalse: + [self highlightWithoutClearFrom: e start to: e stop. + e := e next]. + e := element prev. + [e isNil] whileFalse: + [self highlightWithoutClearFrom: e start to: e stop. + e := e prev]]. + textView invalidate + + "Created: / 14-02-2010 / 16:18:36 / Jan Vrany " + "Modified: / 25-06-2010 / 14:18:55 / Jan Vrany " + "Modified: / 30-06-2011 / 11:06:42 / cg" +! + +highlightElementAtCursor + self highlightElementAtLine: textView cursorLine col: textView cursorCol + + "Created: / 14-02-2010 / 16:17:40 / Jan Vrany " + "Modified: / 06-03-2010 / 19:59:18 / Jan Vrany " +! + +highlightElementAtLine:line col:col + |characterPosition index element | + + + characterPosition := textView characterPositionOfLine:line col:col. + index := SortedCollection binarySearch: (codeView syntaxElements) forIndexOf: characterPosition. + index > (codeView syntaxElements) size ifTrue:[^self highlightElement: nil]. + element := (codeView syntaxElements) at: index. + (characterPosition between: element start and: element stop) ifFalse:[^self highlightElement: nil]. + self highlightElement:element + + "Created: / 14-02-2010 / 16:17:22 / Jan Vrany " + "Modified: / 01-08-2010 / 08:50:11 / Jan Vrany " +! + +highlightElementAtX:x y:y + |visibleLine line col| + + codeView syntaxElements ifNil:[^self]. + visibleLine := textView visibleLineOfY:y. + col := textView colOfX:x inVisibleLine:visibleLine. + line := textView visibleLineToAbsoluteLine:visibleLine. + self highlightElementAtLine:line col:col + + "Created: / 14-02-2010 / 16:12:50 / Jan Vrany " + "Modified: / 06-03-2010 / 20:06:17 / Jan Vrany " +! + +highlightLine:lineNo fromLine:startLine col:endLine toLine:startCol col:endCol + |line start end| + + (lineNo between:startLine and:endLine) ifFalse:[ + ^ self + ]. + line := textView listAt:lineNo. + start := lineNo = startLine ifTrue:[ + startCol + ] ifFalse:[ + line indexOfNonSeparator + ]. + end := lineNo = endLine ifTrue:[ + endCol + ] ifFalse:[ line size ]. + line + emphasisFrom:start + to:end + add: currentEmphasis + + "Created: / 25-06-2010 / 14:15:39 / Jan Vrany " + "Modified: / 03-09-2010 / 22:39:33 / Jan Vrany " +! + +highlightVariable:e + (e notNil and:[ e type == #variable ]) ifTrue:[ + self highlightElement:e. + ] ifFalse:[ + self highlightClear. + ] +! + +highlightVariableAtCursor + |e| + + e := self elementAtCursor. + self highlightVariable: e + + "Modified: / 25-06-2010 / 14:53:17 / Jan Vrany " +! + +highlightVariableAtX:x y:y + |e| + + e := self elementAtX:x y:y. + self highlightVariable:e. + + "Created: / 25-06-2010 / 14:52:09 / Jan Vrany " +! + +highlightWithoutClearFrom: start to: end + "Remove underlined emphasis" + + |startLine startCol endLine endCol| + + startLine := textView lineOfCharacterPosition:start. + startCol := start - (textView characterPositionOfLine:startLine col:1) + 1. + endLine := textView lineOfCharacterPosition:end. + endCol := end - (textView characterPositionOfLine:endLine col:1) + 1. + self highlightWithoutClearFromLine: startLine col: startCol toLine: endLine col: endCol + + "Created: / 25-06-2010 / 14:15:21 / Jan Vrany " +! + +highlightWithoutClearFromLine: startLine col: startCol toLine: endLine col: endCol + + textView list keysAndValuesDo: + [:lineNo :line| + |start end| + line isText ifTrue: + [self highlightLine: lineNo fromLine: startLine col: endLine toLine: startCol col: endCol]]. + + "Created: / 25-06-2010 / 14:15:08 / Jan Vrany " +! ! + +!CodeNavigationService class methodsFor:'documentation'! + +version_CVS + ^ '$Header: /cvs/stx/stx/libtool/Tools__CodeNavigationService.st,v 1.1 2011-07-01 13:20:03 cg Exp $' +! + +version_SVN + ^ '§Id: Tools__CodeNavigationService.st 7788 2011-06-17 07:57:48Z vranyj1 §' +! !