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