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)" |
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. |