input.rs

  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}