Render a signed out icon in titlebar

Antonio Scandurra , Nathan Sobo , and Max Brunsfeld created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
Co-Authored-By: Max Brunsfeld <max@zed.dev>

Change summary

zed/assets/icons/signed-out-12.svg |  1 
zed/assets/themes/_base.toml       |  8 ++-
zed/src/theme.rs                   | 12 +++++
zed/src/workspace.rs               | 59 +++++++++++++++++++----------
zed/src/workspace/sidebar.rs       | 64 ++++++++++++++++++-------------
5 files changed, 92 insertions(+), 52 deletions(-)

Detailed changes

zed/assets/themes/_base.toml 🔗

@@ -7,7 +7,9 @@ pane_divider = { width = 1, color = "$border.0" }
 
 [workspace.titlebar]
 border = { width = 1, bottom = true, color = "$border.0" }
-text = { extends = "$text.0" }
+title = "$text.0"
+icon_width = 16
+icon_signed_out = "$text.2.color"
 
 [workspace.tab]
 text = "$text.2"
@@ -26,7 +28,7 @@ background = "$surface.1"
 text = "$text.0"
 
 [workspace.sidebar]
-padding = { left = 12, right = 12 }
+width = 36
 border = { right = true, width = 1, color = "$border.0" }
 
 [workspace.sidebar.resize_handle]
@@ -35,7 +37,7 @@ background = "$border.0"
 
 [workspace.sidebar.icon]
 color = "$text.2.color"
-height = 18
+height = 16
 
 [workspace.sidebar.active_icon]
 extends = "$workspace.sidebar.icon"

zed/src/theme.rs 🔗

@@ -34,7 +34,7 @@ pub struct SyntaxTheme {
 #[derive(Deserialize)]
 pub struct Workspace {
     pub background: Color,
-    pub titlebar: ContainedLabel,
+    pub titlebar: Titlebar,
     pub tab: Tab,
     pub active_tab: Tab,
     pub pane_divider: Border,
@@ -42,6 +42,15 @@ pub struct Workspace {
     pub right_sidebar: Sidebar,
 }
 
+#[derive(Clone, Deserialize)]
+pub struct Titlebar {
+    #[serde(flatten)]
+    pub container: ContainerStyle,
+    pub title: TextStyle,
+    pub icon_width: f32,
+    pub icon_signed_out: Color,
+}
+
 #[derive(Clone, Deserialize)]
 pub struct Tab {
     #[serde(flatten)]
@@ -60,6 +69,7 @@ pub struct Tab {
 pub struct Sidebar {
     #[serde(flatten)]
     pub container: ContainerStyle,
+    pub width: f32,
     pub icon: SidebarIcon,
     pub active_icon: SidebarIcon,
     pub resize_handle: ContainerStyle,

zed/src/workspace.rs 🔗

@@ -21,7 +21,7 @@ use gpui::{
     json::to_string_pretty,
     keymap::Binding,
     platform::WindowOptions,
-    AnyViewHandle, AppContext, ClipboardItem, Entity, ImageData, ModelHandle, MutableAppContext,
+    AnyViewHandle, AppContext, ClipboardItem, Entity, ModelHandle, MutableAppContext,
     PathPromptOptions, PromptLevel, RenderContext, Task, View, ViewContext, ViewHandle,
     WeakModelHandle,
 };
@@ -354,19 +354,10 @@ pub struct Workspace {
         (usize, Arc<Path>),
         postage::watch::Receiver<Option<Result<Box<dyn ItemHandle>, Arc<anyhow::Error>>>>,
     >,
-    image: Arc<ImageData>,
 }
 
 impl Workspace {
     pub fn new(app_state: &AppState, cx: &mut ViewContext<Self>) -> Self {
-        let image_bytes = crate::assets::Assets::get("images/as-cii.jpeg").unwrap();
-        let image = image::io::Reader::new(std::io::Cursor::new(&*image_bytes.data))
-            .with_guessed_format()
-            .unwrap()
-            .decode()
-            .unwrap()
-            .into_bgra8();
-
         let pane = cx.add_view(|_| Pane::new(app_state.settings.clone()));
         let pane_id = pane.id();
         cx.subscribe(&pane, move |me, _, event, cx| {
@@ -410,7 +401,6 @@ impl Workspace {
             worktrees: Default::default(),
             items: Default::default(),
             loading_items: Default::default(),
-            image: ImageData::new(image),
         }
     }
 
@@ -946,6 +936,24 @@ impl Workspace {
     pub fn active_pane(&self) -> &ViewHandle<Pane> {
         &self.active_pane
     }
+
+    fn render_account_status(&self, cx: &mut RenderContext<Self>) -> ElementBox {
+        let theme = &self.settings.borrow().theme;
+        ConstrainedBox::new(
+            Align::new(
+                ConstrainedBox::new(
+                    Svg::new("icons/signed-out-12.svg")
+                        .with_color(theme.workspace.titlebar.icon_signed_out)
+                        .boxed(),
+                )
+                .with_width(theme.workspace.titlebar.icon_width)
+                .boxed(),
+            )
+            .boxed(),
+        )
+        .with_width(theme.workspace.right_sidebar.width)
+        .boxed()
+    }
 }
 
 impl Entity for Workspace {
@@ -964,16 +972,25 @@ impl View for Workspace {
             Flex::column()
                 .with_child(
                     ConstrainedBox::new(
-                        Image::new(self.image.clone()).boxed()
-                        // Container::new(
-                        //     Align::new(
-                        //         Label::new("zed".into(), theme.workspace.titlebar.label.clone())
-                        //             .boxed(),
-                        //     )
-                        //     .boxed(),
-                        // )
-                        // .with_style(&theme.workspace.titlebar.container)
-                        // .boxed(),
+                        Container::new(
+                            Stack::new()
+                                .with_child(
+                                    Align::new(
+                                        Label::new(
+                                            "zed".into(),
+                                            theme.workspace.titlebar.title.clone(),
+                                        )
+                                        .boxed(),
+                                    )
+                                    .boxed(),
+                                )
+                                .with_child(
+                                    Align::new(self.render_account_status(cx)).right().boxed(),
+                                )
+                                .boxed(),
+                        )
+                        .with_style(&theme.workspace.titlebar.container)
+                        .boxed(),
                     )
                     .with_height(32.)
                     .named("titlebar"),

zed/src/workspace/sidebar.rs 🔗

@@ -75,38 +75,48 @@ impl Sidebar {
         );
         let theme = self.theme(settings);
 
-        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_icon
-                    } else {
-                        &theme.icon
-                    };
-                    enum SidebarButton {}
-                    MouseEventHandler::new::<SidebarButton, _, _, _>(item.view.id(), cx, |_, _| {
-                        ConstrainedBox::new(
-                            Align::new(
+        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_icon
+                        } else {
+                            &theme.icon
+                        };
+                        enum SidebarButton {}
+                        MouseEventHandler::new::<SidebarButton, _, _, _>(
+                            item.view.id(),
+                            cx,
+                            |_, _| {
                                 ConstrainedBox::new(
-                                    Svg::new(item.icon_path).with_color(theme.color).boxed(),
+                                    Align::new(
+                                        ConstrainedBox::new(
+                                            Svg::new(item.icon_path)
+                                                .with_color(theme.color)
+                                                .boxed(),
+                                        )
+                                        .with_height(theme.height)
+                                        .boxed(),
+                                    )
+                                    .boxed(),
                                 )
-                                .with_height(theme.height)
-                                .boxed(),
-                            )
-                            .boxed(),
+                                .with_height(line_height + 16.0)
+                                .boxed()
+                            },
                         )
-                        .with_height(line_height + 16.0)
+                        .with_cursor_style(CursorStyle::PointingHand)
+                        .on_mouse_down(move |cx| {
+                            cx.dispatch_action(ToggleSidebarItem(ToggleArg { side, item_index }))
+                        })
                         .boxed()
-                    })
-                    .with_cursor_style(CursorStyle::PointingHand)
-                    .on_mouse_down(move |cx| {
-                        cx.dispatch_action(ToggleSidebarItem(ToggleArg { side, item_index }))
-                    })
-                    .boxed()
-                }))
-                .boxed(),
+                    }))
+                    .boxed(),
+            )
+            .with_style(&theme.container)
+            .boxed(),
         )
-        .with_style(&theme.container)
+        .with_width(theme.width)
         .boxed()
     }