diff --git a/CHANGELOG.md b/CHANGELOG.md index 53b477ed..606931d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w * `Context::request_repaint` will wake up UI thread, if integrations has called `Context::set_request_repaint_callback` ([#1366](https://github.com/emilk/egui/pull/1366)). * Added `Plot::allow_scroll`, `Plot::allow_zoom` no longer affects scrolling ([#1382](https://github.com/emilk/egui/pull/1382)). * Added `Ui::push_id` to resolve id clashes ([#1374](https://github.com/emilk/egui/pull/1374)). +* Added `Ui::scroll_with_delta`. * Added `Frame::outer_margin`. * Added `Painter::hline` and `Painter::vline`. * Added `Link` and `ui.link` ([#1506](https://github.com/emilk/egui/pull/1506)). diff --git a/egui/src/data/input.rs b/egui/src/data/input.rs index 6b918a57..eebe7096 100644 --- a/egui/src/data/input.rs +++ b/egui/src/data/input.rs @@ -201,6 +201,12 @@ pub enum Event { /// So if you get positive values, the content being viewed should move to the right and down, /// revealing new things to the left and up. /// + /// A positive X-value indicates the content is being moved right, + /// as when swiping right on a touch-screen or track-pad with natural scrolling. + /// + /// A positive Y-value indicates the content is being moved down, + /// as when swiping down on a touch-screen or track-pad with natural scrolling. + /// /// Shift-scroll should result in horizontal scrolling (it is up to the integrations to do this). Scroll(Vec2), diff --git a/egui/src/frame_state.rs b/egui/src/frame_state.rs index d949606f..8983aad6 100644 --- a/egui/src/frame_state.rs +++ b/egui/src/frame_state.rs @@ -27,8 +27,11 @@ pub(crate) struct FrameState { /// Initialized to `None` at the start of each frame. pub(crate) tooltip_rect: Option<(Id, Rect, usize)>, + /// Set to [`InputState::scroll_delta`] on the start of each frame. + /// /// Cleared by the first [`ScrollArea`] that makes use of it. pub(crate) scroll_delta: Vec2, // TODO: move to a Mutex inside of `InputState` ? + /// horizontal, vertical pub(crate) scroll_target: [Option<(RangeInclusive, Option)>; 2], } diff --git a/egui/src/input_state.rs b/egui/src/input_state.rs index 87e59cd4..440a3c44 100644 --- a/egui/src/input_state.rs +++ b/egui/src/input_state.rs @@ -33,7 +33,15 @@ pub struct InputState { /// (We keep a separate [`TouchState`] for each encountered touch device.) touch_states: BTreeMap, - /// How many pixels the user scrolled. + /// How many points the user scrolled. + /// + /// The delta dictates how the _content_ should move. + /// + /// A positive X-value indicates the content is being moved right, + /// as when swiping right on a touch-screen or track-pad with natural scrolling. + /// + /// A positive Y-value indicates the content is being moved down, + /// as when swiping down on a touch-screen or track-pad with natural scrolling. pub scroll_delta: Vec2, /// Zoom scale factor this frame (e.g. from ctrl-scroll or pinch gesture). diff --git a/egui/src/response.rs b/egui/src/response.rs index b7a76b54..b6390081 100644 --- a/egui/src/response.rs +++ b/egui/src/response.rs @@ -447,7 +447,7 @@ impl Response { /// /// If `align` is `None`, it'll scroll enough to bring the UI into view. /// - /// See also: [`Ui::scroll_to_cursor`], [`Ui::scroll_to_rect`]. + /// See also: [`Ui::scroll_to_cursor`], [`Ui::scroll_to_rect`]. [`Ui::scroll_with_delta`]. /// /// ``` /// # egui::__run_test_ui(|ui| { diff --git a/egui/src/ui.rs b/egui/src/ui.rs index 65c52bd2..83e52639 100644 --- a/egui/src/ui.rs +++ b/egui/src/ui.rs @@ -920,7 +920,7 @@ impl Ui { /// /// If `align` is `None`, it'll scroll enough to bring the cursor into view. /// - /// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_cursor`]. + /// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_cursor`]. [`Ui::scroll_with_delta`].. /// /// ``` /// # use egui::Align; @@ -945,7 +945,7 @@ impl Ui { /// /// If `align` is not provided, it'll scroll enough to bring the cursor into view. /// - /// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_rect`]. + /// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_rect`]. [`Ui::scroll_with_delta`]. /// /// ``` /// # use egui::Align; @@ -969,6 +969,37 @@ impl Ui { self.ctx().frame_state().scroll_target[d] = Some((target..=target, align)); } } + + /// Scroll this many points in the given direction, in the parent [`ScrollArea`]. + /// + /// The delta dictates how the _content_ (i.e. this UI) should move. + /// + /// A positive X-value indicates the content is being moved right, + /// as when swiping right on a touch-screen or track-pad with natural scrolling. + /// + /// A positive Y-value indicates the content is being moved down, + /// as when swiping down on a touch-screen or track-pad with natural scrolling. + /// + /// /// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_rect`], [`Ui::scroll_to_cursor`] + /// + /// ``` + /// # use egui::{Align, Vec2}; + /// # egui::__run_test_ui(|ui| { + /// let mut scroll_delta = Vec2::ZERO; + /// if ui.button("Scroll down").clicked() { + /// scroll_delta.y -= 64.0; // move content up + /// } + /// egui::ScrollArea::vertical().show(ui, |ui| { + /// ui.scroll_with_delta(scroll_delta); + /// for i in 0..1000 { + /// ui.label(format!("Item {}", i)); + /// } + /// }); + /// # }); + /// ``` + pub fn scroll_with_delta(&self, delta: Vec2) { + self.ctx().frame_state().scroll_delta += delta; + } } /// # Adding widgets