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 `V` 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`].
  8pub trait ViewInputHandler: 'static + Sized {
  9    fn text_for_range(&mut self, range: Range<usize>, cx: &mut ViewContext<Self>)
 10        -> Option<String>;
 11    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>>;
 12    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>>;
 13    fn unmark_text(&mut self, cx: &mut ViewContext<Self>);
 14    fn replace_text_in_range(
 15        &mut self,
 16        range: Option<Range<usize>>,
 17        text: &str,
 18        cx: &mut ViewContext<Self>,
 19    );
 20    fn replace_and_mark_text_in_range(
 21        &mut self,
 22        range: Option<Range<usize>>,
 23        new_text: &str,
 24        new_selected_range: Option<Range<usize>>,
 25        cx: &mut ViewContext<Self>,
 26    );
 27    fn bounds_for_range(
 28        &mut self,
 29        range_utf16: Range<usize>,
 30        element_bounds: Bounds<Pixels>,
 31        cx: &mut ViewContext<Self>,
 32    ) -> Option<Bounds<Pixels>>;
 33}
 34
 35/// The canonical implementation of [`PlatformInputHandler`]. Call [`WindowContext::handle_input`]
 36/// with an instance during your element's paint.
 37pub struct ElementInputHandler<V> {
 38    view: View<V>,
 39    element_bounds: Bounds<Pixels>,
 40}
 41
 42impl<V: 'static> ElementInputHandler<V> {
 43    /// Used in [`Element::paint`][element_paint] with the element's bounds and a view context for its
 44    /// containing view.
 45    ///
 46    /// [element_paint]: crate::Element::paint
 47    pub fn new(element_bounds: Bounds<Pixels>, view: View<V>) -> Self {
 48        ElementInputHandler {
 49            view,
 50            element_bounds,
 51        }
 52    }
 53}
 54
 55impl<V: ViewInputHandler> InputHandler for ElementInputHandler<V> {
 56    fn selected_text_range(&mut self, cx: &mut WindowContext) -> Option<Range<usize>> {
 57        self.view
 58            .update(cx, |view, cx| view.selected_text_range(cx))
 59    }
 60
 61    fn marked_text_range(&mut self, cx: &mut WindowContext) -> Option<Range<usize>> {
 62        self.view.update(cx, |view, cx| view.marked_text_range(cx))
 63    }
 64
 65    fn text_for_range(
 66        &mut self,
 67        range_utf16: Range<usize>,
 68        cx: &mut WindowContext,
 69    ) -> Option<String> {
 70        self.view
 71            .update(cx, |view, cx| view.text_for_range(range_utf16, cx))
 72    }
 73
 74    fn replace_text_in_range(
 75        &mut self,
 76        replacement_range: Option<Range<usize>>,
 77        text: &str,
 78        cx: &mut WindowContext,
 79    ) {
 80        self.view.update(cx, |view, cx| {
 81            view.replace_text_in_range(replacement_range, text, cx)
 82        });
 83    }
 84
 85    fn replace_and_mark_text_in_range(
 86        &mut self,
 87        range_utf16: Option<Range<usize>>,
 88        new_text: &str,
 89        new_selected_range: Option<Range<usize>>,
 90        cx: &mut WindowContext,
 91    ) {
 92        self.view.update(cx, |view, cx| {
 93            view.replace_and_mark_text_in_range(range_utf16, new_text, new_selected_range, cx)
 94        });
 95    }
 96
 97    fn unmark_text(&mut self, cx: &mut WindowContext) {
 98        self.view.update(cx, |view, cx| view.unmark_text(cx));
 99    }
100
101    fn bounds_for_range(
102        &mut self,
103        range_utf16: Range<usize>,
104        cx: &mut WindowContext,
105    ) -> Option<Bounds<Pixels>> {
106        self.view.update(cx, |view, cx| {
107            view.bounds_for_range(range_utf16, self.element_bounds, cx)
108        })
109    }
110}