Merge pull request #2311 from zed-industries/petros/z-279-add-terminals-count

Petros Amoiridis created

Add terminals count

Change summary

crates/project/src/terminals.rs             |  3 +
crates/terminal_view/src/terminal_button.rs | 26 ++++++++++++++++------
crates/theme/src/theme.rs                   |  3 +
crates/workspace/src/sidebar.rs             |  4 +-
styles/src/styleTree/statusBar.ts           |  4 +++
5 files changed, 29 insertions(+), 11 deletions(-)

Detailed changes

crates/project/src/terminals.rs 🔗

@@ -43,11 +43,12 @@ impl Project {
                     .push(terminal_handle.downgrade());
 
                 let id = terminal_handle.id();
-                cx.observe_release(&terminal_handle, move |project, _terminal, _cx| {
+                cx.observe_release(&terminal_handle, move |project, _terminal, cx| {
                     let handles = &mut project.terminals.local_handles;
 
                     if let Some(index) = handles.iter().position(|terminal| terminal.id() == id) {
                         handles.remove(index);
+                        cx.notify();
                     }
                 })
                 .detach();

crates/terminal_view/src/terminal_button.rs 🔗

@@ -19,7 +19,6 @@ pub struct FocusTerminal {
     terminal_handle: WeakModelHandle<Terminal>,
 }
 
-//actions!(terminal, [DeployTerminalMenu]);
 impl_internal_actions!(terminal, [FocusTerminal, DeployTerminalMenu]);
 
 pub fn init(cx: &mut MutableAppContext) {
@@ -56,13 +55,14 @@ impl View for TerminalButton {
             .unwrap_or(false);
 
         let has_terminals = !project.local_terminal_handles().is_empty();
+        let terminal_count = project.local_terminal_handles().len() as i32;
         let theme = cx.global::<Settings>().theme.clone();
 
         Stack::new()
             .with_child(
                 MouseEventHandler::<Self>::new(0, cx, {
                     let theme = theme.clone();
-                    move |state, _| {
+                    move |state, _cx| {
                         let style = theme
                             .workspace
                             .status_bar
@@ -70,10 +70,23 @@ impl View for TerminalButton {
                             .item
                             .style_for(state, active);
 
-                        Svg::new("icons/terminal_12.svg")
-                            .with_color(style.icon_color)
+                        Flex::row()
+                            .with_child(
+                                Svg::new("icons/terminal_12.svg")
+                                    .with_color(style.icon_color)
+                                    .constrained()
+                                    .with_width(style.icon_size)
+                                    .aligned()
+                                    .named("terminals-icon"),
+                            )
+                            .with_children(has_terminals.then(|| {
+                                Label::new(terminal_count.to_string(), style.label.text.clone())
+                                    .contained()
+                                    .with_style(style.label.container)
+                                    .aligned()
+                                    .boxed()
+                            }))
                             .constrained()
-                            .with_width(style.icon_size)
                             .with_height(style.icon_size)
                             .contained()
                             .with_style(style.container)
@@ -112,8 +125,7 @@ impl View for TerminalButton {
 
 impl TerminalButton {
     pub fn new(workspace: ViewHandle<Workspace>, cx: &mut ViewContext<Self>) -> Self {
-        // When terminal moves, redraw so that the icon and toggle status matches.
-        cx.subscribe(&workspace, |_, _, _, cx| cx.notify()).detach();
+        cx.observe(&workspace, |_, _, cx| cx.notify()).detach();
         Self {
             workspace: workspace.downgrade(),
             popup_menu: cx.add_view(|cx| {

crates/theme/src/theme.rs 🔗

@@ -340,12 +340,13 @@ pub struct Sidebar {
     pub container: ContainerStyle,
 }
 
-#[derive(Clone, Copy, Deserialize, Default)]
+#[derive(Clone, Deserialize, Default)]
 pub struct SidebarItem {
     #[serde(flatten)]
     pub container: ContainerStyle,
     pub icon_color: Color,
     pub icon_size: f32,
+    pub label: ContainedText,
 }
 
 #[derive(Deserialize, Default)]

crates/workspace/src/sidebar.rs 🔗

@@ -230,7 +230,7 @@ impl View for SidebarButtons {
         let tooltip_style = theme.tooltip.clone();
         let theme = &theme.workspace.status_bar.sidebar_buttons;
         let sidebar = self.sidebar.read(cx);
-        let item_style = theme.item;
+        let item_style = theme.item.clone();
         let badge_style = theme.badge;
         let active_ix = sidebar.active_item_ix;
         let is_open = sidebar.is_open;
@@ -254,7 +254,7 @@ impl View for SidebarButtons {
                         sidebar_side,
                         item_index: ix,
                     };
-                    MouseEventHandler::<Self>::new(ix, cx, move |state, cx| {
+                    MouseEventHandler::<Self>::new(ix, cx, |state, cx| {
                         let is_active = is_open && ix == active_ix;
                         let style = item_style.style_for(state, is_active);
                         Stack::new()

styles/src/styleTree/statusBar.ts 🔗

@@ -100,6 +100,10 @@ export default function statusBar(colorScheme: ColorScheme) {
                 ...statusContainer,
                 iconSize: 16,
                 iconColor: foreground(layer, "variant"),
+                label: {
+                    margin: { left: 6 },
+                    ...text(layer, "sans", { size: "sm" }),
+                },
                 hover: {
                     iconColor: foreground(layer, "hovered"),
                     background: background(layer, "variant"),