EditTextView.st
changeset 125 3ffa271732f7
parent 123 25ab7ade4d3a
child 127 462396b08e30
equal deleted inserted replaced
124:7abd3a234296 125:3ffa271732f7
    15 TextView subclass:#EditTextView
    15 TextView subclass:#EditTextView
    16 	 instanceVariableNames:'cursorLine cursorVisibleLine cursorCol cursorShown
    16 	 instanceVariableNames:'cursorLine cursorVisibleLine cursorCol cursorShown
    17 		prevCursorState readOnly modified fixedSize exceptionBlock
    17 		prevCursorState readOnly modified fixedSize exceptionBlock
    18 		errorMessage cursorFgColor cursorBgColor cursorType undoAction
    18 		errorMessage cursorFgColor cursorBgColor cursorType undoAction
    19 		typeOfSelection lastString lastReplacement lastAction replacing
    19 		typeOfSelection lastString lastReplacement lastAction replacing
    20 		showMatchingParenthesis hasKeyboardFocus'
    20 		showMatchingParenthesis hasKeyboardFocus acceptAction lockUpdates'
    21 	 classVariableNames:'DefaultCursorForegroundColor DefaultCursorBackgroundColor
    21 	 classVariableNames:'DefaultCursorForegroundColor DefaultCursorBackgroundColor
    22 		DefaultCursorType'
    22 		DefaultCursorType'
    23 	 poolDictionaries:''
    23 	 poolDictionaries:''
    24 	 category:'Views-Text'
    24 	 category:'Views-Text'
    25 !
    25 !
    26 
    26 
    27 EditTextView comment:'
    27 EditTextView comment:'
    28 COPYRIGHT (c) 1989 by Claus Gittinger
    28 COPYRIGHT (c) 1989 by Claus Gittinger
    29 	    All Rights Reserved
    29 	    All Rights Reserved
    30 
    30 
    31 $Header: /cvs/stx/stx/libwidg/EditTextView.st,v 1.26 1995-05-07 01:58:10 claus Exp $
    31 $Header: /cvs/stx/stx/libwidg/EditTextView.st,v 1.27 1995-05-09 01:55:23 claus Exp $
    32 '!
    32 '!
    33 
    33 
    34 !EditTextView class methodsFor:'documentation'!
    34 !EditTextView class methodsFor:'documentation'!
    35 
    35 
    36 copyright
    36 copyright
    47 "
    47 "
    48 !
    48 !
    49 
    49 
    50 version
    50 version
    51 "
    51 "
    52 $Header: /cvs/stx/stx/libwidg/EditTextView.st,v 1.26 1995-05-07 01:58:10 claus Exp $
    52 $Header: /cvs/stx/stx/libwidg/EditTextView.st,v 1.27 1995-05-09 01:55:23 claus Exp $
    53 "
    53 "
    54 !
    54 !
    55 
    55 
    56 documentation
    56 documentation
    57 "
    57 "
    58     a view for editable text - adds editing functionality to TextView
    58     a view for editable text - adds editing functionality to TextView
       
    59     Also, it adds accept functionality, and defines a new actionBlock: 
       
    60       acceptAction to be performed for accept
       
    61 
       
    62     If used with a model, this is informed by sending it a changeMsg with
       
    63     the current contents as argument.
       
    64     (however, it is possible to define moth changeMsg and acceptAction)
       
    65 
    59 
    66 
    60     Instance variables:
    67     Instance variables:
    61 
    68 
    62       cursorLine              <Number>        line where cursor sits (1..)
    69       cursorLine              <Number>        line where cursor sits (1..)
    63       cursorVisibleLine       <Number>        visible line where cursor sits (1..nLinesShown)
    70       cursorVisibleLine       <Number>        visible line where cursor sits (1..nLinesShown)
   102     DefaultCursorForegroundColor := StyleSheet colorAt:'textCursorForegroundColor'.
   109     DefaultCursorForegroundColor := StyleSheet colorAt:'textCursorForegroundColor'.
   103     DefaultCursorBackgroundColor := StyleSheet colorAt:'textCursorBackgroundColor'.
   110     DefaultCursorBackgroundColor := StyleSheet colorAt:'textCursorBackgroundColor'.
   104     DefaultCursorType := StyleSheet at:'textCursorType' default:#block.
   111     DefaultCursorType := StyleSheet at:'textCursorType' default:#block.
   105 ! !
   112 ! !
   106 
   113 
       
   114 !EditTextView methodsFor:'change & update '!
       
   115 
       
   116 getListFromModel
       
   117     "get my contents from the model.
       
   118      Redefined to ignore updates resulting from my own change."
       
   119 
       
   120     "
       
   121      ignore updates from my own change
       
   122     "
       
   123     lockUpdates ifTrue:[
       
   124 	lockUpdates := false.
       
   125 	^ self
       
   126     ].
       
   127     ^ super getListFromModel
       
   128 !
       
   129 
       
   130 accept
       
   131     "accept the current contents by executing the accept-action and/or
       
   132      changeMessage."
       
   133 
       
   134     lockUpdates := true.
       
   135      "/
       
   136      "/ ST/X way of doing things
       
   137      "/ as a historic (and temporary) leftover,
       
   138      "/ the block is called with a stringCollection
       
   139      "/ - not with the actual string
       
   140      "/
       
   141      acceptAction notNil ifTrue:[
       
   142 	 acceptAction value:self list
       
   143      ].
       
   144 
       
   145      "/
       
   146      "/ ST-80 way of doing it
       
   147      "/
       
   148      self sendChangeMessageWith:self contents.
       
   149 
       
   150     lockUpdates := false.
       
   151 ! !
       
   152 
   107 !EditTextView methodsFor:'event processing'!
   153 !EditTextView methodsFor:'event processing'!
   108 
   154 
   109 hasKeyboardFocus:aBoolean
   155 hasKeyboardFocus:aBoolean
   110     "sent by a delegate to make me show a block cursor
   156     "sent by a delegate to make me show a block cursor
   111      (otherwise, I would not know about this)"
   157      (otherwise, I would not know about this)"
   175     ]
   221     ]
   176 !
   222 !
   177 
   223 
   178 keyPress:key x:x y:y
   224 keyPress:key x:x y:y
   179     "handle keyboard input"
   225     "handle keyboard input"
       
   226 
       
   227     |sensor n|
       
   228 
       
   229     sensor := self sensor.
   180 
   230 
   181     (key isMemberOf:Character) ifTrue:[
   231     (key isMemberOf:Character) ifTrue:[
   182 	readOnly ifFalse:[
   232 	readOnly ifFalse:[
   183 	    typeOfSelection == #paste ifTrue:[
   233 	    typeOfSelection == #paste ifTrue:[
   184 		"pasted selection will NOT be replaced by keystroke"
   234 		"pasted selection will NOT be replaced by keystroke"
   233 
   283 
   234     "
   284     "
   235      Fn      pastes a key-sequence (but only if not overlayed with
   285      Fn      pastes a key-sequence (but only if not overlayed with
   236 	     another function in the keyboard map)
   286 	     another function in the keyboard map)
   237 
   287 
   238      see TextView>>keyPress:x:y
   288      see TextView>>:x:y
   239     "
   289     "
   240     (#(F1 F2 F3 F4 F5 F6 F7 F8 F9) includes:key) ifTrue:[
   290     (#(F1 F2 F3 F4 F5 F6 F7 F8 F9) includes:key) ifTrue:[
   241 	device shiftDown ifFalse:[
   291 	device shiftDown ifFalse:[
   242 	    (Smalltalk at:#FunctionKeySequences) notNil ifTrue:[
   292 	    (Smalltalk at:#FunctionKeySequences) notNil ifTrue:[
   243 		self paste:((Smalltalk at:#FunctionKeySequences) at:key) asStringCollection.
   293 		self paste:((Smalltalk at:#FunctionKeySequences) at:key) asStringCollection.
   299 		cursorVisibleLine := self listLineToVisibleLine:cursorLine.
   349 		cursorVisibleLine := self listLineToVisibleLine:cursorLine.
   300 	    ].
   350 	    ].
   301 	    self makeCursorVisible
   351 	    self makeCursorVisible
   302 	].
   352 	].
   303 	self unselect. 
   353 	self unselect. 
   304 	self cursorDown. ^self
   354 
       
   355 	sensor isNil ifTrue:[
       
   356 	    n := 1
       
   357 	] ifFalse:[
       
   358 	    n := 1 + (sensor compressKeyPressEventsWithKey:#CursorDown).
       
   359 	].
       
   360 	self cursorDown:n. 
       
   361 	^ self
   305     ].
   362     ].
   306     (key == #CursorLeft or:[key == #CursorUp]) ifTrue:[
   363     (key == #CursorLeft or:[key == #CursorUp]) ifTrue:[
   307 	selectionStartLine notNil ifTrue:[
   364 	selectionStartLine notNil ifTrue:[
   308 	    cursorLine := selectionStartLine.
   365 	    cursorLine := selectionStartLine.
   309 	    cursorVisibleLine := self listLineToVisibleLine:cursorLine.
   366 	    cursorVisibleLine := self listLineToVisibleLine:cursorLine.
   313 	self unselect. 
   370 	self unselect. 
   314 	(key == #CursorLeft) ifTrue:[
   371 	(key == #CursorLeft) ifTrue:[
   315 	    self cursorLeft. ^self
   372 	    self cursorLeft. ^self
   316 	].
   373 	].
   317 	(key == #CursorUp)        ifTrue:[
   374 	(key == #CursorUp)        ifTrue:[
   318 	    self cursorUp. ^self
   375 	    sensor isNil ifTrue:[
       
   376 		n := 1
       
   377 	    ] ifFalse:[
       
   378 		n := 1 + (sensor compressKeyPressEventsWithKey:#CursorUp).
       
   379 	    ].
       
   380 	    self cursorUp:n. 
       
   381 	    ^ self
   319 	].
   382 	].
   320     ].
   383     ].
   321 
   384 
   322     (key == #Return)    ifTrue:[
   385     (key == #Return)    ifTrue:[
   323 	device shiftDown ifTrue:[
   386 	device shiftDown ifTrue:[
   561     self drawCursor:cursorType with:cursorFgColor and:cursorBgColor.
   624     self drawCursor:cursorType with:cursorFgColor and:cursorBgColor.
   562 !
   625 !
   563 
   626 
   564 drawCursor:cursorType with:fgColor and:bgColor
   627 drawCursor:cursorType with:fgColor and:bgColor
   565     "draw a cursor; the argument cursorType specifies what type
   628     "draw a cursor; the argument cursorType specifies what type
   566      of cursor should be drawn."
   629      of cursor should be drawn.
       
   630      Currently, supported are: #block, #frame, #ibeam, #caret and #solidCaret"
   567 
   631 
   568     |x y w char y2 x1 x2|
   632     |x y w char y2 x1 x2|
   569 
   633 
   570     self hasSelection ifTrue:[
   634     self hasSelection ifTrue:[
   571 	"
   635 	"
   609     x2 := x + w.
   673     x2 := x + w.
   610     cursorType == #caret ifTrue:[
   674     cursorType == #caret ifTrue:[
   611 	self lineWidth:2.
   675 	self lineWidth:2.
   612 	self displayLineFromX:x1 y:y2 toX:x y:y. 
   676 	self displayLineFromX:x1 y:y2 toX:x y:y. 
   613 	self displayLineFromX:x y:y toX:x2 y:y2. 
   677 	self displayLineFromX:x y:y toX:x2 y:y2. 
   614     ].
   678     ] ifFalse:[
   615     cursorType == #solidCaret ifTrue:[
   679 	"anything else: solidCaret"
   616 	self fillPolygon:(Array with:(x1 @ y2)
   680 
   617 				with:(x @ y)
   681 "/        cursorType == #solidCaret ifTrue:[
   618 				with:(x1 @ y2))
   682 	    self fillPolygon:(Array with:(x1 @ y2)
       
   683 				    with:(x @ y)
       
   684 				    with:(x2 @ y2))
       
   685 "/        ]
   619     ].
   686     ].
   620 !
   687 !
   621 
   688 
   622 cursorReturn
   689 cursorReturn
   623     "move cursor to start of next line; scroll if at end of visible text"
   690     "move cursor to start of next line; scroll if at end of visible text"
   676 !
   743 !
   677 
   744 
   678 cursorUp
   745 cursorUp
   679     "move cursor up; scroll if at start of visible text"
   746     "move cursor up; scroll if at start of visible text"
   680 
   747 
   681     |wasOn|
   748     self cursorUp:1
   682 
   749 !
   683     (cursorLine == 1) ifFalse: [
   750 
   684 	cursorLine isNil ifTrue:[
   751 cursorUp:n
   685 	    cursorLine := firstLineShown + nFullLinesShown - 1.
   752     "move cursor up n lines; scroll if at start of visible text"
   686 	].
   753 
       
   754     |wasOn nv nl|
       
   755 
       
   756     cursorLine isNil ifTrue:[
       
   757 	cursorLine := firstLineShown + nFullLinesShown - 1.
       
   758     ].
       
   759     nl := cursorLine - n.
       
   760     nl < 1 ifTrue:[nl := 1].
       
   761 
       
   762     (nl ~~ cursorLine) ifTrue: [
   687 	wasOn := self hideCursor.
   763 	wasOn := self hideCursor.
   688 	(cursorVisibleLine == 1) ifTrue:[self scrollUp].
   764 	cursorVisibleLine notNil ifTrue:[
   689 	cursorLine := cursorLine - 1.
   765 	    nv := cursorVisibleLine - n.
       
   766 	    nv < 1 ifTrue:[
       
   767 		self scrollUp:(nv negated + 1)
       
   768 	    ].
       
   769 	].
       
   770 	cursorLine := nl.
   690 	cursorVisibleLine := self listLineToVisibleLine:cursorLine.
   771 	cursorVisibleLine := self listLineToVisibleLine:cursorLine.
   691 	wasOn ifTrue:[self showCursor].
   772 	wasOn ifTrue:[self showCursor].
   692 "/
   773 "/
   693 "/ to make cursor visible (even if below visible end):
   774 "/ to make cursor visible (even if below visible end):
   694 "/
   775 "/
   716 !
   797 !
   717 
   798 
   718 cursorDown
   799 cursorDown
   719     "move cursor down; scroll if at end of visible text"
   800     "move cursor down; scroll if at end of visible text"
   720 
   801 
   721     |wasOn|
   802     self cursorDown:1
       
   803 !
       
   804 
       
   805 cursorDown:n
       
   806     "move cursor down by n lines; scroll if at end of visible text"
       
   807 
       
   808     |wasOn nv|
   722 
   809 
   723     cursorVisibleLine notNil ifTrue:[
   810     cursorVisibleLine notNil ifTrue:[
   724 	wasOn := self hideCursor.
   811 	wasOn := self hideCursor.
   725 	(cursorVisibleLine >= nFullLinesShown) ifTrue:[self scrollDown].
   812 	nv := cursorVisibleLine + n - 1.
   726 	cursorLine := cursorLine + 1.
   813 	(nv >= nFullLinesShown) ifTrue:[
       
   814 	    self scrollDown:(nv - nFullLinesShown + 1)
       
   815 	].
       
   816 	cursorLine := cursorLine + n.
   727 	cursorVisibleLine := self listLineToVisibleLine:cursorLine.
   817 	cursorVisibleLine := self listLineToVisibleLine:cursorLine.
   728 	wasOn ifTrue:[self showCursor].
   818 	wasOn ifTrue:[self showCursor].
   729     ] ifFalse:[
   819     ] ifFalse:[
   730 	cursorLine isNil ifTrue:[
   820 	cursorLine isNil ifTrue:[
   731 	    cursorLine := firstLineShown
   821 	    cursorLine := firstLineShown
   732 	].
   822 	].
   733 	cursorLine := cursorLine + 1.
   823 	cursorLine := cursorLine + n.
   734 	cursorVisibleLine := self listLineToVisibleLine:cursorLine.
   824 	cursorVisibleLine := self listLineToVisibleLine:cursorLine.
   735 	self makeCursorVisible.
   825 	self makeCursorVisible.
   736     ].
   826     ].
   737 !
   827 !
   738 
   828 
   849 
   939 
   850     self makeLineVisible:aLineNumber.
   940     self makeLineVisible:aLineNumber.
   851     self cursorLine:aLineNumber col:1
   941     self cursorLine:aLineNumber col:1
   852 ! !
   942 ! !
   853 
   943 
   854 !EditTextView methodsFor:'accessing'!
   944 !EditTextView methodsFor:'accessing-behavior'!
       
   945 
       
   946 acceptAction:aBlock
       
   947     "set the action to be performed on accept"
       
   948 
       
   949     acceptAction := aBlock
       
   950 !
       
   951 
       
   952 acceptAction
       
   953     "return the action to be performed on accept (or nil)"
       
   954 
       
   955     ^ acceptAction
       
   956 !
       
   957 
       
   958 exceptionBlock:aBlock
       
   959     "define the action to be triggered when user tries to modify
       
   960      readonly text"
       
   961 
       
   962     exceptionBlock := aBlock
       
   963 ! !
       
   964 
       
   965 !EditTextView methodsFor:'accessing-contents'!
   855 
   966 
   856 characterUnderCursor
   967 characterUnderCursor
   857     "return the character under the cursor - space if behond line.
   968     "return the character under the cursor - space if behond line.
   858      For non-block cursors, this is the character immediately to the right
   969      For non-block cursors, this is the character immediately to the right
   859      of the insertion-bar or caret."
   970      of the insertion-bar or caret."
   928 	middleButtonMenu disable:#cut.
  1039 	middleButtonMenu disable:#cut.
   929 	middleButtonMenu disable:#paste.
  1040 	middleButtonMenu disable:#paste.
   930 	middleButtonMenu disable:#replace.
  1041 	middleButtonMenu disable:#replace.
   931 	middleButtonMenu disable:#indent
  1042 	middleButtonMenu disable:#indent
   932     ]
  1043     ]
   933 !
       
   934 
       
   935 exceptionBlock:aBlock
       
   936     "define the action to be triggered when user tries to modify
       
   937      readonly text"
       
   938 
       
   939     exceptionBlock := aBlock
       
   940 !
  1044 !
   941 
  1045 
   942 fromFile:aFileName
  1046 fromFile:aFileName
   943     "take contents from a named file"
  1047     "take contents from a named file"
   944 
  1048 
  1083 	self unselect
  1187 	self unselect
  1084     ] ifFalse:[
  1188     ] ifFalse:[
  1085 	super selectFromLine:cursorLine col:cursorCol toLine:(list size + 1) col:0.
  1189 	super selectFromLine:cursorLine col:cursorCol toLine:(list size + 1) col:0.
  1086 	typeOfSelection := nil
  1190 	typeOfSelection := nil
  1087     ]
  1191     ]
       
  1192 ! !
       
  1193 
       
  1194 !EditTextView methodsFor:'queries'!
       
  1195 
       
  1196 widthOfContents
       
  1197     "return the width of the contents in pixels
       
  1198      Redefined to add the size of a space (for the cursor).
       
  1199      this enables us to scroll one position further than the longest
       
  1200      line (and possibly see the cursor behind the line)"
       
  1201 
       
  1202     |w|
       
  1203 
       
  1204     w := super widthOfContents.
       
  1205     ^ w + (font widthOf:' ')
  1088 ! !
  1206 ! !
  1089 
  1207 
  1090 !EditTextView methodsFor:'private'!
  1208 !EditTextView methodsFor:'private'!
  1091 
  1209 
  1092 textChanged
  1210 textChanged
  1339     wasOn := self hideCursor.
  1457     wasOn := self hideCursor.
  1340     self insert:aCharacter atLine:cursorLine col:cursorCol.
  1458     self insert:aCharacter atLine:cursorLine col:cursorCol.
  1341     aCharacter == (Character cr) ifTrue:[
  1459     aCharacter == (Character cr) ifTrue:[
  1342 	self cursorReturn
  1460 	self cursorReturn
  1343     ] ifFalse:[
  1461     ] ifFalse:[
  1344 	cursorCol := cursorCol + 1
  1462 	self cursorRight.
  1345     ].
  1463     ].
  1346     self makeCursorVisibleAndShowCursor:wasOn.
  1464     self makeCursorVisibleAndShowCursor:wasOn.
  1347 !
  1465 !
  1348 
  1466 
  1349 insertString:aString atLine:lineNr col:colNr
  1467 insertString:aString atLine:lineNr col:colNr
  1986 
  2104 
  1987     (cursorCol == 1) ifFalse:[
  2105     (cursorCol == 1) ifFalse:[
  1988 	"
  2106 	"
  1989 	 somewhere in the middle of a line
  2107 	 somewhere in the middle of a line
  1990 	"
  2108 	"
  1991 	cursorCol := cursorCol - 1.
  2109 	self cursorLeft.
  1992 	self deleteCharAtLine:cursorLine col:cursorCol.
  2110 	self deleteCharAtLine:cursorLine col:cursorCol.
  1993     ] ifTrue:[
  2111     ] ifTrue:[
  1994 	"
  2112 	"
  1995 	 at begin of line - merge with previous line;
  2113 	 at begin of line - merge with previous line;
  1996 	 except for the very first line.
  2114 	 except for the very first line.
  2169 
  2287 
  2170 initStyle
  2288 initStyle
  2171     "initialize style specific stuff"
  2289     "initialize style specific stuff"
  2172 
  2290 
  2173     super initStyle.
  2291     super initStyle.
       
  2292     lockUpdates := false.
       
  2293 
  2174     cursorFgColor := DefaultCursorForegroundColor.
  2294     cursorFgColor := DefaultCursorForegroundColor.
  2175     cursorFgColor isNil ifTrue:[cursorFgColor := bgColor].
  2295     cursorFgColor isNil ifTrue:[cursorFgColor := bgColor].
  2176     cursorBgColor := DefaultCursorBackgroundColor.
  2296     cursorBgColor := DefaultCursorBackgroundColor.
  2177     cursorBgColor isNil ifTrue:[cursorBgColor := fgColor].
  2297     cursorBgColor isNil ifTrue:[cursorBgColor := fgColor].
  2178     cursorType := DefaultCursorType.
  2298     cursorType := DefaultCursorType.
  2276     ].
  2396     ].
  2277     ^ m.
  2397     ^ m.
  2278 ! !
  2398 ! !
  2279 
  2399 
  2280 !EditTextView methodsFor:'menu actions'!
  2400 !EditTextView methodsFor:'menu actions'!
  2281 
       
  2282 accept
       
  2283     "accept the contents"
       
  2284 
       
  2285     |value|
       
  2286 
       
  2287     value := self contents.
       
  2288 
       
  2289     "model-view behavior"
       
  2290     self sendChangeMessageWith:value.
       
  2291 !
       
  2292 
  2401 
  2293 paste:someText
  2402 paste:someText
  2294     "paste someText at cursor"
  2403     "paste someText at cursor"
  2295 
  2404 
  2296     |s startLine startCol|
  2405     |s startLine startCol|
  2796 						       toLine:line col:col
  2905 						       toLine:line col:col
  2797 				      ]
  2906 				      ]
  2798 			   ifNotFound:[self showNotFound]
  2907 			   ifNotFound:[self showNotFound]
  2799 			      onError:[device beep]
  2908 			      onError:[device beep]
  2800 ! !
  2909 ! !
  2801