dock: Add a way for Panels to track the tab bar they belong to (#1580)
Currently, there is no good way for a Panel in a dock to e.g. add a tab to its own tab bar. This is especially annoying as the state in DockArea::items isn't synced to the underlying views, meaning the `DockArea::add_panel` function will do nothing after first splitting the panel, and then deleting the only element in the first part of the split. https://github.com/user-attachments/assets/2c61f2f0-9b1c-4154-8a53-b917335b94f0 This pull request adds a function that is called when a PanelView is added to a tabbar via `add_panel` or `insert_panel_at` or when it is removed via `detach_panel`. This allows for entities that implement Panel to keep track of and directly access the tab bar they belong to, and for example add new panels to it through buttons in the dropdown menu or the top right of the tab bar.
This commit is contained in:
parent
a176408d81
commit
df57b0b847
2 changed files with 20 additions and 1 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use crate::{button::Button, menu::PopupMenu};
|
||||
use crate::{button::Button, dock::TabPanel, menu::PopupMenu};
|
||||
use gpui::{
|
||||
AnyElement, AnyView, App, AppContext as _, Entity, EntityId, EventEmitter, FocusHandle,
|
||||
Focusable, Global, Hsla, IntoElement, Render, SharedString, WeakEntity, Window,
|
||||
|
|
@ -118,6 +118,12 @@ pub trait Panel: EventEmitter<PanelEvent> + Render + Focusable {
|
|||
/// Only current Panel will touch this method.
|
||||
fn set_zoomed(&mut self, zoomed: bool, window: &mut Window, cx: &mut App) {}
|
||||
|
||||
/// When this Panel is added to a TabPanel, this will be called.
|
||||
fn on_added_to(&mut self, tab_panel: WeakEntity<TabPanel>, window: &mut Window, cx: &mut App) {}
|
||||
|
||||
/// When this Panel is removed from a TabPanel, this will be called.
|
||||
fn on_removed(&mut self, window: &mut Window, cx: &mut App) {}
|
||||
|
||||
/// The addition dropdown menu of the panel, default is `None`.
|
||||
fn dropdown_menu(&self, this: PopupMenu, window: &Window, cx: &App) -> PopupMenu {
|
||||
this
|
||||
|
|
@ -153,6 +159,8 @@ pub trait PanelView: 'static + Send + Sync {
|
|||
fn visible(&self, cx: &App) -> bool;
|
||||
fn set_active(&self, active: bool, window: &mut Window, cx: &mut App);
|
||||
fn set_zoomed(&self, zoomed: bool, window: &mut Window, cx: &mut App);
|
||||
fn on_added_to(&self, tab_panel: WeakEntity<TabPanel>, window: &mut Window, cx: &mut App);
|
||||
fn on_removed(&self, window: &mut Window, cx: &mut App);
|
||||
fn dropdown_menu(&self, menu: PopupMenu, window: &Window, cx: &App) -> PopupMenu;
|
||||
fn toolbar_buttons(&self, window: &mut Window, cx: &mut App) -> Option<Vec<Button>>;
|
||||
fn view(&self) -> AnyView;
|
||||
|
|
@ -210,6 +218,14 @@ impl<T: Panel> PanelView for Entity<T> {
|
|||
})
|
||||
}
|
||||
|
||||
fn on_added_to(&self, tab_panel: WeakEntity<TabPanel>, window: &mut Window, cx: &mut App) {
|
||||
self.update(cx, |this, cx| this.on_added_to(tab_panel, window, cx));
|
||||
}
|
||||
|
||||
fn on_removed(&self, window: &mut Window, cx: &mut App) {
|
||||
self.update(cx, |this, cx| this.on_removed(window, cx));
|
||||
}
|
||||
|
||||
fn dropdown_menu(&self, menu: PopupMenu, window: &Window, cx: &App) -> PopupMenu {
|
||||
self.read(cx).dropdown_menu(menu, window, cx)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -256,6 +256,7 @@ impl TabPanel {
|
|||
return;
|
||||
}
|
||||
|
||||
panel.on_added_to(cx.entity().downgrade(), window, cx);
|
||||
self.panels.push(panel);
|
||||
// set the active panel to the new panel
|
||||
if active {
|
||||
|
|
@ -304,6 +305,7 @@ impl TabPanel {
|
|||
return;
|
||||
}
|
||||
|
||||
panel.on_added_to(cx.entity().downgrade(), window, cx);
|
||||
self.panels.insert(ix, panel);
|
||||
self.set_active_ix(ix, window, cx);
|
||||
cx.emit(PanelEvent::LayoutChanged);
|
||||
|
|
@ -329,6 +331,7 @@ impl TabPanel {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
panel.on_removed(window, cx);
|
||||
let panel_view = panel.view();
|
||||
self.panels.retain(|p| p.view() != panel_view);
|
||||
if self.active_ix >= self.panels.len() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue