diff --git a/assets/icons/panel-bottom.svg b/assets/icons/panel-bottom.svg new file mode 100644 index 00000000..ebe599c7 --- /dev/null +++ b/assets/icons/panel-bottom.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/panel-left.svg b/assets/icons/panel-left.svg new file mode 100644 index 00000000..2eed2667 --- /dev/null +++ b/assets/icons/panel-left.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/panel-right.svg b/assets/icons/panel-right.svg new file mode 100644 index 00000000..d29a4a51 --- /dev/null +++ b/assets/icons/panel-right.svg @@ -0,0 +1 @@ + diff --git a/crates/app/src/story_workspace.rs b/crates/app/src/story_workspace.rs index 0e00c91b..c1af7f9d 100644 --- a/crates/app/src/story_workspace.rs +++ b/crates/app/src/story_workspace.rs @@ -15,7 +15,7 @@ use ui::{ h_flex, popup_menu::PopupMenuExt, theme::{ActiveTheme, Colorize as _, Theme}, - ContextModal, IconName, Root, Sizable, + ContextModal, IconName, Root, Selectable, Sizable, }; use workspace::TitleBar; @@ -274,6 +274,61 @@ impl StoryWorkspace { Ok(window) }) } + + fn render_panel_buttons(&self, cx: &mut ViewContext) -> impl IntoElement { + let left_open = self + .dock_area + .read(cx) + .is_dock_open(ui::dock::DockPlacement::Left, cx); + let bottom_open = self + .dock_area + .read(cx) + .is_dock_open(ui::dock::DockPlacement::Bottom, cx); + let right_open = self + .dock_area + .read(cx) + .is_dock_open(ui::dock::DockPlacement::Right, cx); + + h_flex() + .mr_2() + .gap_1() + .child( + Button::new("panel-left") + .icon(IconName::PanelLeft) + .small() + .ghost() + .selected(left_open) + .on_click(cx.listener(move |this, _: &ClickEvent, cx| { + this.dock_area.update(cx, |dock_area, cx| { + dock_area.toggle_dock(ui::dock::DockPlacement::Left, cx); + }) + })), + ) + .child( + Button::new("panel-bottom") + .icon(IconName::PanelBottom) + .small() + .ghost() + .selected(bottom_open) + .on_click(cx.listener(move |this, _: &ClickEvent, cx| { + this.dock_area.update(cx, |dock_area, cx| { + dock_area.toggle_dock(ui::dock::DockPlacement::Bottom, cx); + }) + })), + ) + .child( + Button::new("panel-right") + .icon(IconName::PanelRight) + .small() + .ghost() + .selected(right_open) + .on_click(cx.listener(move |this, _: &ClickEvent, cx| { + this.dock_area.update(cx, |dock_area, cx| { + dock_area.toggle_dock(ui::dock::DockPlacement::Right, cx); + }) + })), + ) + } } pub fn open_new( @@ -324,6 +379,7 @@ impl Render for StoryWorkspace { .justify_end() .px_2() .gap_2() + .child(self.render_panel_buttons(cx)) .child(self.theme_color_picker.clone()) .child( Button::new("theme-mode") diff --git a/crates/ui/src/dock/dock.rs b/crates/ui/src/dock/dock.rs index a9b6b47b..a52ea28c 100644 --- a/crates/ui/src/dock/dock.rs +++ b/crates/ui/src/dock/dock.rs @@ -105,12 +105,6 @@ impl Dock { Self::new(dock_area, panels, DockPlacement::Right, cx) } - /// Set the Dock to be open. - pub fn open(mut self) -> Self { - self.open = true; - self - } - /// Set the Dock to be resizeable, default: true pub fn resizeable(mut self, resizeable: bool) -> Self { self.resizeable = resizeable; @@ -122,6 +116,15 @@ impl Dock { &self.panels } + pub fn is_open(&self) -> bool { + self.open + } + + pub fn toggle_open(&mut self, cx: &mut ViewContext) { + self.open = !self.open; + cx.notify(); + } + /// Returns the active panel index. pub fn active_ix(&self) -> usize { self.active_ix @@ -177,7 +180,6 @@ impl Dock { .occlude() .absolute() .flex_shrink_0() - .bg(gpui::transparent_white()) .when(self.placement.is_left(), |this| { // FIXME: Improve this to let the scroll bar have px(HANDLE_PADDING) this.cursor_col_resize() diff --git a/crates/ui/src/dock/mod.rs b/crates/ui/src/dock/mod.rs index c9980aa2..84835f16 100644 --- a/crates/ui/src/dock/mod.rs +++ b/crates/ui/src/dock/mod.rs @@ -253,6 +253,26 @@ impl DockArea { }); } + pub fn is_dock_open(&self, placement: DockPlacement, cx: &AppContext) -> bool { + match placement { + DockPlacement::Left => self.left_dock.read(cx).is_open(), + DockPlacement::Bottom => self.bottom_dock.read(cx).is_open(), + DockPlacement::Right => self.right_dock.read(cx).is_open(), + } + } + + pub fn toggle_dock(&self, placement: DockPlacement, cx: &mut ViewContext) { + let dock = match placement { + DockPlacement::Left => &self.left_dock, + DockPlacement::Bottom => &self.bottom_dock, + DockPlacement::Right => &self.right_dock, + }; + + dock.update(cx, |view, cx| { + view.toggle_open(cx); + }) + } + /// Dump the dock panels layout to DockItemState. /// /// See also `DockItemState::to_item` for the load DockItem from DockItemState. diff --git a/crates/ui/src/icon.rs b/crates/ui/src/icon.rs index c9dd751a..08a21694 100644 --- a/crates/ui/src/icon.rs +++ b/crates/ui/src/icon.rs @@ -43,6 +43,9 @@ pub enum IconName { Minus, Moon, Palette, + PanelBottom, + PanelLeft, + PanelRight, Plus, Search, SortAscending, @@ -105,6 +108,9 @@ impl IconName { IconName::ThumbsDown => "icons/thumbs-down.svg", IconName::ThumbsUp => "icons/thumbs-up.svg", IconName::TriangleAlert => "icons/triangle-alert.svg", + IconName::PanelLeft => "icons/panel-left.svg", + IconName::PanelBottom => "icons/panel-bottom.svg", + IconName::PanelRight => "icons/panel-right.svg", } .into() }