audio_processor_iced_design_system/
style.rs

1// Augmented Audio: Audio libraries and applications
2// Copyright (c) 2022 Pedro Tacla Yamada
3//
4// The MIT License (MIT)
5//
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to deal
8// in the Software without restriction, including without limitation the rights
9// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10// copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12//
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15//
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22// THE SOFTWARE.
23pub use button::Button;
24pub use button::ChromelessButton;
25pub use container::Container0;
26pub use container::Container1;
27pub use hover_container::HoverContainer;
28pub use pane_grid::PaneGrid;
29pub use pick_list::PickList;
30pub use rule::Rule;
31
32pub mod button {
33    use iced::widget::button::Appearance;
34    use iced::Color;
35    use iced_style::{Background, Theme};
36
37    use crate::colors::Colors;
38
39    pub fn button_base_style() -> Appearance {
40        Appearance {
41            shadow_offset: Default::default(),
42            background: Some(Background::Color(Colors::background_level0())),
43            border_radius: 0.0,
44            border_width: 1.0,
45            border_color: Colors::border_color(),
46            text_color: Colors::text(),
47        }
48    }
49
50    pub struct Button {
51        active_style: Appearance,
52        hovered_style: Appearance,
53        pressed_style: Appearance,
54        disabled_style: Appearance,
55    }
56
57    impl Button {
58        pub fn set_active(mut self, style: Appearance) -> Self {
59            self.active_style = style;
60            self
61        }
62
63        pub fn set_hovered(mut self, style: Appearance) -> Self {
64            self.hovered_style = style;
65            self
66        }
67
68        pub fn set_pressed(mut self, style: Appearance) -> Self {
69            self.pressed_style = style;
70            self
71        }
72
73        pub fn disabled(mut self, style: Appearance) -> Self {
74            self.disabled_style = style;
75            self
76        }
77    }
78
79    impl Default for Button {
80        fn default() -> Self {
81            Self::new(true)
82        }
83    }
84
85    impl Button {
86        pub fn new(bordered: bool) -> Self {
87            Button {
88                active_style: Appearance {
89                    border_width: if bordered { 1.0 } else { 0.0 },
90                    ..button_base_style()
91                },
92                hovered_style: Appearance {
93                    background: Some(Background::Color(Colors::hover_opacity(
94                        Colors::background_level0(),
95                    ))),
96                    border_color: Colors::active_border_color(),
97                    border_width: if bordered { 1.0 } else { 0.0 },
98                    ..button_base_style()
99                },
100                pressed_style: Appearance {
101                    background: Some(Background::Color(Colors::pressed_opacity(
102                        Colors::background_level0(),
103                    ))),
104                    border_color: Colors::pressed_opacity(Colors::active_border_color()),
105                    text_color: Colors::hover_opacity(Colors::text()),
106                    border_width: if bordered { 1.0 } else { 0.0 },
107                    ..button_base_style()
108                },
109                disabled_style: Appearance {
110                    border_width: if bordered { 1.0 } else { 0.0 },
111                    ..button_base_style()
112                },
113            }
114        }
115    }
116
117    impl From<Button> for iced::theme::Button {
118        fn from(value: Button) -> Self {
119            Self::Custom(Box::new(value))
120        }
121    }
122
123    impl iced::widget::button::StyleSheet for Button {
124        type Style = Theme;
125
126        fn active(&self, _style: &Self::Style) -> Appearance {
127            self.active_style
128        }
129
130        fn hovered(&self, _style: &Self::Style) -> Appearance {
131            self.hovered_style
132        }
133
134        fn pressed(&self, _style: &Self::Style) -> Appearance {
135            self.pressed_style
136        }
137
138        fn disabled(&self, _style: &Self::Style) -> Appearance {
139            self.disabled_style
140        }
141    }
142
143    pub struct ChromelessButton;
144
145    impl From<ChromelessButton> for iced::theme::Button {
146        fn from(value: ChromelessButton) -> Self {
147            Self::Custom(Box::new(value))
148        }
149    }
150
151    impl iced::widget::button::StyleSheet for ChromelessButton {
152        type Style = Theme;
153
154        fn active(&self, _style: &Self::Style) -> Appearance {
155            Appearance {
156                shadow_offset: Default::default(),
157                background: None,
158                border_radius: 0.0,
159                border_width: 0.0,
160                border_color: Default::default(),
161                text_color: Color::new(1.0, 1.0, 1.0, 0.8),
162            }
163        }
164
165        fn hovered(&self, _style: &Self::Style) -> Appearance {
166            Appearance {
167                shadow_offset: Default::default(),
168                background: None,
169                border_radius: 0.0,
170                border_width: 0.0,
171                border_color: Default::default(),
172                text_color: Color::new(1.0, 1.0, 1.0, 0.5),
173            }
174        }
175
176        fn pressed(&self, _style: &Self::Style) -> Appearance {
177            Appearance {
178                shadow_offset: Default::default(),
179                background: None,
180                border_radius: 0.0,
181                border_width: 0.0,
182                border_color: Default::default(),
183                text_color: Color::new(1.0, 1.0, 1.0, 0.8),
184            }
185        }
186
187        fn disabled(&self, _style: &Self::Style) -> Appearance {
188            Appearance {
189                shadow_offset: Default::default(),
190                background: None,
191                border_radius: 0.0,
192                border_width: 0.0,
193                border_color: Default::default(),
194                text_color: Color::new(1.0, 1.0, 1.0, 0.8),
195            }
196        }
197    }
198}
199
200pub mod pane_grid {
201    use iced::widget::pane_grid;
202    use iced::widget::pane_grid::Line;
203    use iced_style::Theme;
204
205    use crate::colors::Colors;
206
207    pub struct PaneGrid;
208
209    impl From<PaneGrid> for iced_native::theme::PaneGrid {
210        fn from(value: PaneGrid) -> Self {
211            Self::Custom(Box::new(value))
212        }
213    }
214
215    impl pane_grid::StyleSheet for PaneGrid {
216        type Style = Theme;
217
218        fn picked_split(&self, _style: &Self::Style) -> Option<Line> {
219            Some(Line {
220                color: Colors::active_border_color(),
221                width: 2.0,
222            })
223        }
224
225        fn hovered_split(&self, _style: &Self::Style) -> Option<Line> {
226            Some(Line {
227                color: Colors::active_border_color(),
228                width: 2.0,
229            })
230        }
231    }
232}
233
234pub mod rule {
235    use iced::widget::rule;
236    use iced_style::Theme;
237
238    use crate::colors::Colors;
239
240    pub struct Rule;
241
242    impl From<Rule> for iced::theme::Rule {
243        fn from(value: Rule) -> Self {
244            Self::Custom(Box::new(value))
245        }
246    }
247
248    impl rule::StyleSheet for Rule {
249        type Style = Theme;
250
251        fn appearance(&self, _style: &Self::Style) -> rule::Appearance {
252            rule::Appearance {
253                color: Colors::border_color(),
254                width: 1,
255                radius: 0.0,
256                fill_mode: rule::FillMode::Full,
257            }
258        }
259    }
260}
261
262pub mod pick_list {
263    use iced::widget::pick_list;
264    use iced::widget::pick_list::Appearance;
265    use iced_style::{Background, Theme};
266    use std::rc::Rc;
267
268    use crate::colors::Colors;
269
270    pub struct PickList;
271
272    impl From<PickList> for iced::theme::PickList {
273        fn from(pick_list: PickList) -> iced_style::theme::PickList {
274            let t = Rc::new(pick_list);
275            // TODO: This is broken
276            iced_style::theme::PickList::Custom(t.clone(), t)
277        }
278    }
279
280    impl iced_style::menu::StyleSheet for PickList {
281        type Style = Theme;
282
283        fn appearance(&self, _style: &Self::Style) -> iced_style::menu::Appearance {
284            iced_style::menu::Appearance {
285                text_color: Colors::text(),
286                background: Background::Color(Colors::background_level0()),
287                border_width: 1.0,
288                border_radius: 0.0,
289                border_color: Colors::border_color(),
290                selected_text_color: Colors::text(),
291                selected_background: Background::Color(Colors::selected_background()),
292            }
293        }
294    }
295
296    impl pick_list::StyleSheet for PickList {
297        type Style = Theme;
298
299        fn active(&self, _style: &Self::Style) -> Appearance {
300            Appearance {
301                text_color: Colors::text(),
302                placeholder_color: Default::default(),
303                handle_color: Default::default(),
304                background: Background::Color(Colors::background_level0()),
305                border_radius: 0.0,
306                border_width: 1.0,
307                border_color: Colors::border_color(),
308            }
309        }
310
311        fn hovered(&self, _style: &Self::Style) -> Appearance {
312            Appearance {
313                text_color: Colors::text(),
314                handle_color: Default::default(),
315                placeholder_color: Default::default(),
316                background: Background::Color(Colors::hover_opacity(Colors::background_level0())),
317                border_radius: 0.0,
318                border_width: 1.0,
319                border_color: Colors::selected_background(),
320            }
321        }
322    }
323}
324
325pub mod container {
326    use iced::widget::container::Appearance;
327    use iced::Background;
328    use iced_style::Theme;
329
330    use crate::colors::Colors;
331
332    pub struct Container0 {
333        border_width: f32,
334        border_radius: f32,
335    }
336
337    impl Default for Container0 {
338        fn default() -> Self {
339            Self {
340                border_width: 0.0,
341                border_radius: 0.0,
342            }
343        }
344    }
345
346    impl Container0 {
347        pub fn border_width(mut self, border_width: f32) -> Self {
348            self.border_width = border_width;
349            self
350        }
351
352        pub fn border_radius(mut self, border_radius: f32) -> Self {
353            self.border_radius = border_radius;
354            self
355        }
356    }
357
358    impl From<Container0> for iced::theme::Container {
359        fn from(value: Container0) -> Self {
360            Self::Custom(Box::new(value))
361        }
362    }
363
364    impl iced::widget::container::StyleSheet for Container0 {
365        type Style = Theme;
366
367        fn appearance(&self, _style: &Self::Style) -> Appearance {
368            Appearance {
369                text_color: Some(Colors::text()),
370                background: Some(Background::Color(Colors::background_level0())),
371                border_radius: self.border_radius,
372                border_width: self.border_width,
373                border_color: Colors::border_color(),
374            }
375        }
376    }
377
378    pub struct Container1 {
379        border_width: f32,
380    }
381
382    impl Default for Container1 {
383        fn default() -> Self {
384            Self::new()
385        }
386    }
387
388    impl Container1 {
389        pub fn new() -> Self {
390            Container1 { border_width: 0.0 }
391        }
392
393        pub fn border(mut self) -> Self {
394            self.border_width = 1.0;
395            self
396        }
397    }
398
399    impl From<Container1> for iced::theme::Container {
400        fn from(value: Container1) -> Self {
401            Self::Custom(Box::new(value))
402        }
403    }
404
405    impl iced::widget::container::StyleSheet for Container1 {
406        type Style = Theme;
407
408        fn appearance(&self, _style: &Self::Style) -> Appearance {
409            Appearance {
410                text_color: Some(Colors::text()),
411                background: Some(Background::Color(Colors::background_level1())),
412                border_radius: 0.0,
413                border_width: self.border_width,
414                border_color: Colors::border_color(),
415            }
416        }
417    }
418}
419
420mod hover_container {
421    use crate::colors::Colors;
422    use crate::container::hover_container::style::Style;
423    use crate::container::hover_container::style::StyleSheet;
424
425    #[derive(Default)]
426    pub struct HoverContainer;
427
428    impl StyleSheet for HoverContainer {
429        fn style(&self) -> Style {
430            Style {
431                text_color: None,
432                background: None,
433                border_radius: 0.0,
434                border_width: 0.0,
435                border_color: Colors::border_color(),
436            }
437        }
438
439        fn hovered(&self) -> Style {
440            Style {
441                text_color: None,
442                background: None,
443                border_radius: 0.0,
444                border_width: 1.0,
445                border_color: Colors::border_color(),
446            }
447        }
448    }
449}
450
451pub mod v_slider {
452    use iced_audio::v_slider::{Appearance, RectAppearance};
453    use iced_style::Theme;
454
455    use crate::colors::Colors;
456
457    pub struct VSlider;
458
459    impl iced_audio::style::v_slider::StyleSheet for VSlider {
460        type Style = Theme;
461
462        fn active(&self, _style: &Self::Style) -> Appearance {
463            Appearance::Rect(RectAppearance {
464                back_color: Colors::background_level0(),
465                back_border_width: 1.0,
466                back_border_radius: 0.0,
467                back_border_color: Colors::border_color(),
468                filled_color: Colors::active_border_color(),
469                handle_color: Colors::hover_opacity(Colors::text()),
470                handle_height: 5,
471                handle_filled_gap: 2.0,
472            })
473        }
474
475        fn hovered(&self, _style: &Self::Style) -> Appearance {
476            Appearance::Rect(RectAppearance {
477                back_color: Colors::background_level0(),
478                back_border_width: 1.0,
479                back_border_radius: 0.0,
480                back_border_color: Colors::border_color(),
481                filled_color: Colors::active_border_color(),
482                handle_color: Colors::text(),
483                handle_height: 5,
484                handle_filled_gap: 2.0,
485            })
486        }
487
488        fn dragging(&self, _style: &Self::Style) -> Appearance {
489            Appearance::Rect(RectAppearance {
490                back_color: Colors::background_level0(),
491                back_border_width: 1.0,
492                back_border_radius: 0.0,
493                back_border_color: Colors::border_color(),
494                filled_color: Colors::active_border_color(),
495                handle_color: Colors::text(),
496                handle_height: 5,
497                handle_filled_gap: 2.0,
498            })
499        }
500    }
501}