Skip to content

Commit

Permalink
Fix style of disabled widgets (#4163)
Browse files Browse the repository at this point in the history
* Broke in https://github.com/emilk/egui/pull/4026/files

The `Response::sense` for `enabled: false` widgets was wrong, leading to
the wrong widget style.
  • Loading branch information
emilk authored Mar 12, 2024
1 parent 827fdef commit d0a6bbf
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 21 deletions.
17 changes: 8 additions & 9 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1018,12 +1018,7 @@ impl Context {
///
/// If the widget already exists, its state (sense, Rect, etc) will be updated.
#[allow(clippy::too_many_arguments)]
pub(crate) fn create_widget(&self, mut w: WidgetRect) -> Response {
if !w.enabled {
w.sense.click = false;
w.sense.drag = false;
}

pub(crate) fn create_widget(&self, w: WidgetRect) -> Response {
// Remember this widget
self.write(|ctx| {
let viewport = ctx.viewport();
Expand Down Expand Up @@ -1130,7 +1125,8 @@ impl Context {
let input = &viewport.input;
let memory = &mut ctx.memory;

if sense.click
if enabled
&& sense.click
&& memory.has_focus(id)
&& (input.key_pressed(Key::Space) || input.key_pressed(Key::Enter))
{
Expand All @@ -1139,7 +1135,10 @@ impl Context {
}

#[cfg(feature = "accesskit")]
if sense.click && input.has_accesskit_action_request(id, accesskit::Action::Default) {
if enabled
&& sense.click
&& input.has_accesskit_action_request(id, accesskit::Action::Default)
{
res.clicked[PointerButton::Primary as usize] = true;
}

Expand All @@ -1159,7 +1158,7 @@ impl Context {

for pointer_event in &input.pointer.pointer_events {
if let PointerEvent::Released { click, button } = pointer_event {
if sense.click && clicked {
if enabled && sense.click && clicked {
if let Some(click) = click {
res.clicked[*button as usize] = true;
res.double_clicked[*button as usize] = click.is_double();
Expand Down
10 changes: 10 additions & 0 deletions crates/egui/src/hit_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ pub fn hit_test(
let top_layer = closest_hit.layer_id;
close.retain(|w| w.layer_id == top_layer);

// If the widget is disabled, treat it as if it isn't sensing anything.
// This simplifies the code in `hit_test_on_close` so it doesn't have to check
// the `enabled` flag everywhere:
for w in &mut close {
if !w.enabled {
w.sense.click = false;
w.sense.drag = false;
}
}

let pos_in_layer = pos_in_layers.get(&top_layer).copied().unwrap_or(pos);
let hits = hit_test_on_close(&close, pos_in_layer);

Expand Down
26 changes: 14 additions & 12 deletions crates/egui/src/interaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,18 +161,20 @@ pub(crate) fn interact(
if dragged.is_none() {
// Check if we started dragging something new:
if let Some(widget) = interaction.potential_drag_id.and_then(|id| widgets.get(id)) {
let is_dragged = if widget.sense.click && widget.sense.drag {
// This widget is sensitive to both clicks and drags.
// When the mouse first is pressed, it could be either,
// so we postpone the decision until we know.
input.pointer.is_decidedly_dragging()
} else {
// This widget is just sensitive to drags, so we can mark it as dragged right away:
widget.sense.drag
};

if is_dragged {
dragged = Some(widget.id);
if widget.enabled {
let is_dragged = if widget.sense.click && widget.sense.drag {
// This widget is sensitive to both clicks and drags.
// When the mouse first is pressed, it could be either,
// so we postpone the decision until we know.
input.pointer.is_decidedly_dragging()
} else {
// This widget is just sensitive to drags, so we can mark it as dragged right away:
widget.sense.drag
};

if is_dragged {
dragged = Some(widget.id);
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions crates/egui/src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ pub struct Response {
pub interact_rect: Rect,

/// The senses (click and/or drag) that the widget was interested in (if any).
///
/// Note: if [`Self::enabled`] is `false`, then
/// the widget _effectively_ doesn't sense anything,
/// but can still have the same `Sense`.
/// This is because the sense informs the styling of the widget,
/// but we don't want to change the style when a widget is disabled
/// (that is handled by the `Painter` directly).
pub sense: Sense,

/// Was the widget enabled?
Expand Down
7 changes: 7 additions & 0 deletions crates/egui/src/widget_rect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ pub struct WidgetRect {
pub interact_rect: Rect,

/// How the widget responds to interaction.
///
/// Note: if [`Self::enabled`] is `false`, then
/// the widget _effectively_ doesn't sense anything,
/// but can still have the same `Sense`.
/// This is because the sense informs the styling of the widget,
/// but we don't want to change the style when a widget is disabled
/// (that is handled by the `Painter` directly).
pub sense: Sense,

/// Is the widget enabled?
Expand Down

0 comments on commit d0a6bbf

Please sign in to comment.