From 8aa1ba8cbcaafb1d6a63f81b913b4ad0df974a9f Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 7 Aug 2024 13:46:59 +0200 Subject: [PATCH] assistant: Tweak tab bar layout (#15901) - Add "New Context" button next to the hamburger - Add "History" - Allow Pane tab rendering callback to return items for both left and right side of the tab bar. ![image](https://github.com/user-attachments/assets/d5aa599d-c9e4-4f26-ad66-ffc290c53c29) Release Notes: - N/A --- assets/icons/text-search.svg | 1 + crates/assistant/src/assistant_panel.rs | 30 ++++++++++++++++++++-- crates/terminal_view/src/terminal_panel.rs | 7 ++--- crates/ui/src/components/icon.rs | 2 ++ crates/workspace/src/pane.rs | 23 +++++++++-------- 5 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 assets/icons/text-search.svg diff --git a/assets/icons/text-search.svg b/assets/icons/text-search.svg new file mode 100644 index 0000000000..379284cdea --- /dev/null +++ b/assets/icons/text-search.svg @@ -0,0 +1 @@ + diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index c5c504c401..cceadea49c 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -362,8 +362,32 @@ impl AssistantPanel { pane.display_nav_history_buttons(None); pane.set_should_display_tab_bar(|_| true); pane.set_render_tab_bar_buttons(cx, move |pane, cx| { - h_flex() + let focus_handle = pane.focus_handle(cx); + let left_children = IconButton::new("history", IconName::TextSearch) + .on_click( + cx.listener(|_, _, cx| cx.dispatch_action(DeployHistory.boxed_clone())), + ) + .tooltip(move |cx| { + cx.new_view(|cx| { + let keybind = + KeyBinding::for_action_in(&DeployHistory, &focus_handle, cx); + Tooltip::new("History").key_binding(keybind) + }) + .into() + }) + .selected( + pane.active_item() + .map_or(false, |item| item.downcast::().is_some()), + ); + let right_children = h_flex() .gap(Spacing::Small.rems(cx)) + .child( + IconButton::new("new-context", IconName::Plus) + .on_click( + cx.listener(|_, _, cx| cx.dispatch_action(NewFile.boxed_clone())), + ) + .tooltip(|cx| Tooltip::for_action("New Context", &NewFile, cx)), + ) .child( IconButton::new("menu", IconName::Menu) .icon_size(IconSize::Small) @@ -392,7 +416,9 @@ impl AssistantPanel { el.child(Pane::render_menu_overlay(new_item_menu)) }) .into_any_element() - .into() + .into(); + + (Some(left_children.into_any_element()), right_children) }); pane.toolbar().update(cx, |toolbar, cx| { toolbar.add_item(context_editor_toolbar.clone(), cx); diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index f7ae2f3857..e4d40e561c 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -174,9 +174,9 @@ impl TerminalPanel { self.pane.update(cx, |pane, cx| { pane.set_render_tab_bar_buttons(cx, move |pane, cx| { if !pane.has_focus(cx) { - return None; + return (None, None); } - h_flex() + let right_children = h_flex() .gap_2() .children(additional_buttons.clone()) .child( @@ -232,7 +232,8 @@ impl TerminalPanel { }) }) .into_any_element() - .into() + .into(); + (None, right_children) }); }); } diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs index 4ef5e0574e..9e87e8046a 100644 --- a/crates/ui/src/components/icon.rs +++ b/crates/ui/src/components/icon.rs @@ -253,6 +253,7 @@ pub enum IconName { Tab, Terminal, TextCursor, + TextSearch, Trash, TriangleRight, Update, @@ -414,6 +415,7 @@ impl IconName { IconName::Tab => "icons/tab.svg", IconName::Terminal => "icons/terminal.svg", IconName::TextCursor => "icons/text-cursor.svg", + IconName::TextSearch => "icons/text-search.svg", IconName::Trash => "icons/trash.svg", IconName::TriangleRight => "icons/triangle_right.svg", IconName::Update => "icons/update.svg", diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index c7fbee1a6e..414d62febb 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -237,7 +237,8 @@ pub struct Pane { Option) -> ControlFlow<(), ()>>>, can_split: bool, should_display_tab_bar: Rc) -> bool>, - render_tab_bar_buttons: Rc) -> Option>, + render_tab_bar_buttons: + Rc) -> (Option, Option)>, _subscriptions: Vec, tab_bar_scroll_handle: ScrollHandle, /// Is None if navigation buttons are permanently turned off (and should not react to setting changes). @@ -357,11 +358,11 @@ impl Pane { should_display_tab_bar: Rc::new(|cx| TabBarSettings::get_global(cx).show), render_tab_bar_buttons: Rc::new(move |pane, cx| { if !pane.has_focus(cx) { - return None; + return (None, None); } // Ideally we would return a vec of elements here to pass directly to the [TabBar]'s // `end_slot`, but due to needing a view here that isn't possible. - h_flex() + let right_children = h_flex() // Instead we need to replicate the spacing from the [TabBar]'s `end_slot` here. .gap(Spacing::Small.rems(cx)) .child( @@ -441,7 +442,8 @@ impl Pane { el.child(Self::render_menu_overlay(split_item_menu)) }) .into_any_element() - .into() + .into(); + (None, right_children) }), display_nav_history_buttons: Some( TabBarSettings::get_global(cx).show_nav_history_buttons, @@ -586,7 +588,8 @@ impl Pane { pub fn set_render_tab_bar_buttons(&mut self, cx: &mut ViewContext, render: F) where - F: 'static + Fn(&mut Pane, &mut ViewContext) -> Option, + F: 'static + + Fn(&mut Pane, &mut ViewContext) -> (Option, Option), { self.render_tab_bar_buttons = Rc::new(render); cx.notify(); @@ -1892,11 +1895,11 @@ impl Pane { ) .map(|tab_bar| { let render_tab_buttons = self.render_tab_bar_buttons.clone(); - if let Some(buttons) = render_tab_buttons(self, cx) { - tab_bar.end_child(buttons) - } else { - tab_bar - } + let (left_children, right_children) = render_tab_buttons(self, cx); + + tab_bar + .start_children(left_children) + .end_children(right_children) }) .children( self.items