Detailed changes
@@ -161,54 +161,10 @@
},
"cursor": "Arrow"
},
- "left_sidebar": {
- "width": 30,
- "background": "#26232a",
- "border": {
- "color": "#19171c",
- "width": 1,
- "right": true
- },
- "item": {
- "height": 32,
- "icon_color": "#8b8792",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#efecf4",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#19171c",
- "padding": {
- "left": 1
- }
- }
- },
- "right_sidebar": {
- "width": 30,
- "background": "#26232a",
- "border": {
- "color": "#19171c",
- "width": 1,
- "left": true
- },
- "item": {
- "height": 32,
- "icon_color": "#8b8792",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#efecf4",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#19171c",
- "padding": {
- "left": 1
- }
+ "sidebar_resize_handle": {
+ "background": "#19171c",
+ "padding": {
+ "left": 1
}
},
"pane_divider": {
@@ -252,6 +208,21 @@
"family": "Zed Sans",
"color": "#8b8792",
"size": 14
+ },
+ "sidebar_item": {
+ "height": 32,
+ "icon_color": "#8b8792",
+ "icon_size": 18
+ },
+ "sidebar_item_hover": {
+ "height": 32,
+ "icon_color": "#8b8792",
+ "icon_size": 18
+ },
+ "sidebar_item_active": {
+ "height": 32,
+ "icon_color": "#efecf4",
+ "icon_size": 18
}
},
"titlebar": {
@@ -161,54 +161,10 @@
},
"cursor": "Arrow"
},
- "left_sidebar": {
- "width": 30,
- "background": "#e2dfe7",
- "border": {
- "color": "#efecf4",
- "width": 1,
- "right": true
- },
- "item": {
- "height": 32,
- "icon_color": "#585260",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#19171c",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#efecf4",
- "padding": {
- "left": 1
- }
- }
- },
- "right_sidebar": {
- "width": 30,
- "background": "#e2dfe7",
- "border": {
- "color": "#efecf4",
- "width": 1,
- "left": true
- },
- "item": {
- "height": 32,
- "icon_color": "#585260",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#19171c",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#efecf4",
- "padding": {
- "left": 1
- }
+ "sidebar_resize_handle": {
+ "background": "#efecf4",
+ "padding": {
+ "left": 1
}
},
"pane_divider": {
@@ -252,6 +208,21 @@
"family": "Zed Sans",
"color": "#585260",
"size": 14
+ },
+ "sidebar_item": {
+ "height": 32,
+ "icon_color": "#585260",
+ "icon_size": 18
+ },
+ "sidebar_item_hover": {
+ "height": 32,
+ "icon_color": "#585260",
+ "icon_size": 18
+ },
+ "sidebar_item_active": {
+ "height": 32,
+ "icon_color": "#19171c",
+ "icon_size": 18
}
},
"titlebar": {
@@ -161,54 +161,10 @@
},
"cursor": "Arrow"
},
- "left_sidebar": {
- "width": 30,
- "background": "#1c1c1c",
- "border": {
- "color": "#070707",
- "width": 1,
- "right": true
- },
- "item": {
- "height": 32,
- "icon_color": "#9c9c9c",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#ffffff",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#070707",
- "padding": {
- "left": 1
- }
- }
- },
- "right_sidebar": {
- "width": 30,
- "background": "#1c1c1c",
- "border": {
- "color": "#070707",
- "width": 1,
- "left": true
- },
- "item": {
- "height": 32,
- "icon_color": "#9c9c9c",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#ffffff",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#070707",
- "padding": {
- "left": 1
- }
+ "sidebar_resize_handle": {
+ "background": "#070707",
+ "padding": {
+ "left": 1
}
},
"pane_divider": {
@@ -252,6 +208,21 @@
"family": "Zed Sans",
"color": "#808080",
"size": 14
+ },
+ "sidebar_item": {
+ "height": 32,
+ "icon_color": "#9c9c9c",
+ "icon_size": 18
+ },
+ "sidebar_item_hover": {
+ "height": 32,
+ "icon_color": "#9c9c9c",
+ "icon_size": 18
+ },
+ "sidebar_item_active": {
+ "height": 32,
+ "icon_color": "#ffffff",
+ "icon_size": 18
}
},
"titlebar": {
@@ -161,54 +161,10 @@
},
"cursor": "Arrow"
},
- "left_sidebar": {
- "width": 30,
- "background": "#f8f8f8",
- "border": {
- "color": "#d5d5d5",
- "width": 1,
- "right": true
- },
- "item": {
- "height": 32,
- "icon_color": "#717171",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#000000",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#d5d5d5",
- "padding": {
- "left": 1
- }
- }
- },
- "right_sidebar": {
- "width": 30,
- "background": "#f8f8f8",
- "border": {
- "color": "#d5d5d5",
- "width": 1,
- "left": true
- },
- "item": {
- "height": 32,
- "icon_color": "#717171",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#000000",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#d5d5d5",
- "padding": {
- "left": 1
- }
+ "sidebar_resize_handle": {
+ "background": "#d5d5d5",
+ "padding": {
+ "left": 1
}
},
"pane_divider": {
@@ -252,6 +208,21 @@
"family": "Zed Sans",
"color": "#636363",
"size": 14
+ },
+ "sidebar_item": {
+ "height": 32,
+ "icon_color": "#717171",
+ "icon_size": 18
+ },
+ "sidebar_item_hover": {
+ "height": 32,
+ "icon_color": "#717171",
+ "icon_size": 18
+ },
+ "sidebar_item_active": {
+ "height": 32,
+ "icon_color": "#000000",
+ "icon_size": 18
}
},
"titlebar": {
@@ -161,54 +161,10 @@
},
"cursor": "Arrow"
},
- "left_sidebar": {
- "width": 30,
- "background": "#073642",
- "border": {
- "color": "#002b36",
- "width": 1,
- "right": true
- },
- "item": {
- "height": 32,
- "icon_color": "#93a1a1",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#fdf6e3",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#002b36",
- "padding": {
- "left": 1
- }
- }
- },
- "right_sidebar": {
- "width": 30,
- "background": "#073642",
- "border": {
- "color": "#002b36",
- "width": 1,
- "left": true
- },
- "item": {
- "height": 32,
- "icon_color": "#93a1a1",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#fdf6e3",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#002b36",
- "padding": {
- "left": 1
- }
+ "sidebar_resize_handle": {
+ "background": "#002b36",
+ "padding": {
+ "left": 1
}
},
"pane_divider": {
@@ -252,6 +208,21 @@
"family": "Zed Sans",
"color": "#93a1a1",
"size": 14
+ },
+ "sidebar_item": {
+ "height": 32,
+ "icon_color": "#93a1a1",
+ "icon_size": 18
+ },
+ "sidebar_item_hover": {
+ "height": 32,
+ "icon_color": "#93a1a1",
+ "icon_size": 18
+ },
+ "sidebar_item_active": {
+ "height": 32,
+ "icon_color": "#fdf6e3",
+ "icon_size": 18
}
},
"titlebar": {
@@ -161,54 +161,10 @@
},
"cursor": "Arrow"
},
- "left_sidebar": {
- "width": 30,
- "background": "#eee8d5",
- "border": {
- "color": "#fdf6e3",
- "width": 1,
- "right": true
- },
- "item": {
- "height": 32,
- "icon_color": "#586e75",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#002b36",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#fdf6e3",
- "padding": {
- "left": 1
- }
- }
- },
- "right_sidebar": {
- "width": 30,
- "background": "#eee8d5",
- "border": {
- "color": "#fdf6e3",
- "width": 1,
- "left": true
- },
- "item": {
- "height": 32,
- "icon_color": "#586e75",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#002b36",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#fdf6e3",
- "padding": {
- "left": 1
- }
+ "sidebar_resize_handle": {
+ "background": "#fdf6e3",
+ "padding": {
+ "left": 1
}
},
"pane_divider": {
@@ -252,6 +208,21 @@
"family": "Zed Sans",
"color": "#586e75",
"size": 14
+ },
+ "sidebar_item": {
+ "height": 32,
+ "icon_color": "#586e75",
+ "icon_size": 18
+ },
+ "sidebar_item_hover": {
+ "height": 32,
+ "icon_color": "#586e75",
+ "icon_size": 18
+ },
+ "sidebar_item_active": {
+ "height": 32,
+ "icon_color": "#002b36",
+ "icon_size": 18
}
},
"titlebar": {
@@ -161,54 +161,10 @@
},
"cursor": "Arrow"
},
- "left_sidebar": {
- "width": 30,
- "background": "#293256",
- "border": {
- "color": "#202746",
- "width": 1,
- "right": true
- },
- "item": {
- "height": 32,
- "icon_color": "#979db4",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#f5f7ff",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#202746",
- "padding": {
- "left": 1
- }
- }
- },
- "right_sidebar": {
- "width": 30,
- "background": "#293256",
- "border": {
- "color": "#202746",
- "width": 1,
- "left": true
- },
- "item": {
- "height": 32,
- "icon_color": "#979db4",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#f5f7ff",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#202746",
- "padding": {
- "left": 1
- }
+ "sidebar_resize_handle": {
+ "background": "#202746",
+ "padding": {
+ "left": 1
}
},
"pane_divider": {
@@ -252,6 +208,21 @@
"family": "Zed Sans",
"color": "#979db4",
"size": 14
+ },
+ "sidebar_item": {
+ "height": 32,
+ "icon_color": "#979db4",
+ "icon_size": 18
+ },
+ "sidebar_item_hover": {
+ "height": 32,
+ "icon_color": "#979db4",
+ "icon_size": 18
+ },
+ "sidebar_item_active": {
+ "height": 32,
+ "icon_color": "#f5f7ff",
+ "icon_size": 18
}
},
"titlebar": {
@@ -161,54 +161,10 @@
},
"cursor": "Arrow"
},
- "left_sidebar": {
- "width": 30,
- "background": "#dfe2f1",
- "border": {
- "color": "#f5f7ff",
- "width": 1,
- "right": true
- },
- "item": {
- "height": 32,
- "icon_color": "#5e6687",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#202746",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#f5f7ff",
- "padding": {
- "left": 1
- }
- }
- },
- "right_sidebar": {
- "width": 30,
- "background": "#dfe2f1",
- "border": {
- "color": "#f5f7ff",
- "width": 1,
- "left": true
- },
- "item": {
- "height": 32,
- "icon_color": "#5e6687",
- "icon_size": 18
- },
- "active_item": {
- "height": 32,
- "icon_color": "#202746",
- "icon_size": 18
- },
- "resize_handle": {
- "background": "#f5f7ff",
- "padding": {
- "left": 1
- }
+ "sidebar_resize_handle": {
+ "background": "#f5f7ff",
+ "padding": {
+ "left": 1
}
},
"pane_divider": {
@@ -252,6 +208,21 @@
"family": "Zed Sans",
"color": "#5e6687",
"size": 14
+ },
+ "sidebar_item": {
+ "height": 32,
+ "icon_color": "#5e6687",
+ "icon_size": 18
+ },
+ "sidebar_item_hover": {
+ "height": 32,
+ "icon_color": "#5e6687",
+ "icon_size": 18
+ },
+ "sidebar_item_active": {
+ "height": 32,
+ "icon_color": "#202746",
+ "icon_size": 18
}
},
"titlebar": {
@@ -38,8 +38,7 @@ pub struct Workspace {
pub pane_divider: Border,
pub leader_border_opacity: f32,
pub leader_border_width: f32,
- pub left_sidebar: Sidebar,
- pub right_sidebar: Sidebar,
+ pub sidebar_resize_handle: ContainerStyle,
pub status_bar: StatusBar,
pub toolbar: Toolbar,
pub disconnected_overlay: ContainedText,
@@ -139,16 +138,13 @@ pub struct FindEditor {
#[derive(Deserialize, Default)]
pub struct Sidebar {
- #[serde(flatten)]
- pub container: ContainerStyle,
- pub width: f32,
- pub item: SidebarItem,
- pub active_item: SidebarItem,
pub resize_handle: ContainerStyle,
}
-#[derive(Deserialize, Default)]
+#[derive(Clone, Copy, Deserialize, Default)]
pub struct SidebarItem {
+ #[serde(flatten)]
+ pub container: ContainerStyle,
pub icon_color: Color,
pub icon_size: f32,
pub height: f32,
@@ -165,6 +161,9 @@ pub struct StatusBar {
pub lsp_message: TextStyle,
pub auto_update_progress_message: TextStyle,
pub auto_update_done_message: TextStyle,
+ pub sidebar_item: SidebarItem,
+ pub sidebar_item_active: SidebarItem,
+ pub sidebar_item_hover: SidebarItem,
}
#[derive(Deserialize, Default)]
@@ -1,9 +1,14 @@
-use super::Workspace;
-use gpui::{elements::*, impl_actions, platform::CursorStyle, AnyViewHandle, RenderContext};
+use gpui::{
+ elements::*, impl_actions, platform::CursorStyle, AnyViewHandle, Entity, RenderContext, View,
+ ViewContext, ViewHandle,
+};
use serde::Deserialize;
+use settings::Settings;
use std::{cell::RefCell, rc::Rc};
use theme::Theme;
+use crate::StatusItemView;
+
pub struct Sidebar {
side: Side,
items: Vec<Item>,
@@ -12,31 +17,36 @@ pub struct Sidebar {
custom_width: Rc<RefCell<f32>>,
}
-#[derive(Clone, Copy, Deserialize)]
+#[derive(Clone, Copy, Debug, Deserialize)]
pub enum Side {
Left,
Right,
}
+#[derive(Clone)]
struct Item {
icon_path: &'static str,
view: AnyViewHandle,
}
-#[derive(Clone, Deserialize)]
-pub struct ToggleSidebarItem(pub SidebarItemId);
-
-#[derive(Clone, Deserialize)]
-pub struct ToggleSidebarItemFocus(pub SidebarItemId);
+pub struct SidebarButtons {
+ sidebar: ViewHandle<Sidebar>,
+}
-impl_actions!(workspace, [ToggleSidebarItem, ToggleSidebarItemFocus]);
+#[derive(Clone, Debug, Deserialize)]
+pub struct ToggleSidebarItem {
+ pub side: Side,
+ pub item_index: usize,
+}
-#[derive(Clone, Deserialize)]
-pub struct SidebarItemId {
+#[derive(Clone, Debug, Deserialize)]
+pub struct ToggleSidebarItemFocus {
pub side: Side,
pub item_index: usize,
}
+impl_actions!(workspace, [ToggleSidebarItem, ToggleSidebarItemFocus]);
+
impl Sidebar {
pub fn new(side: Side) -> Self {
Self {
@@ -48,20 +58,28 @@ impl Sidebar {
}
}
- pub fn add_item(&mut self, icon_path: &'static str, view: AnyViewHandle) {
+ pub fn add_item(
+ &mut self,
+ icon_path: &'static str,
+ view: AnyViewHandle,
+ cx: &mut ViewContext<Self>,
+ ) {
self.items.push(Item { icon_path, view });
+ cx.notify()
}
- pub fn activate_item(&mut self, item_ix: usize) {
+ pub fn activate_item(&mut self, item_ix: usize, cx: &mut ViewContext<Self>) {
self.active_item_ix = Some(item_ix);
+ cx.notify();
}
- pub fn toggle_item(&mut self, item_ix: usize) {
+ pub fn toggle_item(&mut self, item_ix: usize, cx: &mut ViewContext<Self>) {
if self.active_item_ix == Some(item_ix) {
self.active_item_ix = None;
} else {
self.active_item_ix = Some(item_ix);
}
+ cx.notify();
}
pub fn active_item(&self) -> Option<&AnyViewHandle> {
@@ -70,75 +88,56 @@ impl Sidebar {
.map(|item| &item.view)
}
- fn theme<'a>(&self, theme: &'a Theme) -> &'a theme::Sidebar {
- match self.side {
- Side::Left => &theme.workspace.left_sidebar,
- Side::Right => &theme.workspace.right_sidebar,
- }
- }
-
- pub fn render(&self, theme: &Theme, cx: &mut RenderContext<Workspace>) -> ElementBox {
+ fn render_resize_handle(&self, theme: &Theme, cx: &mut RenderContext<Self>) -> ElementBox {
+ let actual_width = self.actual_width.clone();
+ let custom_width = self.custom_width.clone();
let side = self.side;
- let theme = self.theme(theme);
-
- ConstrainedBox::new(
- Container::new(
- Flex::column()
- .with_children(self.items.iter().enumerate().map(|(item_index, item)| {
- let theme = if Some(item_index) == self.active_item_ix {
- &theme.active_item
- } else {
- &theme.item
- };
- enum SidebarButton {}
- MouseEventHandler::new::<SidebarButton, _, _>(item.view.id(), cx, |_, _| {
- ConstrainedBox::new(
- Align::new(
- ConstrainedBox::new(
- Svg::new(item.icon_path)
- .with_color(theme.icon_color)
- .boxed(),
- )
- .with_height(theme.icon_size)
- .boxed(),
- )
- .boxed(),
- )
- .with_height(theme.height)
- .boxed()
- })
- .with_cursor_style(CursorStyle::PointingHand)
- .on_mouse_down(move |cx| {
- cx.dispatch_action(ToggleSidebarItem(SidebarItemId {
- side,
- item_index,
- }))
- })
- .boxed()
- }))
- .boxed(),
- )
- .with_style(theme.container)
- .boxed(),
- )
- .with_width(theme.width)
+ MouseEventHandler::new::<Self, _, _>(side as usize, cx, |_, _| {
+ Empty::new()
+ .contained()
+ .with_style(theme.workspace.sidebar_resize_handle)
+ .boxed()
+ })
+ .with_padding(Padding {
+ left: 4.,
+ right: 4.,
+ ..Default::default()
+ })
+ .with_cursor_style(CursorStyle::ResizeLeftRight)
+ .on_drag(move |delta, cx| {
+ let prev_width = *actual_width.borrow();
+ match side {
+ Side::Left => *custom_width.borrow_mut() = 0f32.max(prev_width + delta.x()),
+ Side::Right => *custom_width.borrow_mut() = 0f32.max(prev_width - delta.x()),
+ }
+
+ cx.notify();
+ })
.boxed()
}
+}
+
+impl Entity for Sidebar {
+ type Event = ();
+}
- pub fn render_active_item(
- &self,
- theme: &Theme,
- cx: &mut RenderContext<Workspace>,
- ) -> Option<ElementBox> {
+impl View for Sidebar {
+ fn ui_name() -> &'static str {
+ "Sidebar"
+ }
+
+ fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
+ let theme = cx.global::<Settings>().theme.clone();
if let Some(active_item) = self.active_item() {
let mut container = Flex::row();
if matches!(self.side, Side::Right) {
- container.add_child(self.render_resize_handle(theme, cx));
+ container.add_child(self.render_resize_handle(&theme, cx));
}
container.add_child(
Hook::new(
- ConstrainedBox::new(ChildView::new(active_item).boxed())
+ ChildView::new(active_item)
+ .constrained()
.with_max_width(*self.custom_width.borrow())
.boxed(),
)
@@ -150,38 +149,76 @@ impl Sidebar {
.boxed(),
);
if matches!(self.side, Side::Left) {
- container.add_child(self.render_resize_handle(theme, cx));
+ container.add_child(self.render_resize_handle(&theme, cx));
}
- Some(container.boxed())
+ container.boxed()
} else {
- None
+ Empty::new().boxed()
}
}
+}
- fn render_resize_handle(&self, theme: &Theme, cx: &mut RenderContext<Workspace>) -> ElementBox {
- let actual_width = self.actual_width.clone();
- let custom_width = self.custom_width.clone();
- let side = self.side;
- MouseEventHandler::new::<Self, _, _>(side as usize, cx, |_, _| {
- Container::new(Empty::new().boxed())
- .with_style(self.theme(theme).resize_handle)
+impl SidebarButtons {
+ pub fn new(sidebar: ViewHandle<Sidebar>, cx: &mut ViewContext<Self>) -> Self {
+ cx.observe(&sidebar, |_, _, cx| cx.notify()).detach();
+ Self { sidebar }
+ }
+}
+
+impl Entity for SidebarButtons {
+ type Event = ();
+}
+
+impl View for SidebarButtons {
+ fn ui_name() -> &'static str {
+ "SidebarToggleButton"
+ }
+
+ fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
+ let theme = &cx.global::<Settings>().theme.workspace.status_bar;
+ let style = theme.sidebar_item;
+ let hover_style = theme.sidebar_item_hover;
+ let active_style = theme.sidebar_item_active;
+ let sidebar = self.sidebar.read(cx);
+ let active_ix = sidebar.active_item_ix;
+ let side = sidebar.side;
+ let items = sidebar.items.clone();
+ Flex::row()
+ .with_children(items.iter().enumerate().map(|(ix, item)| {
+ MouseEventHandler::new::<Self, _, _>(ix, cx, move |state, _| {
+ let style = if Some(ix) == active_ix {
+ active_style
+ } else if state.hovered {
+ hover_style
+ } else {
+ style
+ };
+ Svg::new(item.icon_path)
+ .with_color(style.icon_color)
+ .constrained()
+ .with_height(style.icon_size)
+ .contained()
+ .with_style(style.container)
+ .boxed()
+ })
+ .with_cursor_style(CursorStyle::PointingHand)
+ .on_click(move |cx| {
+ cx.dispatch_action(ToggleSidebarItem {
+ side,
+ item_index: ix,
+ })
+ })
.boxed()
- })
- .with_padding(Padding {
- left: 4.,
- right: 4.,
- ..Default::default()
- })
- .with_cursor_style(CursorStyle::ResizeLeftRight)
- .on_drag(move |delta, cx| {
- let prev_width = *actual_width.borrow();
- match side {
- Side::Left => *custom_width.borrow_mut() = 0f32.max(prev_width + delta.x()),
- Side::Right => *custom_width.borrow_mut() = 0f32.max(prev_width - delta.x()),
- }
+ }))
+ .boxed()
+ }
+}
- cx.notify();
- })
- .boxed()
+impl StatusItemView for SidebarButtons {
+ fn set_active_pane_item(
+ &mut self,
+ _: Option<&dyn crate::ItemHandle>,
+ _: &mut ViewContext<Self>,
+ ) {
}
}
@@ -1,9 +1,9 @@
use crate::{ItemHandle, Pane};
-use settings::Settings;
use gpui::{
elements::*, AnyViewHandle, ElementBox, Entity, MutableAppContext, RenderContext, Subscription,
View, ViewContext, ViewHandle,
};
+use settings::Settings;
pub trait StatusItemView: View {
fn set_active_pane_item(
@@ -48,7 +48,7 @@ impl View for StatusBar {
.with_margin_right(theme.item_spacing)
.boxed()
}))
- .with_children(self.right_items.iter().map(|i| {
+ .with_children(self.right_items.iter().rev().map(|i| {
ChildView::new(i.as_ref())
.aligned()
.contained()
@@ -31,7 +31,7 @@ pub use pane_group::*;
use postage::prelude::Stream;
use project::{fs, Fs, Project, ProjectEntryId, ProjectPath, Worktree};
use settings::Settings;
-use sidebar::{Side, Sidebar, SidebarItemId, ToggleSidebarItem, ToggleSidebarItemFocus};
+use sidebar::{Side, Sidebar, SidebarButtons, ToggleSidebarItem, ToggleSidebarItemFocus};
use status_bar::StatusBar;
pub use status_bar::StatusItemView;
use std::{
@@ -678,8 +678,8 @@ pub struct Workspace {
themes: Arc<ThemeRegistry>,
modal: Option<AnyViewHandle>,
center: PaneGroup,
- left_sidebar: Sidebar,
- right_sidebar: Sidebar,
+ left_sidebar: ViewHandle<Sidebar>,
+ right_sidebar: ViewHandle<Sidebar>,
panes: Vec<ViewHandle<Pane>>,
active_pane: ViewHandle<Pane>,
status_bar: ViewHandle<StatusBar>,
@@ -751,7 +751,6 @@ impl Workspace {
cx.focus(&pane);
cx.emit(Event::PaneAdded(pane.clone()));
- let status_bar = cx.add_view(|cx| StatusBar::new(&pane, cx));
let mut current_user = params.user_store.read(cx).watch_current_user().clone();
let mut connection_status = params.client.status().clone();
let _observe_current_user = cx.spawn_weak(|this, mut cx| async move {
@@ -773,6 +772,18 @@ impl Workspace {
cx.emit_global(WorkspaceCreated(weak_self.clone()));
+ let left_sidebar = cx.add_view(|_| Sidebar::new(Side::Left));
+ let right_sidebar = cx.add_view(|_| Sidebar::new(Side::Right));
+ let left_sidebar_buttons = cx.add_view(|cx| SidebarButtons::new(left_sidebar.clone(), cx));
+ let right_sidebar_buttons =
+ cx.add_view(|cx| SidebarButtons::new(right_sidebar.clone(), cx));
+ let status_bar = cx.add_view(|cx| {
+ let mut status_bar = StatusBar::new(&pane.clone(), cx);
+ status_bar.add_left_item(left_sidebar_buttons, cx);
+ status_bar.add_right_item(right_sidebar_buttons, cx);
+ status_bar
+ });
+
let mut this = Workspace {
modal: None,
weak_self,
@@ -785,8 +796,8 @@ impl Workspace {
user_store: params.user_store.clone(),
fs: params.fs.clone(),
themes: params.themes.clone(),
- left_sidebar: Sidebar::new(Side::Left),
- right_sidebar: Sidebar::new(Side::Right),
+ left_sidebar,
+ right_sidebar,
project: params.project.clone(),
leader_state: Default::default(),
follower_states_by_leader: Default::default(),
@@ -801,12 +812,12 @@ impl Workspace {
self.weak_self.clone()
}
- pub fn left_sidebar_mut(&mut self) -> &mut Sidebar {
- &mut self.left_sidebar
+ pub fn left_sidebar(&self) -> &ViewHandle<Sidebar> {
+ &self.left_sidebar
}
- pub fn right_sidebar_mut(&mut self) -> &mut Sidebar {
- &mut self.right_sidebar
+ pub fn right_sidebar(&self) -> &ViewHandle<Sidebar> {
+ &self.right_sidebar
}
pub fn status_bar(&self) -> &ViewHandle<StatusBar> {
@@ -1028,12 +1039,15 @@ impl Workspace {
}
pub fn toggle_sidebar_item(&mut self, action: &ToggleSidebarItem, cx: &mut ViewContext<Self>) {
- let sidebar = match action.0.side {
+ let sidebar = match action.side {
Side::Left => &mut self.left_sidebar,
Side::Right => &mut self.right_sidebar,
};
- sidebar.toggle_item(action.0.item_index);
- if let Some(active_item) = sidebar.active_item() {
+ let active_item = sidebar.update(cx, |sidebar, cx| {
+ sidebar.toggle_item(action.item_index, cx);
+ sidebar.active_item().cloned()
+ });
+ if let Some(active_item) = active_item {
cx.focus(active_item);
} else {
cx.focus_self();
@@ -1046,12 +1060,15 @@ impl Workspace {
action: &ToggleSidebarItemFocus,
cx: &mut ViewContext<Self>,
) {
- let sidebar = match action.0.side {
+ let sidebar = match action.side {
Side::Left => &mut self.left_sidebar,
Side::Right => &mut self.right_sidebar,
};
- sidebar.activate_item(action.0.item_index);
- if let Some(active_item) = sidebar.active_item() {
+ let active_item = sidebar.update(cx, |sidebar, cx| {
+ sidebar.toggle_item(action.item_index, cx);
+ sidebar.active_item().cloned()
+ });
+ if let Some(active_item) = active_item {
if active_item.is_focused(cx) {
cx.focus_self();
} else {
@@ -1610,7 +1627,7 @@ impl Workspace {
.boxed(),
)
.constrained()
- .with_width(theme.workspace.right_sidebar.width)
+ .with_width(theme.workspace.titlebar.avatar_width)
.contained()
.with_margin_left(2.)
.boxed();
@@ -1656,7 +1673,7 @@ impl Workspace {
.with_width(24.)
.aligned()
.constrained()
- .with_width(theme.workspace.right_sidebar.width)
+ .with_width(24.)
.aligned()
.boxed()
})
@@ -1983,37 +2000,39 @@ impl View for Workspace {
.with_child(
Stack::new()
.with_child({
- let mut content = Flex::row();
- content.add_child(self.left_sidebar.render(&theme, cx));
- if let Some(element) =
- self.left_sidebar.render_active_item(&theme, cx)
- {
- content
- .add_child(FlexItem::new(element).flex(0.8, false).boxed());
- }
- content.add_child(
- Flex::column()
- .with_child(
- FlexItem::new(self.center.render(
- &theme,
- &self.follower_states_by_leader,
- self.project.read(cx).collaborators(),
- ))
- .flex(1., true)
- .boxed(),
- )
- .with_child(ChildView::new(&self.status_bar).boxed())
+ Flex::row()
+ .with_children(
+ if self.left_sidebar.read(cx).active_item().is_some() {
+ Some(
+ ChildView::new(&self.left_sidebar)
+ .flex(0.8, false)
+ .boxed(),
+ )
+ } else {
+ None
+ },
+ )
+ .with_child(
+ FlexItem::new(self.center.render(
+ &theme,
+ &self.follower_states_by_leader,
+ self.project.read(cx).collaborators(),
+ ))
.flex(1., true)
.boxed(),
- );
- if let Some(element) =
- self.right_sidebar.render_active_item(&theme, cx)
- {
- content
- .add_child(FlexItem::new(element).flex(0.8, false).boxed());
- }
- content.add_child(self.right_sidebar.render(&theme, cx));
- content.boxed()
+ )
+ .with_children(
+ if self.right_sidebar.read(cx).active_item().is_some() {
+ Some(
+ ChildView::new(&self.right_sidebar)
+ .flex(0.8, false)
+ .boxed(),
+ )
+ } else {
+ None
+ },
+ )
+ .boxed()
})
.with_children(self.modal.as_ref().map(|m| {
ChildView::new(m)
@@ -2026,6 +2045,7 @@ impl View for Workspace {
.flex(1.0, true)
.boxed(),
)
+ .with_child(ChildView::new(&self.status_bar).boxed())
.contained()
.with_background_color(theme.workspace.background)
.boxed(),
@@ -2202,10 +2222,10 @@ pub fn open_paths(
let mut workspace = (app_state.build_workspace)(project, &app_state, cx);
if contains_directory {
workspace.toggle_sidebar_item(
- &ToggleSidebarItem(SidebarItemId {
+ &ToggleSidebarItem {
side: Side::Left,
item_index: 0,
- }),
+ },
cx,
);
}
@@ -6,7 +6,6 @@ pub mod test;
use anyhow::{anyhow, Context, Result};
use breadcrumbs::Breadcrumbs;
-use chat_panel::ChatPanel;
pub use client;
pub use contacts_panel;
use contacts_panel::ContactsPanel;
@@ -147,7 +146,7 @@ pub fn build_workspace(
user_store: app_state.user_store.clone(),
channel_list: app_state.channel_list.clone(),
};
- let mut workspace = Workspace::new(&workspace_params, cx);
+ let workspace = Workspace::new(&workspace_params, cx);
let project = workspace.project().clone();
let theme_names = app_state.themes.list().collect();
@@ -171,22 +170,15 @@ pub fn build_workspace(
}));
});
- workspace.left_sidebar_mut().add_item(
- "icons/folder-tree-16.svg",
- ProjectPanel::new(project, cx).into(),
- );
- workspace.right_sidebar_mut().add_item(
- "icons/user-16.svg",
- cx.add_view(|cx| ContactsPanel::new(app_state.clone(), cx))
- .into(),
- );
- workspace.right_sidebar_mut().add_item(
- "icons/comment-16.svg",
- cx.add_view(|cx| {
- ChatPanel::new(app_state.client.clone(), app_state.channel_list.clone(), cx)
- })
- .into(),
- );
+ let project_panel = ProjectPanel::new(project, cx);
+ let contact_panel = cx.add_view(|cx| ContactsPanel::new(app_state.clone(), cx));
+
+ workspace.left_sidebar().update(cx, |sidebar, cx| {
+ sidebar.add_item("icons/folder-tree-16.svg", project_panel.into(), cx)
+ });
+ workspace.right_sidebar().update(cx, |sidebar, cx| {
+ sidebar.add_item("icons/user-16.svg", contact_panel.into(), cx)
+ });
let diagnostic_message = cx.add_view(|_| editor::items::DiagnosticMessage::new());
let diagnostic_summary =
@@ -200,8 +192,8 @@ pub fn build_workspace(
status_bar.add_left_item(diagnostic_summary, cx);
status_bar.add_left_item(diagnostic_message, cx);
status_bar.add_left_item(lsp_status, cx);
- status_bar.add_right_item(auto_update, cx);
status_bar.add_right_item(cursor_position, cx);
+ status_bar.add_right_item(auto_update, cx);
});
workspace
@@ -362,7 +354,7 @@ mod tests {
let workspace_1 = cx.root_view::<Workspace>(cx.window_ids()[0]).unwrap();
workspace_1.update(cx, |workspace, cx| {
assert_eq!(workspace.worktrees(cx).count(), 2);
- assert!(workspace.left_sidebar_mut().active_item().is_some());
+ assert!(workspace.left_sidebar().read(cx).active_item().is_some());
assert!(workspace.active_pane().is_focused(cx));
});
@@ -52,22 +52,6 @@ export default function workspace(theme: Theme) {
iconColor: iconColor(theme, "secondary"),
iconSize: 18,
};
- const sidebar = {
- width: 30,
- background: backgroundColor(theme, 300),
- border: border(theme, "primary", { right: true }),
- item: sidebarItem,
- activeItem: {
- ...sidebarItem,
- iconColor: iconColor(theme, "active"),
- },
- resizeHandle: {
- background: border(theme, "primary").color,
- padding: {
- left: 1,
- },
- },
- };
const shareIcon = {
margin: { top: 3, bottom: 2 },
cornerRadius: 6,
@@ -86,19 +70,17 @@ export default function workspace(theme: Theme) {
},
cursor: "Arrow"
},
- leftSidebar: {
- ...sidebar,
- border: border(theme, "primary", { right: true }),
- },
- rightSidebar: {
- ...sidebar,
- border: border(theme, "primary", { left: true }),
+ sidebarResizeHandle: {
+ background: border(theme, "primary").color,
+ padding: {
+ left: 1,
+ },
},
paneDivider: {
color: border(theme, "secondary").color,
width: 1,
},
- status_bar: {
+ statusBar: {
height: 24,
itemSpacing: 8,
padding: {
@@ -111,6 +93,16 @@ export default function workspace(theme: Theme) {
lspMessage: text(theme, "sans", "muted"),
autoUpdateProgressMessage: text(theme, "sans", "muted"),
autoUpdateDoneMessage: text(theme, "sans", "muted"),
+ sidebarItem: {
+ ...sidebarItem
+ },
+ sidebarItemHover: {
+ ...sidebarItem
+ },
+ sidebarItemActive: {
+ ...sidebarItem,
+ iconColor: iconColor(theme, "active"),
+ },
},
titlebar: {
avatarWidth: 18,