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