assistant: Display hamburger menu even when the panel is not focused (#15612)

This commit gives tab button renderers control over the condition in
which they should be displayed. Previously we displayed tab buttons only
when the pane was focused. Now tab renderers can return an Option of
AnyElement, which in turn makes it possible for them to control when and
how they're rendered. Pane and Terminal handlers still check for self
focus condition and Assistant Panel does not.



Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2024-08-01 15:08:48 +02:00 committed by GitHub
parent dc0f7436e0
commit 79213637e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 22 additions and 11 deletions

View file

@ -378,6 +378,7 @@ impl AssistantPanel {
el.child(Pane::render_menu_overlay(new_item_menu))
})
.into_any_element()
.into()
});
pane.toolbar().update(cx, |toolbar, cx| {
toolbar.add_item(context_editor_toolbar.clone(), cx);

View file

@ -173,6 +173,9 @@ impl TerminalPanel {
let additional_buttons = self.additional_tab_bar_buttons.clone();
self.pane.update(cx, |pane, cx| {
pane.set_render_tab_bar_buttons(cx, move |pane, cx| {
if !pane.has_focus(cx) {
return None;
}
h_flex()
.gap_2()
.children(additional_buttons.clone())
@ -229,6 +232,7 @@ impl TerminalPanel {
})
})
.into_any_element()
.into()
});
});
}

View file

@ -237,7 +237,7 @@ pub struct Pane {
Option<Arc<dyn Fn(&mut Pane, &dyn Any, &mut ViewContext<Pane>) -> ControlFlow<(), ()>>>,
can_split: bool,
should_display_tab_bar: Rc<dyn Fn(&ViewContext<Pane>) -> bool>,
render_tab_bar_buttons: Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement>,
render_tab_bar_buttons: Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> Option<AnyElement>>,
_subscriptions: Vec<Subscription>,
tab_bar_scroll_handle: ScrollHandle,
/// Is None if navigation buttons are permanently turned off (and should not react to setting changes).
@ -356,6 +356,9 @@ impl Pane {
can_split: true,
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;
}
// 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()
@ -438,6 +441,7 @@ impl Pane {
el.child(Self::render_menu_overlay(split_item_menu))
})
.into_any_element()
.into()
}),
display_nav_history_buttons: Some(
TabBarSettings::get_global(cx).show_nav_history_buttons,
@ -483,10 +487,10 @@ impl Pane {
pub fn has_focus(&self, cx: &WindowContext) -> bool {
// We not only check whether our focus handle contains focus, but also
// whether the active_item might have focus, because we might have just activated an item
// but that hasn't rendered yet.
// So before the next render, we might have transferred focus
// to the item and `focus_handle.contains_focus` returns false because the `active_item`
// whether the active item might have focus, because we might have just activated an item
// that hasn't rendered yet.
// Before the next render, we might transfer focus
// to the item, and `focus_handle.contains_focus` returns false because the `active_item`
// is not hooked up to us in the dispatch tree.
self.focus_handle.contains_focused(cx)
|| self
@ -582,7 +586,7 @@ impl Pane {
pub fn set_render_tab_bar_buttons<F>(&mut self, cx: &mut ViewContext<Self>, render: F)
where
F: 'static + Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement,
F: 'static + Fn(&mut Pane, &mut ViewContext<Pane>) -> Option<AnyElement>,
{
self.render_tab_bar_buttons = Rc::new(render);
cx.notify();
@ -1886,11 +1890,13 @@ impl Pane {
.start_child(navigate_forward)
},
)
.when(self.has_focus(cx), |tab_bar| {
tab_bar.end_child({
let render_tab_buttons = self.render_tab_bar_buttons.clone();
render_tab_buttons(self, cx)
})
.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
}
})
.children(
self.items