linux_window_controls.rs

  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}