1use gpui::{prelude::*, Action, Rgba, WindowAppearance};
2
3use crate::prelude::*;
4
5#[derive(IntoElement)]
6pub struct LinuxWindowControls {
7 button_height: Pixels,
8 close_window_action: Box<dyn Action>,
9}
10
11impl LinuxWindowControls {
12 pub fn new(button_height: Pixels, close_window_action: Box<dyn Action>) -> Self {
13 Self {
14 button_height,
15 close_window_action,
16 }
17 }
18}
19
20impl RenderOnce for LinuxWindowControls {
21 fn render(self, cx: &mut WindowContext) -> impl IntoElement {
22 let close_button_hover_color = Rgba {
23 r: 232.0 / 255.0,
24 g: 17.0 / 255.0,
25 b: 32.0 / 255.0,
26 a: 1.0,
27 };
28
29 let button_hover_color = match cx.appearance() {
30 WindowAppearance::Light | WindowAppearance::VibrantLight => Rgba {
31 r: 0.1,
32 g: 0.1,
33 b: 0.1,
34 a: 0.2,
35 },
36 WindowAppearance::Dark | WindowAppearance::VibrantDark => Rgba {
37 r: 0.9,
38 g: 0.9,
39 b: 0.9,
40 a: 0.1,
41 },
42 };
43
44 div()
45 .id("linux-window-controls")
46 .flex()
47 .flex_row()
48 .justify_center()
49 .content_stretch()
50 .max_h(self.button_height)
51 .min_h(self.button_height)
52 .child(TitlebarButton::new(
53 "minimize",
54 TitlebarButtonType::Minimize,
55 button_hover_color,
56 self.close_window_action.boxed_clone(),
57 ))
58 .child(TitlebarButton::new(
59 "maximize-or-restore",
60 if cx.is_maximized() {
61 TitlebarButtonType::Restore
62 } else {
63 TitlebarButtonType::Maximize
64 },
65 button_hover_color,
66 self.close_window_action.boxed_clone(),
67 ))
68 .child(TitlebarButton::new(
69 "close",
70 TitlebarButtonType::Close,
71 close_button_hover_color,
72 self.close_window_action,
73 ))
74 }
75}
76
77#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
78enum TitlebarButtonType {
79 Minimize,
80 Restore,
81 Maximize,
82 Close,
83}
84
85#[derive(IntoElement)]
86struct TitlebarButton {
87 id: ElementId,
88 icon: TitlebarButtonType,
89 hover_background_color: Rgba,
90 close_window_action: Box<dyn Action>,
91}
92
93impl TitlebarButton {
94 pub fn new(
95 id: impl Into<ElementId>,
96 icon: TitlebarButtonType,
97 hover_background_color: Rgba,
98 close_window_action: Box<dyn Action>,
99 ) -> Self {
100 Self {
101 id: id.into(),
102 icon,
103 hover_background_color,
104 close_window_action,
105 }
106 }
107}
108
109impl RenderOnce for TitlebarButton {
110 fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
111 let width = px(36.);
112
113 h_flex()
114 .id(self.id)
115 .justify_center()
116 .content_center()
117 .w(width)
118 .h_full()
119 .hover(|style| style.bg(self.hover_background_color))
120 .active(|style| {
121 let mut active_color = self.hover_background_color;
122 active_color.a *= 0.2;
123
124 style.bg(active_color)
125 })
126 .child(Icon::new(match self.icon {
127 TitlebarButtonType::Minimize => IconName::Dash,
128 TitlebarButtonType::Restore => IconName::Minimize,
129 TitlebarButtonType::Maximize => IconName::Maximize,
130 TitlebarButtonType::Close => IconName::Close,
131 }))
132 .on_mouse_move(|_, cx| cx.stop_propagation())
133 .on_click(move |_, cx| {
134 cx.stop_propagation();
135 match self.icon {
136 TitlebarButtonType::Minimize => cx.minimize_window(),
137 TitlebarButtonType::Restore => cx.zoom_window(),
138 TitlebarButtonType::Maximize => cx.zoom_window(),
139 TitlebarButtonType::Close => {
140 cx.dispatch_action(self.close_window_action.boxed_clone())
141 }
142 }
143 })
144 }
145}