Add Ui.input_mut & InputState.ignore_key (#1212)
This commit is contained in:
parent
c8c871fcd1
commit
c1569ed0d7
|
|
@ -8,6 +8,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w
|
|||
## Unreleased
|
||||
|
||||
### Added ⭐
|
||||
* `Ui::input_mut` to modify how subsequent widgets see the `InputState` and a convenience method `InputState::consume_key` for shortcuts or hotkeys ([#1212](https://github.com/emilk/egui/pull/1212)).
|
||||
* Much improved font selection ([#1154](https://github.com/emilk/egui/pull/1154)):
|
||||
* You can now select any font size and family using `RichText::size` amd `RichText::family` and the new `FontId`.
|
||||
* Easily change text styles with `Style::text_styles`.
|
||||
|
|
|
|||
|
|
@ -264,6 +264,42 @@ pub struct Modifiers {
|
|||
}
|
||||
|
||||
impl Modifiers {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
pub fn alt(self, value: bool) -> Self {
|
||||
Self { alt: value, ..self }
|
||||
}
|
||||
|
||||
pub fn ctrl(self, value: bool) -> Self {
|
||||
Self {
|
||||
ctrl: value,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shift(self, value: bool) -> Self {
|
||||
Self {
|
||||
shift: value,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mac_cmd(self, value: bool) -> Self {
|
||||
Self {
|
||||
mac_cmd: value,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn command(self, value: bool) -> Self {
|
||||
Self {
|
||||
command: value,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_none(&self) -> bool {
|
||||
self == &Self::default()
|
||||
|
|
|
|||
|
|
@ -192,6 +192,24 @@ impl InputState {
|
|||
self.pointer.wants_repaint() || self.scroll_delta != Vec2::ZERO || !self.events.is_empty()
|
||||
}
|
||||
|
||||
/// Ignore a key if it was pressed or released this frame. Useful for hotkeys.
|
||||
/// Matches on both key press and key release, consuming them and removing them from `self.events`.
|
||||
/// Returns true if the key was pressed this frame (even if the key release was consumed).
|
||||
pub fn consume_key(&mut self, modifiers: Modifiers, key: Key) -> bool {
|
||||
self.events.retain(|event| {
|
||||
!matches!(
|
||||
event,
|
||||
Event::Key {
|
||||
key: ev_key,
|
||||
modifiers: ev_mods,
|
||||
..
|
||||
} if *ev_key == key && *ev_mods == modifiers
|
||||
)
|
||||
});
|
||||
|
||||
self.keys_down.remove(&key)
|
||||
}
|
||||
|
||||
/// Was the given key pressed this frame?
|
||||
pub fn key_pressed(&self, desired_key: Key) -> bool {
|
||||
self.num_presses(desired_key) > 0
|
||||
|
|
|
|||
|
|
@ -338,6 +338,21 @@ impl Ui {
|
|||
self.ctx().input()
|
||||
}
|
||||
|
||||
/// The [`InputState`] of the [`Context`] associated with this [`Ui`].
|
||||
/// Equivalent to `.ctx().input_mut()`.
|
||||
///
|
||||
/// Note that this locks the [`Context`], so be careful with if-let bindings
|
||||
/// like for [`Self::input()`].
|
||||
/// ```
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// ui.input_mut().consume_key(egui::Modifiers::default(), egui::Key::Enter);
|
||||
/// # });
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn input_mut(&self) -> RwLockWriteGuard<'_, InputState> {
|
||||
self.ctx().input_mut()
|
||||
}
|
||||
|
||||
/// The [`Memory`] of the [`Context`] associated with this ui.
|
||||
/// Equivalent to `.ctx().memory()`.
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -117,59 +117,27 @@ impl EasyMarkEditor {
|
|||
|
||||
fn shortcuts(ui: &Ui, code: &mut dyn TextBuffer, ccursor_range: &mut CCursorRange) -> bool {
|
||||
let mut any_change = false;
|
||||
for event in &ui.input().events {
|
||||
if let Event::Key {
|
||||
key,
|
||||
pressed: true,
|
||||
modifiers,
|
||||
} = event
|
||||
for (key, surrounding) in [
|
||||
(Key::B, "*"), // *bold*
|
||||
(Key::C, "`"), // `code`
|
||||
(Key::I, "/"), // /italics/
|
||||
(Key::L, "$"), // $subscript$
|
||||
(Key::R, "^"), // ^superscript^
|
||||
(Key::S, "~"), // ~strikethrough~
|
||||
(Key::U, "_"), // _underline_
|
||||
] {
|
||||
if ui
|
||||
.input_mut()
|
||||
.consume_key(egui::Modifiers::new().command(true), key)
|
||||
{
|
||||
if modifiers.command_only() {
|
||||
match &key {
|
||||
// toggle *bold*
|
||||
Key::B => {
|
||||
toggle_surrounding(code, ccursor_range, "*");
|
||||
any_change = true;
|
||||
}
|
||||
// toggle `code`
|
||||
Key::C => {
|
||||
toggle_surrounding(code, ccursor_range, "`");
|
||||
any_change = true;
|
||||
}
|
||||
// toggle /italics/
|
||||
Key::I => {
|
||||
toggle_surrounding(code, ccursor_range, "/");
|
||||
any_change = true;
|
||||
}
|
||||
// toggle $lowered$
|
||||
Key::L => {
|
||||
toggle_surrounding(code, ccursor_range, "$");
|
||||
any_change = true;
|
||||
}
|
||||
// toggle ^raised^
|
||||
Key::R => {
|
||||
toggle_surrounding(code, ccursor_range, "^");
|
||||
any_change = true;
|
||||
}
|
||||
// toggle ~strikethrough~
|
||||
Key::S => {
|
||||
toggle_surrounding(code, ccursor_range, "~");
|
||||
any_change = true;
|
||||
}
|
||||
// toggle _underline_
|
||||
Key::U => {
|
||||
toggle_surrounding(code, ccursor_range, "_");
|
||||
any_change = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
toggle_surrounding(code, ccursor_range, surrounding);
|
||||
any_change = true;
|
||||
};
|
||||
}
|
||||
any_change
|
||||
}
|
||||
|
||||
/// E.g. toggle *strong* with `toggle(&mut text, &mut cursor, "*")`
|
||||
/// E.g. toggle *strong* with `toggle_surrounding(&mut text, &mut cursor, "*")`
|
||||
fn toggle_surrounding(
|
||||
code: &mut dyn TextBuffer,
|
||||
ccursor_range: &mut CCursorRange,
|
||||
|
|
|
|||
Loading…
Reference in New Issue