From 5434dc95d5df6d8da0fb3e7fb7c91b6c6aee3637 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Wed, 13 Aug 2025 12:13:05 +0200 Subject: [PATCH] feat(segmented_button): pressed state style --- src/theme/style/segmented_button.rs | 4 ++ src/widget/segmented_button/style.rs | 1 + src/widget/segmented_button/widget.rs | 55 ++++++++++++++++----------- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/theme/style/segmented_button.rs b/src/theme/style/segmented_button.rs index 3f5d92db..5306b3bf 100644 --- a/src/theme/style/segmented_button.rs +++ b/src/theme/style/segmented_button.rs @@ -63,6 +63,7 @@ impl StyleSheet for Theme { text_color: container.component.on.into(), }, hover: hover(cosmic, &active, 0.2), + pressed: hover(cosmic, &active, 0.15), active, ..Default::default() } @@ -117,6 +118,7 @@ impl StyleSheet for Theme { text_color: container.component.on.into(), }, hover: hover(cosmic, &active, 0.2), + pressed: hover(cosmic, &active, 0.15), active, ..Default::default() } @@ -169,6 +171,7 @@ mod horizontal { text_color: container.component.on.into(), }, hover: super::hover(cosmic, &active, 0.3), + pressed: super::hover(cosmic, &active, 0.25), active, ..Default::default() } @@ -262,6 +265,7 @@ mod vertical { ..active }, hover: super::hover(cosmic, &active, 0.3), + pressed: super::hover(cosmic, &active, 0.25), active, ..Default::default() } diff --git a/src/widget/segmented_button/style.rs b/src/widget/segmented_button/style.rs index f09a74a2..4aa856ef 100644 --- a/src/widget/segmented_button/style.rs +++ b/src/widget/segmented_button/style.rs @@ -13,6 +13,7 @@ pub struct Appearance { pub active: ItemStatusAppearance, pub inactive: ItemStatusAppearance, pub hover: ItemStatusAppearance, + pub pressed: ItemStatusAppearance, } /// Appearance of an item in the segmented button. diff --git a/src/widget/segmented_button/widget.rs b/src/widget/segmented_button/widget.rs index 126c78e5..6701bddb 100644 --- a/src/widget/segmented_button/widget.rs +++ b/src/widget/segmented_button/widget.rs @@ -541,6 +541,10 @@ where .is_some_and(|id| id.data.is_some_and(|d| d == key)) } + fn button_is_pressed(&self, state: &LocalState, key: Entity) -> bool { + state.pressed_item == Some(Item::Tab(key)) + } + /// Returns the drag id of the destination. /// /// # Panics @@ -923,28 +927,15 @@ where } } - if let Event::Mouse(mouse::Event::ButtonReleased(_)) - | Event::Touch(touch::Event::FingerLifted { .. }) = event - { + if is_lifted(&event) { state.unfocus(); } if let Some(on_activate) = self.on_activate.as_ref() { - if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) - | Event::Touch(touch::Event::FingerPressed { .. }) = event - { + if is_pressed(&event) { state.pressed_item = Some(Item::Tab(key)); - } else if let Event::Mouse(mouse::Event::ButtonReleased( - mouse::Button::Left, - )) - | Event::Touch(touch::Event::FingerLifted { .. }) = event - { - let mut can_activate = true; - if state.pressed_item != Some(Item::Tab(key)) { - can_activate = false; - } - - if can_activate { + } else if is_lifted(&event) { + if self.button_is_pressed(state, key) { shell.publish(on_activate(key)); state.set_focused(); state.focused_item = Item::Tab(key); @@ -1046,13 +1037,13 @@ where } } else if state.is_focused() { // Unfocus on clicks outside of the boundaries of the segmented button. - if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) - | Event::Touch(touch::Event::FingerPressed { .. }) = event - { + if is_pressed(&event) { state.unfocus(); state.pressed_item = None; return event::Status::Ignored; } + } else if is_lifted(&event) { + state.pressed_item = None; } if state.is_focused() { @@ -1343,8 +1334,10 @@ where let key_is_active = self.model.is_active(key); let key_is_focused = self.button_is_focused(state, key); - let key_is_hovered = LazyCell::new(|| self.button_is_hovered(state, key)); - let status_appearance = if *key_is_hovered || menu_open() { + let key_is_hovered = self.button_is_hovered(state, key); + let status_appearance = if self.button_is_pressed(state, key) && key_is_hovered { + appearance.pressed + } else if key_is_hovered || menu_open() { appearance.hover } else if key_is_active { appearance.active @@ -1504,7 +1497,7 @@ where // Whether to show the close button on this tab. let show_close_button = - (key_is_active || !self.show_close_icon_on_hover || *key_is_hovered) + (key_is_active || !self.show_close_icon_on_hover || key_is_hovered) && self.model.is_closable(key); // Width of the icon used by the close button, which we will subtract from the text bounds. @@ -1856,6 +1849,22 @@ fn right_button_released(event: &Event) -> bool { ) } +fn is_pressed(event: &Event) -> bool { + matches!( + event, + Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) + | Event::Touch(touch::Event::FingerPressed { .. }) + ) +} + +fn is_lifted(event: &Event) -> bool { + matches!( + event, + Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left,)) + | Event::Touch(touch::Event::FingerLifted { .. }) + ) +} + fn touch_lifted(event: &Event) -> bool { matches!(event, Event::Touch(touch::Event::FingerLifted { .. })) }