162 {
163
164 _Bool didEdit = false, didCaptureEvent = false;
165
167 if (this->isEditable) {
168 if (event->type == SDL_MOUSEBUTTONDOWN) {
172 SDL_StartTextInput();
173 if (this->delegate.didBeginEditing) {
174 this->delegate.didBeginEditing(this);
175 }
176 }
177 didCaptureEvent = true;
178 } else {
180 self->state &= ~ControlStateFocused;
181 SDL_StopTextInput();
182 if (this->delegate.didEndEditing) {
183 this->delegate.didEndEditing(this);
184 }
185 didCaptureEvent = true;
186 }
187 }
188 } else if (event->type == SDL_TEXTINPUT) {
190 if (this->position == this->attributedText->string.length) {
191 $(this->attributedText, appendCharacters, event->text.text);
192 } else {
193 $(this->attributedText, insertCharactersAtIndex, event->text.text, this->position);
194 }
195 this->position += strlen(event->text.text);
196 didEdit = didCaptureEvent = true;
197 }
198 } else if (event->type == SDL_KEYDOWN) {
200 didCaptureEvent = true;
201
202 const char *chars = this->attributedText->string.chars;
203 const size_t len = this->attributedText->string.length;
204
205 switch (event->key.keysym.sym) {
206
207 case SDLK_ESCAPE:
208 case SDLK_KP_ENTER:
209 case SDLK_KP_TAB:
210 case SDLK_RETURN:
211 case SDLK_TAB:
212 self->state &= ~ControlStateFocused;
213 SDL_StopTextInput();
214 if (this->delegate.didEndEditing) {
215 this->delegate.didEndEditing(this);
216 }
217 break;
218
219 case SDLK_BACKSPACE:
220 case SDLK_KP_BACKSPACE:
221 if (this->position > 0) {
222 const Range range = { .location = this->position - 1, .length = 1 };
223 $(this->attributedText, deleteCharactersInRange, range);
224 this->position--;
225 didEdit = true;
226 }
227 break;
228
229 case SDLK_DELETE:
230 if (this->position < len) {
231 const Range range = { .location = this->position, .length = 1 };
232 $(this->attributedText, deleteCharactersInRange, range);
233 didEdit = true;
234 }
235 break;
236
237 case SDLK_LEFT:
238 if (SDL_GetModState() & KMOD_CTRL) {
239 while (this->position > 0 && chars[this->position] == ' ') {
240 this->position--;
241 }
242 while (this->position > 0 && chars[this->position] != ' ') {
243 this->position--;
244 }
245 } else if (this->position > 0) {
246 this->position--;
247 }
248 break;
249
250 case SDLK_RIGHT:
251 if (SDL_GetModState() & KMOD_CTRL) {
252 while (this->position < len && chars[this->position] == ' ') {
253 this->position++;
254 }
255 while (this->position < len && chars[this->position] != ' ') {
256 this->position++;
257 }
258 if (this->position < len) {
259 this->position++;
260 }
261 } else if (this->position < len) {
262 this->position++;
263 }
264 break;
265
266 case SDLK_HOME:
267 this->position = 0;
268 break;
269
270 case SDLK_END:
271 this->position = len;
272 break;
273
274 case SDLK_a:
275 if (SDL_GetModState() & KMOD_CTRL) {
276 this->position = 0;
277 }
278 break;
279 case SDLK_e:
280 if (SDL_GetModState() & KMOD_CTRL) {
281 this->position = len;
282 }
283 break;
284
285 case SDLK_v:
286 if ((SDL_GetModState() & (KMOD_CTRL | KMOD_GUI)) && SDL_HasClipboardText()) {
287 const char *text = SDL_GetClipboardText();
288 if (this->position == len) {
289 $(this->attributedText, appendCharacters, text);
290 } else {
291 $(this->attributedText, insertCharactersAtIndex, text, this->position);
292 }
293 this->position += strlen(text);
294 didEdit = true;
295 }
296 break;
297
298 default:
299 break;
300 }
301 }
302 }
303
304 if (didEdit) {
306 if (this->delegate.didEdit) {
307 this->delegate.didEdit(this);
308 }
309 }
310 }
311
312 return didCaptureEvent;
313}
_Bool needsLayout
If true, this View will layout its subviews before it is drawn.
_Bool didReceiveEvent(const View *self, const SDL_Event *event)