Skip to main content

agg_gui/widgets/text_field/
keyboard_mode.rs

1//! Keyboard-mode hooks for `TextField`.
2//!
3//! Split out of `text_field.rs` to keep that file under the 800-line
4//! cap.  The storage (`keyboard_mode: Rc<Cell<KeyboardInputMode>>`)
5//! lives on `TextField`; everything else — builders, the shared-cell
6//! handle, and the runtime setter — lives here.
7//!
8//! Why a `Cell` instead of a plain field?
9//! Demo / app code that wants a radio button to swap a focused field
10//! between "letters" and "numeric" needs to mutate the mode after the
11//! widget tree has been built and handed off as `Box<dyn Widget>`.
12//! Threading a `&mut TextField` back out is awkward; an `Rc<Cell<…>>`
13//! gives the demo a stable handle to flip whenever the radio fires.
14
15use std::cell::Cell;
16use std::rc::Rc;
17
18use super::TextField;
19use crate::widgets::on_screen_keyboard::KeyboardInputMode;
20
21impl TextField {
22    /// Assign a stable id for the programmatic focus channel. App code can
23    /// then call [`crate::focus::request_focus(id)`](crate::focus::request_focus)
24    /// to move keyboard focus here (and raise the on-screen keyboard) the
25    /// next frame — e.g. to auto-focus a search field when its overlay opens.
26    pub fn with_focus_id(mut self, id: crate::focus::FocusId) -> Self {
27        self.focus_request_id = Some(id);
28        self
29    }
30
31    /// Set the preferred keyboard input mode for this field — picks
32    /// which layer the on-screen software keyboard slides up into the
33    /// next time this field gains focus.  Defaults to
34    /// [`KeyboardInputMode::Text`].
35    ///
36    /// This does **not** install a character filter: a numeric field
37    /// still accepts whatever the user actually types (including via
38    /// a paste or the on-screen `ABC` mode switch).  Combine with
39    /// [`TextField::with_char_filter`] when you want hard validation.
40    pub fn with_keyboard_mode(self, mode: KeyboardInputMode) -> Self {
41        self.keyboard_mode.set(mode);
42        self
43    }
44
45    /// Bind the field's keyboard mode to an externally-owned cell.
46    /// The caller keeps a clone and can flip the mode at any time —
47    /// the next focus event re-queries the cell, so the keyboard
48    /// re-targets without a widget rebuild.  Mirrors the
49    /// [`TextField::with_text_cell`](super::TextField) pattern.
50    pub fn with_keyboard_mode_cell(mut self, cell: Rc<Cell<KeyboardInputMode>>) -> Self {
51        self.keyboard_mode = cell;
52        self
53    }
54
55    /// Read the current mode.  Used by the `Widget::text_input_mode`
56    /// override and exposed publicly so app code can inspect it
57    /// without going through a `dyn Widget` trait dispatch.
58    pub fn keyboard_mode(&self) -> KeyboardInputMode {
59        self.keyboard_mode.get()
60    }
61
62    /// Update the mode at runtime — typically called from a callback
63    /// (e.g. a radio button's `on_change`).  Equivalent to mutating
64    /// the cell directly via [`TextField::keyboard_mode_handle`] but
65    /// reads better at the call site.
66    pub fn set_keyboard_mode(&self, mode: KeyboardInputMode) {
67        self.keyboard_mode.set(mode);
68    }
69
70    /// Clone the underlying cell so a parent can drive this field's
71    /// mode from somewhere else in the tree (a radio button, a menu
72    /// item, a feature-flag observer).  Multiple fields can share the
73    /// same handle to ride a single switch.
74    pub fn keyboard_mode_handle(&self) -> Rc<Cell<KeyboardInputMode>> {
75        Rc::clone(&self.keyboard_mode)
76    }
77}