2 "from key presses to function calls on the textbox"
3 Graphics define: #InputTranslator &parents: {Cloneable}.
4 Graphics define: #HashTableInputTranslator &parents: {InputTranslator} &slots: {#table -> Dictionary new}.
5 Graphics define: #TextboxInputTranslator &parents: {InputTranslator}.
6 Graphics define: #LineEditorInputTranslator &parents: {InputTranslator}.
8 Graphics define: #TextboxMorph &parents: {Morph} &slots: {
12 #inputTranslator -> TextboxInputTranslator new.
15 Graphics define: #LineEditorMorph &parents: {Morph} &slots: {
16 #editor -> LineEditor new.
18 #inputTranslator -> LineEditorInputTranslator new.
21 m@(LineEditorMorph traits) new
23 resend `>> [editor := m editor new. ]
26 "let the input translator class handle all keyboard input on me"
27 m@(TextboxMorph traits) handleMyself: e@(KeyboardEvent traits)
29 m inputTranslator handle: e on: m
32 m@(LineEditorMorph traits) handleMyself: e@(KeyboardEvent traits)
34 m inputTranslator handle: e on: m
37 it@(InputTranslator traits) handle: e@(InputEvent traits) on: m@(Morph traits)
39 inform: 'Default handler %s does not handle event %s', it, e.
43 it@(HashTableInputTranslator traits) handle: e@(KeyboardEvent traits) on: m@(Morph traits)
45 it table at: e key ifPresent: [| :func | func applyTo: {m. e}]
48 it@(TextboxInputTranslator traits) handle: e@(KeyboardPressEvent traits) on: m@(TextboxMorph traits) [].
49 it@(LineEditorInputTranslator traits) handle: e@(KeyboardPressEvent traits) on: m@(LineEditorMorph traits) [].
51 "someone pressed enter"
52 m@(TextboxMorph traits) activate [].
54 it@(TextboxInputTranslator traits) handle: e@(KeyboardReleaseEvent traits) on: m@(TextboxMorph traits)
58 -> [m repaint. m position := m position - 1 max: 0].
60 -> [m repaint. m position := m position + 1 min: m printText size].
66 m text := (m text first: m position - 1) ; (m text allButFirst: m position).
67 m position := m position - 1 max: 0].
71 m text := (m text first: m position) ; (m text allButFirst: m position + 1)].
74 [e character isPrintable]
76 m text := (m text first: m position) ; (e character as: String) ; (m text allButFirst: m position).
77 m position := m position + 1]
81 it@(LineEditorInputTranslator traits) handle: e@(KeyboardReleaseEvent traits) on: m@(LineEditorMorph traits)
85 -> [m repaint. m editor cursor setTo: (m editor cursor forwardOn: m editor)].
86 [e key = 102 /\ [e isControlOnly]]
87 -> [m repaint. m editor cursor setTo: (m editor cursor forwardOn: m editor).
88 m ensureVisibleCursor: m editor].
90 -> [m repaint. m editor cursor setTo: (m editor cursor backwardOn: m editor)].
91 [e key = 98 /\ [e isControlOnly]]
92 -> [m repaint. m editor cursor setTo: (m editor cursor backwardOn: m editor).
93 m ensureVisibleCursor: m editor].
95 -> [m repaint. m editor cursor setTo: (m editor cursor previousLineOn: m editor)].
96 [e key = 112 /\ [e isControlOnly]]
97 -> [m repaint. m editor cursor setTo: (m editor cursor previousLineOn: m editor).
98 m ensureVisibleCursor: m editor].
100 -> [m repaint. m editor cursor setTo: (m editor cursor nextLineOn: m editor)].
101 [e key = 110 /\ [e isControlOnly]]
102 -> [m repaint. m editor cursor setTo: (m editor cursor nextLineOn: m editor).
103 m ensureVisibleCursor: m editor].
105 [e key = 100 /\ [e isAltOnly]]
106 -> [('' concatenateAll: (m editor lines collect: #contents `er) &separator: m editor lineDelimeter)
110 -> [m repaint. m editor deleteBackwardAt: m editor cursor].
113 -> [m repaint. m editor deleteAt: m editor cursor].
115 [e key = 32 /\ [e isControlOnly]]
116 -> [m repaint. m editor setMark].
118 [e key = 103 /\ [e isControlOnly]]
119 -> [m repaint. m editor deleteMark].
121 [e key = 47 /\ [e isControlOnly]]
122 -> [m repaint. m editor undo].
124 [e key = 92 /\ [e isControlOnly]]
125 -> [m repaint. m editor redo].
127 [e key = 119 /\ [e isControlOnly]]
128 -> [m repaint. m editor cutTo: e window].
130 [e key = 119 /\ [e isAltOnly]]
131 -> [m repaint. m editor copyTo: e window].
133 [e key = 121 /\ [e isControlOnly]]
134 -> [m repaint. m editor pasteFrom: e window].
137 [e character `cache isPrintable \/ [e key = 13]]
138 -> [m repaint. m editor insert: e character at: m editor cursor]
142 m@(TextboxMorph traits) printText
143 ["this is the text as a string in case i change the underlying representation"
147 m@(TextboxMorph traits) handleMyself: input@(LeftMouseButtonReleaseEvent traits)
148 [ "don't drop focus like usual"
152 m@(TextboxMorph traits) paintMyselfOn: surface@(Surface traits)
154 surface sourceRGB: m theme textboxColor alpha: m theme textboxAlpha.
155 surface rectangleObject: m.
157 surface sourceRGB: m theme foregroundColor alpha: m theme foregroundAlpha.
158 surface rectangleObject: m.
160 surface fontSize: m fontSize.
161 "fixme, we should use cairo's text_extents function to see how large the text is and draw
162 the appropriate cursor. "
165 "print cursor... text is invisible here because we chose the foreground color"
166 surface moveTo: 10 <> ((m height // 2) + 2).
167 surface sourceRGB: m theme textboxColor alpha: m theme textboxAlpha.
168 surface showText: (text first: m position).
169 surface sourceRGB: m theme cursorColor alpha: m theme cursorAlpha.
170 surface showText: '_'.
173 surface moveTo: 10 <> (m height // 2).
174 surface sourceRGB: m theme textColor alpha: m theme textAlpha.
175 surface showText: text.
178 m@(LineEditorMorph traits) handleMyself: input@(LeftMouseButtonReleaseEvent traits)
179 [ "don't drop focus like usual"
183 m@(LineEditorMorph traits) ensureVisibleCursor: le@(LineEditor traits)
185 (m visibleRange includes: le cursor line)
186 ifFalse: [m editor firstVisibleLine: (le cursor line - (m editor visibleLines // 2) max: 0)].
189 m@(LineEditorMorph traits) visibleRange
191 (m editor firstVisibleLine to: (m editor firstVisibleLine + m editor visibleLines min: m editor lineCount - 1))
194 m@(LineEditorMorph traits) paintMyselfOn: surface@(Surface traits)
196 surface sourceRGB: m theme textboxColor alpha: m theme textboxAlpha.
197 surface rectangleObject: m. surface fill.
198 surface sourceRGB: m theme foregroundColor alpha: m theme foregroundAlpha.
199 surface rectangleObject: m. surface stroke.
200 surface fontSize: m fontSize.
201 "fixme, we should use cairo's text_extents function to see how large the text is and draw
202 the appropriate cursor. "
204 "fixme scrollbar position?"
206 do: [| :lineNumber line offset |
207 line: ((m editor lineAt: lineNumber) as: String).
208 offset: lineNumber - m editor firstVisibleLine + 1.
211 (cursor line = lineNumber)
212 ifTrue: ["print cursor... text is invisible here because we chose the foreground color"
213 surface moveTo: 5 <> (offset * m fontSize + 2).
214 surface sourceRGB: m theme textboxColor alpha: m theme textboxAlpha.
215 surface showText: (line first: cursor column).
216 "if it is the main cursor or not"
217 cursor == m editor cursor
218 ifTrue: [surface sourceRGB: m theme cursorColor alpha: m theme cursorAlpha]
219 ifFalse: [surface sourceRGB: m theme alternateCursorColor alpha: m theme alternateCursorAlpha].
220 surface showText: '_']].
222 surface moveTo: 5 <> (offset * m fontSize).
223 surface sourceRGB: m theme textColor alpha: m theme textAlpha.
224 surface showText: line].