input.rs

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