Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add functions to check which button triggered a drag start & end #2507

Merged
merged 4 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG

## Unreleased
### Added ⭐
* Add `Response::drag_started_by` and `Response::drag_released_by` for convenience, similar to `dragged` and `dragged_by`.
* Add `PointerState::*_pressed` to check if the given button was pressed in this frame.
* `Event::Key` now has a `repeat` field that is set to `true` if the event was the result of a key-repeat ([#2435](https://github.com/emilk/egui/pull/2435)).
* Add `Slider::drag_value_speed`, which lets you ask for finer precision when dragging the slider value rather than the actual slider.
* Add `Memory::any_popup_open`, which returns true if any popup is currently open ([#2464](https://github.com/emilk/egui/pull/2464)).
Expand All @@ -18,6 +20,7 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG
* Improved the algorithm for picking the number of decimals to show when hovering values in the `Plot`.

### Fixed 🐛
* Trigger `PointerEvent::Released` for drags ([#2094](https://github.com/emilk/egui/pull/2094)).
* Expose `TextEdit`'s multiline flag to AccessKit ([#2448](https://github.com/emilk/egui/pull/2448)).
* Don't render `\r` (Carriage Return) ([#2452](https://github.com/emilk/egui/pull/2452)).

Expand Down
8 changes: 4 additions & 4 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,17 +564,17 @@ impl Context {
}
}
}
PointerEvent::Released(click) => {
PointerEvent::Released { click, button } => {
response.drag_released = response.dragged;
response.dragged = false;

if hovered && response.is_pointer_button_down_on {
if let Some(click) = click {
let clicked = hovered && response.is_pointer_button_down_on;
response.clicked[click.button as usize] = clicked;
response.double_clicked[click.button as usize] =
response.clicked[*button as usize] = clicked;
response.double_clicked[*button as usize] =
clicked && click.is_double();
response.triple_clicked[click.button as usize] =
response.triple_clicked[*button as usize] =
clicked && click.is_triple();
}
}
Expand Down
69 changes: 44 additions & 25 deletions crates/egui/src/input_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,6 @@ impl InputState {
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct Click {
pub pos: Pos2,
pub button: PointerButton,
/// 1 or 2 (double-click) or 3 (triple-click)
pub count: u32,
/// Allows you to check for e.g. shift-click
Expand All @@ -471,7 +470,10 @@ pub(crate) enum PointerEvent {
position: Pos2,
button: PointerButton,
},
Released(Option<Click>),
Released {
click: Option<Click>,
button: PointerButton,
},
}

impl PointerEvent {
Expand All @@ -480,11 +482,11 @@ impl PointerEvent {
}

pub fn is_release(&self) -> bool {
matches!(self, PointerEvent::Released(_))
matches!(self, PointerEvent::Released { .. })
}

pub fn is_click(&self) -> bool {
matches!(self, PointerEvent::Released(Some(_click)))
matches!(self, PointerEvent::Released { click: Some(_), .. })
}
}

Expand Down Expand Up @@ -639,15 +641,15 @@ impl PointerState {

Some(Click {
pos,
button,
count,
modifiers,
})
} else {
None
};

self.pointer_events.push(PointerEvent::Released(click));
self.pointer_events
.push(PointerEvent::Released { click, button });

self.press_origin = None;
self.press_start_time = None;
Expand Down Expand Up @@ -775,11 +777,28 @@ impl PointerState {
self.pointer_events.iter().any(|event| event.is_release())
}

/// Was the button given pressed this frame?
pub fn button_pressed(&self, button: PointerButton) -> bool {
self.pointer_events
.iter()
.any(|event| matches!(event, &PointerEvent::Pressed{button: b, ..} if button == b))
}

/// Was the button given released this frame?
pub fn button_released(&self, button: PointerButton) -> bool {
self.pointer_events
.iter()
.any(|event| matches!(event, &PointerEvent::Released(Some(Click{button: b, ..})) if button == b))
.any(|event| matches!(event, &PointerEvent::Released{button: b, ..} if button == b))
}

/// Was the primary button pressed this frame?
pub fn primary_pressed(&self) -> bool {
self.button_pressed(PointerButton::Primary)
}

/// Was the secondary button pressed this frame?
pub fn secondary_pressed(&self) -> bool {
self.button_pressed(PointerButton::Secondary)
}

/// Was the primary button released this frame?
Expand Down Expand Up @@ -811,16 +830,28 @@ impl PointerState {

/// Was the button given double clicked this frame?
pub fn button_double_clicked(&self, button: PointerButton) -> bool {
self.pointer_events
.iter()
.any(|event| matches!(&event, PointerEvent::Released(Some(click)) if click.button == button && click.is_double()))
self.pointer_events.iter().any(|event| {
matches!(
&event,
PointerEvent::Released {
click: Some(click),
button: b,
} if *b == button && click.is_double()
)
})
}

/// Was the button given triple clicked this frame?
pub fn button_triple_clicked(&self, button: PointerButton) -> bool {
self.pointer_events
.iter()
.any(|event| matches!(&event, PointerEvent::Released(Some(click)) if click.button == button && click.is_triple()))
self.pointer_events.iter().any(|event| {
matches!(
&event,
PointerEvent::Released {
click: Some(click),
button: b,
} if *b == button && click.is_triple()
)
})
}

/// Was the primary button clicked this frame?
Expand All @@ -833,18 +864,6 @@ impl PointerState {
self.button_clicked(PointerButton::Secondary)
}

// /// Was this button pressed (`!down -> down`) this frame?
// /// This can sometimes return `true` even if `any_down() == false`
// /// because a press can be shorted than one frame.
// pub fn button_pressed(&self, button: PointerButton) -> bool {
// self.pointer_events.iter().any(|event| event.is_press())
// }

// /// Was this button released (`down -> !down`) this frame?
// pub fn button_released(&self, button: PointerButton) -> bool {
// self.pointer_events.iter().any(|event| event.is_release())
// }

/// Is this button currently down?
#[inline(always)]
pub fn button_down(&self, button: PointerButton) -> bool {
Expand Down
10 changes: 10 additions & 0 deletions crates/egui/src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,21 @@ impl Response {
self.dragged && self.ctx.input().pointer.any_pressed()
}

/// Did a drag on this widgets by the button begin this frame?
pub fn drag_started_by(&self, button: PointerButton) -> bool {
self.drag_started() && self.ctx.input().pointer.button_pressed(button)
}

/// The widget was being dragged, but now it has been released.
pub fn drag_released(&self) -> bool {
self.drag_released
}

/// The widget was being dragged by the button, but now it has been released.
pub fn drag_released_by(&self, button: PointerButton) -> bool {
self.drag_released() && self.ctx.input().pointer.button_released(button)
}

/// If dragged, how many points were we dragged and in what direction?
pub fn drag_delta(&self) -> Vec2 {
if self.dragged() {
Expand Down