freya_components/
titlebar.rs1use freya_core::prelude::*;
2use torin::size::Size;
3
4use crate::{
5 define_theme,
6 get_theme,
7};
8
9define_theme! {
10 %[component]
11 pub TitlebarButton {
12 %[fields]
13 background: Color,
14 hover_background: Color,
15 corner_radius: CornerRadius,
16 width: Size,
17 height: Size,
18 }
19}
20
21#[derive(Clone, PartialEq, Copy)]
22pub enum TitlebarAction {
23 Minimize,
24 Maximize,
25 Close,
26}
27
28#[derive(PartialEq)]
30pub struct TitlebarButton {
31 pub(crate) theme: Option<TitlebarButtonThemePartial>,
32 pub(crate) action: TitlebarAction,
33 pub(crate) on_press: Option<EventHandler<Event<PressEventData>>>,
34 key: DiffKey,
35}
36
37impl KeyExt for TitlebarButton {
38 fn write_key(&mut self) -> &mut DiffKey {
39 &mut self.key
40 }
41}
42
43impl TitlebarButton {
44 pub fn new(action: TitlebarAction) -> Self {
45 Self {
46 theme: None,
47 action,
48 on_press: None,
49 key: DiffKey::None,
50 }
51 }
52
53 pub fn on_press(mut self, on_press: impl Into<EventHandler<Event<PressEventData>>>) -> Self {
54 self.on_press = Some(on_press.into());
55 self
56 }
57}
58
59impl Component for TitlebarButton {
60 fn render(&self) -> impl IntoElement {
61 let mut hovering = use_state(|| false);
62 let theme = get_theme!(
63 &self.theme,
64 TitlebarButtonThemePreference,
65 "titlebar_button"
66 );
67
68 let icon_svg = match self.action {
69 TitlebarAction::Minimize => {
70 r#"<svg viewBox="0 0 12 12"><rect x="1" y="5" width="10" height="2" fill="currentColor"/></svg>"#
71 }
72 TitlebarAction::Maximize => {
73 r#"<svg viewBox="0 0 12 12"><rect x="2" y="2" width="8" height="8" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>"#
74 }
75 TitlebarAction::Close => {
76 r#"<svg viewBox="0 0 12 12"><path d="M3 3l6 6M9 3l-6 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>"#
77 }
78 };
79
80 let icon = svg(Bytes::from_static(icon_svg.as_bytes()))
81 .width(Size::px(12.))
82 .height(Size::px(12.));
83
84 let background = if hovering() {
85 theme.hover_background
86 } else {
87 theme.background
88 };
89
90 rect()
91 .width(theme.width)
92 .height(theme.height)
93 .background(background)
94 .center()
95 .on_pointer_enter(move |_| {
96 hovering.set(true);
97 })
98 .on_pointer_leave(move |_| {
99 hovering.set(false);
100 })
101 .map(self.on_press.clone(), |el, on_press| el.on_press(on_press))
102 .child(icon)
103 }
104
105 fn render_key(&self) -> DiffKey {
106 self.key.clone().or(self.default_key())
107 }
108}