From e77846d2dceec55eff8288abf9c7ff979fb417fb Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 29 Nov 2023 14:33:52 -0500 Subject: [PATCH] Rework `Toggle` into `Toggleable` and `ToggleState` --- crates/collab_ui2/src/collab_panel.rs | 13 ++--- crates/ui2/src/components.rs | 2 - crates/ui2/src/components/disclosure.rs | 48 +++++++++---------- crates/ui2/src/components/list.rs | 10 ++-- crates/ui2/src/components/list/list_header.rs | 13 +++-- crates/ui2/src/components/list/list_item.rs | 13 +++-- .../ui2/src/components/stories/disclosure.rs | 8 ++-- crates/ui2/src/components/toggle.rs | 41 ---------------- crates/ui2/src/toggleable.rs | 38 +++++++++++++++ crates/ui2/src/ui2.rs | 2 + 10 files changed, 95 insertions(+), 93 deletions(-) delete mode 100644 crates/ui2/src/components/toggle.rs create mode 100644 crates/ui2/src/toggleable.rs diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 64580f0efc..32e73f5ee1 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -178,7 +178,7 @@ use serde_derive::{Deserialize, Serialize}; use settings::{Settings, SettingsStore}; use ui::{ h_stack, v_stack, Avatar, Button, Color, Icon, IconButton, IconElement, Label, List, - ListHeader, ListItem, Toggle, Tooltip, + ListHeader, ListItem, Toggleable, Tooltip, }; use util::{maybe, ResultExt, TryFutureExt}; use workspace::{ @@ -2534,9 +2534,10 @@ impl CollabPanel { .when_some(button, |el, button| el.right_button(button)) .selected(is_selected) .when(can_collapse, |el| { - el.toggle(ui::Toggle::Toggled(is_collapsed)).on_toggle( - cx.listener(move |this, _, cx| this.toggle_section_expanded(section, cx)), - ) + el.toggle(Toggleable::Toggleable(is_collapsed.into())) + .on_toggle( + cx.listener(move |this, _, cx| this.toggle_section_expanded(section, cx)), + ) }) } @@ -2853,9 +2854,9 @@ impl CollabPanel { ), ) .toggle(if has_children { - Toggle::Toggled(disclosed) + Toggleable::Toggleable(disclosed.into()) } else { - Toggle::NotToggleable + Toggleable::NotToggleable }) .on_toggle( cx.listener(move |this, _, cx| this.toggle_channel_collapsed(channel_id, cx)), diff --git a/crates/ui2/src/components.rs b/crates/ui2/src/components.rs index 9dc061e31f..0f46e3a378 100644 --- a/crates/ui2/src/components.rs +++ b/crates/ui2/src/components.rs @@ -13,7 +13,6 @@ mod list; mod popover; mod slot; mod stack; -mod toggle; mod tooltip; #[cfg(feature = "stories")] @@ -34,7 +33,6 @@ pub use list::*; pub use popover::*; pub use slot::*; pub use stack::*; -pub use toggle::*; pub use tooltip::*; #[cfg(feature = "stories")] diff --git a/crates/ui2/src/components/disclosure.rs b/crates/ui2/src/components/disclosure.rs index 350a598abb..eafa11c6ea 100644 --- a/crates/ui2/src/components/disclosure.rs +++ b/crates/ui2/src/components/disclosure.rs @@ -1,24 +1,31 @@ use std::rc::Rc; -use gpui::{ClickEvent, Div}; +use gpui::ClickEvent; use crate::prelude::*; -use crate::{Color, Icon, IconButton, IconSize, Toggle}; +use crate::{Color, Icon, IconButton, IconSize, ToggleState, Toggleable}; #[derive(IntoElement)] pub struct Disclosure { - toggle: Toggle, + state: ToggleState, on_toggle: Option>, } impl Disclosure { - pub fn new(toggle: Toggle) -> Self { + pub fn new(state: ToggleState) -> Self { Self { - toggle, + state, on_toggle: None, } } + pub fn from_toggleable(toggleable: Toggleable) -> Option { + match toggleable { + Toggleable::Toggleable(state) => Some(Self::new(state)), + Toggleable::NotToggleable => None, + } + } + pub fn on_toggle( mut self, handler: impl Into>>, @@ -29,27 +36,20 @@ impl Disclosure { } impl RenderOnce for Disclosure { - type Rendered = Div; + type Rendered = IconButton; fn render(self, _cx: &mut WindowContext) -> Self::Rendered { - if !self.toggle.is_toggleable() { - return div(); - } - - div().child( - IconButton::new( - "toggle", - if self.toggle.is_toggled() { - Icon::ChevronDown - } else { - Icon::ChevronRight - }, - ) - .color(Color::Muted) - .size(IconSize::Small) - .when_some(self.on_toggle, move |this, on_toggle| { - this.on_click(move |event, cx| on_toggle(event, cx)) - }), + IconButton::new( + "toggle", + match self.state { + ToggleState::Toggled => Icon::ChevronDown, + ToggleState::NotToggled => Icon::ChevronRight, + }, ) + .color(Color::Muted) + .size(IconSize::Small) + .when_some(self.on_toggle, move |this, on_toggle| { + this.on_click(move |event, cx| on_toggle(event, cx)) + }) } } diff --git a/crates/ui2/src/components/list.rs b/crates/ui2/src/components/list.rs index 227bb801a2..51d3ad8ecb 100644 --- a/crates/ui2/src/components/list.rs +++ b/crates/ui2/src/components/list.rs @@ -7,7 +7,7 @@ use gpui::{AnyElement, Div}; use smallvec::SmallVec; use crate::prelude::*; -use crate::{v_stack, Label, Toggle}; +use crate::{v_stack, Label, ToggleState, Toggleable}; pub use list_header::*; pub use list_item::*; @@ -20,7 +20,7 @@ pub struct List { /// Defaults to "No items" empty_message: SharedString, header: Option, - toggle: Toggle, + toggle: Toggleable, children: SmallVec<[AnyElement; 2]>, } @@ -29,7 +29,7 @@ impl List { Self { empty_message: "No items".into(), header: None, - toggle: Toggle::NotToggleable, + toggle: Toggleable::NotToggleable, children: SmallVec::new(), } } @@ -44,7 +44,7 @@ impl List { self } - pub fn toggle(mut self, toggle: Toggle) -> Self { + pub fn toggle(mut self, toggle: Toggleable) -> Self { self.toggle = toggle; self } @@ -66,7 +66,7 @@ impl RenderOnce for List { .children(self.header.map(|header| header)) .map(|this| match (self.children.is_empty(), self.toggle) { (false, _) => this.children(self.children), - (true, Toggle::Toggled(false)) => this, + (true, Toggleable::Toggleable(ToggleState::NotToggled)) => this, (true, _) => this.child(Label::new(self.empty_message.clone()).color(Color::Muted)), }) } diff --git a/crates/ui2/src/components/list/list_header.rs b/crates/ui2/src/components/list/list_header.rs index f280991c82..70c746d077 100644 --- a/crates/ui2/src/components/list/list_header.rs +++ b/crates/ui2/src/components/list/list_header.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use gpui::{ClickEvent, Div}; use crate::prelude::*; -use crate::{h_stack, Disclosure, Icon, IconButton, IconElement, IconSize, Label, Toggle}; +use crate::{h_stack, Disclosure, Icon, IconButton, IconElement, IconSize, Label, Toggleable}; pub enum ListHeaderMeta { Tools(Vec), @@ -17,7 +17,7 @@ pub struct ListHeader { label: SharedString, left_icon: Option, meta: Option, - toggle: Toggle, + toggle: Toggleable, on_toggle: Option>, inset: bool, selected: bool, @@ -30,13 +30,13 @@ impl ListHeader { left_icon: None, meta: None, inset: false, - toggle: Toggle::NotToggleable, + toggle: Toggleable::NotToggleable, on_toggle: None, selected: false, } } - pub fn toggle(mut self, toggle: Toggle) -> Self { + pub fn toggle(mut self, toggle: Toggleable) -> Self { self.toggle = toggle; self } @@ -113,7 +113,10 @@ impl RenderOnce for ListHeader { })) .child(Label::new(self.label.clone()).color(Color::Muted)), ) - .child(Disclosure::new(self.toggle).on_toggle(self.on_toggle)), + .children( + Disclosure::from_toggleable(self.toggle) + .map(|disclosure| disclosure.on_toggle(self.on_toggle)), + ), ) .child(meta), ) diff --git a/crates/ui2/src/components/list/list_item.rs b/crates/ui2/src/components/list/list_item.rs index dbab306d93..feb123c8cc 100644 --- a/crates/ui2/src/components/list/list_item.rs +++ b/crates/ui2/src/components/list/list_item.rs @@ -6,7 +6,7 @@ use gpui::{ use smallvec::SmallVec; use crate::prelude::*; -use crate::{Avatar, Disclosure, GraphicSlot, Icon, IconElement, IconSize, Toggle}; +use crate::{Avatar, Disclosure, GraphicSlot, Icon, IconElement, IconSize, Toggleable}; #[derive(IntoElement)] pub struct ListItem { @@ -17,7 +17,7 @@ pub struct ListItem { indent_level: usize, indent_step_size: Pixels, left_slot: Option, - toggle: Toggle, + toggle: Toggleable, inset: bool, on_click: Option>, on_toggle: Option>, @@ -33,7 +33,7 @@ impl ListItem { indent_level: 0, indent_step_size: px(12.), left_slot: None, - toggle: Toggle::NotToggleable, + toggle: Toggleable::NotToggleable, inset: false, on_click: None, on_secondary_mouse_down: None, @@ -70,7 +70,7 @@ impl ListItem { self } - pub fn toggle(mut self, toggle: Toggle) -> Self { + pub fn toggle(mut self, toggle: Toggleable) -> Self { self.toggle = toggle; self } @@ -150,7 +150,10 @@ impl RenderOnce for ListItem { .gap_1() .items_center() .relative() - .child(Disclosure::new(self.toggle).on_toggle(self.on_toggle)) + .children( + Disclosure::from_toggleable(self.toggle) + .map(|disclosure| disclosure.on_toggle(self.on_toggle)), + ) .map(|this| match self.left_slot { Some(GraphicSlot::Icon(i)) => this.child( IconElement::new(i) diff --git a/crates/ui2/src/components/stories/disclosure.rs b/crates/ui2/src/components/stories/disclosure.rs index 0c27f5b2e9..f08bd43f4e 100644 --- a/crates/ui2/src/components/stories/disclosure.rs +++ b/crates/ui2/src/components/stories/disclosure.rs @@ -2,7 +2,7 @@ use gpui::{Div, Render}; use story::Story; use crate::prelude::*; -use crate::{Disclosure, Toggle}; +use crate::{Disclosure, ToggleState}; pub struct DisclosureStory; @@ -13,10 +13,8 @@ impl Render for DisclosureStory { Story::container() .child(Story::title_for::()) .child(Story::label("Toggled")) - .child(Disclosure::new(Toggle::Toggled(true))) + .child(Disclosure::new(ToggleState::Toggled)) .child(Story::label("Not Toggled")) - .child(Disclosure::new(Toggle::Toggled(false))) - .child(Story::label("Not Toggleable")) - .child(Disclosure::new(Toggle::NotToggleable)) + .child(Disclosure::new(ToggleState::NotToggled)) } } diff --git a/crates/ui2/src/components/toggle.rs b/crates/ui2/src/components/toggle.rs deleted file mode 100644 index 2d56c06e55..0000000000 --- a/crates/ui2/src/components/toggle.rs +++ /dev/null @@ -1,41 +0,0 @@ -/// Whether the entry is toggleable, and if so, whether it is currently toggled. -/// -/// To make an element toggleable, simply add a `Toggle::Toggled(_)` and handle it's cases. -/// -/// You can check if an element is toggleable with `.is_toggleable()` -/// -/// Possible values: -/// - `Toggle::NotToggleable` - The entry is not toggleable -/// - `Toggle::Toggled(true)` - The entry is toggleable and toggled -/// - `Toggle::Toggled(false)` - The entry is toggleable and not toggled -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum Toggle { - NotToggleable, - Toggled(bool), -} - -impl Toggle { - /// Returns true if the entry is toggled (or is not toggleable.) - /// - /// As element that isn't toggleable is always "expanded" or "enabled" - /// returning true in that case makes sense. - pub fn is_toggled(&self) -> bool { - match self { - Self::Toggled(false) => false, - _ => true, - } - } - - pub fn is_toggleable(&self) -> bool { - match self { - Self::Toggled(_) => true, - _ => false, - } - } -} - -impl From for Toggle { - fn from(toggled: bool) -> Self { - Toggle::Toggled(toggled) - } -} diff --git a/crates/ui2/src/toggleable.rs b/crates/ui2/src/toggleable.rs new file mode 100644 index 0000000000..99c2df0b0d --- /dev/null +++ b/crates/ui2/src/toggleable.rs @@ -0,0 +1,38 @@ +/// Whether an element is able to be toggled. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] +pub enum Toggleable { + Toggleable(ToggleState), + NotToggleable, +} + +/// The current state of a [`Toggleable`] element. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] +pub enum ToggleState { + Toggled, + NotToggled, +} + +impl ToggleState { + /// Returns whether an entry is toggled. + pub fn is_toggled(&self) -> bool { + match self { + ToggleState::Toggled => true, + ToggleState::NotToggled => false, + } + } +} + +impl From for ToggleState { + fn from(toggled: bool) -> Self { + match toggled { + true => Self::Toggled, + false => Self::NotToggled, + } + } +} + +impl From for bool { + fn from(value: ToggleState) -> Self { + value.is_toggled() + } +} diff --git a/crates/ui2/src/ui2.rs b/crates/ui2/src/ui2.rs index 6c5669741b..997abe4bd6 100644 --- a/crates/ui2/src/ui2.rs +++ b/crates/ui2/src/ui2.rs @@ -20,6 +20,7 @@ pub mod prelude; mod selectable; mod styled_ext; mod styles; +mod toggleable; pub mod utils; pub use clickable::*; @@ -30,3 +31,4 @@ pub use prelude::*; pub use selectable::*; pub use styled_ext::*; pub use styles::*; +pub use toggleable::*;