1use gpui::{AnyView, ClickEvent};
2
3use crate::{prelude::*, ButtonLike, ButtonLikeRounding};
4
5/// The position of a [`ToggleButton`] within a group of buttons.
6#[derive(Debug, PartialEq, Eq, Clone, Copy)]
7pub enum ToggleButtonPosition {
8 /// The toggle button is first in the group.
9 First,
10
11 /// The toggle button is in the middle of the group (i.e., it is not the first or last toggle button).
12 Middle,
13
14 /// The toggle button is last in the group.
15 Last,
16}
17
18#[derive(IntoElement)]
19pub struct ToggleButton {
20 base: ButtonLike,
21 position_in_group: Option<ToggleButtonPosition>,
22 label: SharedString,
23 label_color: Option<Color>,
24}
25
26impl ToggleButton {
27 pub fn new(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self {
28 Self {
29 base: ButtonLike::new(id),
30 position_in_group: None,
31 label: label.into(),
32 label_color: None,
33 }
34 }
35
36 pub fn color(mut self, label_color: impl Into<Option<Color>>) -> Self {
37 self.label_color = label_color.into();
38 self
39 }
40
41 pub fn position_in_group(mut self, position: ToggleButtonPosition) -> Self {
42 self.position_in_group = Some(position);
43 self
44 }
45
46 pub fn first(self) -> Self {
47 self.position_in_group(ToggleButtonPosition::First)
48 }
49
50 pub fn middle(self) -> Self {
51 self.position_in_group(ToggleButtonPosition::Middle)
52 }
53
54 pub fn last(self) -> Self {
55 self.position_in_group(ToggleButtonPosition::Last)
56 }
57}
58
59impl Selectable for ToggleButton {
60 fn selected(mut self, selected: bool) -> Self {
61 self.base = self.base.selected(selected);
62 self
63 }
64}
65
66impl Disableable for ToggleButton {
67 fn disabled(mut self, disabled: bool) -> Self {
68 self.base = self.base.disabled(disabled);
69 self
70 }
71}
72
73impl Clickable for ToggleButton {
74 fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
75 self.base = self.base.on_click(handler);
76 self
77 }
78}
79
80impl ButtonCommon for ToggleButton {
81 fn id(&self) -> &ElementId {
82 self.base.id()
83 }
84
85 fn style(mut self, style: ButtonStyle) -> Self {
86 self.base = self.base.style(style);
87 self
88 }
89
90 fn size(mut self, size: ButtonSize) -> Self {
91 self.base = self.base.size(size);
92 self
93 }
94
95 fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
96 self.base = self.base.tooltip(tooltip);
97 self
98 }
99}
100
101impl RenderOnce for ToggleButton {
102 fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
103 let is_disabled = self.base.disabled;
104 let is_selected = self.base.selected;
105
106 let label_color = if is_disabled {
107 Color::Disabled
108 } else if is_selected {
109 Color::Selected
110 } else {
111 self.label_color.unwrap_or_default()
112 };
113
114 self.base
115 .when_some(self.position_in_group, |this, position| match position {
116 ToggleButtonPosition::First => this.rounding(ButtonLikeRounding::Left),
117 ToggleButtonPosition::Middle => this.rounding(None),
118 ToggleButtonPosition::Last => this.rounding(ButtonLikeRounding::Right),
119 })
120 .child(
121 Label::new(self.label)
122 .color(label_color)
123 .line_height_style(LineHeightStyle::UiLabel),
124 )
125 }
126}