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