1use crate::widget::segmented_button::{Appearance, ItemAppearance, StyleSheet};
7use crate::{theme::Theme, widget::segmented_button::ItemStatusAppearance};
8use cosmic_theme::{Component, Container};
9use iced_core::{Background, border::Radius};
10
11#[derive(Default)]
12pub enum SegmentedButton {
13 #[default]
15 TabBar,
16 Control,
18 Custom(Box<dyn Fn(&Theme) -> Appearance>),
20}
21
22impl StyleSheet for Theme {
23 type Style = SegmentedButton;
24
25 #[allow(clippy::too_many_lines)]
26 fn horizontal(&self, style: &Self::Style) -> Appearance {
27 let container = &self.current_container();
28
29 match style {
30 SegmentedButton::TabBar => {
31 let cosmic = self.cosmic();
32 let active = horizontal::tab_bar_active(cosmic);
33 let hc = cosmic.is_high_contrast;
34 let (border_end, border_start, border_top) = if hc {
35 (
36 Some((1., container.component.border.into())),
37 Some((1., container.component.border.into())),
38 Some((1., container.component.border.into())),
39 )
40 } else {
41 (None, None, None)
42 };
43 Appearance {
44 border_radius: cosmic.corner_radii.radius_0.into(),
45 inactive: ItemStatusAppearance {
46 background: None,
47 first: ItemAppearance {
48 border_radius: cosmic.corner_radii.radius_0.into(),
49 border_bottom: Some((1.0, cosmic.accent.base.into())),
50 border_end,
51 border_start,
52 border_top,
53 },
54 middle: ItemAppearance {
55 border_radius: cosmic.corner_radii.radius_0.into(),
56 border_bottom: Some((1.0, cosmic.accent.base.into())),
57 border_end,
58 border_start,
59 border_top,
60 },
61 last: ItemAppearance {
62 border_radius: cosmic.corner_radii.radius_0.into(),
63 border_bottom: Some((1.0, cosmic.accent.base.into())),
64 border_end,
65 border_start,
66 border_top,
67 },
68 text_color: container.component.on.into(),
69 },
70 hover: hover(cosmic, &container.component, &active),
71 focus: focus(cosmic, container, &active),
72 active,
73 ..Default::default()
74 }
75 }
76 SegmentedButton::Control => {
77 let cosmic = self.cosmic();
78 let active = horizontal::selection_active(cosmic, &container.component);
79 let rad_m = cosmic.corner_radii.radius_m;
80 let rad_0 = cosmic.corner_radii.radius_0;
81 Appearance {
82 background: Some(Background::Color(container.small_widget.into())),
83 border_radius: rad_m.into(),
84 inactive: ItemStatusAppearance {
85 background: None,
86 first: ItemAppearance {
87 border_radius: Radius::from([rad_m[0], rad_0[1], rad_0[2], rad_m[3]]),
88 ..Default::default()
89 },
90 middle: ItemAppearance {
91 border_radius: cosmic.corner_radii.radius_0.into(),
92 ..Default::default()
93 },
94 last: ItemAppearance {
95 border_radius: Radius::from([rad_0[0], rad_m[1], rad_m[2], rad_0[3]]),
96 ..Default::default()
97 },
98 text_color: container.component.on.into(),
99 },
100 hover: hover(cosmic, &container.component, &active),
101 focus: focus(cosmic, container, &active),
102 active,
103 ..Default::default()
104 }
105 }
106 SegmentedButton::Custom(func) => func(self),
107 }
108 }
109
110 #[allow(clippy::too_many_lines)]
111 fn vertical(&self, style: &Self::Style) -> Appearance {
112 let cosmic = self.cosmic();
113 let rad_m = cosmic.corner_radii.radius_m;
114 let rad_0 = cosmic.corner_radii.radius_0;
115 match style {
116 SegmentedButton::TabBar => {
117 let container = &self.cosmic().primary;
118 let active = vertical::tab_bar_active(cosmic);
119 Appearance {
120 border_radius: cosmic.corner_radii.radius_0.into(),
121 inactive: ItemStatusAppearance {
122 background: None,
123 text_color: container.component.on.into(),
124 ..active
125 },
126 hover: hover(cosmic, &container.component, &active),
127 focus: focus(cosmic, container, &active),
128 active,
129 ..Default::default()
130 }
131 }
132 SegmentedButton::Control => {
133 let container = self.current_container();
134 let active = vertical::selection_active(cosmic, &container.component);
135 Appearance {
136 background: Some(Background::Color(container.small_widget.into())),
137 border_radius: rad_m.into(),
138 inactive: ItemStatusAppearance {
139 background: None,
140 first: ItemAppearance {
141 border_radius: Radius::from([rad_m[0], rad_m[1], rad_0[0], rad_0[0]]),
142 ..Default::default()
143 },
144 middle: ItemAppearance {
145 border_radius: cosmic.corner_radii.radius_0.into(),
146 ..Default::default()
147 },
148 last: ItemAppearance {
149 border_radius: Radius::from([rad_0[0], rad_0[1], rad_m[2], rad_m[3]]),
150 ..Default::default()
151 },
152 text_color: container.component.on.into(),
153 },
154 hover: hover(cosmic, &container.component, &active),
155 focus: focus(cosmic, container, &active),
156 active,
157 ..Default::default()
158 }
159 }
160 SegmentedButton::Custom(func) => func(self),
161 }
162 }
163}
164
165mod horizontal {
166 use crate::widget::segmented_button::{ItemAppearance, ItemStatusAppearance};
167 use cosmic_theme::Component;
168 use iced_core::{Background, border::Radius};
169
170 pub fn selection_active(
171 cosmic: &cosmic_theme::Theme,
172 component: &Component,
173 ) -> ItemStatusAppearance {
174 let mut color = cosmic.palette.neutral_5;
175 color.alpha = 0.2;
176
177 let rad_m = cosmic.corner_radii.radius_m;
178 let rad_0 = cosmic.corner_radii.radius_0;
179
180 ItemStatusAppearance {
181 background: Some(Background::Color(color.into())),
182 first: ItemAppearance {
183 border_radius: Radius::from([rad_m[0], rad_0[1], rad_0[2], rad_m[3]]),
184 ..Default::default()
185 },
186 middle: ItemAppearance {
187 border_radius: cosmic.corner_radii.radius_0.into(),
188 ..Default::default()
189 },
190 last: ItemAppearance {
191 border_radius: Radius::from([rad_0[0], rad_m[1], rad_m[2], rad_0[3]]),
192 ..Default::default()
193 },
194 text_color: cosmic.accent.base.into(),
195 }
196 }
197
198 pub fn tab_bar_active(cosmic: &cosmic_theme::Theme) -> ItemStatusAppearance {
199 let mut neutral_5 = cosmic.palette.neutral_5;
200 neutral_5.alpha = 0.2;
201 let rad_s = cosmic.corner_radii.radius_s;
202 let rad_0 = cosmic.corner_radii.radius_0;
203 ItemStatusAppearance {
204 background: Some(Background::Color(neutral_5.into())),
205 first: ItemAppearance {
206 border_radius: Radius::from([rad_s[0], rad_s[1], rad_0[2], rad_0[3]]),
207 border_bottom: Some((4.0, cosmic.accent.base.into())),
208 ..Default::default()
209 },
210 middle: ItemAppearance {
211 border_radius: Radius::from([rad_s[0], rad_s[1], rad_0[2], rad_0[3]]),
212 border_bottom: Some((4.0, cosmic.accent.base.into())),
213 ..Default::default()
214 },
215 last: ItemAppearance {
216 border_radius: Radius::from([rad_s[0], rad_s[1], rad_0[2], rad_0[3]]),
217 border_bottom: Some((4.0, cosmic.accent.base.into())),
218 ..Default::default()
219 },
220 text_color: cosmic.accent.base.into(),
221 }
222 }
223}
224
225pub fn focus(
226 cosmic: &cosmic_theme::Theme,
227 container: &Container,
228 default: &ItemStatusAppearance,
229) -> ItemStatusAppearance {
230 let color = container.small_widget;
231 ItemStatusAppearance {
232 background: Some(Background::Color(color.into())),
233 text_color: cosmic.accent.base.into(),
234 ..*default
235 }
236}
237
238pub fn hover(
239 cosmic: &cosmic_theme::Theme,
240 component: &Component,
241 default: &ItemStatusAppearance,
242) -> ItemStatusAppearance {
243 let mut color = cosmic.palette.neutral_8;
244 color.alpha = 0.2;
245 ItemStatusAppearance {
246 background: Some(Background::Color(color.into())),
247 text_color: cosmic.accent.base.into(),
248 ..*default
249 }
250}
251
252mod vertical {
253 use crate::widget::segmented_button::{ItemAppearance, ItemStatusAppearance};
254 use cosmic_theme::Component;
255 use iced_core::{Background, border::Radius};
256
257 pub fn selection_active(
258 cosmic: &cosmic_theme::Theme,
259 component: &Component,
260 ) -> ItemStatusAppearance {
261 let mut color = component.selected_state_color();
262 color.alpha = 0.3;
263
264 let rad_0 = cosmic.corner_radii.radius_0;
265 let rad_m = cosmic.corner_radii.radius_m;
266
267 ItemStatusAppearance {
268 background: Some(Background::Color(color.into())),
269 first: ItemAppearance {
270 border_radius: Radius::from([rad_m[0], rad_m[1], rad_0[2], rad_0[3]]),
271 ..Default::default()
272 },
273 middle: ItemAppearance {
274 border_radius: cosmic.corner_radii.radius_0.into(),
275 ..Default::default()
276 },
277 last: ItemAppearance {
278 border_radius: Radius::from([rad_0[0], rad_0[1], rad_m[2], rad_m[3]]),
279 ..Default::default()
280 },
281 text_color: cosmic.accent.base.into(),
282 }
283 }
284
285 pub fn tab_bar_active(cosmic: &cosmic_theme::Theme) -> ItemStatusAppearance {
286 let mut neutral_5 = cosmic.palette.neutral_5;
287 neutral_5.alpha = 0.2;
288 ItemStatusAppearance {
289 background: Some(Background::Color(neutral_5.into())),
290 first: ItemAppearance {
291 border_radius: cosmic.corner_radii.radius_m.into(),
292 ..Default::default()
293 },
294 middle: ItemAppearance {
295 border_radius: cosmic.corner_radii.radius_m.into(),
296 ..Default::default()
297 },
298 last: ItemAppearance {
299 border_radius: cosmic.corner_radii.radius_m.into(),
300 ..Default::default()
301 },
302 text_color: cosmic.accent.base.into(),
303 }
304 }
305}