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
 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}