diff --git a/src/window/utils.rs b/src/window/utils.rs index df2f748..7465794 100644 --- a/src/window/utils.rs +++ b/src/window/utils.rs @@ -1,8 +1,9 @@ use std::ops::{Bound, RangeBounds}; use egui::{ - ecolor::HexColor, Align, Color32, CursorIcon, Frame, Layout, Margin, Rect, Response, RichText, - Rounding, Sense, Shape, Stroke, TextEdit, Ui, UiBuilder, Vec2, Widget, WidgetText, + ecolor::HexColor, Align, Color32, CursorIcon, Event, Frame, Key, Layout, Margin, Rect, + Response, RichText, Rounding, Sense, Shape, Stroke, TextEdit, Ui, UiBuilder, Vec2, Widget, + WidgetText, }; pub trait UiExt { @@ -117,10 +118,13 @@ impl<'a> NumberEdit<'a> { impl Widget for NumberEdit<'_> { fn ui(self, ui: &mut Ui) -> Response { - let (last_value, mut str) = ui.memory(|m| { - m.data + let (last_value, mut str, focus) = ui.memory(|m| { + let (lv, s) = m + .data .get_temp(ui.id()) - .unwrap_or((*self.value, self.value.to_string())) + .unwrap_or((*self.value, self.value.to_string())); + let focus = m.has_focus(ui.id()); + (lv, s, focus) }); let mut stale = false; if *self.value != last_value { @@ -128,8 +132,34 @@ impl Widget for NumberEdit<'_> { stale = true; } let valid = str.parse().is_ok_and(|v: usize| v == *self.value); + let mut up_pressed = false; + let mut down_pressed = false; + if focus { + ui.input_mut(|i| { + i.events.retain(|e| match e { + Event::Key { + key: Key::ArrowUp, + pressed: true, + .. + } => { + up_pressed = true; + false + } + Event::Key { + key: Key::ArrowDown, + pressed: true, + .. + } => { + down_pressed = true; + false + } + _ => true, + }) + }); + } let text = TextEdit::singleline(&mut str) .horizontal_align(Align::Max) + .id(ui.id()) .margin(Margin { left: 4.0, right: 20.0, @@ -167,14 +197,14 @@ impl Widget for NumberEdit<'_> { min: (arrow_left, arrow_top).into(), max: (arrow_right, arrow_middle).into(), }; - if draw_arrow(ui, top_arrow_rect, true).clicked_or_dragged() { + if draw_arrow(ui, top_arrow_rect, true).clicked_or_dragged() || up_pressed { delta = 1; } let bottom_arrow_rect = Rect { min: (arrow_left, arrow_middle).into(), max: (arrow_right, arrow_bottom).into(), }; - if draw_arrow(ui, bottom_arrow_rect, false).clicked_or_dragged() { + if draw_arrow(ui, bottom_arrow_rect, false).clicked_or_dragged() || down_pressed { delta = -1; } @@ -201,7 +231,14 @@ impl Widget for NumberEdit<'_> { fn draw_arrow(ui: &mut Ui, rect: Rect, up: bool) -> Response { let arrow_res = ui - .allocate_rect(rect, Sense::click_and_drag()) + .allocate_rect( + rect, + Sense { + click: true, + drag: true, + focusable: false, + }, + ) .on_hover_cursor(CursorIcon::Default); let visuals = ui.style().visuals.widgets.style(&arrow_res); let painter = ui.painter_at(arrow_res.rect);