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 rect = Rect {
496 pos: self.rect().pos + self.frame_offset,
497 size: self.rect().size - self.frame_size,
498 };
499 let _ = self.scroll.set_sizes(rect.size, self.inner.typeset_size());
500 self.scroll.scroll(cx, self.id(), rect, scroll);
501 self.update_scroll_bar(cx);
502 }
503 }
504
505 impl Scrollable for Self {
506 fn content_size(&self) -> Size {
507 self.inner.rect().size
508 }
509
510 fn max_scroll_offset(&self) -> Offset {
511 self.scroll.max_offset()
512 }
513
514 fn scroll_offset(&self) -> Offset {
515 self.scroll.offset()
516 }
517
518 fn set_scroll_offset(&mut self, cx: &mut EventCx, offset: Offset) -> Offset {
519 let action = self.scroll.set_offset(offset);
520 let offset = self.scroll.offset();
521 if !action.is_empty() {
522 cx.action(&self, action);
523 self.vert_bar.set_value(cx, offset.1);
524 }
525 offset
526 }
527 }
528
529 impl Self {
530 #[inline]
532 pub fn new(guard: G) -> Self {
533 EditBox {
534 core: Default::default(),
535 scroll: Default::default(),
536 inner: EditField::new(guard),
537 vert_bar: Default::default(),
538 frame_offset: Default::default(),
539 frame_size: Default::default(),
540 frame_offset_ex_margin: Default::default(),
541 inner_margin: Default::default(),
542 clip_rect: Default::default(),
543 }
544 }
545
546 fn update_scroll_bar(&mut self, cx: &mut EventState) {
547 let max_offset = self.scroll.max_offset().1;
548 self.vert_bar
549 .set_limits(cx, max_offset, self.inner.rect().size.1);
550 self.vert_bar.set_value(cx, self.scroll.offset().1);
551 }
552
553 #[inline]
555 pub fn as_str(&self) -> &str {
556 self.inner.as_str()
557 }
558
559 #[inline]
561 pub fn clone_string(&self) -> String {
562 self.inner.clone_string()
563 }
564
565 #[inline]
567 pub fn set_str(&mut self, cx: &mut EventState, text: &str) {
568 self.inner.set_str(cx, text);
569 }
570
571 #[inline]
575 pub fn set_string(&mut self, cx: &mut EventState, text: String) {
576 self.inner.set_string(cx, text);
577 }
578
579 #[inline]
581 pub fn guard(&self) -> &G {
582 &self.inner.guard
583 }
584 }
585}
586
587impl<A: 'static> EditBox<DefaultGuard<A>> {
588 #[inline]
590 pub fn text<S: ToString>(text: S) -> Self {
591 EditBox {
592 inner: EditField::text(text),
593 ..Default::default()
594 }
595 }
596
597 #[inline]
599 pub fn string(value_fn: impl Fn(&A) -> String + 'static) -> EditBox<StringGuard<A>> {
600 EditBox::new(StringGuard::new(value_fn)).with_editable(false)
601 }
602
603 #[inline]
617 pub fn parser<T: Debug + Display + FromStr, M: Debug + 'static>(
618 value_fn: impl Fn(&A) -> T + 'static,
619 msg_fn: impl Fn(T) -> M + 'static,
620 ) -> EditBox<ParseGuard<A, T>> {
621 EditBox::new(ParseGuard::new(value_fn, msg_fn))
622 }
623
624 pub fn instant_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<InstantParseGuard<A, T>> {
637 EditBox::new(InstantParseGuard::new(value_fn, msg_fn))
638 }
639}
640
641impl<A: 'static> EditBox<StringGuard<A>> {
642 #[must_use]
649 pub fn with_msg<M>(mut self, msg_fn: impl Fn(&str) -> M + 'static) -> Self
650 where
651 M: Debug + 'static,
652 {
653 self.inner.guard = self.inner.guard.with_msg(msg_fn);
654 self.inner.editable = true;
655 self
656 }
657}
658
659impl<G: EditGuard> EditBox<G> {
660 #[inline]
664 #[must_use]
665 pub fn with_text(mut self, text: impl ToString) -> Self {
666 self.inner = self.inner.with_text(text);
667 self
668 }
669
670 #[inline]
672 #[must_use]
673 pub fn with_editable(mut self, editable: bool) -> Self {
674 self.inner = self.inner.with_editable(editable);
675 self
676 }
677
678 #[inline]
680 pub fn is_editable(&self) -> bool {
681 self.inner.is_editable()
682 }
683
684 #[inline]
686 pub fn set_editable(&mut self, editable: bool) {
687 self.inner.set_editable(editable);
688 }
689
690 #[inline]
698 #[must_use]
699 pub fn with_multi_line(mut self, multi_line: bool) -> Self {
700 self.inner = self.inner.with_multi_line(multi_line);
701 self
702 }
703
704 #[inline]
708 pub fn multi_line(&self) -> bool {
709 self.inner.multi_line()
710 }
711
712 #[inline]
714 #[must_use]
715 pub fn with_class(mut self, class: TextClass) -> Self {
716 self.inner = self.inner.with_class(class);
717 self
718 }
719
720 #[inline]
722 pub fn class(&self) -> TextClass {
723 self.inner.class()
724 }
725
726 #[inline]
728 pub fn set_lines(&mut self, min_lines: f32, ideal_lines: f32) {
729 self.inner.set_lines(min_lines, ideal_lines);
730 }
731
732 #[inline]
734 #[must_use]
735 pub fn with_lines(mut self, min_lines: f32, ideal_lines: f32) -> Self {
736 self.set_lines(min_lines, ideal_lines);
737 self
738 }
739
740 #[inline]
742 pub fn set_width_em(&mut self, min_em: f32, ideal_em: f32) {
743 self.inner.set_width_em(min_em, ideal_em);
744 }
745
746 #[inline]
748 #[must_use]
749 pub fn with_width_em(mut self, min_em: f32, ideal_em: f32) -> Self {
750 self.set_width_em(min_em, ideal_em);
751 self
752 }
753
754 #[inline]
758 pub fn has_edit_focus(&self) -> bool {
759 self.inner.has_edit_focus()
760 }
761
762 #[inline]
764 pub fn has_error(&self) -> bool {
765 self.inner.has_error()
766 }
767
768 pub fn set_error_state(&mut self, cx: &mut EventState, error_state: bool) {
773 self.inner.set_error_state(cx, error_state);
774 }
775}
776
777#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
779enum CurrentAction {
780 #[default]
781 None,
782 DragSelect,
783 ImeStart,
784 ImeEdit,
785}
786
787impl CurrentAction {
788 fn is_select(self) -> bool {
789 matches!(self, CurrentAction::DragSelect)
790 }
791
792 fn is_ime(self) -> bool {
793 matches!(self, CurrentAction::ImeStart | CurrentAction::ImeEdit)
794 }
795
796 fn is_active_ime(self) -> bool {
797 false
798 }
799
800 fn clear_active(&mut self) {
801 if matches!(self, CurrentAction::DragSelect | CurrentAction::ImeEdit) {
802 *self = CurrentAction::None;
803 }
804 }
805
806 fn clear_selection(&mut self) {
807 if matches!(self, CurrentAction::DragSelect) {
808 *self = CurrentAction::None;
809 }
810 }
811}
812
813#[impl_self]
814mod EditField {
815 #[autoimpl(Clone, Debug where G: trait)]
856 #[widget]
857 pub struct EditField<G: EditGuard = DefaultGuard<()>> {
858 core: widget_core!(),
859 editable: bool,
860 width: (f32, f32),
861 lines: (f32, f32),
862 text: Text<String>,
863 selection: SelectionHelper,
864 edit_x_coord: Option<f32>,
865 old_state: Option<(String, usize, usize)>,
866 last_edit: LastEdit,
867 has_key_focus: bool,
868 current: CurrentAction,
869 error_state: bool,
870 input_handler: TextInput,
871 pub guard: G,
873 }
874
875 impl Layout for Self {
876 #[inline]
877 fn rect(&self) -> Rect {
878 self.text.rect()
879 }
880
881 fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
882 let (min, mut ideal): (i32, i32);
883 if axis.is_horizontal() {
884 let dpem = sizer.dpem();
885 min = (self.width.0 * dpem).cast_ceil();
886 ideal = (self.width.1 * dpem).cast_ceil();
887 } else {
888 let dpem = sizer.dpem();
891 min = (self.lines.0 * dpem).cast_ceil();
892 ideal = (self.lines.1 * dpem).cast_ceil();
893 };
894
895 let rules = self.text.size_rules(sizer.re(), axis);
896 ideal = ideal.max(rules.ideal_size());
897
898 let margins = sizer.text_margins().extract(axis);
899 let stretch = if axis.is_horizontal() || self.multi_line() {
900 Stretch::High
901 } else {
902 Stretch::None
903 };
904 SizeRules::new(min, ideal, margins, stretch)
905 }
906
907 fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, mut hints: AlignHints) {
908 hints.vert = Some(if self.multi_line() {
909 Align::Default
910 } else {
911 Align::Center
912 });
913 self.text.set_rect(cx, rect, hints);
914 self.text.ensure_no_left_overhang();
915 if self.current.is_ime() {
916 self.set_ime_cursor_area(cx);
917 }
918 }
919
920 fn draw(&self, draw: DrawCx) {
921 self.draw_with_offset(draw, self.rect(), Offset::ZERO);
922 }
923 }
924
925 impl Tile for Self {
926 fn navigable(&self) -> bool {
927 true
928 }
929
930 fn role(&self, _: &mut dyn RoleCx) -> Role<'_> {
931 Role::TextInput {
932 text: self.text.as_str(),
933 multi_line: self.multi_line(),
934 cursor: self.selection.edit_index(),
935 sel_index: self.selection.sel_index(),
936 }
937 }
938
939 fn probe(&self, _: Coord) -> Id {
940 self.id()
941 }
942 }
943
944 impl Events for Self {
945 const REDRAW_ON_MOUSE_OVER: bool = true;
946
947 type Data = G::Data;
948
949 #[inline]
950 fn mouse_over_icon(&self) -> Option<CursorIcon> {
951 Some(CursorIcon::Text)
952 }
953
954 fn configure(&mut self, cx: &mut ConfigCx) {
955 cx.text_configure(&mut self.text);
956 G::configure(self, cx);
957 }
958
959 fn update(&mut self, cx: &mut ConfigCx, data: &G::Data) {
960 G::update(self, cx, data);
961 }
962
963 fn handle_event(&mut self, cx: &mut EventCx, data: &G::Data, event: Event) -> IsUsed {
964 match event {
965 Event::NavFocus(source) if source == FocusSource::Key => {
966 if !self.has_key_focus && !self.current.is_select() {
967 let ime = Some(ImePurpose::Normal);
968 cx.request_key_focus(self.id(), ime, source);
969 }
970 Used
971 }
972 Event::NavFocus(_) => Used,
973 Event::LostNavFocus => Used,
974 Event::SelFocus(source) => {
975 self.has_key_focus = true;
978 if source == FocusSource::Pointer {
979 self.set_primary(cx);
980 }
981 Used
982 }
983 Event::KeyFocus => {
984 self.has_key_focus = true;
985 self.set_view_offset_from_cursor(cx);
986 G::focus_gained(self, cx, data);
987 Used
988 }
989 Event::ImeFocus => {
990 self.current = CurrentAction::ImeStart;
991 self.set_ime_cursor_area(cx);
992 Used
993 }
994 Event::LostImeFocus => {
995 if self.current.is_ime() {
996 self.current = CurrentAction::None;
997 }
998 Used
999 }
1000 Event::LostKeyFocus => {
1001 self.has_key_focus = false;
1002 cx.redraw(&self);
1003 G::focus_lost(self, cx, data);
1004 Used
1005 }
1006 Event::LostSelFocus => {
1007 self.current = CurrentAction::None;
1009 self.selection.set_empty();
1010 cx.redraw(self);
1011 Used
1012 }
1013 Event::Command(cmd, code) => match self.control_key(cx, data, cmd, code) {
1014 Ok(r) => r,
1015 Err(NotReady) => Used,
1016 },
1017 Event::Key(event, false) if event.state == ElementState::Pressed => {
1018 if let Some(text) = &event.text {
1019 let used = self.received_text(cx, text);
1020 G::edit(self, cx, data);
1021 used
1022 } else {
1023 let opt_cmd = cx
1024 .config()
1025 .shortcuts()
1026 .try_match(cx.modifiers(), &event.logical_key);
1027 if let Some(cmd) = opt_cmd {
1028 match self.control_key(cx, data, cmd, Some(event.physical_key)) {
1029 Ok(r) => r,
1030 Err(NotReady) => Used,
1031 }
1032 } else {
1033 Unused
1034 }
1035 }
1036 }
1037 Event::ImePreedit(text, cursor) => {
1038 if self.current != CurrentAction::ImeEdit {
1039 if cursor.is_some() {
1040 self.selection.set_anchor_to_range_start();
1041 self.current = CurrentAction::ImeEdit;
1042 } else {
1043 return Used;
1044 }
1045 }
1046
1047 let range = self.selection.anchor_to_edit_range();
1048 self.text.replace_range(range.clone(), text);
1049
1050 if let Some((start, end)) = cursor {
1051 self.selection.set_sel_index_only(range.start + start);
1052 self.selection.set_edit_index(range.start + end);
1053 } else {
1054 self.selection.set_all(range.start + text.len());
1055 }
1056 self.edit_x_coord = None;
1057 self.prepare_text(cx);
1058 Used
1059 }
1060 Event::ImeCommit(text) => {
1061 if self.current != CurrentAction::ImeEdit {
1062 self.selection.set_anchor_to_range_start();
1063 }
1064 self.current = CurrentAction::None;
1065
1066 let range = self.selection.anchor_to_edit_range();
1067 self.text.replace_range(range.clone(), text);
1068
1069 self.selection.set_all(range.start + text.len());
1070 self.edit_x_coord = None;
1071 self.prepare_text(cx);
1072 Used
1073 }
1074 Event::PressStart(press) if press.is_tertiary() => {
1075 press.grab_click(self.id()).complete(cx)
1076 }
1077 Event::PressEnd { press, .. } if press.is_tertiary() => {
1078 if let Some(content) = cx.get_primary() {
1079 self.set_cursor_from_coord(cx, press.coord);
1080 self.current.clear_selection();
1081 self.selection.set_empty();
1082 let index = self.selection.edit_index();
1083 let range = self.trim_paste(&content);
1084 let len = range.len();
1085
1086 self.old_state =
1087 Some((self.text.clone_string(), index, self.selection.sel_index()));
1088 self.last_edit = LastEdit::Paste;
1089
1090 self.text.replace_range(index..index, &content[range]);
1091 self.selection.set_all(index + len);
1092 self.edit_x_coord = None;
1093 self.prepare_text(cx);
1094
1095 G::edit(self, cx, data);
1096 }
1097 Used
1098 }
1099 event => match self.input_handler.handle(cx, self.id(), event) {
1100 TextInputAction::Used => Used,
1101 TextInputAction::Unused => Unused,
1102 TextInputAction::Focus { coord, action }
1103 if self.current.is_select() || action.anchor =>
1104 {
1105 if self.current.is_ime() {
1106 cx.cancel_ime_focus(self.id());
1107 }
1108 self.current = CurrentAction::DragSelect;
1109 self.set_cursor_from_coord(cx, coord);
1110 self.selection.action(&self.text, action);
1111
1112 if self.has_key_focus {
1113 self.set_primary(cx);
1114 }
1115 Used
1116 }
1117 TextInputAction::Finish if self.current.is_select() => {
1118 self.current = CurrentAction::None;
1119 let ime = Some(ImePurpose::Normal);
1120 cx.request_key_focus(self.id(), ime, FocusSource::Pointer);
1121 Used
1122 }
1123 _ => Used,
1124 },
1125 }
1126 }
1127
1128 fn handle_messages(&mut self, cx: &mut EventCx, data: &G::Data) {
1129 if !self.editable {
1130 return;
1131 }
1132
1133 if let Some(SetValueText(string)) = cx.try_pop() {
1134 self.set_string(cx, string);
1135 G::edit(self, cx, data);
1136 G::activate(self, cx, data);
1137 } else if let Some(ReplaceSelectedText(text)) = cx.try_pop() {
1138 self.received_text(cx, &text);
1139 G::edit(self, cx, data);
1140 G::activate(self, cx, data);
1141 }
1142 }
1143 }
1144
1145 impl Default for Self
1146 where
1147 G: Default,
1148 {
1149 #[inline]
1150 fn default() -> Self {
1151 EditField::new(G::default())
1152 }
1153 }
1154
1155 impl Self {
1156 #[inline]
1158 pub fn new(guard: G) -> EditField<G> {
1159 EditField {
1160 core: Default::default(),
1161 editable: true,
1162 width: (8.0, 16.0),
1163 lines: (1.0, 1.0),
1164 text: Text::default().with_class(TextClass::Edit(false)),
1165 selection: Default::default(),
1166 edit_x_coord: None,
1167 old_state: None,
1168 last_edit: Default::default(),
1169 has_key_focus: false,
1170 current: CurrentAction::None,
1171 error_state: false,
1172 input_handler: Default::default(),
1173 guard,
1174 }
1175 }
1176
1177 #[inline]
1179 pub fn as_str(&self) -> &str {
1180 self.text.as_str()
1181 }
1182
1183 #[inline]
1185 pub fn clone_string(&self) -> String {
1186 self.text.clone_string()
1187 }
1188
1189 #[inline]
1191 pub fn set_str(&mut self, cx: &mut EventState, text: &str) {
1192 if self.text.as_str() != text {
1193 self.set_string(cx, text.to_string());
1194 }
1195 }
1196
1197 pub fn set_string(&mut self, cx: &mut EventState, string: String) {
1201 if !self.text.set_string(string) || !self.text.prepare() {
1202 return;
1203 }
1204
1205 self.current.clear_active();
1206 self.selection.set_max_len(self.text.str_len());
1207 cx.redraw(&self);
1208 if self.current.is_ime() {
1209 self.set_ime_cursor_area(cx);
1210 }
1211 self.set_error_state(cx, false);
1212 }
1213
1214 pub fn replace_selection(&mut self, cx: &mut EventCx, text: &str) {
1218 self.received_text(cx, text);
1219 }
1220
1221 fn set_ime_cursor_area(&self, cx: &mut EventState) {
1223 if let Ok(display) = self.text.display() {
1224 if let Some(mut rect) = self.selection.cursor_rect(display) {
1225 rect.pos += Offset::conv(self.rect().pos);
1226 cx.set_ime_cursor_area(self.id_ref(), rect);
1227 }
1228 }
1229 }
1230
1231 #[inline]
1235 pub fn typeset_size(&self) -> Size {
1236 let mut size = self.rect().size;
1237 if let Ok((tl, br)) = self.text.bounding_box() {
1238 size.1 = size.1.max((br.1 - tl.1).cast_ceil());
1239 size.0 = size.0.max((br.0 - tl.0).cast_ceil());
1240 }
1241 size
1242 }
1243
1244 pub fn draw_with_offset(&self, mut draw: DrawCx, rect: Rect, offset: Offset) {
1250 let pos = self.rect().pos - offset;
1251
1252 draw.text_selected(pos, rect, &self.text, self.selection.range());
1253
1254 if self.editable && draw.ev_state().has_key_focus(self.id_ref()).0 {
1255 draw.text_cursor(pos, rect, &self.text, self.selection.edit_index());
1256 }
1257 }
1258 }
1259}
1260
1261impl<A: 'static> EditField<DefaultGuard<A>> {
1262 #[inline]
1264 pub fn text<S: ToString>(text: S) -> Self {
1265 let text = text.to_string();
1266 let len = text.len();
1267 EditField {
1268 editable: true,
1269 text: Text::new(text, TextClass::Edit(false)),
1270 selection: SelectionHelper::new(len, len),
1271 ..Default::default()
1272 }
1273 }
1274
1275 #[inline]
1277 pub fn string(value_fn: impl Fn(&A) -> String + 'static) -> EditField<StringGuard<A>> {
1278 EditField::new(StringGuard::new(value_fn)).with_editable(false)
1279 }
1280
1281 #[inline]
1295 pub fn parser<T: Debug + Display + FromStr, M: Debug + 'static>(
1296 value_fn: impl Fn(&A) -> T + 'static,
1297 msg_fn: impl Fn(T) -> M + 'static,
1298 ) -> EditField<ParseGuard<A, T>> {
1299 EditField::new(ParseGuard::new(value_fn, msg_fn))
1300 }
1301
1302 pub fn instant_parser<T: Debug + Display + FromStr, M: Debug + 'static>(
1312 value_fn: impl Fn(&A) -> T + 'static,
1313 msg_fn: impl Fn(T) -> M + 'static,
1314 ) -> EditField<InstantParseGuard<A, T>> {
1315 EditField::new(InstantParseGuard::new(value_fn, msg_fn))
1316 }
1317}
1318
1319impl<A: 'static> EditField<StringGuard<A>> {
1320 #[must_use]
1327 pub fn with_msg<M>(mut self, msg_fn: impl Fn(&str) -> M + 'static) -> Self
1328 where
1329 M: Debug + 'static,
1330 {
1331 self.guard = self.guard.with_msg(msg_fn);
1332 self.editable = true;
1333 self
1334 }
1335}
1336
1337impl<G: EditGuard> EditField<G> {
1338 #[inline]
1342 #[must_use]
1343 pub fn with_text(mut self, text: impl ToString) -> Self {
1344 debug_assert!(self.current == CurrentAction::None);
1345 let text = text.to_string();
1346 let len = text.len();
1347 self.text.set_string(text);
1348 self.selection.set_all(len);
1349 self
1350 }
1351
1352 #[inline]
1354 #[must_use]
1355 pub fn with_editable(mut self, editable: bool) -> Self {
1356 self.editable = editable;
1357 self
1358 }
1359
1360 #[inline]
1362 pub fn is_editable(&self) -> bool {
1363 self.editable
1364 }
1365
1366 #[inline]
1368 pub fn set_editable(&mut self, editable: bool) {
1369 self.editable = editable;
1370 }
1371
1372 #[inline]
1379 #[must_use]
1380 pub fn with_multi_line(mut self, multi_line: bool) -> Self {
1381 self.text.set_class(TextClass::Edit(multi_line));
1382 self.lines = match multi_line {
1383 false => (1.0, 1.0),
1384 true => (4.0, 7.0),
1385 };
1386 self
1387 }
1388
1389 #[inline]
1393 pub fn multi_line(&self) -> bool {
1394 self.class().multi_line()
1395 }
1396
1397 #[inline]
1399 #[must_use]
1400 pub fn with_class(mut self, class: TextClass) -> Self {
1401 self.text.set_class(class);
1402 self
1403 }
1404
1405 #[inline]
1407 pub fn class(&self) -> TextClass {
1408 self.text.class()
1409 }
1410
1411 #[inline]
1413 pub fn set_lines(&mut self, min_lines: f32, ideal_lines: f32) {
1414 self.lines = (min_lines, ideal_lines);
1415 }
1416
1417 #[inline]
1419 #[must_use]
1420 pub fn with_lines(mut self, min_lines: f32, ideal_lines: f32) -> Self {
1421 self.set_lines(min_lines, ideal_lines);
1422 self
1423 }
1424
1425 #[inline]
1427 pub fn set_width_em(&mut self, min_em: f32, ideal_em: f32) {
1428 self.width = (min_em, ideal_em);
1429 }
1430
1431 #[inline]
1433 #[must_use]
1434 pub fn with_width_em(mut self, min_em: f32, ideal_em: f32) -> Self {
1435 self.set_width_em(min_em, ideal_em);
1436 self
1437 }
1438
1439 #[inline]
1443 pub fn has_edit_focus(&self) -> bool {
1444 self.editable && self.has_key_focus
1445 }
1446
1447 #[inline]
1449 pub fn has_error(&self) -> bool {
1450 self.error_state
1451 }
1452
1453 pub fn set_error_state(&mut self, cx: &mut EventState, error_state: bool) {
1459 self.error_state = error_state;
1460 cx.redraw(self);
1461 }
1462
1463 fn prepare_text(&mut self, cx: &mut EventCx) {
1464 if self.text.prepare() {
1465 self.text.ensure_no_left_overhang();
1466 cx.redraw(&self);
1467 }
1468
1469 self.set_view_offset_from_cursor(cx);
1470 }
1471
1472 fn trim_paste(&self, text: &str) -> Range<usize> {
1473 let mut end = text.len();
1474 if !self.multi_line() {
1475 for (i, c) in text.char_indices() {
1479 if c < '\u{20}' || ('\u{7f}'..='\u{9f}').contains(&c) {
1480 end = i;
1481 break;
1482 }
1483 }
1484 }
1485 0..end
1486 }
1487
1488 fn received_text(&mut self, cx: &mut EventCx, text: &str) -> IsUsed {
1489 if !self.editable || self.current.is_active_ime() {
1490 return Unused;
1491 }
1492
1493 self.current.clear_selection();
1494 let index = self.selection.edit_index();
1495 let selection = self.selection.range();
1496 let have_sel = selection.start < selection.end;
1497 if self.last_edit != LastEdit::Insert || have_sel {
1498 self.old_state = Some((self.text.clone_string(), index, self.selection.sel_index()));
1499 self.last_edit = LastEdit::Insert;
1500 }
1501 if have_sel {
1502 self.text.replace_range(selection.clone(), text);
1503 self.selection.set_all(selection.start + text.len());
1504 } else {
1505 let mut s = self.text.clone_string();
1508 s.insert_str(index, text);
1509 self.text.set_text(s);
1510 self.selection.set_all(index + text.len());
1512 }
1513 self.edit_x_coord = None;
1514
1515 self.prepare_text(cx);
1516 Used
1517 }
1518
1519 fn control_key(
1520 &mut self,
1521 cx: &mut EventCx,
1522 data: &G::Data,
1523 cmd: Command,
1524 code: Option<PhysicalKey>,
1525 ) -> Result<IsUsed, NotReady> {
1526 let editable = self.editable;
1527 let mut shift = cx.modifiers().shift_key();
1528 let mut buf = [0u8; 4];
1529 let cursor = self.selection.edit_index();
1530 let len = self.text.str_len();
1531 let multi_line = self.multi_line();
1532 let selection = self.selection.range();
1533 let have_sel = selection.end > selection.start;
1534 let string;
1535
1536 enum Action<'a> {
1537 None,
1538 Activate,
1539 Edit,
1540 Insert(&'a str, LastEdit),
1541 Delete(Range<usize>),
1542 Move(usize, Option<f32>),
1543 }
1544
1545 let action = match cmd {
1546 Command::Escape | Command::Deselect
1547 if !self.current.is_active_ime() && !selection.is_empty() =>
1548 {
1549 self.current.clear_selection();
1550 self.selection.set_empty();
1551 cx.redraw(&self);
1552 Action::None
1553 }
1554 Command::Activate => Action::Activate,
1555 Command::Enter if shift || !multi_line => Action::Activate,
1556 Command::Enter if editable && multi_line => {
1557 Action::Insert('\n'.encode_utf8(&mut buf), LastEdit::Insert)
1558 }
1559 Command::Left | Command::Home if !shift && have_sel => {
1563 Action::Move(selection.start, None)
1564 }
1565 Command::Left if cursor > 0 => {
1566 let mut cursor = GraphemeCursor::new(cursor, len, true);
1567 cursor
1568 .prev_boundary(self.text.text(), 0)
1569 .unwrap()
1570 .map(|index| Action::Move(index, None))
1571 .unwrap_or(Action::None)
1572 }
1573 Command::Right | Command::End if !shift && have_sel => {
1574 Action::Move(selection.end, None)
1575 }
1576 Command::Right if cursor < len => {
1577 let mut cursor = GraphemeCursor::new(cursor, len, true);
1578 cursor
1579 .next_boundary(self.text.text(), 0)
1580 .unwrap()
1581 .map(|index| Action::Move(index, None))
1582 .unwrap_or(Action::None)
1583 }
1584 Command::WordLeft if cursor > 0 => {
1585 let mut iter = self.text.text()[0..cursor].split_word_bound_indices();
1586 let mut p = iter.next_back().map(|(index, _)| index).unwrap_or(0);
1587 while self.text.text()[p..]
1588 .chars()
1589 .next()
1590 .map(|c| c.is_whitespace())
1591 .unwrap_or(false)
1592 {
1593 if let Some((index, _)) = iter.next_back() {
1594 p = index;
1595 } else {
1596 break;
1597 }
1598 }
1599 Action::Move(p, None)
1600 }
1601 Command::WordRight if cursor < len => {
1602 let mut iter = self.text.text()[cursor..]
1603 .split_word_bound_indices()
1604 .skip(1);
1605 let mut p = iter.next().map(|(index, _)| cursor + index).unwrap_or(len);
1606 while self.text.text()[p..]
1607 .chars()
1608 .next()
1609 .map(|c| c.is_whitespace())
1610 .unwrap_or(false)
1611 {
1612 if let Some((index, _)) = iter.next() {
1613 p = cursor + index;
1614 } else {
1615 break;
1616 }
1617 }
1618 Action::Move(p, None)
1619 }
1620 Command::Left | Command::Right | Command::WordLeft | Command::WordRight => Action::None,
1622 Command::Up | Command::Down if multi_line => {
1623 let x = match self.edit_x_coord {
1624 Some(x) => x,
1625 None => self
1626 .text
1627 .text_glyph_pos(cursor)?
1628 .next_back()
1629 .map(|r| r.pos.0)
1630 .unwrap_or(0.0),
1631 };
1632 let mut line = self.text.find_line(cursor)?.map(|r| r.0).unwrap_or(0);
1633 line = match cmd {
1635 Command::Up => line.wrapping_sub(1),
1636 Command::Down => line.wrapping_add(1),
1637 _ => unreachable!(),
1638 };
1639 const HALF: usize = usize::MAX / 2;
1640 let nearest_end = match line {
1641 0..=HALF => len,
1642 _ => 0,
1643 };
1644 self.text
1645 .line_index_nearest(line, x)?
1646 .map(|index| Action::Move(index, Some(x)))
1647 .unwrap_or(Action::Move(nearest_end, None))
1648 }
1649 Command::Home if cursor > 0 => {
1650 let index = self.text.find_line(cursor)?.map(|r| r.1.start).unwrap_or(0);
1651 Action::Move(index, None)
1652 }
1653 Command::End if cursor < len => {
1654 let index = self.text.find_line(cursor)?.map(|r| r.1.end).unwrap_or(len);
1655 Action::Move(index, None)
1656 }
1657 Command::DocHome if cursor > 0 => Action::Move(0, None),
1658 Command::DocEnd if cursor < len => Action::Move(len, None),
1659 Command::Home | Command::End | Command::DocHome | Command::DocEnd => Action::None,
1661 Command::PageUp | Command::PageDown if multi_line => {
1662 let mut v = self
1663 .text
1664 .text_glyph_pos(cursor)?
1665 .next_back()
1666 .map(|r| r.pos.into())
1667 .unwrap_or(Vec2::ZERO);
1668 if let Some(x) = self.edit_x_coord {
1669 v.0 = x;
1670 }
1671 const FACTOR: f32 = 2.0 / 3.0;
1672 let mut h_dist = f32::conv(self.text.rect().size.1) * FACTOR;
1673 if cmd == Command::PageUp {
1674 h_dist *= -1.0;
1675 }
1676 v.1 += h_dist;
1677 Action::Move(self.text.text_index_nearest(v)?, Some(v.0))
1678 }
1679 Command::Delete | Command::DelBack if editable && have_sel => {
1680 Action::Delete(selection.clone())
1681 }
1682 Command::Delete if editable => GraphemeCursor::new(cursor, len, true)
1683 .next_boundary(self.text.text(), 0)
1684 .unwrap()
1685 .map(|next| Action::Delete(cursor..next))
1686 .unwrap_or(Action::None),
1687 Command::DelBack if editable => {
1688 let prev = self.text.text()[0..cursor]
1690 .char_indices()
1691 .next_back()
1692 .map(|(i, _)| i)
1693 .unwrap_or(0);
1694 Action::Delete(prev..cursor)
1695 }
1696 Command::DelWord if editable => {
1697 let next = self.text.text()[cursor..]
1698 .split_word_bound_indices()
1699 .nth(1)
1700 .map(|(index, _)| cursor + index)
1701 .unwrap_or(len);
1702 Action::Delete(cursor..next)
1703 }
1704 Command::DelWordBack if editable => {
1705 let prev = self.text.text()[0..cursor]
1706 .split_word_bound_indices()
1707 .next_back()
1708 .map(|(index, _)| index)
1709 .unwrap_or(0);
1710 Action::Delete(prev..cursor)
1711 }
1712 Command::SelectAll => {
1713 self.selection.set_sel_index(0);
1714 shift = true; Action::Move(len, None)
1716 }
1717 Command::Cut if editable && have_sel => {
1718 cx.set_clipboard((self.text.text()[selection.clone()]).into());
1719 Action::Delete(selection.clone())
1720 }
1721 Command::Copy if have_sel => {
1722 cx.set_clipboard((self.text.text()[selection.clone()]).into());
1723 Action::None
1724 }
1725 Command::Paste if editable => {
1726 if let Some(content) = cx.get_clipboard() {
1727 let range = self.trim_paste(&content);
1728 string = content;
1729 Action::Insert(&string[range], LastEdit::Paste)
1730 } else {
1731 Action::None
1732 }
1733 }
1734 Command::Undo | Command::Redo if editable => {
1735 if let Some((state, c2, sel)) = self.old_state.as_mut() {
1737 self.text.swap_string(state);
1738 self.selection.set_edit_index(*c2);
1739 *c2 = cursor;
1740 let index = *sel;
1741 *sel = self.selection.sel_index();
1742 self.selection.set_sel_index(index);
1743 self.edit_x_coord = None;
1744 self.last_edit = LastEdit::None;
1745 }
1746 Action::Edit
1747 }
1748 _ => return Ok(Unused),
1749 };
1750
1751 if !self.has_key_focus {
1752 let ime = Some(ImePurpose::Normal);
1755 cx.request_key_focus(self.id(), ime, FocusSource::Synthetic);
1756 }
1757
1758 if !matches!(action, Action::None) {
1759 self.current = CurrentAction::None;
1760 }
1761
1762 let result = match action {
1763 Action::None => EditAction::None,
1764 Action::Activate => EditAction::Activate,
1765 Action::Edit => EditAction::Edit,
1766 Action::Insert(s, edit) => {
1767 let mut index = cursor;
1768 if have_sel {
1769 self.old_state =
1770 Some((self.text.clone_string(), index, self.selection.sel_index()));
1771 self.last_edit = edit;
1772
1773 self.text.replace_range(selection.clone(), s);
1774 index = selection.start;
1775 } else {
1776 if self.last_edit != edit {
1777 self.old_state =
1778 Some((self.text.clone_string(), index, self.selection.sel_index()));
1779 self.last_edit = edit;
1780 }
1781
1782 self.text.replace_range(index..index, s);
1783 }
1784 self.selection.set_all(index + s.len());
1785 self.edit_x_coord = None;
1786 EditAction::Edit
1787 }
1788 Action::Delete(sel) => {
1789 if self.last_edit != LastEdit::Delete {
1790 self.old_state =
1791 Some((self.text.clone_string(), cursor, self.selection.sel_index()));
1792 self.last_edit = LastEdit::Delete;
1793 }
1794
1795 self.text.replace_range(sel.clone(), "");
1796 self.selection.set_all(sel.start);
1797 self.edit_x_coord = None;
1798 EditAction::Edit
1799 }
1800 Action::Move(index, x_coord) => {
1801 self.selection.set_edit_index(index);
1802 if !shift {
1803 self.selection.set_empty();
1804 } else {
1805 self.set_primary(cx);
1806 }
1807 self.edit_x_coord = x_coord;
1808 cx.redraw(&self);
1809 EditAction::None
1810 }
1811 };
1812
1813 self.prepare_text(cx);
1814
1815 Ok(match result {
1816 EditAction::None => Used,
1817 EditAction::Activate => {
1818 cx.depress_with_key(&self, code);
1819 G::activate(self, cx, data)
1820 }
1821 EditAction::Edit => {
1822 G::edit(self, cx, data);
1823 Used
1824 }
1825 })
1826 }
1827
1828 fn set_cursor_from_coord(&mut self, cx: &mut EventCx, coord: Coord) {
1829 let rel_pos = (coord - self.rect().pos).cast();
1830 if let Ok(index) = self.text.text_index_nearest(rel_pos) {
1831 if index != self.selection.edit_index() {
1832 self.selection.set_edit_index(index);
1833 self.set_view_offset_from_cursor(cx);
1834 self.edit_x_coord = None;
1835 cx.redraw(self);
1836 }
1837 }
1838 }
1839
1840 fn set_primary(&self, cx: &mut EventCx) {
1841 if self.has_key_focus && !self.selection.is_empty() && cx.has_primary() {
1842 let range = self.selection.range();
1843 cx.set_primary(String::from(&self.text.as_str()[range]));
1844 }
1845 }
1846
1847 fn set_view_offset_from_cursor(&mut self, cx: &mut EventCx) {
1851 let cursor = self.selection.edit_index();
1852 if let Some(marker) = self
1853 .text
1854 .text_glyph_pos(cursor)
1855 .ok()
1856 .and_then(|mut m| m.next_back())
1857 {
1858 let y0 = (marker.pos.1 - marker.ascent).cast_floor();
1859 let pos = self.rect().pos + Offset(marker.pos.0.cast_nearest(), y0);
1860 let size = Size(0, i32::conv_ceil(marker.pos.1 - marker.descent) - y0);
1861 cx.set_scroll(Scroll::Rect(Rect { pos, size }));
1862 }
1863 }
1864}