From 2faaeddb059ca17460779430097b19d4c3922b91 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 11 Sep 2024 12:51:19 -0600 Subject: [PATCH] feat(segmented_button): Support adding divider above items in vertical segmented button --- src/widget/segmented_button/model/builder.rs | 5 +++++ src/widget/segmented_button/model/entity.rs | 6 ++++++ src/widget/segmented_button/model/mod.rs | 19 +++++++++++++++++++ src/widget/segmented_button/vertical.rs | 16 ++++++++++++++-- 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/widget/segmented_button/model/builder.rs b/src/widget/segmented_button/model/builder.rs index df59bd4d..c7e3239e 100644 --- a/src/widget/segmented_button/model/builder.rs +++ b/src/widget/segmented_button/model/builder.rs @@ -95,6 +95,11 @@ where self } + pub fn divider_above(mut self) -> Self { + self.model.0.divider_above_set(self.id, true); + self + } + /// Defines an icon for the item. /// /// ```ignore diff --git a/src/widget/segmented_button/model/entity.rs b/src/widget/segmented_button/model/entity.rs index f23f7130..77f591b9 100644 --- a/src/widget/segmented_button/model/entity.rs +++ b/src/widget/segmented_button/model/entity.rs @@ -83,6 +83,12 @@ where self } + #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + pub fn divider_above(self, divider_above: bool) -> Self { + self.model.divider_above_set(self.id, divider_above); + self + } + /// Define an icon for the item. /// /// ```ignore diff --git a/src/widget/segmented_button/model/mod.rs b/src/widget/segmented_button/model/mod.rs index 49003239..f790bff5 100644 --- a/src/widget/segmented_button/model/mod.rs +++ b/src/widget/segmented_button/model/mod.rs @@ -58,6 +58,9 @@ pub struct Model { /// The content used for drawing segmented items. pub(super) items: SlotMap, + /// Divider optionally-defined for each item. + pub(super) divider_aboves: SecondaryMap, + /// Icons optionally-defined for each item. pub(super) icons: SecondaryMap, @@ -200,6 +203,22 @@ where .and_then(|storage| storage.remove(id)); } + pub fn divider_above(&self, id: Entity) -> Option { + self.divider_aboves.get(id).copied() + } + + pub fn divider_above_set(&mut self, id: Entity, divider_above: bool) -> Option { + if !self.contains_item(id) { + return None; + } + + self.divider_aboves.insert(id, divider_above) + } + + pub fn divider_above_remove(&mut self, id: Entity) -> Option { + self.divider_aboves.remove(id) + } + /// Enable or disable an item. /// /// ```ignore diff --git a/src/widget/segmented_button/vertical.rs b/src/widget/segmented_button/vertical.rs index 0802da0d..205022b9 100644 --- a/src/widget/segmented_button/vertical.rs +++ b/src/widget/segmented_button/vertical.rs @@ -57,7 +57,19 @@ where .iter() .copied() .enumerate() - .map(move |(nth, key)| { + .flat_map(move |(nth, key)| { + let mut divider = None; + if self.model.divider_above(key).unwrap_or(false) && nth > 0 { + let mut divider_bounds = bounds; + divider_bounds.height = 1.0; + divider_bounds.x += f32::from(self.button_padding[0]); + divider_bounds.width -= f32::from(self.button_padding[0]); + divider_bounds.width -= f32::from(self.button_padding[2]); + divider = Some(ItemBounds::Divider(divider_bounds)); + + bounds.y += divider_bounds.height + spacing; + } + let mut layout_bounds = bounds; let layout_size = state.internal_layout[nth].0; @@ -66,7 +78,7 @@ where bounds.y += layout_bounds.height + spacing; - ItemBounds::Button(key, layout_bounds) + std::iter::once(ItemBounds::Button(key, layout_bounds)).chain(divider) }), ) }