1use gpui::{prelude::*, Rgba, WindowAppearance};
2
3use crate::prelude::*;
4
5#[derive(IntoElement)]
6pub struct WindowsWindowControls {
7 button_height: Pixels,
8}
9
10impl WindowsWindowControls {
11 pub fn new(button_height: Pixels) -> Self {
12 Self { button_height }
13 }
14}
15
16impl RenderOnce for WindowsWindowControls {
17 fn render(self, cx: &mut WindowContext) -> impl IntoElement {
18 let close_button_hover_color = Rgba {
19 r: 232.0 / 255.0,
20 g: 17.0 / 255.0,
21 b: 32.0 / 255.0,
22 a: 1.0,
23 };
24
25 let button_hover_color = match cx.appearance() {
26 WindowAppearance::Light | WindowAppearance::VibrantLight => Rgba {
27 r: 0.1,
28 g: 0.1,
29 b: 0.1,
30 a: 0.2,
31 },
32 WindowAppearance::Dark | WindowAppearance::VibrantDark => Rgba {
33 r: 0.9,
34 g: 0.9,
35 b: 0.9,
36 a: 0.1,
37 },
38 };
39
40 div()
41 .id("windows-window-controls")
42 .flex()
43 .flex_row()
44 .justify_center()
45 .content_stretch()
46 .max_h(self.button_height)
47 .min_h(self.button_height)
48 .child(WindowsCaptionButton::new(
49 "minimize",
50 WindowsCaptionButtonIcon::Minimize,
51 button_hover_color,
52 ))
53 .child(WindowsCaptionButton::new(
54 "maximize-or-restore",
55 if cx.is_maximized() {
56 WindowsCaptionButtonIcon::Restore
57 } else {
58 WindowsCaptionButtonIcon::Maximize
59 },
60 button_hover_color,
61 ))
62 .child(WindowsCaptionButton::new(
63 "close",
64 WindowsCaptionButtonIcon::Close,
65 close_button_hover_color,
66 ))
67 }
68}
69
70#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
71enum WindowsCaptionButtonIcon {
72 Minimize,
73 Restore,
74 Maximize,
75 Close,
76}
77
78#[derive(IntoElement)]
79struct WindowsCaptionButton {
80 id: ElementId,
81 icon: WindowsCaptionButtonIcon,
82 hover_background_color: Rgba,
83}
84
85impl WindowsCaptionButton {
86 pub fn new(
87 id: impl Into<ElementId>,
88 icon: WindowsCaptionButtonIcon,
89 hover_background_color: Rgba,
90 ) -> Self {
91 Self {
92 id: id.into(),
93 icon,
94 hover_background_color,
95 }
96 }
97}
98
99impl RenderOnce for WindowsCaptionButton {
100 fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
101 // todo(windows) report this width to the Windows platform API
102 // NOTE: this is intentionally hard coded. An option to use the 'native' size
103 // could be added when the width is reported to the Windows platform API
104 // as this could change between future Windows versions.
105 let width = px(36.);
106
107 h_flex()
108 .id(self.id)
109 .justify_center()
110 .content_center()
111 .w(width)
112 .h_full()
113 .font_family("Segoe Fluent Icons")
114 .text_size(px(10.0))
115 .hover(|style| style.bg(self.hover_background_color))
116 .active(|style| {
117 let mut active_color = self.hover_background_color;
118 active_color.a *= 0.2;
119
120 style.bg(active_color)
121 })
122 .child(match self.icon {
123 WindowsCaptionButtonIcon::Minimize => "\u{e921}",
124 WindowsCaptionButtonIcon::Restore => "\u{e923}",
125 WindowsCaptionButtonIcon::Maximize => "\u{e922}",
126 WindowsCaptionButtonIcon::Close => "\u{e8bb}",
127 })
128 }
129}