Skip to main content

kas_widgets/edit/
mod.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! The [`EditField`] and [`EditBox`] widgets, plus supporting items
7
8mod edit_box;
9mod edit_field;
10mod editor;
11mod guard;
12
13pub use edit_box::EditBox;
14pub use edit_field::EditField;
15pub use editor::Editor;
16pub use guard::*;
17
18use std::fmt::Debug;
19use std::ops::Range;
20
21/// Describes the change source of a history (undo) state
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23enum EditOp {
24    /// Initial state
25    Initial,
26    /// Cursor movement or selection adjustment
27    Cursor,
28    /// Keyboard
29    KeyInput,
30    /// Input Method Editor
31    Ime,
32    /// Deletion due to key press
33    Delete,
34    /// Cut to or paste from clipboard
35    Clipboard,
36    /// Programmatic edit
37    Synthetic,
38}
39
40impl EditOp {
41    /// An edit may be merged with a previous one if both are equal and this method returns `true`
42    fn try_merge(self, last_op: &mut Option<Self>) -> bool {
43        match (self, last_op) {
44            (EditOp::Cursor, Some(last)) => {
45                *last = self;
46                true
47            }
48            (EditOp::KeyInput | EditOp::Delete, Some(last)) if self == *last => true,
49            _ => false,
50        }
51    }
52}
53
54enum CmdAction {
55    /// Key not used, no action
56    Unused,
57    /// Key used, no action
58    Used,
59    /// Cursor and/or selection changed
60    Cursor,
61    /// Enter key in single-line editor
62    Activate,
63    /// Text was edited by key command
64    Edit,
65}
66
67/// Used to track ongoing incompatible actions
68#[derive(Clone, Debug, Default, PartialEq, Eq)]
69enum CurrentAction {
70    /// No current action
71    #[default]
72    None,
73    /// IME is enabled but no input has yet been given. This is special in that
74    /// a selection may exist (which would get replaced by the pre-edit text).
75    ImeStart,
76    /// We have some pre-edit text within the given range (if non-empty).
77    ///
78    /// This text should be deleted if IME is cancelled.
79    ImePreedit {
80        /// Range of the pre-edit text
81        edit_range: Range<u32>,
82    },
83    Selection,
84}
85
86impl CurrentAction {
87    fn is_none(&self) -> bool {
88        *self == CurrentAction::None
89    }
90
91    /// Check whether IME is enabled
92    ///
93    /// This does not imply a pre-edit (or any IME input).
94    fn is_ime_enabled(&self) -> bool {
95        matches!(
96            self,
97            CurrentAction::ImeStart | CurrentAction::ImePreedit { .. }
98        )
99    }
100}