--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/EditTextViewCompletionSupport.st Thu Sep 26 19:07:20 2013 +0200
@@ -0,0 +1,291 @@
+"{ Package: 'stx:libwidg' }"
+
+Object subclass:#EditTextViewCompletionSupport
+ instanceVariableNames:'completionView completionProcess editView autoSelect'
+ classVariableNames:'LastCompletions'
+ poolDictionaries:''
+ category:'Views-Text'
+!
+
+!EditTextViewCompletionSupport class methodsFor:'documentation'!
+
+documentation
+"
+ An abstract supperclass to support completion in text views.
+ Individual completion engines may create a subclass of
+ EditTextCompletionSupport and customize it.
+
+ Basucally, they have to implement #computeCompletions
+
+ [author:]
+ Claus Gittinger
+
+ [instance variables:]
+
+ [class variables:]
+
+ [see also:]
+
+"
+! !
+
+!EditTextViewCompletionSupport class methodsFor:'instance creation'!
+
+for:anEditView
+ ^ self new editView:anEditView
+! !
+
+!EditTextViewCompletionSupport class methodsFor:'queries'!
+
+isAbstract
+ ^true
+
+ "Created: / 26-09-2013 / 16:22:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!EditTextViewCompletionSupport methodsFor:'accessing'!
+
+editView:anEditTextView
+ editView := anEditTextView.
+! !
+
+!EditTextViewCompletionSupport methodsFor:'events'!
+
+buttonPress:button x:x y:y
+ self closeCompletionView.
+!
+
+editViewLostFocus
+ completionView notNil ifTrue:[
+ self closeCompletionView
+ ]
+!
+
+handleKeyPress:key x:x y:y
+ "return true, if I have eaten this keypress"
+
+ |ch completeImmediate eatCursorLeftOrRight|
+
+ completeImmediate := UserPreferences current immediateCodeCompletion.
+
+ "/ open on CTRL- or TAB-key?
+ (completionView isNil or:[completionView realized not]) ifTrue:[
+ editView hasSelection ifFalse:[
+ ((ch := editView characterBeforeCursor) notNil "/ i.e. not at begin of line
+ and:[ ch isSeparator not ]) ifTrue:[
+ (key == #Control_L or:[ key == #Ctrl or:[ key == #Control_R or:[ key == #Control]]]) ifTrue:[
+ UserPreferences current codeCompletionOnControlKey ifTrue:[
+ autoSelect := true.
+ self updateCompletionList
+ ]
+ ].
+ (key == #Tab) ifTrue:[
+ UserPreferences current codeCompletionOnTabKey ifTrue:[
+ autoSelect := true.
+ self updateCompletionList.
+ ^ true
+ ].
+ ]
+ ].
+ ].
+ ^ false.
+ ].
+
+ "/ key for completion view ? (careful: do not forward too many, it would disturb user's typing)
+ key isCharacter ifFalse:[
+ "/ forward to menu
+ (completionView notNil) ifTrue:[
+ eatCursorLeftOrRight := false.
+"/ completeImmediate not
+"/ or:[ editView sensor shiftDown
+"/ or:[ editView sensor ctrlDown ]].
+ (key == #CursorDown
+ or:[ (key == #CursorUp)
+ or:[ ((key == #CursorLeft) and:[eatCursorLeftOrRight])
+ or:[ ((key == #CursorRight) and:[eatCursorLeftOrRight])
+ or:[ ((key == #Return) and:[ completionView hasSelection ])
+ ]]]]) ifTrue:[
+ "/ only with shift - normal user typing should not interfere with completion
+ true "editView sensor shiftDown" ifTrue:[
+ "/ forward to completion view
+ completionView sensor pushUserEvent:#value for:[ completionView keyPress:key x:0 y:0 ].
+ ^ true.
+ ].
+ ].
+
+ (key == #Control_L or:[ key == #Control_R or:[ key == #Control or:[ key == #Ctrl ]]]) ifTrue:[
+ "/ CTRL is a toggle
+ self closeCompletionView.
+ ^ true.
+ "/ ^ false
+ ].
+ (key == #Escape) ifTrue:[
+ self closeCompletionView.
+ ^ true "/ EAT
+ ].
+ "/ shift does not close
+ (key == #Shift_L or:[ key == #Shift_R or:[ key == #Shift]]) ifTrue:[
+ ^ false "/ don' eat
+ ].
+
+ self closeCompletionView.
+ ^ false "/ don' eat
+ ].
+ ].
+ ^ false.
+!
+
+postKeyPress:key
+ UserPreferences current immediateCodeCompletion ifFalse:[
+ "/ only update, if already open
+ completionView isNil ifTrue:[^ self].
+ ].
+
+ (key == #BackSpace or:[key == #BasicBackspace]) ifTrue:[
+ autoSelect := false.
+ self updateCompletionList.
+ ^ self
+ ].
+
+ key isCharacter ifTrue:[
+ key isSeparator ifTrue:[
+ self closeCompletionView
+ ] ifFalse:[
+ autoSelect := false.
+ self updateCompletionList.
+ ].
+ ^ self
+ ].
+! !
+
+!EditTextViewCompletionSupport methodsFor:'private'!
+
+release
+ self stopCompletionProcess.
+ self closeCompletionView.
+ super release
+!
+
+startCompletionProcess
+ "start the code completion process in the background"
+
+ |initialList cursorX cursorY|
+
+ "/ terminate any previous process
+ self stopCompletionProcess.
+
+ (editView sensor hasKeyPressEventFor:nil) ifTrue:[
+ self closeCompletionView.
+ ^ self
+ ].
+ ((cursorX := editView xOfCursor) isNil
+ or:[ (cursorY := editView yOfCursor) isNil ]) ifTrue:[
+ "/ no cursor - user is selecting, or cursor has been scrolled out of sight.
+ self closeCompletionView.
+ ^ self
+ ].
+
+ initialList := #( 'busy...' ).
+
+ self openCompletionView.
+
+ completionProcess :=
+ [
+ self computeCompletions.
+ ] forkAt:(Processor activePriority - 1).
+
+ "Modified: / 26-09-2013 / 17:36:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+stopCompletionProcess
+ "kill any background completion process"
+
+ |p|
+
+ (p := completionProcess) notNil ifTrue:[
+ completionProcess := nil.
+ p terminate.
+ ].
+!
+
+updateCompletionList
+ "called for keypress events"
+
+ self startCompletionProcess.
+! !
+
+!EditTextViewCompletionSupport methodsFor:'private-API'!
+
+closeCompletionView
+ |v|
+
+ (v := completionView) notNil ifTrue:[
+ completionView := nil.
+ "/ let it close itself - avoids synchronization problems
+ v sensor
+ pushUserEvent:#value
+ for:[ v topView destroy ]
+ ].
+!
+
+computeCompletions
+ "Actually compute the completions and update the completion view."
+
+ self subclassResponsibility
+
+ "Created: / 26-09-2013 / 17:35:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+openCompletionView
+ "Opens the completion view with an initial list. Called as soon as
+ completion is initiated but completion options are not yet computed."
+
+ self openCompletionView: (Array with: 'Busy...')
+
+ "Created: / 26-09-2013 / 17:06:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+openCompletionView: list
+ "Makes sure the completion view is opened and with given `list`."
+
+ | movePos topView |
+ "/ move the window
+ movePos := editView device translatePoint:(editView xOfCursor @ editView yOfCursor) fromView:editView toView:nil.
+ movePos := movePos - (editView viewOrigin x @ 0).
+ "/ currently, we have to stay away a bit, to avoid getting the focus
+ movePos := movePos + (60 @ (editView font height)).
+
+ completionView isNil ifTrue:[
+ completionView := CodeCompletionHelpMenuView new.
+ completionView name:'completion'.
+ completionView level:0.
+ completionView list:list.
+ completionView enable:false.
+ completionView extent:completionView preferredExtentForContents.
+ completionView font: editView font.
+ topView := CodeCompletionHelpView with:completionView.
+ topView origin:movePos.
+ topView resizeToFit.
+ "/ topView open.
+ ] ifFalse:[
+ completionView list:list.
+ topView := completionView topView.
+ topView ~~ completionView ifTrue:[
+ topView origin:movePos.
+ topView resizeToFit.
+ ]
+ ].
+
+ "Created: / 26-09-2013 / 17:07:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!EditTextViewCompletionSupport class methodsFor:'documentation'!
+
+version
+ ^ '$Header: /cvs/stx/stx/libwidg/EditTextViewCompletionSupport.st,v 1.1 2013-09-26 17:07:20 vrany Exp $'
+!
+
+version_CVS
+ ^ '$Header: /cvs/stx/stx/libwidg/EditTextViewCompletionSupport.st,v 1.1 2013-09-26 17:07:20 vrany Exp $'
+! !
+