pub trait EntityInputHandler: 'static + Sized {
Show 15 methods
// Required methods
fn text_for_range(
&mut self,
range: Range<usize>,
adjusted_range: &mut Option<Range<usize>>,
window: &mut Window,
cx: &mut Context<'_, Self>,
) -> Option<String>;
fn selected_text_range(
&mut self,
ignore_disabled_input: bool,
window: &mut Window,
cx: &mut Context<'_, Self>,
) -> Option<UTF16Selection>;
fn marked_text_range(
&self,
window: &mut Window,
cx: &mut Context<'_, Self>,
) -> Option<Range<usize>>;
fn unmark_text(&mut self, window: &mut Window, cx: &mut Context<'_, Self>);
fn replace_text_in_range(
&mut self,
range: Option<Range<usize>>,
text: &str,
window: &mut Window,
cx: &mut Context<'_, Self>,
);
fn replace_and_mark_text_in_range(
&mut self,
range: Option<Range<usize>>,
new_text: &str,
new_selected_range: Option<Range<usize>>,
window: &mut Window,
cx: &mut Context<'_, Self>,
);
fn bounds_for_range(
&mut self,
range_utf16: Range<usize>,
element_bounds: Bounds<Pixels>,
window: &mut Window,
cx: &mut Context<'_, Self>,
) -> Option<Bounds<Pixels>>;
fn character_index_for_point(
&mut self,
point: Point<Pixels>,
window: &mut Window,
cx: &mut Context<'_, Self>,
) -> Option<usize>;
// Provided methods
fn paste(
&mut self,
item: ClipboardItem,
window: &mut Window,
cx: &mut Context<'_, Self>,
) { ... }
fn selection_bounds_for_range(
&mut self,
_range_utf16: Range<usize>,
_element_bounds: Bounds<Pixels>,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
) -> Vec<Bounds<Pixels>> { ... }
fn set_selected_text_range(
&mut self,
_range_utf16: Range<usize>,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
) { ... }
fn text_length_utf16(
&mut self,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
) -> Option<usize> { ... }
fn accepts_text_input(
&self,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
) -> bool { ... }
fn text_input_configuration(
&mut self,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
) -> TextInputConfiguration { ... }
fn text_input_editable_range(
&mut self,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
) -> Option<Range<usize>> { ... }
}Expand description
Text input for a view: the methods the platform calls for typed text, IME composition, paste and selection.
Implement this on a view that edits text, such as a text field. Then wrap the
view in an ElementInputHandler and install it during paint with
Window::handle_input. The platform’s input method sends its requests
through that wrapper, and each method runs with the view updated.
Ranges are in UTF-16 code units, the unit the platform uses, and are
relative to the whole document. Convert with utf8_to_utf16_offset and
utf16_to_utf8_offset when your text is a UTF-8 String. Every method has
the same meaning as the matching method on InputHandler, which documents
the platform side.
On touch platforms, dismissing the software keyboard can leave the view focused. Call
Window::request_virtual_keyboard from an editing gesture, such as a tap on the field,
to show it again. After edits or selection changes that your app makes itself, call
Window::notify_text_input_changed or Window::notify_text_selection_changed so the
platform’s text services stay in sync. UIKit also needs
text_length_utf16, or a bounded
text_input_editable_range, and
set_selected_text_range. For native selection
rectangles, implement selection_bounds_for_range,
which returns all of a range’s line fragments at once.
The text guide has a complete editable field: text input.
§Examples
use gpui::{
Bounds, Context, ElementInputHandler, EntityInputHandler, FocusHandle, IntoElement,
Pixels, Point, Render, TestApp, UTF16Selection, Window, canvas, div, prelude::*,
};
use std::ops::Range;
struct Field {
focus_handle: FocusHandle,
text: String,
}
impl EntityInputHandler for Field {
fn text_for_range(
&mut self,
range: Range<usize>,
adjusted_range: &mut Option<Range<usize>>,
_window: &mut Window,
_cx: &mut Context<Self>,
) -> Option<String> {
*adjusted_range = Some(range.clone());
let start = gpui::utf16_to_utf8_offset(&self.text, range.start);
let end = gpui::utf16_to_utf8_offset(&self.text, range.end);
Some(self.text[start..end].to_string())
}
fn selected_text_range(
&mut self,
_ignore_disabled_input: bool,
_window: &mut Window,
_cx: &mut Context<Self>,
) -> Option<UTF16Selection> {
let end = gpui::utf8_to_utf16_offset(&self.text, self.text.len());
Some(UTF16Selection { range: end..end, reversed: false })
}
fn marked_text_range(&self, _window: &mut Window, _cx: &mut Context<Self>) -> Option<Range<usize>> {
None
}
fn unmark_text(&mut self, _window: &mut Window, _cx: &mut Context<Self>) {}
fn replace_text_in_range(
&mut self,
range: Option<Range<usize>>,
text: &str,
_window: &mut Window,
cx: &mut Context<Self>,
) {
let range = range.unwrap_or_else(|| {
let end = gpui::utf8_to_utf16_offset(&self.text, self.text.len());
end..end
});
let start = gpui::utf16_to_utf8_offset(&self.text, range.start);
let end = gpui::utf16_to_utf8_offset(&self.text, range.end);
self.text.replace_range(start..end, text);
cx.notify();
}
fn replace_and_mark_text_in_range(
&mut self,
range: Option<Range<usize>>,
new_text: &str,
_new_selected_range: Option<Range<usize>>,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.replace_text_in_range(range, new_text, window, cx);
}
fn bounds_for_range(
&mut self,
_range: Range<usize>,
element_bounds: Bounds<Pixels>,
_window: &mut Window,
_cx: &mut Context<Self>,
) -> Option<Bounds<Pixels>> {
Some(element_bounds)
}
fn character_index_for_point(
&mut self,
_point: Point<Pixels>,
_window: &mut Window,
_cx: &mut Context<Self>,
) -> Option<usize> {
Some(0)
}
}
impl Render for Field {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let view = cx.entity();
let focus_handle = self.focus_handle.clone();
div().size_full().track_focus(&self.focus_handle).child(
canvas(
|_, _, _| {},
move |bounds, _, window, cx| {
window.handle_input(&focus_handle, ElementInputHandler::new(bounds, view), cx);
},
)
.size_full(),
)
}
}
let mut app = TestApp::new();
let mut window = app.open_window(|window, cx| {
let focus_handle = cx.focus_handle();
window.focus(&focus_handle, cx);
Field { focus_handle, text: String::new() }
});
window.simulate_input("Ada");
assert_eq!(window.read(|field, _| field.text.clone()), "Ada");Required Methods§
Sourcefn text_for_range(
&mut self,
range: Range<usize>,
adjusted_range: &mut Option<Range<usize>>,
window: &mut Window,
cx: &mut Context<'_, Self>,
) -> Option<String>
fn text_for_range( &mut self, range: Range<usize>, adjusted_range: &mut Option<Range<usize>>, window: &mut Window, cx: &mut Context<'_, Self>, ) -> Option<String>
Returns the text in a UTF-16 range, for the platform to read back.
The platform uses this to read text around the cursor, for example for
autocorrect or the character picker. If you return text for a different
range than was asked for, such as one snapped to a character boundary,
write the range you returned into adjusted_range.
Sourcefn selected_text_range(
&mut self,
ignore_disabled_input: bool,
window: &mut Window,
cx: &mut Context<'_, Self>,
) -> Option<UTF16Selection>
fn selected_text_range( &mut self, ignore_disabled_input: bool, window: &mut Window, cx: &mut Context<'_, Self>, ) -> Option<UTF16Selection>
Returns the current selection as a UTF-16 range and direction.
Returns None if there is no selection to report. ignore_disabled_input
is passed through from the platform, and each implementation decides what it
means. The bundled text elements ignore it.
Sourcefn marked_text_range(
&self,
window: &mut Window,
cx: &mut Context<'_, Self>,
) -> Option<Range<usize>>
fn marked_text_range( &self, window: &mut Window, cx: &mut Context<'_, Self>, ) -> Option<Range<usize>>
Returns the UTF-16 range of the text in the current IME composition, or
None if no composition is active.
Composition is the text an input method is still building, such as the underlined kana before a Japanese conversion is confirmed.
Sourcefn unmark_text(&mut self, window: &mut Window, cx: &mut Context<'_, Self>)
fn unmark_text(&mut self, window: &mut Window, cx: &mut Context<'_, Self>)
Ends the IME composition and keeps its text as ordinary text.
The platform calls this when it finishes composing. After this call,
EntityInputHandler::marked_text_range returns None.
Sourcefn replace_text_in_range(
&mut self,
range: Option<Range<usize>>,
text: &str,
window: &mut Window,
cx: &mut Context<'_, Self>,
)
fn replace_text_in_range( &mut self, range: Option<Range<usize>>, text: &str, window: &mut Window, cx: &mut Context<'_, Self>, )
Replaces a UTF-16 range with typed text, or inserts at a cursor.
This is how typed characters reach your field. A None range means the
platform gave no range. The bundled text elements then replace the marked
text if there is any, and otherwise the selection.
Sourcefn replace_and_mark_text_in_range(
&mut self,
range: Option<Range<usize>>,
new_text: &str,
new_selected_range: Option<Range<usize>>,
window: &mut Window,
cx: &mut Context<'_, Self>,
)
fn replace_and_mark_text_in_range( &mut self, range: Option<Range<usize>>, new_text: &str, new_selected_range: Option<Range<usize>>, window: &mut Window, cx: &mut Context<'_, Self>, )
Replaces a range with IME text and marks that text as composing.
The platform calls this for each step of an input method’s composition.
The marked text is underlined and stays editable until
EntityInputHandler::unmark_text is called. new_selected_range is the
selection within new_text, in UTF-16 units, counted from the start of
new_text. When it is None, the cursor goes to the end of the new text.
Sourcefn bounds_for_range(
&mut self,
range_utf16: Range<usize>,
element_bounds: Bounds<Pixels>,
window: &mut Window,
cx: &mut Context<'_, Self>,
) -> Option<Bounds<Pixels>>
fn bounds_for_range( &mut self, range_utf16: Range<usize>, element_bounds: Bounds<Pixels>, window: &mut Window, cx: &mut Context<'_, Self>, ) -> Option<Bounds<Pixels>>
Returns where a UTF-16 range is drawn, so the platform can place its candidate window and other overlays next to the text.
element_bounds is the bounds of the element that installed this handler.
Return None when the text cannot be measured. Returned bounds are in window
coordinates, in logical pixels.
Sourcefn character_index_for_point(
&mut self,
point: Point<Pixels>,
window: &mut Window,
cx: &mut Context<'_, Self>,
) -> Option<usize>
fn character_index_for_point( &mut self, point: Point<Pixels>, window: &mut Window, cx: &mut Context<'_, Self>, ) -> Option<usize>
See InputHandler::character_index_for_point for details
Provided Methods§
Sourcefn paste(
&mut self,
item: ClipboardItem,
window: &mut Window,
cx: &mut Context<'_, Self>,
)
fn paste( &mut self, item: ClipboardItem, window: &mut Window, cx: &mut Context<'_, Self>, )
Inserts clipboard contents at the selection, for platforms that deliver paste as an input event, such as the web.
The default inserts only the plain-text part of item, through
EntityInputHandler::replace_text_in_range with a None range. Override
it to handle rich content.
Sourcefn selection_bounds_for_range(
&mut self,
_range_utf16: Range<usize>,
_element_bounds: Bounds<Pixels>,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
) -> Vec<Bounds<Pixels>>
fn selection_bounds_for_range( &mut self, _range_utf16: Range<usize>, _element_bounds: Bounds<Pixels>, _window: &mut Window, _cx: &mut Context<'_, Self>, ) -> Vec<Bounds<Pixels>>
Returns the UTF-16 index of the character at point, which the platform uses
to map a screen position to text.
point is in window coordinates, in logical pixels.
See InputHandler::selection_bounds_for_range for details.
Sourcefn set_selected_text_range(
&mut self,
_range_utf16: Range<usize>,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
)
fn set_selected_text_range( &mut self, _range_utf16: Range<usize>, _window: &mut Window, _cx: &mut Context<'_, Self>, )
Sets the selection to a UTF-16 range, when the platform moves it.
Platforms call this for system-driven selection changes, such as a dragged
selection handle or Select All from system UI. It is the reverse of
EntityInputHandler::selected_text_range. The default does nothing.
Sourcefn text_length_utf16(
&mut self,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
) -> Option<usize>
fn text_length_utf16( &mut self, _window: &mut Window, _cx: &mut Context<'_, Self>, ) -> Option<usize>
Returns the length of the document in UTF-16 code units, or None if it is
not known. The default is None.
Sourcefn accepts_text_input(
&self,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
) -> bool
fn accepts_text_input( &self, _window: &mut Window, _cx: &mut Context<'_, Self>, ) -> bool
Returns whether the field accepts typed text right now.
Return false for a read-only or disabled field. The default is true.
For a keystroke with KeyDownEvent::prefer_character_input set, the window
sends the keystroke to text input instead of key bindings only when this
returns true.
Sourcefn text_input_configuration(
&mut self,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
) -> TextInputConfiguration
fn text_input_configuration( &mut self, _window: &mut Window, _cx: &mut Context<'_, Self>, ) -> TextInputConfiguration
Returns platform text assistance settings for this field, such as autocorrect and the action key on the software keyboard.
The window asks on every frame and forwards the result only when it changes, so return a cheap value. You can vary it with application state, such as the cursor position. The default disables text assistance.
Sourcefn text_input_editable_range(
&mut self,
_window: &mut Window,
_cx: &mut Context<'_, Self>,
) -> Option<Range<usize>>
fn text_input_editable_range( &mut self, _window: &mut Window, _cx: &mut Context<'_, Self>, ) -> Option<Range<usize>>
Returns the UTF-16 range that the platform may read and edit around the
selection, or None for no limit.
Platforms that mirror text into an IME-editable buffer use this range to
keep multi-step edits, such as word deletion and autocorrect, inside the
region you choose. The range should contain the selection. The default is
None.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".