1use crate::{ScrollBar, ScrollMsg};
9use kas::event::components::{ScrollComponent, TextInput, TextInputAction};
10use kas::event::{CursorIcon, ElementState, FocusSource, ImePurpose, PhysicalKey, Scroll};
11use kas::geom::Vec2;
12use kas::messages::{ReplaceSelectedText, SetValueText};
13use kas::prelude::*;
14use kas::text::{NotReady, SelectionHelper};
15use kas::theme::{Background, FrameStyle, Text, TextClass};
16use std::fmt::{Debug, Display};
17use std::marker::PhantomData;
18use std::ops::Range;
19use std::str::FromStr;
20use unicode_segmentation::{GraphemeCursor, UnicodeSegmentation};
21
22#[derive(Clone, Debug, Default, PartialEq)]
23enum LastEdit {
24 #[default]
25 None,
26 Insert,
27 Delete,
28 Paste,
29}
30
31enum EditAction {
32 None,
33 Activate,
34 Edit,
35}
36
37pub trait EditGuard: Sized {
47 type Data;
49
50 fn configure(edit: &mut EditField<Self>, cx: &mut ConfigCx) {
54 let _ = (edit, cx);
55 }
56
57 fn update(edit: &mut EditField<Self>, cx: &mut ConfigCx, data: &Self::Data) {
69 let _ = (edit, cx, data);
70 }
71
72 fn activate(edit: &mut EditField<Self>, cx: &mut EventCx, data: &Self::Data) -> IsUsed {
84 if edit.editable {
85 Self::focus_lost(edit, cx, data);
86 Used
87 } else {
88 Unused
89 }
90 }
91
92 fn focus_gained(edit: &mut EditField<Self>, cx: &mut EventCx, data: &Self::Data) {
96 let _ = (edit, cx, data);
97 }
98
99 fn focus_lost(edit: &mut EditField<Self>, cx: &mut EventCx, data: &Self::Data) {
103 let _ = (edit, cx, data);
104 }
105
106 fn edit(edit: &mut EditField<Self>, cx: &mut EventCx, data: &Self::Data) {
110 let _ = (edit, cx, data);
111 }
112}
113
114#[autoimpl(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
119pub struct DefaultGuard<A>(PhantomData<A>);
120impl<A: 'static> EditGuard for DefaultGuard<A> {
121 type Data = A;
122}
123
124#[impl_self]
125mod StringGuard {
126 #[autoimpl(Debug ignore self.value_fn, self.on_afl)]
132 pub struct StringGuard<A> {
133 value_fn: Box<dyn Fn(&A) -> String>,
134 on_afl: Option<Box<dyn Fn(&mut EventCx, &A, &str)>>,
135 edited: bool,
136 }
137
138 impl Self {
139 pub fn new(value_fn: impl Fn(&A) -> String + 'static) -> Self {
146 StringGuard {
147 value_fn: Box::new(value_fn),
148 on_afl: None,
149 edited: false,
150 }
151 }
152
153 pub fn with(mut self, f: impl Fn(&mut EventCx, &A, &str) + 'static) -> Self {
158 debug_assert!(self.on_afl.is_none());
159 self.on_afl = Some(Box::new(f));
160 self
161 }
162
163 pub fn with_msg<M: Debug + 'static>(self, f: impl Fn(&str) -> M + 'static) -> Self {
168 self.with(move |cx, _, value| cx.push(f(value)))
169 }
170 }
171
172 impl EditGuard for Self {
173 type Data = A;
174
175 fn focus_lost(edit: &mut EditField<Self>, cx: &mut EventCx, data: &A) {
176 if edit.guard.edited {
177 edit.guard.edited = false;
178 if let Some(ref on_afl) = edit.guard.on_afl {
179 return on_afl(cx, data, edit.as_str());
180 }
181 }
182
183 let string = (edit.guard.value_fn)(data);
186 edit.set_string(cx, string);
187 }
188
189 fn update(edit: &mut EditField<Self>, cx: &mut ConfigCx, data: &A) {
190 if !edit.has_edit_focus() {
191 let string = (edit.guard.value_fn)(data);
192 edit.set_string(cx, string);
193 }
194 }
195
196 fn edit(edit: &mut EditField<Self>, _: &mut EventCx, _: &Self::Data) {
197 edit.guard.edited = true;
198 }
199 }
200}
201
202#[impl_self]
203mod ParseGuard {
204 #[autoimpl(Debug ignore self.value_fn, self.on_afl)]
210 pub struct ParseGuard<A, T: Debug + Display + FromStr> {
211 parsed: Option<T>,
212 value_fn: Box<dyn Fn(&A) -> T>,
213 on_afl: Box<dyn Fn(&mut EventCx, T)>,
214 }
215
216 impl Self {
217 pub fn new<M: Debug + 'static>(
231 value_fn: impl Fn(&A) -> T + 'static,
232 on_afl: impl Fn(T) -> M + 'static,
233 ) -> Self {
234 ParseGuard {
235 parsed: None,
236 value_fn: Box::new(value_fn),
237 on_afl: Box::new(move |cx, value| cx.push(on_afl(value))),
238 }
239 }
240 }
241
242 impl EditGuard for Self {
243 type Data = A;
244
245 fn focus_lost(edit: &mut EditField<Self>, cx: &mut EventCx, data: &A) {
246 if let Some(value) = edit.guard.parsed.take() {
247 (edit.guard.on_afl)(cx, value);
248 } else {
249 let value = (edit.guard.value_fn)(data);
252 edit.set_string(cx, format!("{value}"));
253 }
254 }
255
256 fn edit(edit: &mut EditField<Self>, cx: &mut EventCx, _: &A) {
257 edit.guard.parsed = edit.as_str().parse().ok();
258 edit.set_error_state(cx, edit.guard.parsed.is_none());
259 }
260
261 fn update(edit: &mut EditField<Self>, cx: &mut ConfigCx, data: &A) {
262 if !edit.has_edit_focus() {
263 let value = (edit.guard.value_fn)(data);
264 edit.set_string(cx, format!("{value}"));
265 edit.guard.parsed = None;
266 }
267 }
268 }
269}
270
271#[impl_self]
272mod InstantParseGuard {
273 #[autoimpl(Debug ignore self.value_fn, self.on_afl)]
279 pub struct InstantParseGuard<A, T: Debug + Display + FromStr> {
280 value_fn: Box<dyn Fn(&A) -> T>,
281 on_afl: Box<dyn Fn(&mut EventCx, T)>,
282 }
283
284 impl Self {
285 pub fn new<M: Debug + 'static>(
295 value_fn: impl Fn(&A) -> T + 'static,
296 on_afl: impl Fn(T) -> M + 'static,
297 ) -> Self {
298 InstantParseGuard {
299 value_fn: Box::new(value_fn),
300 on_afl: Box::new(move |cx, value| cx.push(on_afl(value))),
301 }
302 }
303 }
304
305 impl EditGuard for Self {
306 type Data = A;
307
308 fn focus_lost(edit: &mut EditField<Self>, cx: &mut EventCx, data: &A) {
309 let value = (edit.guard.value_fn)(data);
311 edit.set_string(cx, format!("{value}"));
312 }
313
314 fn edit(edit: &mut EditField<Self>, cx: &mut EventCx, _: &A) {
315 let result = edit.as_str().parse();
316 edit.set_error_state(cx, result.is_err());
317 if let Ok(value) = result {
318 (edit.guard.on_afl)(cx, value);
319 }
320 }
321
322 fn update(edit: &mut EditField<Self>, cx: &mut ConfigCx, data: &A) {
323 if !edit.has_edit_focus() {
324 let value = (edit.guard.value_fn)(data);
325 edit.set_string(cx, format!("{value}"));
326 }
327 }
328 }
329}
330
331#[impl_self]
332mod EditBox {
333 #[autoimpl(Clone, Default, Debug where G: trait)]
350 #[widget]
351 pub struct EditBox<G: EditGuard = DefaultGuard<()>> {
352 core: widget_core!(),
353 scroll: ScrollComponent,
354 #[widget]
355 inner: EditField<G>,
356 #[widget(&())]
357 vert_bar: ScrollBar<kas::dir::Down>,
358 frame_offset: Offset,
359 frame_size: Size,
360 frame_offset_ex_margin: Offset,
361 inner_margin: i32,
362 clip_rect: Rect,
363 }
364
365 impl Layout for Self {
366 fn size_rules(&mut self, sizer: SizeCx, mut axis: AxisInfo) -> SizeRules {
367 axis.sub_other(self.frame_size.extract(axis.flipped()));
368
369 let mut rules = self.inner.size_rules(sizer.re(), axis);
370 let bar_rules = self.vert_bar.size_rules(sizer.re(), axis);
371 if axis.is_horizontal() && self.multi_line() {
372 self.inner_margin = rules.margins_i32().1.max(bar_rules.margins_i32().0);
373 rules.append(bar_rules);
374 }
375
376 let frame_rules = sizer.frame(FrameStyle::EditBox, axis);
377 self.frame_offset_ex_margin
378 .set_component(axis, frame_rules.size());
379 let (rules, offset, size) = frame_rules.surround(rules);
380 self.frame_offset.set_component(axis, offset);
381 self.frame_size.set_component(axis, size);
382 rules
383 }
384
385 fn set_rect(&mut self, cx: &mut ConfigCx, outer_rect: Rect, hints: AlignHints) {
386 widget_set_rect!(outer_rect);
387 let mut rect = outer_rect;
388
389 self.clip_rect = Rect {
390 pos: rect.pos + self.frame_offset_ex_margin,
391 size: rect.size - (self.frame_offset_ex_margin * 2).cast(),
392 };
393
394 rect.pos += self.frame_offset;
395 rect.size -= self.frame_size;
396
397 let mut bar_rect = Rect::ZERO;
398 if self.multi_line() {
399 let bar_width = cx.size_cx().scroll_bar_width();
400 let x1 = rect.pos.0 + rect.size.0;
401 let x0 = x1 - bar_width;
402 bar_rect = Rect::new(Coord(x0, rect.pos.1), Size(bar_width, rect.size.1));
403 rect.size.0 = (rect.size.0 - bar_width - self.inner_margin).max(0);
404 }
405 self.vert_bar.set_rect(cx, bar_rect, AlignHints::NONE);
406
407 self.inner.set_rect(cx, rect, hints);
408 let _ = self.scroll.set_sizes(rect.size, self.inner.typeset_size());
409 self.update_scroll_bar(cx);
410 }
411
412 fn draw(&self, mut draw: DrawCx) {
413 let mut draw_inner = draw.re();
414 draw_inner.set_id(self.inner.id());
415 let bg = if self.inner.has_error() {
416 Background::Error
417 } else {
418 Background::Default
419 };
420 draw_inner.frame(self.rect(), FrameStyle::EditBox, bg);
421
422 self.inner
423 .draw_with_offset(draw.re(), self.clip_rect, self.scroll.offset());
424
425 if self.scroll.max_offset().1 > 0 {
426 self.vert_bar.draw(draw.re());
427 }
428 }
429 }
430
431 impl Tile for Self {
432 fn role(&self, _: &mut dyn RoleCx) -> Role<'_> {
433 Role::ScrollRegion {
434 offset: self.scroll_offset(),
435 max_offset: self.max_scroll_offset(),
436 }
437 }
438
439 fn translation(&self, index: usize) -> Offset {
440 if index == widget_index!(self.inner) {
441 self.scroll.offset()
442 } else {
443 Offset::ZERO
444 }
445 }
446
447 fn probe(&self, coord: Coord) -> Id {
448 if self.scroll.max_offset().1 > 0 {
449 if let Some(id) = self.vert_bar.try_probe(coord) {
450 return id;
451 }
452 }
453
454 self.inner.id()
457 }
458 }
459
460 impl Events for Self {
461 type Data = G::Data;
462
463 fn handle_event(&mut self, cx: &mut EventCx, _: &Self::Data, event: Event) -> IsUsed {
464 let rect = Rect {
465 pos: self.rect().pos + self.frame_offset,
466 size: self.rect().size - self.frame_size,
467 };
468 let used = self.scroll.scroll_by_event(cx, event, self.id(), rect);
469 self.update_scroll_bar(cx);
470 used
471 }
472
473 fn handle_messages(&mut self, cx: &mut EventCx<'_>, data: &G::Data) {
474 if cx.last_child() == Some(widget_index![self.vert_bar])
475 && let Some(ScrollMsg(y)) = cx.try_pop()
476 {
477 let offset = Offset(self.scroll.offset().0, y);
478 let action = self.scroll.set_offset(offset);
479 cx.action(&self, action);
480 self.update_scroll_bar(cx);
481 } else if self.is_editable()
482 && let Some(SetValueText(string)) = cx.try_pop()
483 {
484 self.set_string(cx, string);
485 G::edit(&mut self.inner, cx, data);
486 G::activate(&mut self.inner, cx, data);
487 } else if let Some(kas::messages::SetScrollOffset(offset)) = cx.try_pop() {
488 self.set_scroll_offset(cx, offset);
489 }
490 }
492
493 fn handle_scroll(&mut self, cx: &mut EventCx<'_>, _: &G::Data, scroll: Scroll) {
494 let pos = self.rect().pos + self.frame_offset;
496 let size = self.update_content_size();
497 let rect = Rect { pos, size };
498 self.scroll.scroll(cx, self.id(), rect, scroll);
499 self.update_scroll_bar(cx);
500 }
501 }
502
503 impl Scrollable for Self {
504 fn content_size(&self) -> Size {
505 self.inner.rect().size
506 }
507
508 fn max_scroll_offset(&self) -> Offset {
509 self.scroll.max_offset()
510 }
511
512 fn scroll_offset(&self) -> Offset {
513 self.scroll.offset()
514 }
515
516 fn set_scroll_offset(&mut self, cx: &mut EventCx, offset: Offset) -> Offset {
517 let action = self.scroll.set_offset(offset);
518 let offset = self.scroll.offset();
519 if !action.is_empty() {
520 cx.action(&self, action);
521 self.vert_bar.set_value(cx, offset.1);
522 }
523 offset
524 }
525 }
526
527 impl Self {
528 #[inline]
530 pub fn new(guard: G) -> Self {
531 EditBox {
532 core: Default::default(),
533 scroll: Default::default(),
534 inner: EditField::new(guard),
535 vert_bar: Default::default(),
536 frame_offset: Default::default(),
537 frame_size: Default::default(),
538 frame_offset_ex_margin: Default::default(),
539 inner_margin: Default::default(),
540 clip_rect: Default::default(),
541 }
542 }
543
544 fn update_content_size(&mut self) -> Size {
545 let size = self.rect().size - self.frame_size;
546 let _ = self.scroll.set_sizes(size, self.inner.typeset_size());
547 size
548 }
549
550 fn update_scroll_bar(&mut self, cx: &mut EventState) {
551 let max_offset = self.scroll.max_offset().1;
552 self.vert_bar
553 .set_limits(cx, max_offset, self.inner.rect().size.1);
554 self.vert_bar.set_value(cx, self.scroll.offset().1);
555 }
556
557 #[inline]
559 pub fn as_str(&self) -> &str {
560 self.inner.as_str()
561 }
562
563 #[inline]
565 pub fn clone_string(&self) -> String {
566 self.inner.clone_string()
567 }
568
569 #[inline]
571 pub fn set_str(&mut self, cx: &mut EventState, text: &str) {
572 if self.inner.set_str(cx, text) {
573 self.update_content_size();
574 self.update_scroll_bar(cx);
575 }
576 }
577
578 #[inline]
582 pub fn set_string(&mut self, cx: &mut EventState, text: String) {
583 if self.inner.set_string(cx, text) {
584 self.update_content_size();
585 self.update_scroll_bar(cx);
586 }
587 }
588
589 #[inline]
591 pub fn guard(&self) -> &G {
592 &self.inner.guard
593 }
594
595 #[inline]
597 pub fn guard_mut(&mut self) -> &mut G {
598 &mut self.inner.guard
599 }
600 }
601}
602
603impl<A: 'static> EditBox<DefaultGuard<A>> {
604 #[inline]
606 pub fn text<S: ToString>(text: S) -> Self {
607 EditBox {
608 inner: EditField::text(text),
609 ..Default::default()
610 }
611 }
612
613 #[inline]
615 pub fn string(value_fn: impl Fn(&A) -> String + 'static) -> EditBox<StringGuard<A>> {
616 EditBox::new(StringGuard::new(value_fn)).with_editable(false)
617 }
618
619 #[inline]
633 pub fn parser<T: Debug + Display + FromStr, M: Debug + 'static>(
634 value_fn: impl Fn(&A) -> T + 'static,
635 msg_fn: impl Fn(T) -> M + 'static,
636 ) -> EditBox<ParseGuard<A, T>> {
637 EditBox::new(ParseGuard::new(value_fn, msg_fn))
638 }
639
640 pub fn instant_parser<T: Debug + Display + FromStr, M: Debug + 'static>(
650 value_fn: impl Fn(&A) -> T + 'static,
651 msg_fn: impl Fn(T) -> M + 'static,
652 ) -> EditBox<InstantParseGuard<A, T>> {
653 EditBox::new(InstantParseGuard::new(value_fn, msg_fn))
654 }
655}
656
657impl<A: 'static> EditBox<StringGuard<A>> {
658 #[must_use]
665 pub fn with_msg<M>(mut self, msg_fn: impl Fn(&str) -> M + 'static) -> Self
666 where
667 M: Debug + 'static,
668 {
669 self.inner.guard = self.inner.guard.with_msg(msg_fn);
670 self.inner.editable = true;
671 self
672 }
673}
674
675impl<G: EditGuard> EditBox<G> {
676 #[inline]
680 #[must_use]
681 pub fn with_text(mut self, text: impl ToString) -> Self {
682 self.inner = self.inner.with_text(text);
683 self
684 }
685
686 #[inline]
688 #[must_use]
689 pub fn with_editable(mut self, editable: bool) -> Self {
690 self.inner = self.inner.with_editable(editable);
691 self
692 }
693
694 #[inline]
696 pub fn is_editable(&self) -> bool {
697 self.inner.is_editable()
698 }
699
700 #[inline]
702 pub fn set_editable(&mut self, editable: bool) {
703 self.inner.set_editable(editable);
704 }
705
706 #[inline]
714 #[must_use]
715 pub fn with_multi_line(mut self, multi_line: bool) -> Self {
716 self.inner = self.inner.with_multi_line(multi_line);
717 self
718 }
719
720 #[inline]
724 pub fn multi_line(&self) -> bool {
725 self.inner.multi_line()
726 }
727
728 #[inline]
730 #[must_use]
731 pub fn with_class(mut self, class: TextClass) -> Self {
732 self.inner = self.inner.with_class(class);
733 self
734 }
735
736 #[inline]
738 pub fn class(&self) -> TextClass {
739 self.inner.class()
740 }
741
742 #[inline]
744 pub fn set_lines(&mut self, min_lines: f32, ideal_lines: f32) {
745 self.inner.set_lines(min_lines, ideal_lines);
746 }
747
748 #[inline]
750 #[must_use]
751 pub fn with_lines(mut self, min_lines: f32, ideal_lines: f32) -> Self {
752 self.set_lines(min_lines, ideal_lines);
753 self
754 }
755
756 #[inline]
758 pub fn set_width_em(&mut self, min_em: f32, ideal_em: f32) {
759 self.inner.set_width_em(min_em, ideal_em);
760 }
761
762 #[inline]
764 #[must_use]
765 pub fn with_width_em(mut self, min_em: f32, ideal_em: f32) -> Self {
766 self.set_width_em(min_em, ideal_em);
767 self
768 }
769
770 #[inline]
774 pub fn has_edit_focus(&self) -> bool {
775 self.inner.has_edit_focus()
776 }
777
778 #[inline]
780 pub fn has_error(&self) -> bool {
781 self.inner.has_error()
782 }
783
784 pub fn set_error_state(&mut self, cx: &mut EventState, error_state: bool) {
789 self.inner.set_error_state(cx, error_state);
790 }
791}
792
793#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
795enum CurrentAction {
796 #[default]
797 None,
798 DragSelect,
799 ImeStart,
800 ImeEdit,
801}
802
803impl CurrentAction {
804 fn is_select(self) -> bool {
805 matches!(self, CurrentAction::DragSelect)
806 }
807
808 fn is_ime(self) -> bool {
809 matches!(self, CurrentAction::ImeStart | CurrentAction::ImeEdit)
810 }
811
812 fn is_active_ime(self) -> bool {
813 false
814 }
815
816 fn clear_active(&mut self) {
817 if matches!(self, CurrentAction::DragSelect | CurrentAction::ImeEdit) {
818 *self = CurrentAction::None;
819 }
820 }
821
822 fn clear_selection(&mut self) {
823 if matches!(self, CurrentAction::DragSelect) {
824 *self = CurrentAction::None;
825 }
826 }
827}
828
829#[impl_self]
830mod EditField {
831 #[autoimpl(Clone, Debug where G: trait)]
872 #[widget]
873 pub struct EditField<G: EditGuard = DefaultGuard<()>> {
874 core: widget_core!(),
875 editable: bool,
876 width: (f32, f32),
877 lines: (f32, f32),
878 text: Text<String>,
879 selection: SelectionHelper,
880 edit_x_coord: Option<f32>,
881 old_state: Option<(String, usize, usize)>,
882 last_edit: LastEdit,
883 has_key_focus: bool,
884 current: CurrentAction,
885 error_state: bool,
886 input_handler: TextInput,
887 pub guard: G,
889 }
890
891 impl Layout for Self {
892 #[inline]
893 fn rect(&self) -> Rect {
894 self.text.rect()
895 }
896
897 fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
898 let (min, mut ideal): (i32, i32);
899 if axis.is_horizontal() {
900 let dpem = sizer.dpem();
901 min = (self.width.0 * dpem).cast_ceil();
902 ideal = (self.width.1 * dpem).cast_ceil();
903 } else {
904 let dpem = sizer.dpem();
907 min = (self.lines.0 * dpem).cast_ceil();
908 ideal = (self.lines.1 * dpem).cast_ceil();
909 };
910
911 let rules = self.text.size_rules(sizer.re(), axis);
912 ideal = ideal.max(rules.ideal_size());
913
914 let margins = sizer.text_margins().extract(axis);
915 let stretch = if axis.is_horizontal() || self.multi_line() {
916 Stretch::High
917 } else {
918 Stretch::None
919 };
920 SizeRules::new(min, ideal, margins, stretch)
921 }
922
923 fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, mut hints: AlignHints) {
924 hints.vert = Some(if self.multi_line() {
925 Align::Default
926 } else {
927 Align::Center
928 });
929 self.text.set_rect(cx, rect, hints);
930 self.text.ensure_no_left_overhang();
931 if self.current.is_ime() {
932 self.set_ime_cursor_area(cx);
933 }
934 }
935
936 fn draw(&self, draw: DrawCx) {
937 self.draw_with_offset(draw, self.rect(), Offset::ZERO);
938 }
939 }
940
941 impl Tile for Self {
942 fn navigable(&self) -> bool {
943 true
944 }
945
946 fn role(&self, _: &mut dyn RoleCx) -> Role<'_> {
947 Role::TextInput {
948 text: self.text.as_str(),
949 multi_line: self.multi_line(),
950 cursor: self.selection.edit_index(),
951 sel_index: self.selection.sel_index(),
952 }
953 }
954
955 fn probe(&self, _: Coord) -> Id {
956 self.id()
957 }
958 }
959
960 impl Events for Self {
961 const REDRAW_ON_MOUSE_OVER: bool = true;
962
963 type Data = G::Data;
964
965 #[inline]
966 fn mouse_over_icon(&self) -> Option<CursorIcon> {
967 Some(CursorIcon::Text)
968 }
969
970 fn configure(&mut self, cx: &mut ConfigCx) {
971 cx.text_configure(&mut self.text);
972 G::configure(self, cx);
973 }
974
975 fn update(&mut self, cx: &mut ConfigCx, data: &G::Data) {
976 G::update(self, cx, data);
977 }
978
979 fn handle_event(&mut self, cx: &mut EventCx, data: &G::Data, event: Event) -> IsUsed {
980 match event {
981 Event::NavFocus(source) if source == FocusSource::Key => {
982 if !self.has_key_focus && !self.current.is_select() {
983 let ime = Some(ImePurpose::Normal);
984 cx.request_key_focus(self.id(), ime, source);
985 }
986 Used
987 }
988 Event::NavFocus(_) => Used,
989 Event::LostNavFocus => Used,
990 Event::SelFocus(source) => {
991 self.has_key_focus = true;
994 if source == FocusSource::Pointer {
995 self.set_primary(cx);
996 }
997 Used
998 }
999 Event::KeyFocus => {
1000 self.has_key_focus = true;
1001 self.set_view_offset_from_cursor(cx);
1002 G::focus_gained(self, cx, data);
1003 Used
1004 }
1005 Event::ImeFocus => {
1006 self.current = CurrentAction::ImeStart;
1007 self.set_ime_cursor_area(cx);
1008 Used
1009 }
1010 Event::LostImeFocus => {
1011 if self.current.is_ime() {
1012 self.current = CurrentAction::None;
1013 }
1014 Used
1015 }
1016 Event::LostKeyFocus => {
1017 self.has_key_focus = false;
1018 cx.redraw(&self);
1019 G::focus_lost(self, cx, data);
1020 Used
1021 }
1022 Event::LostSelFocus => {
1023 self.current = CurrentAction::None;
1025 self.selection.set_empty();
1026 cx.redraw(self);
1027 Used
1028 }
1029 Event::Command(cmd, code) => match self.control_key(cx, data, cmd, code) {
1030 Ok(r) => r,
1031 Err(NotReady) => Used,
1032 },
1033 Event::Key(event, false) if event.state == ElementState::Pressed => {
1034 if let Some(text) = &event.text {
1035 let used = self.received_text(cx, text);
1036 G::edit(self, cx, data);
1037 used
1038 } else {
1039 let opt_cmd = cx
1040 .config()
1041 .shortcuts()
1042 .try_match(cx.modifiers(), &event.logical_key);
1043 if let Some(cmd) = opt_cmd {
1044 match self.control_key(cx, data, cmd, Some(event.physical_key)) {
1045 Ok(r) => r,
1046 Err(NotReady) => Used,
1047 }
1048 } else {
1049 Unused
1050 }
1051 }
1052 }
1053 Event::ImePreedit(text, cursor) => {
1054 if self.current != CurrentAction::ImeEdit {
1055 if cursor.is_some() {
1056 self.selection.set_anchor_to_range_start();
1057 self.current = CurrentAction::ImeEdit;
1058 } else {
1059 return Used;
1060 }
1061 }
1062
1063 let range = self.selection.anchor_to_edit_range();
1064 self.text.replace_range(range.clone(), text);
1065
1066 if let Some((start, end)) = cursor {
1067 self.selection.set_sel_index_only(range.start + start);
1068 self.selection.set_edit_index(range.start + end);
1069 } else {
1070 self.selection.set_all(range.start + text.len());
1071 }
1072 self.edit_x_coord = None;
1073 self.prepare_text(cx);
1074 Used
1075 }
1076 Event::ImeCommit(text) => {
1077 if self.current != CurrentAction::ImeEdit {
1078 self.selection.set_anchor_to_range_start();
1079 }
1080 self.current = CurrentAction::None;
1081
1082 let range = self.selection.anchor_to_edit_range();
1083 self.text.replace_range(range.clone(), text);
1084
1085 self.selection.set_all(range.start + text.len());
1086 self.edit_x_coord = None;
1087 self.prepare_text(cx);
1088 Used
1089 }
1090 Event::PressStart(press) if press.is_tertiary() => {
1091 press.grab_click(self.id()).complete(cx)
1092 }
1093 Event::PressEnd { press, .. } if press.is_tertiary() => {
1094 if let Some(content) = cx.get_primary() {
1095 self.set_cursor_from_coord(cx, press.coord);
1096 self.current.clear_selection();
1097 self.selection.set_empty();
1098 let index = self.selection.edit_index();
1099 let range = self.trim_paste(&content);
1100 let len = range.len();
1101
1102 self.old_state =
1103 Some((self.text.clone_string(), index, self.selection.sel_index()));
1104 self.last_edit = LastEdit::Paste;
1105
1106 self.text.replace_range(index..index, &content[range]);
1107 self.selection.set_all(index + len);
1108 self.edit_x_coord = None;
1109 self.prepare_text(cx);
1110
1111 G::edit(self, cx, data);
1112 }
1113 Used
1114 }
1115 event => match self.input_handler.handle(cx, self.id(), event) {
1116 TextInputAction::Used => Used,
1117 TextInputAction::Unused => Unused,
1118 TextInputAction::Focus { coord, action }
1119 if self.current.is_select() || action.anchor =>
1120 {
1121 if self.current.is_ime() {
1122 cx.cancel_ime_focus(self.id());
1123 }
1124 self.current = CurrentAction::DragSelect;
1125 self.set_cursor_from_coord(cx, coord);
1126 self.selection.action(&self.text, action);
1127
1128 if self.has_key_focus {
1129 self.set_primary(cx);
1130 }
1131 Used
1132 }
1133 TextInputAction::Finish if self.current.is_select() => {
1134 self.current = CurrentAction::None;
1135 let ime = Some(ImePurpose::Normal);
1136 cx.request_key_focus(self.id(), ime, FocusSource::Pointer);
1137 Used
1138 }
1139 _ => Used,
1140 },
1141 }
1142 }
1143
1144 fn handle_messages(&mut self, cx: &mut EventCx, data: &G::Data) {
1145 if !self.editable {
1146 return;
1147 }
1148
1149 if let Some(SetValueText(string)) = cx.try_pop() {
1150 self.set_string(cx, string);
1151 G::edit(self, cx, data);
1152 G::activate(self, cx, data);
1153 } else if let Some(ReplaceSelectedText(text)) = cx.try_pop() {
1154 self.received_text(cx, &text);
1155 G::edit(self, cx, data);
1156 G::activate(self, cx, data);
1157 }
1158 }
1159 }
1160
1161 impl Default for Self
1162 where
1163 G: Default,
1164 {
1165 #[inline]
1166 fn default() -> Self {
1167 EditField::new(G::default())
1168 }
1169 }
1170
1171 impl Self {
1172 #[inline]
1174 pub fn new(guard: G) -> EditField<G> {
1175 EditField {
1176 core: Default::default(),
1177 editable: true,
1178 width: (8.0, 16.0),
1179 lines: (1.0, 1.0),
1180 text: Text::default().with_class(TextClass::Edit(false)),
1181 selection: Default::default(),
1182 edit_x_coord: None,
1183 old_state: None,
1184 last_edit: Default::default(),
1185 has_key_focus: false,
1186 current: CurrentAction::None,
1187 error_state: false,
1188 input_handler: Default::default(),
1189 guard,
1190 }
1191 }
1192
1193 #[inline]
1195 pub fn as_str(&self) -> &str {
1196 self.text.as_str()
1197 }
1198
1199 #[inline]
1201 pub fn clone_string(&self) -> String {
1202 self.text.clone_string()
1203 }
1204
1205 #[inline]
1209 pub fn set_str(&mut self, cx: &mut EventState, text: &str) -> bool {
1210 if self.text.as_str() != text {
1211 self.set_string(cx, text.to_string());
1212 true
1213 } else {
1214 false
1215 }
1216 }
1217
1218 pub fn set_string(&mut self, cx: &mut EventState, string: String) -> bool {
1224 if !self.text.set_string(string) || !self.text.prepare() {
1225 return false;
1226 }
1227
1228 self.current.clear_active();
1229 self.selection.set_max_len(self.text.str_len());
1230 cx.redraw(&self);
1231 if self.current.is_ime() {
1232 self.set_ime_cursor_area(cx);
1233 }
1234 self.set_error_state(cx, false);
1235 true
1236 }
1237
1238 pub fn replace_selection(&mut self, cx: &mut EventCx, text: &str) {
1242 self.received_text(cx, text);
1243 }
1244
1245 fn set_ime_cursor_area(&self, cx: &mut EventState) {
1247 if let Ok(display) = self.text.display() {
1248 if let Some(mut rect) = self.selection.cursor_rect(display) {
1249 rect.pos += Offset::conv(self.rect().pos);
1250 cx.set_ime_cursor_area(self.id_ref(), rect);
1251 }
1252 }
1253 }
1254
1255 #[inline]
1259 pub fn typeset_size(&self) -> Size {
1260 let mut size = self.rect().size;
1261 if let Ok((tl, br)) = self.text.bounding_box() {
1262 size.1 = size.1.max((br.1 - tl.1).cast_ceil());
1263 size.0 = size.0.max((br.0 - tl.0).cast_ceil());
1264 }
1265 size
1266 }
1267
1268 pub fn draw_with_offset(&self, mut draw: DrawCx, rect: Rect, offset: Offset) {
1274 let pos = self.rect().pos - offset;
1275
1276 draw.text_selected(pos, rect, &self.text, self.selection.range());
1277
1278 if self.editable && draw.ev_state().has_key_focus(self.id_ref()).0 {
1279 draw.text_cursor(pos, rect, &self.text, self.selection.edit_index());
1280 }
1281 }
1282 }
1283}
1284
1285impl<A: 'static> EditField<DefaultGuard<A>> {
1286 #[inline]
1288 pub fn text<S: ToString>(text: S) -> Self {
1289 let text = text.to_string();
1290 let len = text.len();
1291 EditField {
1292 editable: true,
1293 text: Text::new(text, TextClass::Edit(false)),
1294 selection: SelectionHelper::new(len, len),
1295 ..Default::default()
1296 }
1297 }
1298
1299 #[inline]
1301 pub fn string(value_fn: impl Fn(&A) -> String + 'static) -> EditField<StringGuard<A>> {
1302 EditField::new(StringGuard::new(value_fn)).with_editable(false)
1303 }
1304
1305 #[inline]
1319 pub fn parser<T: Debug + Display + FromStr, M: Debug + 'static>(
1320 value_fn: impl Fn(&A) -> T + 'static,
1321 msg_fn: impl Fn(T) -> M + 'static,
1322 ) -> EditField<ParseGuard<A, T>> {
1323 EditField::new(ParseGuard::new(value_fn, msg_fn))
1324 }
1325
1326 pub fn instant_parser<T: Debug + Display + FromStr, M: Debug + 'static>(
1336 value_fn: impl Fn(&A) -> T + 'static,
1337 msg_fn: impl Fn(T) -> M + 'static,
1338 ) -> EditField<InstantParseGuard<A, T>> {
1339 EditField::new(InstantParseGuard::new(value_fn, msg_fn))
1340 }
1341}
1342
1343impl<A: 'static> EditField<StringGuard<A>> {
1344 #[must_use]
1351 pub fn with_msg<M>(mut self, msg_fn: impl Fn(&str) -> M + 'static) -> Self
1352 where
1353 M: Debug + 'static,
1354 {
1355 self.guard = self.guard.with_msg(msg_fn);
1356 self.editable = true;
1357 self
1358 }
1359}
1360
1361impl<G: EditGuard> EditField<G> {
1362 #[inline]
1366 #[must_use]
1367 pub fn with_text(mut self, text: impl ToString) -> Self {
1368 debug_assert!(self.current == CurrentAction::None);
1369 let text = text.to_string();
1370 let len = text.len();
1371 self.text.set_string(text);
1372 self.selection.set_all(len);
1373 self
1374 }
1375
1376 #[inline]
1378 #[must_use]
1379 pub fn with_editable(mut self, editable: bool) -> Self {
1380 self.editable = editable;
1381 self
1382 }
1383
1384 #[inline]
1386 pub fn is_editable(&self) -> bool {
1387 self.editable
1388 }
1389
1390 #[inline]
1392 pub fn set_editable(&mut self, editable: bool) {
1393 self.editable = editable;
1394 }
1395
1396 #[inline]
1403 #[must_use]
1404 pub fn with_multi_line(mut self, multi_line: bool) -> Self {
1405 self.text.set_class(TextClass::Edit(multi_line));
1406 self.lines = match multi_line {
1407 false => (1.0, 1.0),
1408 true => (4.0, 7.0),
1409 };
1410 self
1411 }
1412
1413 #[inline]
1417 pub fn multi_line(&self) -> bool {
1418 self.class().multi_line()
1419 }
1420
1421 #[inline]
1423 #[must_use]
1424 pub fn with_class(mut self, class: TextClass) -> Self {
1425 self.text.set_class(class);
1426 self
1427 }
1428
1429 #[inline]
1431 pub fn class(&self) -> TextClass {
1432 self.text.class()
1433 }
1434
1435 #[inline]
1437 pub fn set_lines(&mut self, min_lines: f32, ideal_lines: f32) {
1438 self.lines = (min_lines, ideal_lines);
1439 }
1440
1441 #[inline]
1443 #[must_use]
1444 pub fn with_lines(mut self, min_lines: f32, ideal_lines: f32) -> Self {
1445 self.set_lines(min_lines, ideal_lines);
1446 self
1447 }
1448
1449 #[inline]
1451 pub fn set_width_em(&mut self, min_em: f32, ideal_em: f32) {
1452 self.width = (min_em, ideal_em);
1453 }
1454
1455 #[inline]
1457 #[must_use]
1458 pub fn with_width_em(mut self, min_em: f32, ideal_em: f32) -> Self {
1459 self.set_width_em(min_em, ideal_em);
1460 self
1461 }
1462
1463 #[inline]
1467 pub fn has_edit_focus(&self) -> bool {
1468 self.editable && self.has_key_focus
1469 }
1470
1471 #[inline]
1473 pub fn has_error(&self) -> bool {
1474 self.error_state
1475 }
1476
1477 pub fn set_error_state(&mut self, cx: &mut EventState, error_state: bool) {
1483 self.error_state = error_state;
1484 cx.redraw(self);
1485 }
1486
1487 fn prepare_text(&mut self, cx: &mut EventCx) {
1488 if self.text.prepare() {
1489 self.text.ensure_no_left_overhang();
1490 cx.redraw(&self);
1491 }
1492
1493 self.set_view_offset_from_cursor(cx);
1494 }
1495
1496 fn trim_paste(&self, text: &str) -> Range<usize> {
1497 let mut end = text.len();
1498 if !self.multi_line() {
1499 for (i, c) in text.char_indices() {
1503 if c < '\u{20}' || ('\u{7f}'..='\u{9f}').contains(&c) {
1504 end = i;
1505 break;
1506 }
1507 }
1508 }
1509 0..end
1510 }
1511
1512 fn received_text(&mut self, cx: &mut EventCx, text: &str) -> IsUsed {
1513 if !self.editable || self.current.is_active_ime() {
1514 return Unused;
1515 }
1516
1517 self.current.clear_selection();
1518 let index = self.selection.edit_index();
1519 let selection = self.selection.range();
1520 let have_sel = selection.start < selection.end;
1521 if self.last_edit != LastEdit::Insert || have_sel {
1522 self.old_state = Some((self.text.clone_string(), index, self.selection.sel_index()));
1523 self.last_edit = LastEdit::Insert;
1524 }
1525 if have_sel {
1526 self.text.replace_range(selection.clone(), text);
1527 self.selection.set_all(selection.start + text.len());
1528 } else {
1529 let mut s = self.text.clone_string();
1532 s.insert_str(index, text);
1533 self.text.set_text(s);
1534 self.selection.set_all(index + text.len());
1536 }
1537 self.edit_x_coord = None;
1538
1539 self.prepare_text(cx);
1540 Used
1541 }
1542
1543 fn control_key(
1544 &mut self,
1545 cx: &mut EventCx,
1546 data: &G::Data,
1547 cmd: Command,
1548 code: Option<PhysicalKey>,
1549 ) -> Result<IsUsed, NotReady> {
1550 let editable = self.editable;
1551 let mut shift = cx.modifiers().shift_key();
1552 let mut buf = [0u8; 4];
1553 let cursor = self.selection.edit_index();
1554 let len = self.text.str_len();
1555 let multi_line = self.multi_line();
1556 let selection = self.selection.range();
1557 let have_sel = selection.end > selection.start;
1558 let string;
1559
1560 enum Action<'a> {
1561 None,
1562 Activate,
1563 Edit,
1564 Insert(&'a str, LastEdit),
1565 Delete(Range<usize>),
1566 Move(usize, Option<f32>),
1567 }
1568
1569 let action = match cmd {
1570 Command::Escape | Command::Deselect
1571 if !self.current.is_active_ime() && !selection.is_empty() =>
1572 {
1573 self.current.clear_selection();
1574 self.selection.set_empty();
1575 cx.redraw(&self);
1576 Action::None
1577 }
1578 Command::Activate => Action::Activate,
1579 Command::Enter if shift || !multi_line => Action::Activate,
1580 Command::Enter if editable && multi_line => {
1581 Action::Insert('\n'.encode_utf8(&mut buf), LastEdit::Insert)
1582 }
1583 Command::Left | Command::Home if !shift && have_sel => {
1587 Action::Move(selection.start, None)
1588 }
1589 Command::Left if cursor > 0 => {
1590 let mut cursor = GraphemeCursor::new(cursor, len, true);
1591 cursor
1592 .prev_boundary(self.text.text(), 0)
1593 .unwrap()
1594 .map(|index| Action::Move(index, None))
1595 .unwrap_or(Action::None)
1596 }
1597 Command::Right | Command::End if !shift && have_sel => {
1598 Action::Move(selection.end, None)
1599 }
1600 Command::Right if cursor < len => {
1601 let mut cursor = GraphemeCursor::new(cursor, len, true);
1602 cursor
1603 .next_boundary(self.text.text(), 0)
1604 .unwrap()
1605 .map(|index| Action::Move(index, None))
1606 .unwrap_or(Action::None)
1607 }
1608 Command::WordLeft if cursor > 0 => {
1609 let mut iter = self.text.text()[0..cursor].split_word_bound_indices();
1610 let mut p = iter.next_back().map(|(index, _)| index).unwrap_or(0);
1611 while self.text.text()[p..]
1612 .chars()
1613 .next()
1614 .map(|c| c.is_whitespace())
1615 .unwrap_or(false)
1616 {
1617 if let Some((index, _)) = iter.next_back() {
1618 p = index;
1619 } else {
1620 break;
1621 }
1622 }
1623 Action::Move(p, None)
1624 }
1625 Command::WordRight if cursor < len => {
1626 let mut iter = self.text.text()[cursor..]
1627 .split_word_bound_indices()
1628 .skip(1);
1629 let mut p = iter.next().map(|(index, _)| cursor + index).unwrap_or(len);
1630 while self.text.text()[p..]
1631 .chars()
1632 .next()
1633 .map(|c| c.is_whitespace())
1634 .unwrap_or(false)
1635 {
1636 if let Some((index, _)) = iter.next() {
1637 p = cursor + index;
1638 } else {
1639 break;
1640 }
1641 }
1642 Action::Move(p, None)
1643 }
1644 Command::Left | Command::Right | Command::WordLeft | Command::WordRight => Action::None,
1646 Command::Up | Command::Down if multi_line => {
1647 let x = match self.edit_x_coord {
1648 Some(x) => x,
1649 None => self
1650 .text
1651 .text_glyph_pos(cursor)?
1652 .next_back()
1653 .map(|r| r.pos.0)
1654 .unwrap_or(0.0),
1655 };
1656 let mut line = self.text.find_line(cursor)?.map(|r| r.0).unwrap_or(0);
1657 line = match cmd {
1659 Command::Up => line.wrapping_sub(1),
1660 Command::Down => line.wrapping_add(1),
1661 _ => unreachable!(),
1662 };
1663 const HALF: usize = usize::MAX / 2;
1664 let nearest_end = match line {
1665 0..=HALF => len,
1666 _ => 0,
1667 };
1668 self.text
1669 .line_index_nearest(line, x)?
1670 .map(|index| Action::Move(index, Some(x)))
1671 .unwrap_or(Action::Move(nearest_end, None))
1672 }
1673 Command::Home if cursor > 0 => {
1674 let index = self.text.find_line(cursor)?.map(|r| r.1.start).unwrap_or(0);
1675 Action::Move(index, None)
1676 }
1677 Command::End if cursor < len => {
1678 let index = self.text.find_line(cursor)?.map(|r| r.1.end).unwrap_or(len);
1679 Action::Move(index, None)
1680 }
1681 Command::DocHome if cursor > 0 => Action::Move(0, None),
1682 Command::DocEnd if cursor < len => Action::Move(len, None),
1683 Command::Home | Command::End | Command::DocHome | Command::DocEnd => Action::None,
1685 Command::PageUp | Command::PageDown if multi_line => {
1686 let mut v = self
1687 .text
1688 .text_glyph_pos(cursor)?
1689 .next_back()
1690 .map(|r| r.pos.into())
1691 .unwrap_or(Vec2::ZERO);
1692 if let Some(x) = self.edit_x_coord {
1693 v.0 = x;
1694 }
1695 const FACTOR: f32 = 2.0 / 3.0;
1696 let mut h_dist = f32::conv(self.text.rect().size.1) * FACTOR;
1697 if cmd == Command::PageUp {
1698 h_dist *= -1.0;
1699 }
1700 v.1 += h_dist;
1701 Action::Move(self.text.text_index_nearest(v)?, Some(v.0))
1702 }
1703 Command::Delete | Command::DelBack if editable && have_sel => {
1704 Action::Delete(selection.clone())
1705 }
1706 Command::Delete if editable => GraphemeCursor::new(cursor, len, true)
1707 .next_boundary(self.text.text(), 0)
1708 .unwrap()
1709 .map(|next| Action::Delete(cursor..next))
1710 .unwrap_or(Action::None),
1711 Command::DelBack if editable => {
1712 let prev = self.text.text()[0..cursor]
1714 .char_indices()
1715 .next_back()
1716 .map(|(i, _)| i)
1717 .unwrap_or(0);
1718 Action::Delete(prev..cursor)
1719 }
1720 Command::DelWord if editable => {
1721 let next = self.text.text()[cursor..]
1722 .split_word_bound_indices()
1723 .nth(1)
1724 .map(|(index, _)| cursor + index)
1725 .unwrap_or(len);
1726 Action::Delete(cursor..next)
1727 }
1728 Command::DelWordBack if editable => {
1729 let prev = self.text.text()[0..cursor]
1730 .split_word_bound_indices()
1731 .next_back()
1732 .map(|(index, _)| index)
1733 .unwrap_or(0);
1734 Action::Delete(prev..cursor)
1735 }
1736 Command::SelectAll => {
1737 self.selection.set_sel_index(0);
1738 shift = true; Action::Move(len, None)
1740 }
1741 Command::Cut if editable && have_sel => {
1742 cx.set_clipboard((self.text.text()[selection.clone()]).into());
1743 Action::Delete(selection.clone())
1744 }
1745 Command::Copy if have_sel => {
1746 cx.set_clipboard((self.text.text()[selection.clone()]).into());
1747 Action::None
1748 }
1749 Command::Paste if editable => {
1750 if let Some(content) = cx.get_clipboard() {
1751 let range = self.trim_paste(&content);
1752 string = content;
1753 Action::Insert(&string[range], LastEdit::Paste)
1754 } else {
1755 Action::None
1756 }
1757 }
1758 Command::Undo | Command::Redo if editable => {
1759 if let Some((state, c2, sel)) = self.old_state.as_mut() {
1761 self.text.swap_string(state);
1762 self.selection.set_edit_index(*c2);
1763 *c2 = cursor;
1764 let index = *sel;
1765 *sel = self.selection.sel_index();
1766 self.selection.set_sel_index(index);
1767 self.edit_x_coord = None;
1768 self.last_edit = LastEdit::None;
1769 }
1770 Action::Edit
1771 }
1772 _ => return Ok(Unused),
1773 };
1774
1775 if !self.has_key_focus {
1776 let ime = Some(ImePurpose::Normal);
1779 cx.request_key_focus(self.id(), ime, FocusSource::Synthetic);
1780 }
1781
1782 if !matches!(action, Action::None) {
1783 self.current = CurrentAction::None;
1784 }
1785
1786 let result = match action {
1787 Action::None => EditAction::None,
1788 Action::Activate => EditAction::Activate,
1789 Action::Edit => EditAction::Edit,
1790 Action::Insert(s, edit) => {
1791 let mut index = cursor;
1792 if have_sel {
1793 self.old_state =
1794 Some((self.text.clone_string(), index, self.selection.sel_index()));
1795 self.last_edit = edit;
1796
1797 self.text.replace_range(selection.clone(), s);
1798 index = selection.start;
1799 } else {
1800 if self.last_edit != edit {
1801 self.old_state =
1802 Some((self.text.clone_string(), index, self.selection.sel_index()));
1803 self.last_edit = edit;
1804 }
1805
1806 self.text.replace_range(index..index, s);
1807 }
1808 self.selection.set_all(index + s.len());
1809 self.edit_x_coord = None;
1810 EditAction::Edit
1811 }
1812 Action::Delete(sel) => {
1813 if self.last_edit != LastEdit::Delete {
1814 self.old_state =
1815 Some((self.text.clone_string(), cursor, self.selection.sel_index()));
1816 self.last_edit = LastEdit::Delete;
1817 }
1818
1819 self.text.replace_range(sel.clone(), "");
1820 self.selection.set_all(sel.start);
1821 self.edit_x_coord = None;
1822 EditAction::Edit
1823 }
1824 Action::Move(index, x_coord) => {
1825 self.selection.set_edit_index(index);
1826 if !shift {
1827 self.selection.set_empty();
1828 } else {
1829 self.set_primary(cx);
1830 }
1831 self.edit_x_coord = x_coord;
1832 cx.redraw(&self);
1833 EditAction::None
1834 }
1835 };
1836
1837 self.prepare_text(cx);
1838
1839 Ok(match result {
1840 EditAction::None => Used,
1841 EditAction::Activate => {
1842 cx.depress_with_key(&self, code);
1843 G::activate(self, cx, data)
1844 }
1845 EditAction::Edit => {
1846 G::edit(self, cx, data);
1847 Used
1848 }
1849 })
1850 }
1851
1852 fn set_cursor_from_coord(&mut self, cx: &mut EventCx, coord: Coord) {
1853 let rel_pos = (coord - self.rect().pos).cast();
1854 if let Ok(index) = self.text.text_index_nearest(rel_pos) {
1855 if index != self.selection.edit_index() {
1856 self.selection.set_edit_index(index);
1857 self.set_view_offset_from_cursor(cx);
1858 self.edit_x_coord = None;
1859 cx.redraw(self);
1860 }
1861 }
1862 }
1863
1864 fn set_primary(&self, cx: &mut EventCx) {
1865 if self.has_key_focus && !self.selection.is_empty() && cx.has_primary() {
1866 let range = self.selection.range();
1867 cx.set_primary(String::from(&self.text.as_str()[range]));
1868 }
1869 }
1870
1871 fn set_view_offset_from_cursor(&mut self, cx: &mut EventCx) {
1875 let cursor = self.selection.edit_index();
1876 if let Some(marker) = self
1877 .text
1878 .text_glyph_pos(cursor)
1879 .ok()
1880 .and_then(|mut m| m.next_back())
1881 {
1882 let y0 = (marker.pos.1 - marker.ascent).cast_floor();
1883 let pos = self.rect().pos + Offset(marker.pos.0.cast_nearest(), y0);
1884 let size = Size(0, i32::conv_ceil(marker.pos.1 - marker.descent) - y0);
1885 cx.set_scroll(Scroll::Rect(Rect { pos, size }));
1886 }
1887 }
1888}