toggle_dock_button.rs

  1use gpui::{
  2    elements::{Empty, MouseEventHandler, Svg},
  3    CursorStyle, Element, ElementBox, Entity, MouseButton, View, ViewContext, ViewHandle,
  4    WeakViewHandle,
  5};
  6use settings::Settings;
  7
  8use crate::{handle_dropped_item, StatusItemView, Workspace};
  9
 10use super::{icon_for_dock_anchor, FocusDock, HideDock};
 11
 12pub struct ToggleDockButton {
 13    workspace: WeakViewHandle<Workspace>,
 14}
 15
 16impl ToggleDockButton {
 17    pub fn new(workspace: ViewHandle<Workspace>, cx: &mut ViewContext<Self>) -> Self {
 18        // When dock moves, redraw so that the icon and toggle status matches.
 19        cx.subscribe(&workspace, |_, _, _, cx| cx.notify()).detach();
 20
 21        Self {
 22            workspace: workspace.downgrade(),
 23        }
 24    }
 25}
 26
 27impl Entity for ToggleDockButton {
 28    type Event = ();
 29}
 30
 31impl View for ToggleDockButton {
 32    fn ui_name() -> &'static str {
 33        "Dock Toggle"
 34    }
 35
 36    fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
 37        let workspace = self.workspace.upgrade(cx);
 38
 39        if workspace.is_none() {
 40            return Empty::new().boxed();
 41        }
 42
 43        let workspace = workspace.unwrap();
 44        let dock_position = workspace.read(cx).dock.position;
 45        let dock_pane = workspace.read(cx.app).dock_pane().clone();
 46
 47        let theme = cx.global::<Settings>().theme.clone();
 48
 49        let button = MouseEventHandler::<Self>::new(0, cx, {
 50            let theme = theme.clone();
 51            move |state, _| {
 52                let style = theme
 53                    .workspace
 54                    .status_bar
 55                    .sidebar_buttons
 56                    .item
 57                    .style_for(state, dock_position.is_visible());
 58
 59                Svg::new(icon_for_dock_anchor(dock_position.anchor()))
 60                    .with_color(style.icon_color)
 61                    .constrained()
 62                    .with_width(style.icon_size)
 63                    .with_height(style.icon_size)
 64                    .contained()
 65                    .with_style(style.container)
 66                    .boxed()
 67            }
 68        })
 69        .with_cursor_style(CursorStyle::PointingHand)
 70        .on_up(MouseButton::Left, move |event, cx| {
 71            let drop_index = dock_pane.read(cx.app).items_len() + 1;
 72            handle_dropped_item(event, &dock_pane.downgrade(), drop_index, false, None, cx);
 73        });
 74
 75        if dock_position.is_visible() {
 76            button
 77                .on_click(MouseButton::Left, |_, cx| {
 78                    cx.dispatch_action(HideDock);
 79                })
 80                .with_tooltip::<Self, _>(
 81                    0,
 82                    "Hide Dock".into(),
 83                    Some(Box::new(HideDock)),
 84                    theme.tooltip.clone(),
 85                    cx,
 86                )
 87        } else {
 88            button
 89                .on_click(MouseButton::Left, |_, cx| {
 90                    cx.dispatch_action(FocusDock);
 91                })
 92                .with_tooltip::<Self, _>(
 93                    0,
 94                    "Focus Dock".into(),
 95                    Some(Box::new(FocusDock)),
 96                    theme.tooltip.clone(),
 97                    cx,
 98                )
 99        }
100        .boxed()
101    }
102}
103
104impl StatusItemView for ToggleDockButton {
105    fn set_active_pane_item(
106        &mut self,
107        _active_pane_item: Option<&dyn crate::ItemHandle>,
108        _cx: &mut ViewContext<Self>,
109    ) {
110        //Not applicable
111    }
112}