"
COPYRIGHT (c) 2010 by Jan Vrany, SWING Research Group. CTU in Prague
All Rights Reserved
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:libtool' }"
"{ NameSpace: Tools }"
SimpleView subclass:#CodeView2
instanceVariableNames:'gutterView textView textViewScroller methodHolder languageHolder
classHolder browserHolder codeAspect modifiedChannel
showGutterChannel showAcceptCancelBarChannel modeHolder
serviceManager services servicesFromClient syntaxElements
syntaxElementSelection highlightEmphasis diffMode
synchronizedCodeViews'
classVariableNames:'TraceSelectors'
poolDictionaries:''
category:'Interface-CodeView'
!
SimpleView subclass:#GutterView
instanceVariableNames:'codeView textView textViewScroller widthAcceptCancel
widthAnnotations widthDiffInfo firstLineShown lastLineShown
numberOfLines acceptColor cancelColor diffColor menuHolder'
classVariableNames:''
poolDictionaries:''
privateIn:CodeView2
!
CodeView subclass:#TextView
instanceVariableNames:'listOriginal codeView gutterView diffMode deletedLines
insertedLines lastFirstLine changedLines scrolled originDiffText
emptyLines changedDiffText suppressNotifications
reallyModifiedChannel'
classVariableNames:''
poolDictionaries:''
privateIn:CodeView2
!
!CodeView2 class methodsFor:'documentation'!
copyright
"
COPYRIGHT (c) 2010 by Jan Vrany, SWING Research Group. CTU in Prague
All Rights Reserved
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.
"
! !
!CodeView2 class methodsFor:'initialization'!
initialize
"Invoked at system start or when the class is dynamically loaded."
"/ please change as required (and remove this comment)
TraceSelectors := IdentitySet new.
"Modified: / 14-02-2010 / 15:36:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 class methodsFor:'debugging'!
trace: aSelector
TraceSelectors add: aSelector
"Created: / 14-02-2010 / 09:26:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
untrace: aSelector
TraceSelectors remove: aSelector ifAbsent:[]
"Created: / 14-02-2010 / 09:50:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
untraceAll
TraceSelectors := IdentitySet new
"Created: / 14-02-2010 / 09:53:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 class methodsFor:'examples'!
example1
| window codeView |
window := StandardSystemView new.
window extent: 300 @ 300.
window label: 'CodeView2 example1'.
codeView := Tools::CodeView2 in: window.
codeView
origin: 0.1 @ 0.1
corner: 0.9 @ 0.9.
window open.
"Created: / 02-09-2009 / 21:48:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 class methodsFor:'menu specs'!
debugMenu
"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:Tools::CodeView2 andSelector:#editMenu_stxStyle
(Menu new fromLiteralArrayEncoding:(Tools::CodeView2 editMenu_stxStyle)) startUp
"
<resource: #menu>
^
#(Menu
(
(MenuItem
label: 'Inspect '
itemValue: inspectView
translateLabel: true
)
(MenuItem
label: 'Inspect Syntax Elements'
itemValue: inspectSyntaxElements
translateLabel: true
)
(MenuItem
label: 'Inspect Selected Selector'
itemValue: inspectSelectedSelector
translateLabel: true
)
)
nil
nil
)
"Created: / 08-07-2011 / 13:36:02 / cg"
!
editMenu
"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:Tools::CodeView2 andSelector:#editMenu
(Menu new fromLiteralArrayEncoding:(Tools::CodeView2 editMenu)) startUp
"
UserPreferences current eclipseStyleMenus ifTrue:[
^ self editMenu_eclipseStyle
].
^ self editMenu_stxStyle
"Modified: / 08-07-2011 / 13:23:35 / cg"
!
editMenu_eclipseStyle
"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:Tools::CodeView2 andSelector:#editMenu_eclipseStyle
(Menu new fromLiteralArrayEncoding:(Tools::CodeView2 editMenu_eclipseStyle)) startUp
"
<resource: #menu>
^
#(Menu
(
(MenuItem
label: 'Implementors...'
itemValue: browseImplementorsOfIt
translateLabel: true
submenuChannel: implementorsMenu
shortcutKey: ImplementorsOfIt
)
(MenuItem
label: 'Senders...'
itemValue: browseSendersOfIt
translateLabel: true
submenuChannel: sendersMenu
shortcutKey: SendersOfIt
)
(MenuItem
label: 'Refactor'
nameKey: refactor
translateLabel: true
isVisible: false
shortcutKey: Shift
)
(MenuItem
label: '-'
)
(MenuItem
label: 'Accept'
itemValue: accept
translateLabel: true
shortcutKey: Accept
)
(MenuItem
label: '-'
)
(MenuItem
label: 'Cut'
itemValue: cut
translateLabel: true
shortcutKey: Cut
)
(MenuItem
label: 'Copy'
itemValue: copySelection
translateLabel: true
shortcutKey: Copy
)
(MenuItem
label: 'Paste'
itemValue: pasteOrReplace
translateLabel: true
shortcutKey: Paste
)
(MenuItem
label: '-'
)
(MenuItem
label: 'Undo'
itemValue: undo
translateLabel: true
shortcutKey: Undo
)
(MenuItem
label: '-'
)
(MenuItem
label: 'Do it'
itemValue: doIt
translateLabel: true
shortcutKey: DoIt
)
(MenuItem
label: 'Print it'
itemValue: printIt
translateLabel: true
shortcutKey: PrintIt
)
(MenuItem
label: 'Inspect it'
itemValue: inspectIt
translateLabel: true
shortcutKey: InspectIt
)
(MenuItem
label: 'Profile it'
itemValue: profileIt
translateLabel: true
shortcutKey: InspectIt
)
(MenuItem
label: '-'
)
(MenuItem
label: 'Show Gutter'
nameKey: ShowGutter
translateLabel: true
indication: showGutterChannel
)
(MenuItem
label: 'More'
nameKey: More
translateLabel: true
)
(MenuItem
label: 'Services'
translateLabel: true
submenuChannel: servicesMenu
)
(MenuItem
label: 'Debug'
translateLabel: true
submenuChannel: debugMenu
)
)
nil
nil
)
"Modified: / 08-03-2012 / 12:36:18 / cg"
!
editMenu_stxStyle
"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:Tools::CodeView2 andSelector:#editMenu_stxStyle
(Menu new fromLiteralArrayEncoding:(Tools::CodeView2 editMenu_stxStyle)) startUp
"
<resource: #menu>
^
#(Menu
(
(MenuItem
label: 'Undo'
itemValue: undo
translateLabel: true
shortcutKey: Undo
)
(MenuItem
label: 'Again'
itemValue: again
translateLabel: true
shortcutKey: Again
)
(MenuItem
label: '-'
)
(MenuItem
label: 'Cut'
itemValue: cut
translateLabel: true
shortcutKey: Cut
)
(MenuItem
label: 'Copy'
itemValue: copySelection
translateLabel: true
shortcutKey: Copy
)
(MenuItem
label: 'Paste'
itemValue: pasteOrReplace
translateLabel: true
shortcutKey: Paste
)
(MenuItem
label: '-'
)
(MenuItem
label: 'DoIt'
itemValue: doIt
translateLabel: true
shortcutKey: DoIt
)
(MenuItem
label: 'PrintIt'
itemValue: printIt
translateLabel: true
shortcutKey: PrintIt
)
(MenuItem
label: 'InspectIt'
itemValue: inspectIt
translateLabel: true
shortcutKey: InspectIt
)
(MenuItem
label: '-'
)
(MenuItem
label: 'Accept'
itemValue: accept
translateLabel: true
shortcutKey: Accept
)
(MenuItem
label: '-'
isVisible: false
)
(MenuItem
label: 'Refactor'
nameKey: refactor
translateLabel: true
isVisible: false
shortcutKey: Shift
)
(MenuItem
label: 'Services'
translateLabel: true
isVisible: false
submenuChannel: servicesMenu
)
(MenuItem
label: '='
)
(MenuItem
label: 'More'
nameKey: More
translateLabel: true
shortcutKey: Ctrl
)
)
nil
nil
)
"Modified: / 02-03-2012 / 19:53:19 / cg"
! !
!CodeView2 methodsFor:'accessing'!
acceptAction:aBlock
textView acceptAction: aBlock
"Modified: / 01-08-2010 / 20:40:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
breakpointService
"that one or nil"
^ services detect:[:any| (any isKindOf: BreakpointService)] ifNone:nil
!
breakpoints
|s|
(s := self breakpointService) notNil ifTrue:[
^ s breakpoints
].
^ nil
"Created: / 06-07-2011 / 18:05:35 / jv"
"Modified: / 06-10-2011 / 14:13:53 / cg"
!
browser
^self browserHolder value
"Created: / 07-07-2011 / 12:25:59 / Jan Vrany <jan.vrant@fit.cvut,cz>"
!
codeAspect
|app|
codeAspect ifNotNil:[^codeAspect].
methodHolder value ifNotNil:[^SyntaxHighlighter codeAspectMethod].
^((app := self topView application) notNil and:[app respondsTo: #codeAspect])
ifTrue:[app codeAspect]
ifFalse:[(SyntaxHighlighter codeAspectExpression)]
"Modified: / 27-07-2011 / 13:05:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 27-07-2012 / 22:22:27 / cg"
!
codeAspect:aSymbol
self assert:( #(expression method classDefinition) includes:aSymbol ).
codeAspect := aSymbol.
"Modified: / 27-07-2012 / 22:32:19 / cg"
!
contents
^textView contents
"Created: / 14-02-2010 / 22:13:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
contents: aStringOrStringCollection
textView contents: aStringOrStringCollection.
"/self update:#value with: aStringOrStringCollection from: textView model
"Modified: / 19-07-2011 / 13:18:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
diffMode
^ diffMode
!
diffMode:aBoolean
diffMode := aBoolean.
textView diffMode: aBoolean
"Modified: / 08-04-2011 / 20:50:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
editedMethodOrClass:aMethodOrClass
textView editedMethodOrClass:aMethodOrClass.
aMethodOrClass isBehavior ifFalse:[
self methodHolder value:aMethodOrClass
].
!
font
^textView font
"Created: / 16-02-2010 / 10:26:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
font: aFont
^textView font: aFont
"Created: / 16-02-2010 / 10:26:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
mode
^self modeHolder value
"Created: / 13-06-2011 / 10:49:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
mode: aSymbol
"is this the same as codeAspect ?"
self assert: (#(expression method) includes: aSymbol).
^self modeHolder value: aSymbol
"Created: / 13-06-2011 / 10:50:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 15-06-2011 / 16:37:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (comment): / 27-07-2012 / 22:19:49 / cg"
!
model
^textView model.
"Created: / 27-07-2011 / 12:47:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
model: aValueModel
|oldValue newValue|
textView model notNil ifTrue:[
oldValue := textView model value.
textView model removeDependent:self.
].
textView model: aValueModel.
textView model notNil ifTrue:[
textView model addDependent:self.
].
newValue := textView model value.
oldValue ~~ newValue ifTrue:[
self update:#value with:newValue from:textView model.
].
"Modified: / 27-07-2011 / 12:58:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
modified
"return true if text was modified"
^ self modifiedChannel value
"Modified: / 07-07-2011 / 12:15:43 / Jan Vrany <jan.vrant@fit.cvut,cz>"
!
modified:aBoolean
"set/clear the modified flag"
self modifiedChannel value:aBoolean
"Modified: / 14-02-1997 / 16:44:05 / cg"
"Modified: / 07-07-2011 / 12:15:39 / Jan Vrany <jan.vrant@fit.cvut,cz>"
!
scrolledView
^self
"Created: / 14-02-2010 / 22:54:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
services
^ services ? #()
"Created: / 05-08-2011 / 10:14:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (format): / 06-10-2011 / 14:11:11 / cg"
!
services:aCollectionOfServices
"allow setting of the services (instances);
this is needed for FileBrowser, to setup a codeView2 without Smalltalk-specific
services"
servicesFromClient := true.
services := aCollectionOfServices.
"Created: / 06-10-2011 / 14:15:36 / cg"
!
showAcceptCancelBar
^showAcceptCancelBarChannel value
"Created: / 10-10-2011 / 16:25:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
showGutter
^showGutterChannel value
"Created: / 23-06-2010 / 19:37:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
synchronizeWith: aCodeView
self assert: aCodeView ~= self.
(synchronizedCodeViews includes: aCodeView) ifTrue:[^self].
synchronizedCodeViews := synchronizedCodeViews copyWith: aCodeView.
"Created: / 06-04-2010 / 14:13:14 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 23-06-2010 / 17:01:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'accessing-code component'!
klass
| v |
(v := self classHolder value) notNil ifTrue:[^v].
(v := self methodHolder value) notNil ifTrue:[^v mclass].
^UndefinedObject
"Created: / 27-07-2011 / 13:14:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
klass: aClass
"Created: / 27-07-2011 / 13:13:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
language
"return the value in 'languageHolder'"
| v |
(v := self languageHolder value) notNil ifTrue:[^v].
(v := self methodHolder value) notNil ifTrue:[^v programmingLanguage].
(v := self classHolder value) notNil ifTrue:[^v programmingLanguage].
"/No, no default language, please.
"/^SmalltalkLanguage instance
^nil
"Modified: / 07-12-2011 / 16:38:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
language: newValue
"set the value in 'languageHolder'"
self languageHolder value: newValue
!
method
^self methodHolder value
"Created: / 27-07-2011 / 13:12:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
method: aMethod
^self methodHolder value: aMethod
"Created: / 27-07-2011 / 13:12:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'aspects'!
browserHolder
browserHolder isNil ifTrue:[
browserHolder := ValueHolder new
].
^browserHolder
"Modified: / 14-02-2010 / 19:27:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 18-11-2011 / 14:58:15 / cg"
!
browserHolder:aValueModel
browserHolder := aValueModel.
!
classHolder
"return/create the 'classHolder' value holder (automatically generated)"
classHolder isNil ifTrue:[
classHolder := ValueHolder with: nil.
classHolder addDependent:self.
].
^ classHolder
"Modified: / 27-07-2011 / 13:15:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
classHolder:aValueModel
"set the 'classHolder' value holder (automatically generated)"
|old oldValue newValue|
classHolder notNil ifTrue:[
oldValue := classHolder value.
classHolder removeDependent:self.
].
classHolder := aValueModel.
classHolder notNil ifTrue:[
classHolder addDependent:self.
].
old := methodHolder.
newValue := classHolder value.
oldValue ~~ newValue ifTrue:[
self update:#value with:newValue from:classHolder.
].
self changed: #classHolder with: old -> classHolder
"Modified: / 17-06-2011 / 12:56:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
languageHolder
languageHolder isNil ifTrue:[
"/ cg: I dont like the smalltalk default here, because everyone who is not showing ST-code (expecco, filebrowser etc.)
"/ has to explicitely clear the valueholder. I guess, it is better for the few
"/ others to explicitely set it, if they do not provide syntaxHighlighter per method
"/ or class.
languageHolder := ValueHolder with: nil "SmalltalkLanguage instance".
languageHolder addDependent:self.
].
^ languageHolder
"Modified: / 19-07-2012 / 16:51:04 / cg"
!
languageHolder:aValueModel
"set the 'languageHolder' value holder (automatically generated)"
|old oldValue newValue|
languageHolder notNil ifTrue:[
oldValue := languageHolder value.
languageHolder removeDependent:self.
].
languageHolder := aValueModel.
languageHolder notNil ifTrue:[
languageHolder addDependent:self.
].
old := languageHolder.
newValue := languageHolder value.
oldValue ~~ newValue ifTrue:[
self update:#value with:newValue from:languageHolder.
].
self changed: #languageHolder with: old -> languageHolder
"Modified: / 17-06-2011 / 12:56:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 19-07-2012 / 16:51:08 / cg"
!
methodHolder
"return/create the 'methodHolder' value holder (automatically generated)"
methodHolder isNil ifTrue:[
methodHolder := ValueHolder new.
methodHolder addDependent:self.
].
^ methodHolder
!
methodHolder:aValueModel
"set the 'methodHolder' value holder (automatically generated)"
|old oldValue newValue|
methodHolder notNil ifTrue:[
oldValue := methodHolder value.
methodHolder removeDependent:self.
].
old := methodHolder.
methodHolder := aValueModel.
methodHolder notNil ifTrue:[
methodHolder addDependent:self.
].
newValue := methodHolder value.
oldValue ~~ newValue ifTrue:[
self update:#value with:newValue from:methodHolder.
].
self changed: #methodHolder with: old -> methodHolder
"Modified: / 17-06-2011 / 12:55:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
modeHolder
"return/create the 'modeHolder' value holder (automatically generated)"
"is this the codeAspect?"
modeHolder isNil ifTrue:[
modeHolder := #expression asValue.
modeHolder addDependent:self.
].
^ modeHolder
"Modified: / 13-06-2011 / 10:52:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (comment): / 27-07-2012 / 22:22:19 / cg"
!
modeHolder:something
"set the 'modeHolder' value holder (automatically generated)"
|oldValue newValue|
modeHolder notNil ifTrue:[
oldValue := modeHolder value.
modeHolder removeDependent:self.
].
modeHolder := something.
modeHolder notNil ifTrue:[
modeHolder addDependent:self.
].
newValue := modeHolder value.
oldValue ~~ newValue ifTrue:[
self update:#value with:newValue from:modeHolder.
].
self changed: #modeHolder with: modeHolder
"Modified: / 17-06-2011 / 12:55:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'change & update'!
update:aspect with:param from:sender
"/ sender == methodHolder ifTrue:[
"/ self updateGutter.
"/ ].
sender == showGutterChannel ifTrue: [
self updateGutterVisibility.
^self.
].
services do:[:each |
each isEnabled ifTrue:[
each update:aspect with:param from:sender
]
].
super update:aspect with:param from:sender
"Modified: / 23-06-2010 / 19:05:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 07-07-2011 / 12:07:04 / Jan Vrany <jan.vrant@fit.cvut,cz>"
"Modified: / 06-10-2011 / 14:14:36 / cg"
!
updateGutter
self showGutterChannel value ifTrue:[
gutterView invalidate.
]
"Created: / 23-06-2010 / 19:05:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
updateGutterVisibility
self showGutterChannel value ifTrue:[
textViewScroller origin:(gutterView width @ 0.0) corner:(1.0 @ 1.0).
gutterView beVisible.
] ifFalse:[
textViewScroller origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
gutterView beInvisible.
]
"Created: / 23-06-2010 / 19:05:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'channels'!
modifiedChannel
"return the valueHolder holding true if text was modified"
^ textView modifiedChannel
"/ ^ modifiedChannel
"Modified: / 07-07-2011 / 12:07:26 / Jan Vrany <jan.vrant@fit.cvut,cz>"
!
modifiedChannel:aValueHolder
"set the valueHolder holding true if text was modified"
textView modifiedChannel removeDependent:self.
textView modifiedChannel:aValueHolder.
textView modifiedChannel addDependent:self.
"/ |prev|
"/
"/ prev := modifiedChannel.
"/ modifiedChannel := aValueHolder.
"/ self setupChannel:aValueHolder for:nil withOld:prev
"Created: / 30-01-1998 / 14:51:32 / cg"
"Modified: / 07-07-2011 / 12:07:43 / Jan Vrany <jan.vrant@fit.cvut,cz>"
"Modified: / 05-09-2011 / 05:13:27 / cg"
!
reallyModifiedChannel
"return the valueHolder holding true if text was modified"
^ textView reallyModifiedChannel
"Modified: / 07-07-2011 / 12:07:26 / Jan Vrany <jan.vrant@fit.cvut,cz>"
"Created: / 08-10-2011 / 12:47:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
reallyModifiedChannel: aValueModel
^ textView reallyModifiedChannel: aValueModel
"Modified: / 07-07-2011 / 12:07:26 / Jan Vrany <jan.vrant@fit.cvut,cz>"
"Created: / 08-10-2011 / 12:47:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
showAcceptCancelBarChannel
^showAcceptCancelBarChannel
"Created: / 10-10-2011 / 16:23:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
showAcceptCancelBarChannel:aValueHolder
"set the valueHolder holding true if text was modified"
|prev|
prev := showAcceptCancelBarChannel.
showAcceptCancelBarChannel := aValueHolder.
self setupChannel:aValueHolder for:nil withOld:prev.
"Created: / 10-10-2011 / 16:24:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
showGutterChannel
^showGutterChannel
"Created: / 23-06-2010 / 19:02:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
showGutterChannel:aValueHolder
"set the valueHolder holding true if text was modified"
|prev|
prev := showGutterChannel.
showGutterChannel := aValueHolder.
self setupChannel:aValueHolder for:nil withOld:prev
"Created: / 23-06-2010 / 19:03:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'code services'!
browseMethod: method
self browseMethod: method label: nil.
"Created: / 14-02-2010 / 19:41:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
browseMethod: method label: label
self browser isNil ifTrue: [^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 <vranyj1@fel.cvut.cz>"
"Modified: / 25-07-2010 / 13:34:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 18-11-2011 / 14:58:12 / cg"
!
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 <vranyj1@fel.cvut.cz>"
!
extractSelectorAndSelectedTextFrom: givenSelectedText
| selector selectedText compilerClass na |
selectedText := givenSelectedText.
compilerClass := self language compilerClass.
selectedText size > 0 ifTrue:[
"/ self windowGroup withWaitCursorDo:[
"/ hack, for now and expecco; must ask the Parser eventually...
(compilerClass notNil and:[compilerClass includesBehavior:JavaScriptParser]) ifTrue:[
"/ selector is in one piece anyway
(selectedText includes:$_) ifFalse:[
"/ zero or one args - sigh (need to parse more to figure this out)
selector := JavaScriptParser basicNew translatedSmalltalkSelectorFor:selectedText numArgs:1.
selectedText := JavaScriptParser basicNew translatedSmalltalkSelectorFor:selectedText numArgs:0.
] ifTrue:[
"/ count _#s plus one arg - sigh
na := (selectedText occurrencesOf:$_) + 1.
selector := JavaScriptParser basicNew translatedSmalltalkSelectorFor:selectedText numArgs:na
].
] ifFalse:[
selector := SystemBrowser extractSelectorFrom:selectedText.
].
"/ ]
].
^Array with: selector with: selectedText
"Created: / 30-06-2011 / 19:49:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 05-03-2012 / 09:04:12 / cg"
!
implementorsOf: selector
selector isNil ifTrue:[^#()].
^SystemBrowser
findImplementorsOf: selector
in: Smalltalk allClasses
ignoreCase: false
"Created: / 26-12-2007 / 11:37:11 / janfrog"
"Modified: / 18-11-2011 / 14:58:17 / cg"
!
sendersOf: selector
|senderBlock|
selector isNil ifTrue:[^#()].
"/ not exact, but much faster (looks for symbol only, does not parse code for real send)
senderBlock := SystemBrowser searchBlockForSymbol:selector.
senderBlock == false ifTrue:[ ^ #() ].
^ SystemBrowser
allMethodsIn:Smalltalk allClasses
where:senderBlock.
"/ exact, but much slower
"/ ^SystemBrowser
"/ findSendersOf: selector
"/ in: Smalltalk allClasses
"/ ignoreCase: false
"Created: / 26-12-2007 / 11:37:22 / janfrog"
"Modified: / 30-06-2011 / 19:32:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 18-11-2011 / 14:58:19 / cg"
! !
!CodeView2 methodsFor:'delegation'!
doesNotUnderstand: aMessage
((textView respondsTo: aMessage selector)
and:[(TraceSelectors includes:aMessage selector) not])
ifTrue:[^aMessage sendTo: textView].
^super doesNotUnderstand: aMessage
"Created: / 13-02-2010 / 23:27:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 14-02-2010 / 09:53:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
hasSelection
^textView hasSelection
"Created: / 14-02-2010 / 09:53:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'delegation-drawing'!
drawLine:lineNo in: view atX:x y:y width: w height:h from:startCol to:endColOrNil with:fg and:bg
"See the comment in
CodeViewService>>drawLine:in:atX..."
services do:[:each|
each drawLine:lineNo in: view atX:x y:y width: w height:h from:startCol to:endColOrNil with:fg and:bg
]
"Created: / 17-06-2011 / 13:50:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-10-2011 / 14:14:04 / cg"
!
redrawVisibleLine: visLineNr
"Created: / 07-03-2010 / 14:44:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
redrawVisibleLine:visLine col:colNr
"Modified: / 05-11-2007 / 17:35:53 / cg"
"Modified: / 07-03-2010 / 14:45:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
redrawVisibleLine:visLine from:startCol
"Modified: / 07-03-2010 / 14:46:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
redrawVisibleLine:visLine from:startCol to:endCol
"Modified: / 07-03-2010 / 14:46:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'delegation-events'!
buttonMotion: button x:x y:y in: view
"Delegates events to services. Answers true iff at least
one service handler method returns true. In that case,
the event is is NOT processes by the view."
^ services
contains:[:service |
service isEnabled and:[ ((service buttonMotion: button x:x y:y in: view) == true) ]
].
"Modified: / 07-03-2010 / 13:53:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-10-2011 / 14:13:57 / cg"
!
buttonPress: button x:x y:y in: view
"Delegates events to services. Answers true iff at least
one service handler method returns true. In that case,
the event is is NOT processes by the view."
^ services
contains:[:service |
service isEnabled and:[ ((service buttonPress: button x:x y:y in: view) == true) ]
].
"Modified: / 07-03-2010 / 13:53:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-10-2011 / 14:14:00 / cg"
"Modified (format): / 05-03-2012 / 08:56:02 / cg"
!
buttonRelease: button x:x y:y in: view
"Delegates events to services. Answers true iff at least
one service handler method returns true. In that case,
the event is is NOT processes by the view."
^ services
contains:[:service |
service isEnabled and:[ ((service buttonRelease: button x:x y:y in: view) == true) ]
].
!
highlightInstanceVariable:name
services do:[:each|
each highlightInstanceVariable:name
].
!
keyPress: key x:x y:y in: view
"Delegates events to services. Answers true iff at least
one service handler method returns true. In that case,
the event is is NOT processes by the view."
^ services
contains:[:service |
service isEnabled and:[ ((service keyPress: key x:x y:y in: view) == true) ]
].
"Modified: / 07-03-2010 / 13:54:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-10-2011 / 14:14:11 / cg"
!
keyRelease: key x:x y:y in: view
"Delegates events to services. Answers true iff at least
one service handler method returns true. In that case,
the event is is NOT processes by the view."
^ services
contains:[:service |
service isEnabled and:[ ((service keyRelease: key x:x y:y in: view) == true) ]
].
"Modified: / 07-03-2010 / 13:54:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-10-2011 / 14:14:13 / cg"
!
linesDeletedFrom: start to: end
services do: [:each |
each isEnabled ifTrue: [
each linesDeletedFrom: start to: end
]
].
"Created: / 06-07-2011 / 17:12:54 / jv"
"Modified: / 06-10-2011 / 14:14:16 / cg"
"Modified: / 07-10-2011 / 19:14:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
linesInsertedFrom: start to: end
services do: [:each |
each isEnabled ifTrue: [
each linesInsertedFrom: start to: end
]
].
"Created: / 06-07-2011 / 17:12:48 / jv"
"Modified: / 06-10-2011 / 14:14:20 / cg"
!
linesModifiedFrom: start to: end
services do: [:each |
each isEnabled ifTrue: [
each linesModifiedFrom: start to: end
]
].
"Created: / 06-07-2011 / 17:12:58 / jv"
"Modified: / 06-10-2011 / 14:13:44 / cg"
!
scrollDown: nLines in: view
view == textView
ifTrue:
["/my text view scrolled...
synchronizedCodeViews do:[:codeView|codeView scrollDown: nLines in: view]]
ifFalse:
["/other code view scrolls and I'm notified about that
textView basicScrollDown: nLines]
"Created: / 06-04-2010 / 14:02:39 / Jakub <zelenja7@fel.cvut.cz>"
!
scrollUp: nLines in: view
view == textView
ifTrue:
["/my text view scrolled...
synchronizedCodeViews do:[:codeView|codeView scrollUp: nLines in: view]]
ifFalse:
["/other code view scrolls and I'm notified about that
textView basicScrollUp: nLines]
"Created: / 06-04-2010 / 14:02:39 / Jakub <zelenja7@fel.cvut.cz>"
! !
!CodeView2 methodsFor:'diff mode'!
recomputeDiff:view
|t1 t2 pom diffHelper view2|
t1 := view getNewOriginText.
synchronizedCodeViews do:[:codeView |
view2 := codeView
].
view changedDiffText:false.
view2 changedDiffText:false.
t2 := view2 getNewOriginText.
pom := DiffCodeView2 new.
(view == textView) ifTrue:[
diffHelper := pom computeDiffDataForText1:t1 text2:t2.
(view) contents:(diffHelper text1).
(view) deletedLines:(diffHelper deleted).
(view) changedLines:(diffHelper changed).
(view) originDiffText:t1.
(view) emptyLines:(diffHelper inserted).
(view) changedLines:(diffHelper changed).
(view2) contents:(diffHelper text2).
(view2) insertedLines:(diffHelper inserted).
(view2) changedLines:(diffHelper changed).
(view2) originDiffText:t2.
(view2) emptyLines:(diffHelper deleted).
].
"Modified: / 22-06-2010 / 23:35:41 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 23-06-2010 / 17:25:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'initialization'!
initialize
"Invoked when a new instance is created."
"Call super initialize"
super initialize.
"Now set up some visual properties"
self level:-1.
"Now initialize sub-views"
showGutterChannel := ValueHolder with: true.
showGutterChannel addDependent: self.
"/ toDo: I don't like two options in the settings;
"/ showAcceptCancelBarChannel := (ValueHolder with: (UserPreferences current showAcceptCancelBarInBrowser)).
showAcceptCancelBarChannel := ValueHolder with: (UserPreferences current codeView2ShowAcceptCancel).
"/ these views must be created first, as they refer to each other's channels in their
"/ initialize methods
gutterView := CodeView2::GutterView new.
textViewScroller := HVScrollableView for: CodeView2::TextView in: self.
textView := textViewScroller scrolledView.
self initializeGutterView.
self initializeTextView.
textView setCodeView:self.
modifiedChannel := ValueHolder with:false.
diffMode := false.
synchronizedCodeViews := #().
servicesFromClient := false.
services := OrderedCollection new.
self initializeServices.
"Modified: / 14-12-2009 / 13:59:53 / Jindra <a>"
"Modified: / 06-04-2010 / 13:56:35 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 06-10-2011 / 14:15:48 / cg"
"Modified: / 18-10-2011 / 19:17:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
initializeGutterView
gutterView setCodeView:self.
gutterView origin:(0.0 @ 0.0) corner:(gutterView preferredWidth @ 1.0).
showGutterChannel value ifTrue:[self addSubView: gutterView].
"Created: / 02-09-2009 / 21:35:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 23-06-2010 / 19:14:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
initializeServices
| serviceClasses |
"/ only do it, if the services have not yet been defined by the user of this view
"/ (FileBrowser does not want Smalltalk-specific services)
servicesFromClient ifFalse:[
serviceClasses := CodeViewService availableServices sort:[:a :b|name < b name].
serviceClasses do:[:cls|
self registerService: cls new
].
].
"Modified: / 27-07-2011 / 11:37:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-10-2011 / 14:16:01 / cg"
!
initializeTextView
"Initialize textView. gutterView has to be already initialized!!"
textViewScroller
origin: ((self showGutter ifTrue:[gutterView width] ifFalse:[0.0]) @ 0.0)
corner: 1.0@1.0;
level: 0.
textView level: 0.
textView modifiedChannel addDependent: self.
"Created: / 02-09-2009 / 21:36:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 23-06-2010 / 19:38:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'menu actions'!
accept
textView accept
"Created: / 07-09-2011 / 21:29:07 / cg"
!
again
textView again
"Created: / 16-02-2010 / 19:36:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Created: / 22-07-2011 / 17:44:31 / cg"
!
browseImplementorsOfIt
textView browseImplementorsOfIt
"Modified: / 30-06-2011 / 19:22:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
browseSendersOfIt
textView browseSendersOfIt
"Modified: / 30-06-2011 / 19:22:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
copySelection
textView copySelection
"Created: / 16-02-2010 / 19:36:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
cut
textView cut
"Created: / 16-02-2010 / 19:36:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
doIt
textView doIt
"Modified: / 16-02-2010 / 19:38:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
inspectIt
textView inspectIt
"Modified: / 16-02-2010 / 19:38:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
inspectSelectedSelector
self error: 'Not yet implemented'
"Modified: / 14-02-2010 / 15:58:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
inspectSyntaxElements
syntaxElements inspect
"Modified: / 14-02-2010 / 15:57:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
inspectView
self inspect
"Modified: / 25-03-2010 / 17:58:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
pasteOrReplace
textView pasteOrReplace
"Created: / 16-02-2010 / 19:37:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
printIt
textView printIt
"Modified: / 16-02-2010 / 19:38:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
profileIt
textView profileIt
"Created: / 27-08-2010 / 22:12:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
undo
textView undo
"Created: / 16-02-2010 / 19:35:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'menus-dynamic'!
editMenu
| editMenu superEditMenu moreMenu moreMenuItem |
superEditMenu := textView superEditMenu.
textView sensor ctrlDown ifTrue:[
^superEditMenu
].
"/ install the standard 'more' menu into my own menu
moreMenu := superEditMenu subMenuAt: superEditMenu numberOfItems.
editMenu := self class editMenu decodeAsLiteralArray.
moreMenuItem := editMenu menuItemLabeled: 'More'.
moreMenuItem submenu: moreMenu asMenu.
editMenu findGuiResourcesIn: self.
^editMenu
"Created: / 25-12-2007 / 10:10:01 / janfrog"
"Modified: / 25-12-2007 / 19:50:53 / janfrog"
"Modified: / 18-10-2008 / 20:31:16 / Jan Vrany <vranyj1@fel.cvut.cz>"
"Modified: / 08-07-2011 / 13:35:31 / cg"
"Modified: / 07-10-2011 / 17:58:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
implementorsMenu
| selectorAndSelectedText selector selectedText implementors |
selectedText := textView selectionAsString.
selectedText size > 0 ifTrue:[
"/ self windowGroup withWaitCursorDo:[
selectorAndSelectedText := self extractSelectorAndSelectedTextFrom: selectedText.
selector := selectorAndSelectedText first.
selectedText := selectorAndSelectedText second.
(selector notNil and:[selector = selectedText]) ifTrue:[
implementors := (SystemBrowser
findImplementorsOf:selectedText "Any: (Array with:selectedText)"
in:(Smalltalk allClasses)
ignoreCase:false)
] ifFalse:[
implementors := (SystemBrowser
findImplementorsOfAny:(Array with:selectedText with: selector)
in:(Smalltalk allClasses)
ignoreCase:false)
].
"/ ]
] ifFalse:[
implementors := #().
].
^self implementorsMenu: implementors selector: (selector ? selectedText)
"Modified: / 19-10-2008 / 08:16:50 / Jan Vrany <vranyj1@fel.cvut.cz>"
"Created: / 30-06-2011 / 19:28:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 05-03-2012 / 09:02:43 / cg"
!
implementorsMenu: implementors selector: selector
| menu|
menu := Menu new.
implementors isEmptyOrNil ifTrue:[
menu addItem:(MenuItem label:'No implementors found') disable
] ifFalse:[
menu addItem:(MenuItem
label:(selector storeString , (' (all implementors) ') asText allItalic)
itemValue:[
self browseMethods:implementors
label:'Implementors of ' , selector storeString
]).
menu addSeparator.
(implementors asOrderedCollection sort:[:a :b | a mclass name < b mclass name])
"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 <vranyj1@fel.cvut.cz>"
"Created: / 14-02-2010 / 19:39:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 07-03-2012 / 12:56:56 / cg"
!
sendersMenu
| selectorAndSelectedText selector selectedText senders |
selectedText := textView selectionAsString.
selectedText size > 0 ifTrue:[
"/ self windowGroup withWaitCursorDo:[
selectorAndSelectedText := self extractSelectorAndSelectedTextFrom: selectedText.
selector := selectorAndSelectedText first.
selectedText := selectorAndSelectedText second.
(selector notNil and:[selector = selectedText]) ifTrue:[
senders := (SystemBrowser
findSendersOf:selectedText "Any:(Array with:selectedText)"
in:(Smalltalk allClasses)
ignoreCase:false)
] ifFalse:[
senders := (SystemBrowser
findSendersOfAny:(Array with:selectedText with: selector)
in:(Smalltalk allClasses)
ignoreCase:false)
].
"/ ]
] ifFalse:[
senders := #().
].
^self sendersMenu: senders selector: (selector ? selectedText)
"Modified: / 19-10-2008 / 08:16:50 / Jan Vrany <vranyj1@fel.cvut.cz>"
"Created: / 30-06-2011 / 19:28:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 05-03-2012 / 09:02:56 / cg"
!
sendersMenu: senders selector: selector
| menu shownSenderItems numCut sendersSorted|
menu := Menu new.
senders isEmptyOrNil ifTrue:[
menu addItem:(MenuItem label:'No senders found') disable
] ifFalse:[
menu addItem:(MenuItem
label:(selector storeString , (' (all senders)') asText allItalic)
itemValue:[
self browseMethods:senders
label:'Senders of ' , selector storeString
]).
menu addSeparator.
sendersSorted := senders asOrderedCollection
sort:[:a :b | a whoString < b whoString].
shownSenderItems := (senders size > 20) ifTrue:[sendersSorted copyTo:20] ifFalse:[sendersSorted].
numCut := senders size - 20.
shownSenderItems do:[:mth |
menu
addItem:(MenuItem label:(mth selector storeString
, (' in ' , mth containingClass name asText allBold))
value:[ self browseMethod:mth label: 'Sender of ' , selector storeString ])
].
numCut > 0 ifTrue:[
menu addSeparator.
menu addItem:(MenuItem label:('... %1 more senders not shown here' bindWith:numCut)) disable
].
].
^ menu
"Modified: / 19-10-2008 / 08:17:00 / Jan Vrany <vranyj1@fel.cvut.cz>"
"Created: / 14-02-2010 / 19:40:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 07-07-2011 / 14:51:54 / jv"
"Modified: / 07-03-2012 / 12:58:31 / cg"
!
servicesMenu
|menu item anyService|
menu := Menu new.
"/ disabled, because this menu is now on the gutter,
"/ and it makes it hard to show it again, once hidden
"/ item := MenuItem label:(resources string:'Show Gutter').
"/ item indication:(self showGutterChannel).
"/ menu addItem:item.
"/ menu addSeparator.
anyService := false.
services do:[:service |
|item|
item := MenuItem label:(resources string:service label).
item indication:((AspectAdaptor forAspect:#enabled) subject:service).
menu addItem:item.
anyService := true.
].
anyService ifTrue:[
menu addSeparator.
].
item := MenuItem label:(resources string:'Debug').
item submenuChannel:[ self class debugMenu ].
menu addItem:item.
^ menu
"Created: / 07-03-2010 / 14:03:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-10-2011 / 14:14:30 / cg"
! !
!CodeView2 methodsFor:'private'!
codeCompletion
|cls
"/ crsrPos interval node checkedNode
"/ char start stop selectorSoFar matchingSelectors
|
cls := self classHolder value.
cls isNil ifTrue:[
self showInfo:'No class'.
^ self.
].
UserInformation handle:[:ex |
self showInfo:(ex messageText).
ex proceed.
] do:[
self withWaitCursorDo:[
DoWhatIMeanSupport codeCompletionForClass:cls codeView:self.
]
].
^ self.
"/
"/ interval := self selectedInterval.
"/ interval isEmpty ifTrue:[
"/ crsrPos := codeView characterPositionOfCursor - 1.
"/ char := codeView characterUnderCursor.
"/ [crsrPos > 1 and:[char isSeparator or:['.' includes:char]]] whileTrue:[
"/ crsrPos := crsrPos - 1.
"/ char := codeView characterAtCharacterPosition:crsrPos.
"/ ].
"/ interval := crsrPos to:crsrPos.
"/ ].
"/
"/ node := self findNodeForInterval:interval allowErrors:true.
"/ [node isNil] whileTrue:[
"/ "/ expand to the left ...
"/ interval start > 1 ifFalse:[
"/ self showInfo:'No parseNode found'.
"/ ^ self.
"/ ].
"/ interval start:(interval start - 1).
"/ node := self findNodeForInterval:interval allowErrors:true.
"/ ].
"/
"/ node isVariable ifTrue:[
"/ self codeCompletionForVariable:node inClass:cls.
"/ ^ self.
"/ ].
"/
"/ checkedNode := node.
"/ [checkedNode notNil] whileTrue:[
"/ checkedNode isMessage ifTrue:[
"/ self codeCompletionForMessage:checkedNode inClass:cls.
"/ ^ self
"/ ].
"/ checkedNode isMethod ifTrue:[
"/ self codeCompletionForMethod:checkedNode inClass:cls.
"/ ^ self.
"/ ].
"/ checkedNode := checkedNode parent.
"/ ].
"/
"/ self showInfo:'Node is neither variable nor message.'.
"Modified: / 04-07-2006 / 18:48:26 / fm"
"Modified: / 20-11-2006 / 12:30:59 / cg"
"Modified: / 16-02-2010 / 10:53:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
reallyModified
"check for modified code by comparing the source against
the codeViews contents.
Thats the true modified value (in case user undid its changes,
and the displayed text is actually original"
|modified changedSource originalSource s1 s2|
textView modified ifTrue:[^true].
"/ higher prio to prevent it from being changed while we convert it (by editing)
Processor activeProcess
withHigherPriorityDo:[
changedSource := textView contentsAsString asStringCollection.
].
changedSource := changedSource collect:[:line | line string withoutTrailingSeparators withTabsExpanded].
changedSource := changedSource collect:[:line | line isEmpty ifTrue:[nil] ifFalse:[line]].
[changedSource size > 0 and:[changedSource last isNil]] whileTrue:[
changedSource := changedSource copyButLast:1
].
changedSource := changedSource asString.
originalSource := textView model value ? ''.
originalSource := originalSource asStringCollection.
originalSource := originalSource collect:[:line | line string withoutTrailingSeparators withTabsExpanded].
originalSource := originalSource collect:[:line | line isEmpty ifTrue:[nil] ifFalse:[line]].
[originalSource size > 0 and:[originalSource last isNil]] whileTrue:[
originalSource := originalSource copyButLast:1
].
s1 := originalSource asString.
s2 := changedSource asString.
modified := (s1 ~= s2).
^ modified
"Created: / 06-02-2010 / 19:59:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (format): / 05-06-2012 / 23:55:02 / cg"
!
showInfo: message
| app |
(app := self topView application) ifNotNil:
[(app respondsTo: #showInfo:) ifTrue:
[app showInfo: message]].
"Modified: / 13-02-2010 / 23:25:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'private-accessing'!
gutterView
^gutterView
"Created: / 14-02-2010 / 15:21:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
syntaxElementSelection
^ syntaxElementSelection
!
syntaxElementSelection:something
syntaxElementSelection := something.
!
syntaxElements
^ syntaxElements
!
syntaxElements:something
syntaxElements := something.
!
textView
^textView
"Created: / 14-02-2010 / 15:21:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
textViewScroller
^textViewScroller
"Created: / 14-02-2010 / 15:21:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'realization'!
disableAllServices
services do:[:service|
service enabled:false.
]
!
enableAllServices
services do:[:service|
service enabled:true.
]
!
postRealize
services do:[:service|
service viewRealized.
]
"Created: / 23-01-2012 / 10:35:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2 methodsFor:'services'!
registerService: aCodeViewService
services add: aCodeViewService.
aCodeViewService registerIn: self
"Created: / 06-03-2010 / 19:19:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
unregisterService: aCodeViewService
services remove: aCodeViewService ifAbsent:[^self].
aCodeViewService unregister.
"Created: / 06-03-2010 / 19:21:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Created: / 19-07-2012 / 16:34:18 / cg"
! !
!CodeView2 methodsFor:'testing'!
isCodeView2
^true
"Created: / 20-07-2010 / 15:43:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
isTextView
^true
"Created: / 14-02-2010 / 22:13:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::GutterView methodsFor:'accessing'!
menuHolder:aValueThing
menuHolder := aValueThing
!
setTextView: aTextView
self assert: textView isNil message:'Attempting to set textView twice'.
textView := aTextView.
textView addDependent:self.
"/ self backgroundPaint: textView backgroundPaint darkened lighter.
self viewBackground: (View defaultBackgroundColor). "/ textView backgroundPaint darkened lighter.
self paint: textView paint.
self font: textView font.
"Created: / 02-09-2009 / 21:55:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 14-12-2009 / 15:09:29 / Jindra <a>"
"Modified: / 09-02-2010 / 20:03:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 17-08-2011 / 15:15:09 / cg"
!
setTextViewScroller:aScr
textViewScroller := aScr.
"Created: / 07-12-2009 / 22:36:31 / Jindra <a>"
! !
!CodeView2::GutterView methodsFor:'accessing-dimensions'!
acceptButtonBottom
^(self height * 0.6) ceiling.
"Created: / 07-10-2011 / 19:53:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
cancelButtonBottom
^(self height * 0.8) ceiling.
"Created: / 07-10-2011 / 19:54:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
padding
^self paddingLeft + self paddingRight
+ self usedWidthForAcceptCancel
+ (widthAnnotations ? 0)
+ (widthDiffInfo ? 0)
"Created: / 14-02-2010 / 22:28:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 07-10-2011 / 19:01:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (format): / 07-10-2011 / 20:45:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
paddingLeft
^0"px"
"Created: / 14-02-2010 / 22:27:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 16-06-2011 / 13:47:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
paddingRight
^0"px"
"Created: / 14-02-2010 / 22:27:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 16-06-2011 / 13:47:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
preferredExtent
| font w h |
explicitExtent ifNotNil:[^explicitExtent].
preferredExtent ifNotNil:[^preferredExtent].
font := self font.
w := (font widthOf:'00') + self padding.
h := textView notNil
ifTrue:[textView height]
ifFalse:[font height * 12].
^preferredExtent := w @ h
"Modified: / 16-06-2011 / 14:03:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (format): / 26-03-2012 / 11:19:54 / cg"
!
usedWidthForAcceptCancel
^ (codeView showAcceptCancelBar ifTrue:[widthAcceptCancel ? 0] ifFalse:[0])
! !
!CodeView2::GutterView methodsFor:'actions'!
accept
textView accept
"Created: / 07-10-2011 / 20:23:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
cancel
textView cancel
"Created: / 07-10-2011 / 20:23:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
diff
"Created: / 07-10-2011 / 20:23:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
middleButtonMenu
menuHolder notNil ifTrue:[^ menuHolder value].
^ codeView servicesMenu
! !
!CodeView2::GutterView methodsFor:'change & update'!
adjustSizeForLongestLine
"recompute the required width (longest linenumber present, not shown)"
|newNumberOfLines longestLineString textW requiredW newWidth|
newNumberOfLines := textView list size.
longestLineString := self displayedString:(newNumberOfLines max:99).
textW := (longestLineString widthOn:self).
requiredW := textW + self padding.
((requiredW > width) or:[requiredW < (width * 3 // 4)]) ifTrue:[
"/ some hysteresis to avoid quick readjust again
newWidth := (requiredW * 1.1) rounded.
self corner:(newWidth+1 @ 1.0).
[
textView removeDependent:self.
textViewScroller origin:(newWidth+1 @ 0.0) corner:(1.0 @ 1.0).
] ensure:[
textView addDependent:self.
].
self invalidate.
] ifFalse:[
numberOfLines ~= newNumberOfLines ifTrue:[
self invalidate
]
].
!
update:something with:aParameter from:changedObject
"/ self shown ifFalse:[^self].
(changedObject == textView) ifTrue:[
((something == #sizeOfContents)
or:[ false "(something == #sizeOfView)" ]) ifTrue:[
self adjustSizeForLongestLine.
"/ (numberOfLines ~= (textView list size max:textView cursorLine)) ifTrue:[
"/ self invalidate.
"/ ].
^ self.
].
].
(changedObject == textView reallyModifiedChannel) ifTrue:[
"/ cg: I think this is rubbish: if any service needs that, it should make itself
"/ dependent of it itself (leads to many redraws for non-existing accept-cancel bar,
"/ if no such service is active)
"/ self invalidate.
^ self.
].
super update:something with:aParameter from:changedObject
"Modified (format): / 15-07-2011 / 20:14:04 / cg"
"Modified: / 07-10-2011 / 19:25:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::GutterView methodsFor:'event handling'!
buttonPress: btn x: x y: y
|extraSafeArea|
(x <= (self paddingLeft + self usedWidthForAcceptCancel)) ifTrue:[
textView reallyModified ifTrue:[
(y < self acceptButtonBottom) ifTrue:[
self accept.
^self.
].
(y < self cancelButtonBottom) ifTrue:[
self cancel.
^self.
].
self diff.
].
^self.
].
false ifTrue:[
"Do not allow clicking on line numbers..."
extraSafeArea := "('999' widthOn:self)" 5.
x < (self width - self paddingRight - widthDiffInfo - extraSafeArea) ifFalse:[^ self].
].
((x > (self paddingLeft + self usedWidthForAcceptCancel)) or:
[x < (self width - self paddingRight - widthDiffInfo)]
) ifTrue:[
(codeView buttonPress: btn x:x y:y in: self) ifFalse:[
super buttonPress: btn x: x y: y
]
] ifFalse:[
super buttonPress: btn x: x y: y
]
"Created: / 17-06-2011 / 13:02:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (comment): / 18-05-2012 / 10:56:54 / cg"
! !
!CodeView2::GutterView methodsFor:'help'!
flyByHelpText
|bpntService topView|
bpntService := codeView breakpointService.
(bpntService isNil or:[bpntService isEnabled not]) ifTrue:[
^ nil
].
(bpntService canCreateOrToggleBreakpointAtLine:nil) ifFalse:[
((topView := codeView topView) class == DebugView) ifTrue:[
bpntService hasBreakpoints ifFalse:[
^ 'Sorry - cannot add breakpoint in the debugger (would need recompilation)\(can only add breakpoints if stopped at a method breakpoint)' withCRs
].
^ 'Click to toggle existing breakpoint. Shift-Click to toggle tracepoint.\Sorry - cannot add new breakpoint if method is already entered\(i.e. if not stopped at a method breakpoint).' withCRs
].
^ 'Cannot add breakpoint when modified. Please accept first.'
].
^ 'Click to toggle breakpoint. Shift-Click to toggle tracepoint.'
"Created: / 27-01-2012 / 14:04:52 / cg"
! !
!CodeView2::GutterView methodsFor:'initialization'!
initialize
super initialize.
widthAcceptCancel := 16.
widthAnnotations := 8.
widthDiffInfo := 5.
acceptColor := Color green lighter onDevice:device.
cancelColor := Color red lighter lighter onDevice:device.
diffColor := Color yellow lighter lighter onDevice:device.
"Created: / 16-06-2011 / 13:47:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
setCodeView: aCodeView2
codeView := aCodeView2.
textView := aCodeView2 textView.
codeView addDependent: self.
codeView reallyModifiedChannel addDependent: self.
textView addDependent: self.
textViewScroller := aCodeView2 textViewScroller.
"/ self backgroundPaint: (textView viewBackground "backgroundPaint" blendWith: (Color gray:80)).
self viewBackground: (View defaultBackgroundColor).
"Created: / 14-02-2010 / 15:19:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 17-08-2011 / 15:15:55 / cg"
"Modified: / 08-10-2011 / 11:58:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::GutterView methodsFor:'queries'!
displayedString: line
"get text to display in gutter for specified list line number"
^(line asString).
"Created: / 14-12-2009 / 13:37:47 / Jindra <a>"
!
lineColor:line
"return special color for given line if required, nil otherwise"
"used only if lineFont return nil"
^nil
"Created: / 14-12-2009 / 15:01:31 / Jindra <a>"
!
lineDisplayable:line
"true if this list line can be displayed"
^(textView listLineIsVisible:line)
"Created: / 14-12-2009 / 13:38:23 / Jindra <a>"
!
lineFont:line
"return special font for given line if required, nil otherwise"
^nil
"Created: / 14-12-2009 / 14:40:17 / Jindra <a>"
!
yOfTextViewLine:line
^(textView yOfLine:line) + 1
"Created: / 14-12-2009 / 13:35:07 / Jindra <a>"
! !
!CodeView2::GutterView methodsFor:'redrawing'!
invalidateDeviceRectangle:aRectangle repairNow:doRepairNow
^ super invalidateDeviceRectangle:aRectangle repairNow:doRepairNow
!
redrawAcceptCancelBarX: x y: y width:w height:h
| rw acceptBottom cancelBottom |
x > ((self paddingLeft) + (widthAcceptCancel ? 0)) ifTrue:[
^self.
].
rw := ((x + w) min: (self paddingLeft + (widthAcceptCancel ? 0))) - x.
textView reallyModified ifFalse:[
self fillRectangleX:x y:y width:rw height:h color: self viewBackground
] ifTrue:[
acceptBottom := self acceptButtonBottom.
cancelBottom := self cancelButtonBottom.
y < acceptBottom ifTrue:[
self fillRectangleX:x y:y width:rw height: ((y + h) min: acceptBottom) color: acceptColor.
].
(y < cancelBottom) ifTrue:[
self fillRectangleX:x y: acceptBottom + 1width:rw height: ((y + h) min: cancelBottom) - acceptBottom - 1color: cancelColor.
].
(y + h >= cancelBottom) ifTrue:[
self fillRectangleX:x y: cancelBottom + 1 width:rw height: (y + h) - cancelBottom - 1 color: diffColor.
]
]
"Created: / 07-10-2011 / 19:44:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
redrawBackgroundX:x y:y width:w height:h
"redraws gutter background"
|savPaint|
"background is filled with background color"
self
clearRectangleX:x
y:y
width:w
height:h.
"separator line is drawn in grey"
savPaint := self paint.
self paint:Color grey.
self
displayLineFromX:(width - 1)
y:y
toX:(width - 1)
y:(y+h).
self paint:savPaint.
"Created: / 14-12-2009 / 13:15:53 / Jindra <a>"
"Modified: / 14-12-2009 / 15:09:54 / Jindra <a>"
"Modified: / 17-08-2011 / 15:12:47 / cg"
"Modified (comment): / 07-10-2011 / 19:37:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
redrawLine:line
^self redrawLine:line cleared: false.
"Modified: / 17-06-2011 / 14:12:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
redrawLine:line cleared: cleared
"redraws specified line. Returns width of drawn object. Color of drawn objects should be taken from lineFont, lineColor"
^ self redrawLine:line cleared:cleared drawServices:true
!
redrawLine:line cleared:cleared drawServices:drawServices
"redraws specified line. Returns width of drawn object. Color of drawn objects should be taken from lineFont, lineColor"
|lineString y0 textW requiredW oldFont newFont oldColor newColor|
lineString := self displayedString:line.
textW := (lineString widthOn:self).
requiredW := textW + self padding.
oldFont := self font.
oldColor := self paint.
newFont := self lineFont:line.
newFont isNil ifTrue:[
newFont := oldFont.
newColor := self lineColor:line.
newColor ifNotNil:[ self paint:newColor ].
].
newFont ~~ oldFont ifTrue:[
(newFont heightOn:device) > (textView font heightOn:device) ifTrue:[
newFont := textView font.
].
self font:newFont
].
y0 := (textView yOfLine:line)
+ (textView font ascentOn:device)
"/ - (newFont descentOn:device)
+ 1.
cleared ifFalse:[
self clearRectangleX:0 y:y0 - font height width: self width - 2 height: font height + font descent.
].
"/ cg: this should be done differently: services know about the
"/ gutter, so they should respond to a special drawGutter message.
"/ otherwise, some redraws become unusably slow (esecially
"/ with multiple fonts/colors/emphases)...
drawServices ifTrue:[
"Let services draw annotations and other stuff"
codeView
drawLine:line in: self
atX: (self paddingLeft + self usedWidthForAcceptCancel) y:y0 width: widthAnnotations height: font height
from:nil to:nil with:self paint and: self backgroundColor.
].
self
displayString:lineString
x:(self width - textW - 2 - self paddingRight - widthDiffInfo)
y:y0.
newFont
ifNotNil:[
self font:oldFont.
self paint:oldColor
]
ifNil:[
newColor ifNotNil:[ self paint:oldColor ].
].
^ requiredW.
"Modified: / 14-12-2009 / 15:30:44 / Jindra <a>"
"Created: / 17-06-2011 / 14:11:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 18-07-2012 / 19:05:24 / cg"
!
redrawLinesFrom:start
"/ cg: obsolete?
start to: (textView lastLineShown - 1 min: textView list size) do:[:line|
self redrawLine:line cleared: false.
]
"Created: / 06-07-2011 / 17:25:36 / jv"
"Modified: / 12-07-2011 / 17:14:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
redrawX:x y:y width:w height:h
self redrawBackgroundX:x y:y width:w height:h.
codeView showAcceptCancelBar ifTrue:[
self redrawAcceptCancelBarX:x y:y width:w height:h.
].
numberOfLines := (textView list size max:textView cursorLine).
firstLineShown := textView firstLineShown.
lastLineShown := textView lastLineShown - 1 min: numberOfLines.
firstLineShown to:lastLineShown do: [:line |
self redrawLine:line cleared:true drawServices:true
].
! !
!CodeView2::TextView methodsFor:'accessing'!
changedDiffText
^ changedDiffText
!
changedDiffText:something
changedDiffText := something.
!
changedLines
^ changedLines
"Created: / 26-04-2010 / 20:30:32 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 26-04-2010 / 21:48:13 / Jakub <zelenja7@fel.cvut.cz>"
!
changedLines:something
changedLines := something.
"Created: / 26-04-2010 / 20:30:19 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 02-05-2010 / 19:13:32 / Jakub <zelenja7@fel.cvut.cz>"
!
contents: text
super contents: text.
reallyModifiedChannel value: false.
"Created: / 07-10-2011 / 20:32:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
deletedLines
^ deletedLines
"Modified: / 26-04-2010 / 21:48:23 / Jakub <zelenja7@fel.cvut.cz>"
!
deletedLines:something
deletedLines := something.
"Modified: / 26-04-2010 / 21:48:54 / Jakub <zelenja7@fel.cvut.cz>"
"Modified (format): / 17-07-2012 / 18:56:44 / cg"
!
diffMode
^ diffMode
!
diffMode:something
diffMode := something.
!
emptyLines
^ emptyLines
!
emptyLines:something
emptyLines := something.
!
insertedLines
^ insertedLines
"Modified: / 26-04-2010 / 21:48:27 / Jakub <zelenja7@fel.cvut.cz>"
!
insertedLines:something
insertedLines := something.
"Modified: / 26-04-2010 / 21:48:59 / Jakub <zelenja7@fel.cvut.cz>"
"Modified (format): / 17-07-2012 / 18:56:50 / cg"
!
modifiedChannel: aValueHolder
super modifiedChannel: aValueHolder
"Created: / 07-07-2011 / 12:27:11 / Jan Vrany <jan.vrant@fit.cvut,cz>"
!
originDiffText
^ originDiffText
!
originDiffText:something
originDiffText := something.
!
reallyModified
^self reallyModifiedChannel value
"Created: / 07-10-2011 / 19:28:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'accessing-colors'!
colorChanged
^ Color redByte:240 greenByte: 192 blueByte: 192
"Modified: / 24-06-2010 / 14:05:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
colorDeleted
^ self colorInserted.
"/^ Color pink
"Modified: / 24-06-2010 / 14:16:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (format): / 07-10-2011 / 20:26:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (format): / 17-07-2012 / 18:57:14 / cg"
!
colorInserted
^ Color redByte: 239 greenByte: 225 blueByte: 152
"Modified: / 24-06-2010 / 14:13:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'accessing-contents'!
list:aCollection expandTabs:expand scanForNonStrings:scan includesNonStrings:nonStrings
super list:aCollection expandTabs:expand scanForNonStrings:scan includesNonStrings:nonStrings.
listOriginal := aCollection copy.
reallyModifiedChannel value: false.
self notifyLinesModifiedFrom: 1 to: list size.
"Created: / 08-10-2011 / 12:23:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
setList:aCollection expandTabs:expandTabs redraw:doRedraw
super setList:aCollection expandTabs:expandTabs redraw:doRedraw.
listOriginal := aCollection copy.
reallyModifiedChannel value: false.
self notifyLinesModifiedFrom: 1 to: list size.
"Created: / 07-10-2011 / 18:42:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'accessing-state'!
beUnmodified
self modifiedChannel value: false.
reallyModifiedChannel value: false.
listOriginal := list copy.
"Created: / 08-10-2011 / 12:51:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
isModified
^self modified
"Created: / 08-10-2011 / 12:52:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
isReallyModified
^self reallyModified
"Created: / 08-10-2011 / 12:52:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'channels'!
reallyModifiedChannel
^ reallyModifiedChannel
"Created: / 07-10-2011 / 18:50:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
reallyModifiedChannel: aValueModel
|prev|
prev := reallyModifiedChannel.
prev notNil ifTrue:[
gutterView notNil ifTrue:[
reallyModifiedChannel removeDependent: gutterView.
]
].
reallyModifiedChannel := aValueModel.
self setupChannel:aValueModel for:nil withOld:prev.
gutterView notNil ifTrue:[
reallyModifiedChannel addDependent: gutterView.
]
"Created: / 07-10-2011 / 18:50:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'delegation-events'!
isQuickMenuModifierPressed
UserPreferences current codeView2QuickSendersAndImplementorsOnControl ifTrue:[
^ self sensor ctrlDown
].
^ self sensor metaDown
!
isQuickMenuModifierReleased
UserPreferences current codeView2QuickSendersAndImplementorsOnControl ifTrue:[
^ self sensor ctrlDown not
].
^ self sensor metaDown not
! !
!CodeView2::TextView methodsFor:'drawing'!
drawFromVisibleLine:startVisLineNr to:endVisLineNr with:fg and:bg
super
drawFromVisibleLine:startVisLineNr
to:endVisLineNr
with:fg
and:bg.
self redrawLines.
"Created: / 05-04-2010 / 12:08:38 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 02-05-2010 / 18:46:04 / Jakub <zelenja7@fel.cvut.cz>"
!
drawLine:line fromX:x inVisible:visLineNr with:fg and:bg
super
drawLine:line
fromX:x
inVisible:visLineNr
with:fg
and:bg.
self redrawLines.
"Created: / 05-04-2010 / 12:07:07 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 02-05-2010 / 18:46:00 / Jakub <zelenja7@fel.cvut.cz>"
!
drawLine:lineStringArg inVisible:visLineNr col:col with:fg and:bg
super
drawLine:lineStringArg
inVisible:visLineNr
col:col
with:fg
and:bg.
self redrawLines.
"Created: / 05-04-2010 / 11:49:42 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 02-05-2010 / 18:45:56 / Jakub <zelenja7@fel.cvut.cz>"
!
drawLine:lineStringArg inVisible:visLineNr from:startCol to:endColOrNil with:fg and:bg
super
drawLine:lineStringArg
inVisible:visLineNr
from:startCol
to:endColOrNil
with:fg
and:bg.
self redrawLines.
"Created: / 05-04-2010 / 11:54:54 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 02-05-2010 / 18:45:52 / Jakub <zelenja7@fel.cvut.cz>"
!
drawLine:lineString inVisible:visLineNr from:startCol with:fg and:bg
super
drawLine:lineString
inVisible:visLineNr
from:startCol
with:fg
and:bg.
self redrawLines.
"Created: / 05-04-2010 / 11:54:26 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 02-05-2010 / 18:45:48 / Jakub <zelenja7@fel.cvut.cz>"
!
drawVisibleLine:visLineNr with:fg and:bg
super
drawVisibleLine:visLineNr
with:fg
and:bg.
self redrawLines.
"Created: / 05-04-2010 / 11:49:42 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 02-05-2010 / 18:45:44 / Jakub <zelenja7@fel.cvut.cz>"
!
redraw
"/ thisContext fullPrintAll.
super redraw.
"Created: / 30-06-2011 / 11:04:32 / cg"
!
redrawLines
|i pom|
diffMode ifFalse:[^self].
pom := self hasSelection.
(pom) ifTrue:[ ^ self. ].
i := 1.
[
i <= (deletedLines size)
] whileTrue:[
((deletedLines at:i) > 0) ifTrue:[
super
drawVisibleLine:(deletedLines at:i)
with:fgColor
and:self colorDeleted.
].
i := i + 1.
].
i := 1.
[
i <= (insertedLines size)
] whileTrue:[
((insertedLines at:i) > 0) ifTrue:[
super
drawVisibleLine:(insertedLines at:i)
with:fgColor
and:self colorInserted.
].
i := i + 1.
].
i := 1.
[
i <= (changedLines size)
] whileTrue:[
((changedLines at:i) > 0) ifTrue:[
super
drawVisibleLine:(changedLines at:i)
with:fgColor
and:self colorChanged.
].
i := i + 1.
].
"Created: / 26-04-2010 / 21:04:31 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 22-06-2010 / 23:28:30 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 08-04-2011 / 20:52:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'editing'!
contentsChanged
"this one is sent, whenever contents changes its size"
super contentsChanged.
"/ codeView diffMode ifTrue:[
"/ changedDiffText ifTrue:[
"/ codeView recomputeDiff:self.
"/ ] ifFalse:[
"/ changedDiffText := true.
"/ ].
"/ ]
"Created: / 22-06-2010 / 23:13:24 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 01-08-2010 / 20:33:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
deleteCharBeforeCursor
"delete single character to the left of cursor and move cursor to left"
"BIG FAT WARNING: This method is copied from TextEditView,
the fix should be there, but someone smarter should review it
before the patch will be pushed up"
|soCol wasOn lineNrAboveCursor ln originalLine prevTab|
wasOn := self hideCursor.
"JV@2012-01-06: Do not play with autoindent iff cursor is at the very beginning of the line"
(autoIndent
and:[cursorCol ~~ 1
and:[ (tabPositions includes:cursorCol)
]]) ifTrue:[
prevTab := (self prevTabBefore:cursorCol) max:1.
"JV@2011-12-10: The list can be shorter than cursorLine,
trailing because empty lines are not physically in the list."
(list size >= cursorLine) ifTrue:[
ln := originalLine := (list at:cursorLine) ? ''.
] ifFalse:[
ln := originalLine := ''.
].
ln size < prevTab ifTrue:[
ln := ln , (String new:prevTab withAll:Character space).
].
(ln copyTo:prevTab) isBlank ifTrue:[
(ln copyFrom:prevTab+1) isBlank ifTrue:[
cursorCol > prevTab ifTrue:[
self st80EditMode ifTrue:[
"/ ensure that there is no conflict here: st80EditMode will
"/ not allow a cursor position beyond the end of line,
"/ so avoid that cursorLine:col: will force us to the beginning of the line
originalLine size < prevTab ifTrue:[
self at:cursorLine put:ln
]
].
self cursorLine:cursorLine col:prevTab.
wasOn ifTrue:[ self showCursor ].
^ self
].
] ifFalse:[
"/ (ln copyFrom:prevTab+1 to:cursorCol-1) isBlank ifTrue:[
self deleteFromLine:cursorLine col:prevTab toLine:cursorLine col:cursorCol-1.
self cursorLine:cursorLine col:prevTab.
wasOn ifTrue:[ self showCursor ].
^ self.
"/ ]
]
].
].
"/ (autoIndent
"/ and:[cursorCol ~~ 1
"/ and:[cursorLine <= (list size)]])
"/ ifTrue:[
"/ soCol := (self leftIndentForLine:cursorLine) + 1.
"/
"/ (cursorCol == soCol and:[soCol > 1]) ifTrue:[
"/ ln := list at:cursorLine.
"/ (ln notNil and:[(ln indexOfNonSeparatorStartingAt:1) < soCol]) ifTrue:[
"/ soCol := 1
"/ ]
"/ ]
"/ ] ifFalse:[
soCol := 1.
"/ ].
(cursorCol ~~ soCol and:[cursorCol ~~ 1]) ifTrue:[
"
somewhere in the middle of a line
"
self cursorLeft.
self deleteCharAtLine:cursorLine col:cursorCol.
] ifFalse:[
"
at begin of line - merge with previous line;
except for the very first line.
"
(cursorLine == 1) ifFalse:[
lineNrAboveCursor := self validateCursorLine:(cursorLine - 1).
lineNrAboveCursor < cursorLine ifTrue:[
(lineNrAboveCursor > 0 and:[lineNrAboveCursor > list size]) ifTrue:[
"/ we are beyond the end of the text.
"/ move the cursor to the previous line.
self cursorLine:lineNrAboveCursor col:1.
] ifFalse:[
self mergeLine:lineNrAboveCursor removeBlanks:false.
]
]
]
].
wasOn ifTrue:[ self showCursor ]
"Modified: / 16-01-1998 / 22:33:04 / cg"
"Modified: / 06-01-2012 / 12:42:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
getNewOriginText
|i size pole pom text helperText|
i := 1.
pole := list.
size := list size.
text:=''.
emptyLines isNil ifTrue:[emptyLines := #()].
[ i <= size ] whileTrue:[
pom := emptyLines indexOf:i.
(pom = 0) ifFalse:[
helperText := pole at:i.
(helperText = '') ifFalse:[
(helperText isNil)ifTrue:[helperText:=''].
helperText:=helperText,Character cr.
text := text asString , helperText asString.
].
] ifTrue:[
helperText := pole at:i.
(helperText isNil)ifTrue:[helperText:=''].
helperText:=helperText,Character cr.
text := text asString , helperText asString.
].
i:=i+1.
].
^text
"Created: / 22-06-2010 / 22:33:27 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 24-06-2010 / 14:27:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 18-11-2011 / 14:58:22 / cg"
! !
!CodeView2::TextView methodsFor:'editing-basic'!
basicDeleteCharsAtLine:lineNr fromCol:startCol toCol:endCol
"delete characters from startCol to endCol in line lineNr"
super basicDeleteCharsAtLine:lineNr fromCol:startCol toCol:endCol.
self notifyLinesModifiedFrom: lineNr to: lineNr.
"Created: / 16-09-2011 / 15:13:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
basicDeleteFromLine:startLineNr toLine:endLineNr
super basicDeleteFromLine:startLineNr toLine:endLineNr.
self notifyLinesDeletedFrom:startLineNr to:endLineNr.
"Created: / 28-06-2011 / 09:09:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
basicDeleteLineWithoutRedraw:lineNr
super basicDeleteLineWithoutRedraw:lineNr.
self notifyLinesDeletedFrom: lineNr to: lineNr.
"Created: / 28-06-2011 / 09:10:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
basicInsert:aCharacter atLine:lineNr col:colNr
"insert a single character at lineNr/colNr;
set emphasis to character at current position"
super basicInsert:aCharacter atLine:lineNr col:colNr.
self notifyLinesModifiedFrom: lineNr to: lineNr.
"Created: / 16-09-2011 / 15:14:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
basicMergeLine:lineNr removeBlanks:removeBlanks
super basicMergeLine:lineNr removeBlanks:removeBlanks.
self notifyLinesDeletedFrom: lineNr + 1 to: lineNr + 1.
"Created: / 28-06-2011 / 09:13:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
basicSplitLine:lineNr before:colNr
super basicSplitLine:lineNr before:colNr.
self notifyLinesInsertedFrom: lineNr +1 to: lineNr + 1.
"Created: / 28-06-2011 / 09:14:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
insertLines:someText from:start to:end before:lineNr
"/JV@2011-12-20: HACK, the super implementation should
"/not use leftIndent...when pasting. Following is a workaround"
| wasAutoIndent |
wasAutoIndent := autoIndent.
autoIndent := false.
[
super insertLines:someText from:start to:end before:lineNr.
] ensure:[
autoIndent := wasAutoIndent
]
"Created: / 20-12-2011 / 15:32:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'event handling'!
buttonMotion:button x:x y:y
(codeView buttonMotion:button x:x y:y in: self)
ifFalse:[super buttonMotion:button x:x y:y].
"Created: / 14-02-2010 / 16:23:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-03-2010 / 20:10:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
buttonPress: button x: x y: y
| ctrlDown |
(codeView buttonPress:button x:x y:y in: self)
ifFalse:[super buttonPress:button x:x y:y].
"
((ctrlDown := self sensor ctrlDown) and: [ codeView syntaxElementSelection notNil])
ifTrue: [codeView buttonPressInTextView: button x:x y:y ctrlDown: ctrlDown].
super
buttonPress: button
x: x
y: y
"
"Created: / 14-02-2010 / 18:12:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-03-2010 / 20:37:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
buttonRelease: button x: x y: y
(codeView buttonRelease:button x:x y:y in: self)
ifFalse:[super buttonRelease:button x:x y:y].
!
exposeX:x y:y width:w height:h
super
exposeX:x
y:y
width:w
height:h.
self redrawLines.
"Created: / 05-04-2010 / 10:07:50 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 02-05-2010 / 18:41:07 / Jakub <zelenja7@fel.cvut.cz>"
!
keyPress:key x:x y:y
(codeView keyPress:key x:x y:y in: self)
ifFalse:[super keyPress:key x:x y:y].
"Modified: / 06-03-2010 / 20:34:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 05-04-2010 / 09:55:52 / Jakub <zelenja7@fel.cvut.cz>"
!
keyRelease: key x: x y: y
(codeView keyRelease:key x:x y:y in: self)
ifFalse:[super keyRelease:key x:x y:y].
"
(key = #Control_L) ifTrue:
[ codeView highlightClear. self redraw ].
^ super
keyRelease: key
x: x
y: y
"
"Created: / 14-02-2010 / 16:38:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-03-2010 / 21:04:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'formatting'!
leftIndentForLine:lineNr
| lang |
lang := codeView language.
"Bit hacky here, should ask language some language toolbox
for formatting helper, that should do it..."
(lang notNil and:[lang isSmalltalk]) ifTrue:[
| line lineNo indent |
lineNo := lineNr.
[lineNo ~~ 1] whileTrue:[
lineNo := lineNo - 1.
line := self listAt:lineNo.
line notNil ifTrue:[
indent := line indexOfNonSeparatorStartingAt:1.
"beggining od block"
line notEmptyOrNil ifTrue:[
line last == $[ ifTrue:[
indent := indent + 4.
] ifFalse:[
"end of block args"
(line last == $| and: [line includes: $[]) ifTrue:[
indent := indent + 4.
]
].
].
indent ~~ 0 ifTrue:[
^ indent - 1
]
]
].
^0.
].
^super leftIndentForLine:lineNr
"Created: / 10-12-2011 / 11:02:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'initialization'!
initialize
super initialize.
changedDiffText := true.
diffMode := false.
suppressNotifications := false.
reallyModifiedChannel := false asValue.
self enableMotionEvents.
"Created: / 23-06-2010 / 17:28:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-07-2011 / 17:46:31 / jv"
"Modified: / 21-08-2011 / 10:09:29 / cg"
"Modified: / 07-10-2011 / 19:22:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
setCodeView: aCodeView2
codeView := aCodeView2.
codeView addDependent: self.
gutterView := aCodeView2 gutterView.
"Created: / 14-02-2010 / 15:22:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 17-06-2011 / 12:43:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
setGutterView: aGutterView
self assert: gutterView isNil message:'Attempting to set gutterView twice'.
gutterView := aGutterView.
gutterView setTextView: self.
"Created: / 02-09-2009 / 21:57:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'menu & menu actions'!
accept
super accept.
reallyModifiedChannel value: false.
listOriginal := list copy.
"Created: / 07-10-2011 / 19:36:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
cancel
self list: listOriginal
"Created: / 08-02-2010 / 09:29:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
editMenu
^ codeView editMenu
"Created: / 14-02-2010 / 15:49:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (format): / 08-03-2012 / 12:30:22 / cg"
!
searchVariableVisible
"search variable option in searchbox visible?"
^ true
"Created: / 08-03-2012 / 14:01:51 / cg"
! !
!CodeView2::TextView methodsFor:'notification'!
notifyLinesDeletedFrom: startLine to: endLine
self updateReallyModified.
suppressNotifications ifTrue:[^self].
codeView linesDeletedFrom: startLine to: endLine.
suppressNotifications := true.
"Created: / 28-06-2011 / 09:12:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-07-2011 / 17:47:05 / jv"
"Modified: / 07-10-2011 / 19:20:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
notifyLinesInsertedFrom: startLine to: endLine
self updateReallyModified.
suppressNotifications ifTrue:[^self].
codeView linesInsertedFrom: startLine to: endLine.
suppressNotifications := true.
"Created: / 28-06-2011 / 09:12:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-07-2011 / 17:47:20 / jv"
"Modified: / 07-10-2011 / 19:20:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
notifyLinesModifiedFrom: startLine to: endLine
self updateReallyModified.
suppressNotifications ifTrue:[^self].
codeView linesModifiedFrom: startLine to: endLine.
suppressNotifications := true.
"Modified: / 06-07-2011 / 17:47:20 / jv"
"Created: / 16-09-2011 / 15:12:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'private'!
superEditMenu
^super editMenu
"Created: / 14-02-2010 / 15:48:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
updateReallyModified
"check for modified code by comparing the source against
the codeViews contents.
Thats the true modified value (in case user undid its changes,
and the displayed text is actually original"
|modified changedSource originalSource lastLineOfChangedSource lastLineOfOriginalSource|
reallyModifiedChannel isNil ifTrue:[^self].
"JV@2011-10-27: Idea is not to do anything if nobody is
interested. Not sure if it is a good idea, thought."
reallyModifiedChannel dependents isEmptyOrNil ifTrue:[^self].
"/ higher prio to prevent it from being changed while we convert it (by editing)
modified := false.
list size ~~ listOriginal size ifTrue:[
modified := true.
] ifFalse:[
"/ cg: don't do that (collecting original/changedSource);
"/ for huge files (>8Mb), this makes editing annoying slow (editing a trace output, for example)
"/ changedSource := list ? #().
"/ changedSource := changedSource collect:[:line | line isEmptyOrNil ifTrue:[nil] ifFalse:[line]].
"/ [changedSource size > 0 and:[changedSource last isNil]] whileTrue:[
"/ changedSource := changedSource removeLast.
"/ ].
"/
"/ originalSource := listOriginal ? #() "self model value ? ''".
"/ originalSource := originalSource collect:[:line | line isEmptyOrNil ifTrue:[nil] ifFalse:[line]].
"/ [originalSource size > 0 and:[originalSource last isNil]] whileTrue:[
"/ originalSource := originalSource removeLast
"/ ].
"/ originalSource size ~~ changedSource size ifTrue:[
"/ modified := true.
"/ ] ifFalse:[
"/ | i stopIndex |
"/
"/ i := 1.
"/ stopIndex := originalSource size + 1.
"/ [ modified not and:[ i < stopIndex ] ] whileTrue:[
"/ | originalL changedL |
"/
"/ originalL := ((originalSource at: i) ? '') string.
"/ changedL := ((changedSource at: i) ? '') string.
"/ originalL ~= changedL ifTrue:[
"/ originalL withoutTrailingSeparators ~= changedL withoutTrailingSeparators ifTrue:[
"/ modified := true.
"/ ]
"/ ].
"/ i := i + 1.
"/ ]
"/ ].
"/ instead, do everything without collecting a new stringcollection.
changedSource := list ? #().
lastLineOfChangedSource := changedSource size.
[lastLineOfChangedSource > 0 and:[(changedSource at:lastLineOfChangedSource) isEmptyOrNil]] whileTrue:[
lastLineOfChangedSource := lastLineOfChangedSource - 1.
].
originalSource := listOriginal ? #().
lastLineOfOriginalSource := originalSource size.
[lastLineOfOriginalSource > 0 and:[(originalSource at:lastLineOfOriginalSource) isEmptyOrNil]] whileTrue:[
lastLineOfOriginalSource := lastLineOfOriginalSource - 1.
].
lastLineOfOriginalSource ~~ lastLineOfChangedSource ifTrue:[
modified := true.
] ifFalse:[
| i stopIndex |
i := 1.
stopIndex := lastLineOfOriginalSource + 1.
[ modified not and:[ i < stopIndex ] ] whileTrue:[
| originalL changedL |
originalL := ((originalSource at: i) ? '') string.
changedL := ((changedSource at: i) ? '') string.
originalL ~= changedL ifTrue:[
originalL withoutTrailingSeparators ~= changedL withoutTrailingSeparators ifTrue:[
modified := true.
]
].
i := i + 1.
]
].
].
reallyModifiedChannel value: modified
"Created: / 07-10-2011 / 19:16:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 08-10-2011 / 11:10:01 / cg"
"Modified: / 28-10-2011 / 09:23:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'queries'!
supportsSyntaxElements
^ true
!
syntaxElementAtPosition:position
"is there is a syntax element at position?
If so, return the element; otherwise, return nil"
|syntaxElements el element|
syntaxElements := codeView syntaxElements.
syntaxElements isEmptyOrNil ifTrue:[^ nil].
el := syntaxElements detect:[:el | position between:el start and:el stop] ifNone:nil.
el isNil ifTrue:[^ nil].
element := 1234.
^ el.
"Created: / 08-03-2012 / 14:21:52 / cg"
!
syntaxElementForSelectedVariable
"is there is a syntax element for a variable under the cursor?
If so, return the element; otherwise, return nil"
|element startPosition endPosition|
self selectionAsString isEmptyOrNil ifTrue:[^ nil].
startPosition := self characterPositionOfLine:selectionStartLine col:selectionStartCol.
endPosition := self characterPositionOfLine:selectionEndLine col:selectionEndCol.
element := self syntaxElementAtPosition:startPosition.
element isNil ifTrue:[^ nil].
(element start = startPosition and:[element stop = endPosition]) ifFalse:[^ nil].
element isNil ifTrue:[^ nil].
element isVariableOrSelf ifFalse:[^ nil].
^ element
"Created: / 08-03-2012 / 14:21:15 / cg"
!
syntaxElementForSelectorUnderCursor
"is there is a syntax element for a message selector under the cursor?
If so, return the element; otherwise, return nil"
|elementUnderCursor |
elementUnderCursor := self syntaxElementAtPosition:(self characterPositionOfCursor).
elementUnderCursor isNil ifTrue:[^ nil].
elementUnderCursor isSelector ifFalse:[^ nil].
^ elementUnderCursor.
"Created: / 08-03-2012 / 12:44:03 / cg"
!
syntaxElementForVariableUnderCursor
"is there is a syntax element for a variable under the cursor?
If so, return the element; otherwise, return nil"
|elementUnderCursor |
elementUnderCursor := self syntaxElementAtPosition:(self characterPositionOfCursor).
elementUnderCursor isNil ifTrue:[^ nil].
elementUnderCursor isVariableOrSelf ifFalse:[^ nil].
^ elementUnderCursor.
"Created: / 08-03-2012 / 12:44:03 / cg"
! !
!CodeView2::TextView methodsFor:'scrolling'!
basicScrollDown:nLines
|i|
(lastFirstLine isNil) ifTrue:[
lastFirstLine := firstLineShown.
].
super scrollDown:nLines.
(lastFirstLine = firstLineShown) ifFalse:[
i := 1.
[
i <= changedLines size
] whileTrue:[
super
drawVisibleLine:(changedLines at:i)
with:fgColor
and:Color white.
changedLines at:i put:(changedLines at:i) - nLines.
i := i + 1.
].
i := 1.
[
i <= insertedLines size
] whileTrue:[
super
drawVisibleLine:(insertedLines at:i)
with:fgColor
and:Color white.
insertedLines at:i put:(insertedLines at:i) - nLines.
i := i + 1.
].
i := 1.
[
i <= deletedLines size
] whileTrue:[
super
drawVisibleLine:(deletedLines at:i)
with:fgColor
and:Color white.
deletedLines at:i put:(deletedLines at:i) - nLines.
i := i + 1.
].
lastFirstLine := firstLineShown.
self redrawLines.
].
"Created: / 06-04-2010 / 14:03:28 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 02-05-2010 / 19:29:23 / Jakub <zelenja7@fel.cvut.cz>"
!
basicScrollUp:nLines
|i|
(scrolled isNil) ifTrue:[
scrolled := false.
].
(lastFirstLine isNil) ifTrue:[
lastFirstLine := firstLineShown.
].
super scrollUp:nLines.
(lastFirstLine = firstLineShown) ifFalse:[
i := 1.
[
i <= insertedLines size
] whileTrue:[
super
drawVisibleLine:(insertedLines at:i)
with:fgColor
and:Color white.
insertedLines at:i put:(insertedLines at:i) + nLines.
i := i + 1.
].
i := 1.
[
i <= deletedLines size
] whileTrue:[
super
drawVisibleLine:(deletedLines at:i)
with:fgColor
and:Color white.
deletedLines at:i put:(deletedLines at:i) + nLines.
i := i + 1.
].
i := 1.
[
i <= changedLines size
] whileTrue:[
super
drawVisibleLine:(changedLines at:i)
with:fgColor
and:Color white.
changedLines at:i put:(changedLines at:i) + nLines.
i := i + 1.
].
lastFirstLine := firstLineShown.
self redrawLines.
].
"Created: / 06-04-2010 / 14:03:46 / Jakub <zelenja7@fel.cvut.cz>"
"Modified: / 02-05-2010 / 19:19:27 / Jakub <zelenja7@fel.cvut.cz>"
!
originChanged:delta
super originChanged:delta.
gutterView invalidate.
"Created: / 07-12-2009 / 21:50:49 / Jindra <a>"
!
scrollDown:nLines
codeView scrollDown: nLines in: self.
self basicScrollDown: nLines.
"Modified: / 06-04-2010 / 14:04:28 / Jakub <zelenja7@fel.cvut.cz>"
!
scrollUp:nLines
codeView scrollUp: nLines in: self.
self basicScrollUp: nLines.
"Modified: / 06-04-2010 / 14:05:40 / Jakub <zelenja7@fel.cvut.cz>"
! !
!CodeView2::TextView methodsFor:'undo & again'!
nonUndoableDo: aBlock
super nonUndoableDo: aBlock.
suppressNotifications := false.
"Created: / 06-07-2011 / 17:48:27 / jv"
!
undoableDo: aBlock info: into
super undoableDo: aBlock info: into.
suppressNotifications := false.
"Created: / 06-07-2011 / 17:48:49 / jv"
! !
!CodeView2 class methodsFor:'documentation'!
version
^ '$Header: /cvs/stx/stx/libtool/Tools__CodeView2.st,v 1.98 2013-07-04 17:06:05 cg Exp $'
!
version_CVS
^ '$Header: /cvs/stx/stx/libtool/Tools__CodeView2.st,v 1.98 2013-07-04 17:06:05 cg Exp $'
!
version_SVN
^ '$Id: Tools__CodeView2.st,v 1.98 2013-07-04 17:06:05 cg Exp $'
! !
CodeView2 initialize!