1use crate::{Bounds, InputHandler, Pixels, View, ViewContext, WindowContext};
2use std::ops::Range;
3
4/// Implement this trait to allow views to handle textual input when implementing an editor, field, etc.
5///
6/// Once your view implements this trait, you can use it to construct an [`ElementInputHandler<V>`].
7/// This input handler can then be assigned during paint by calling [`WindowContext::handle_input`].
8///
9/// See [`InputHandler`] for details on how to implement each method.
10pub trait ViewInputHandler: 'static + Sized {
11 /// See [`InputHandler::text_for_range`] for details
12 fn text_for_range(&mut self, range: Range<usize>, cx: &mut ViewContext<Self>)
13 -> Option<String>;
14
15 /// See [`InputHandler::selected_text_range`] for details
16 fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>>;
17
18 /// See [`InputHandler::marked_text_range`] for details
19 fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>>;
20
21 /// See [`InputHandler::unmark_text`] for details
22 fn unmark_text(&mut self, cx: &mut ViewContext<Self>);
23
24 /// See [`InputHandler::replace_text_in_range`] for details
25 fn replace_text_in_range(
26 &mut self,
27 range: Option<Range<usize>>,
28 text: &str,
29 cx: &mut ViewContext<Self>,
30 );
31
32 /// See [`InputHandler::replace_and_mark_text_in_range`] for details
33 fn replace_and_mark_text_in_range(
34 &mut self,
35 range: Option<Range<usize>>,
36 new_text: &str,
37 new_selected_range: Option<Range<usize>>,
38 cx: &mut ViewContext<Self>,
39 );
40
41 /// See [`InputHandler::bounds_for_range`] for details
42 fn bounds_for_range(
43 &mut self,
44 range_utf16: Range<usize>,
45 element_bounds: Bounds<Pixels>,
46 cx: &mut ViewContext<Self>,
47 ) -> Option<Bounds<Pixels>>;
48}
49
50/// The canonical implementation of [`PlatformInputHandler`]. Call [`WindowContext::handle_input`]
51/// with an instance during your element's paint.
52pub struct ElementInputHandler<V> {
53 view: View<V>,
54 element_bounds: Bounds<Pixels>,
55}
56
57impl<V: 'static> ElementInputHandler<V> {
58 /// Used in [`Element::paint`][element_paint] with the element's bounds and a view context for its
59 /// containing view.
60 ///
61 /// [element_paint]: crate::Element::paint
62 pub fn new(element_bounds: Bounds<Pixels>, view: View<V>) -> Self {
63 ElementInputHandler {
64 view,
65 element_bounds,
66 }
67 }
68}
69
70impl<V: ViewInputHandler> InputHandler for ElementInputHandler<V> {
71 fn selected_text_range(&mut self, cx: &mut WindowContext) -> Option<Range<usize>> {
72 self.view
73 .update(cx, |view, cx| view.selected_text_range(cx))
74 }
75
76 fn marked_text_range(&mut self, cx: &mut WindowContext) -> Option<Range<usize>> {
77 self.view.update(cx, |view, cx| view.marked_text_range(cx))
78 }
79
80 fn text_for_range(
81 &mut self,
82 range_utf16: Range<usize>,
83 cx: &mut WindowContext,
84 ) -> Option<String> {
85 self.view
86 .update(cx, |view, cx| view.text_for_range(range_utf16, cx))
87 }
88
89 fn replace_text_in_range(
90 &mut self,
91 replacement_range: Option<Range<usize>>,
92 text: &str,
93 cx: &mut WindowContext,
94 ) {
95 self.view.update(cx, |view, cx| {
96 view.replace_text_in_range(replacement_range, text, cx)
97 });
98 }
99
100 fn replace_and_mark_text_in_range(
101 &mut self,
102 range_utf16: Option<Range<usize>>,
103 new_text: &str,
104 new_selected_range: Option<Range<usize>>,
105 cx: &mut WindowContext,
106 ) {
107 self.view.update(cx, |view, cx| {
108 view.replace_and_mark_text_in_range(range_utf16, new_text, new_selected_range, cx)
109 });
110 }
111
112 fn unmark_text(&mut self, cx: &mut WindowContext) {
113 self.view.update(cx, |view, cx| view.unmark_text(cx));
114 }
115
116 fn bounds_for_range(
117 &mut self,
118 range_utf16: Range<usize>,
119 cx: &mut WindowContext,
120 ) -> Option<Bounds<Pixels>> {
121 self.view.update(cx, |view, cx| {
122 view.bounds_for_range(range_utf16, self.element_bounds, cx)
123 })
124 }
125}