window_input_handler.rs

  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}