use gpui::{svg, Action, Hsla}; use ui::prelude::*; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] pub enum WindowControlType { Minimize, Restore, Maximize, Close, } impl WindowControlType { /// Returns the icon name for the window control type. /// /// Will take a [PlatformStyle] in the future to return a different /// icon name based on the platform. pub fn icon(&self) -> IconName { match self { WindowControlType::Minimize => IconName::GenericMinimize, WindowControlType::Restore => IconName::GenericRestore, WindowControlType::Maximize => IconName::GenericMaximize, WindowControlType::Close => IconName::GenericClose, } } } #[allow(unused)] pub struct WindowControlStyle { background: Hsla, background_hover: Hsla, icon: Hsla, icon_hover: Hsla, } impl WindowControlStyle { pub fn default(cx: &mut App) -> Self { let colors = cx.theme().colors(); Self { background: colors.ghost_element_background, background_hover: colors.ghost_element_hover, icon: colors.icon, icon_hover: colors.icon_muted, } } #[allow(unused)] /// Sets the background color of the control. pub fn background(mut self, color: impl Into) -> Self { self.background = color.into(); self } #[allow(unused)] /// Sets the background color of the control when hovered. pub fn background_hover(mut self, color: impl Into) -> Self { self.background_hover = color.into(); self } #[allow(unused)] /// Sets the color of the icon. pub fn icon(mut self, color: impl Into) -> Self { self.icon = color.into(); self } #[allow(unused)] /// Sets the color of the icon when hovered. pub fn icon_hover(mut self, color: impl Into) -> Self { self.icon_hover = color.into(); self } } #[derive(IntoElement)] pub struct WindowControl { id: ElementId, icon: WindowControlType, style: WindowControlStyle, close_action: Option>, } impl WindowControl { pub fn new(id: impl Into, icon: WindowControlType, cx: &mut App) -> Self { let style = WindowControlStyle::default(cx); Self { id: id.into(), icon, style, close_action: None, } } pub fn new_close( id: impl Into, icon: WindowControlType, close_action: Box, cx: &mut App, ) -> Self { let style = WindowControlStyle::default(cx); Self { id: id.into(), icon, style, close_action: Some(close_action.boxed_clone()), } } #[allow(unused)] pub fn custom_style( id: impl Into, icon: WindowControlType, style: WindowControlStyle, ) -> Self { Self { id: id.into(), icon, style, close_action: None, } } } impl RenderOnce for WindowControl { fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement { let icon = svg() .size_4() .flex_none() .path(self.icon.icon().path()) .text_color(self.style.icon) .group_hover("", |this| this.text_color(self.style.icon_hover)); h_flex() .id(self.id) .group("") .cursor_pointer() .justify_center() .content_center() .rounded_2xl() .w_5() .h_5() .hover(|this| this.bg(self.style.background_hover)) .active(|this| this.bg(self.style.background_hover)) .child(icon) .on_mouse_move(|_, _, cx| cx.stop_propagation()) .on_click(move |_, window, cx| { cx.stop_propagation(); match self.icon { WindowControlType::Minimize => window.minimize_window(), WindowControlType::Restore => window.zoom_window(), WindowControlType::Maximize => window.zoom_window(), WindowControlType::Close => window.dispatch_action( self.close_action .as_ref() .expect("Use WindowControl::new_close() for close control.") .boxed_clone(), cx, ), } }) } }