1use crate::{
2 AnyWindowHandle, AppCell, Bounds, Context, Pixels, PlatformInputHandler, View, ViewContext,
3 WindowContext,
4};
5use std::{ops::Range, rc::Weak};
6
7pub struct WindowInputHandler {
8 pub cx: Weak<AppCell>,
9 pub input_handler: Box<dyn InputHandlerView>,
10 pub window: AnyWindowHandle,
11 pub element_bounds: Bounds<Pixels>,
12}
13
14pub trait InputHandlerView {
15 fn text_for_range(&self, range: Range<usize>, cx: &mut WindowContext) -> Option<String>;
16 fn selected_text_range(&self, cx: &mut WindowContext) -> Option<Range<usize>>;
17 fn marked_text_range(&self, cx: &mut WindowContext) -> Option<Range<usize>>;
18 fn unmark_text(&self, cx: &mut WindowContext);
19 fn replace_text_in_range(
20 &self,
21 range: Option<Range<usize>>,
22 text: &str,
23 cx: &mut WindowContext,
24 );
25 fn replace_and_mark_text_in_range(
26 &self,
27 range: Option<Range<usize>>,
28 new_text: &str,
29 new_selected_range: Option<Range<usize>>,
30 cx: &mut WindowContext,
31 );
32 fn bounds_for_range(
33 &self,
34 range_utf16: std::ops::Range<usize>,
35 element_bounds: crate::Bounds<Pixels>,
36 cx: &mut WindowContext,
37 ) -> Option<crate::Bounds<Pixels>>;
38}
39
40pub trait InputHandler: Sized {
41 fn text_for_range(&self, range: Range<usize>, cx: &mut ViewContext<Self>) -> Option<String>;
42 fn selected_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>>;
43 fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>>;
44 fn unmark_text(&mut self, cx: &mut ViewContext<Self>);
45 fn replace_text_in_range(
46 &mut self,
47 range: Option<Range<usize>>,
48 text: &str,
49 cx: &mut ViewContext<Self>,
50 );
51 fn replace_and_mark_text_in_range(
52 &mut self,
53 range: Option<Range<usize>>,
54 new_text: &str,
55 new_selected_range: Option<Range<usize>>,
56 cx: &mut ViewContext<Self>,
57 );
58 fn bounds_for_range(
59 &mut self,
60 range_utf16: std::ops::Range<usize>,
61 element_bounds: crate::Bounds<Pixels>,
62 cx: &mut ViewContext<Self>,
63 ) -> Option<crate::Bounds<Pixels>>;
64}
65
66impl<V: InputHandler + 'static> InputHandlerView for View<V> {
67 fn text_for_range(&self, range: Range<usize>, cx: &mut WindowContext) -> Option<String> {
68 self.update(cx, |this, cx| this.text_for_range(range, cx))
69 }
70
71 fn selected_text_range(&self, cx: &mut WindowContext) -> Option<Range<usize>> {
72 self.update(cx, |this, cx| this.selected_text_range(cx))
73 }
74
75 fn marked_text_range(&self, cx: &mut WindowContext) -> Option<Range<usize>> {
76 self.update(cx, |this, cx| this.marked_text_range(cx))
77 }
78
79 fn unmark_text(&self, cx: &mut WindowContext) {
80 self.update(cx, |this, cx| this.unmark_text(cx))
81 }
82
83 fn replace_text_in_range(
84 &self,
85 range: Option<Range<usize>>,
86 text: &str,
87 cx: &mut WindowContext,
88 ) {
89 self.update(cx, |this, cx| this.replace_text_in_range(range, text, cx))
90 }
91
92 fn replace_and_mark_text_in_range(
93 &self,
94 range: Option<Range<usize>>,
95 new_text: &str,
96 new_selected_range: Option<Range<usize>>,
97 cx: &mut WindowContext,
98 ) {
99 self.update(cx, |this, cx| {
100 this.replace_and_mark_text_in_range(range, new_text, new_selected_range, cx)
101 })
102 }
103
104 fn bounds_for_range(
105 &self,
106 range_utf16: std::ops::Range<usize>,
107 element_bounds: crate::Bounds<Pixels>,
108 cx: &mut WindowContext,
109 ) -> Option<crate::Bounds<Pixels>> {
110 self.update(cx, |this, cx| {
111 this.bounds_for_range(range_utf16, element_bounds, cx)
112 })
113 }
114}
115
116impl PlatformInputHandler for WindowInputHandler {
117 fn selected_text_range(&self) -> Option<Range<usize>> {
118 self.update(|handler, cx| handler.selected_text_range(cx))
119 .flatten()
120 }
121
122 fn marked_text_range(&self) -> Option<Range<usize>> {
123 self.update(|handler, cx| handler.marked_text_range(cx))
124 .flatten()
125 }
126
127 fn text_for_range(&self, range_utf16: Range<usize>) -> Option<String> {
128 self.update(|handler, cx| handler.text_for_range(range_utf16, cx))
129 .flatten()
130 }
131
132 fn replace_text_in_range(&mut self, replacement_range: Option<Range<usize>>, text: &str) {
133 self.update(|handler, cx| handler.replace_text_in_range(replacement_range, text, cx));
134 }
135
136 fn replace_and_mark_text_in_range(
137 &mut self,
138 range_utf16: Option<Range<usize>>,
139 new_text: &str,
140 new_selected_range: Option<Range<usize>>,
141 ) {
142 self.update(|handler, cx| {
143 handler.replace_and_mark_text_in_range(range_utf16, new_text, new_selected_range, cx)
144 });
145 }
146
147 fn unmark_text(&mut self) {
148 self.update(|handler, cx| handler.unmark_text(cx));
149 }
150
151 fn bounds_for_range(&self, range_utf16: Range<usize>) -> Option<Bounds<Pixels>> {
152 self.update(|handler, cx| handler.bounds_for_range(range_utf16, self.element_bounds, cx))
153 .flatten()
154 }
155}
156
157impl WindowInputHandler {
158 fn update<R>(
159 &self,
160 f: impl FnOnce(&dyn InputHandlerView, &mut WindowContext) -> R,
161 ) -> Option<R> {
162 let cx = self.cx.upgrade()?;
163 let mut cx = cx.borrow_mut();
164 cx.update_window(self.window, |_, cx| f(&*self.input_handler, cx))
165 .ok()
166 }
167}