dock: Add DockItem::panel (#464)

**Description**:
Improve the flexibility of `DockArea`, sometime user won't need a
`TabPanel`, just display some message or UI elements. Curren implement
only allow use Tab or Split. So this PR will add `Plain` to `DockItem`,
user can put anything which implement `PanelView` trait.

**Usage**:
```rust
let left_panels = DockItem::panel(Arc::new(<- PanelView ->));

_ = dock_area.update(cx, |view, cx| {
    view.set_version(DOCK_AREA.version, cx);
    view.set_left_dock(left_panels, Some(px(260.)), true, cx);
    view.set_center(dock_item, cx);
    view.set_dock_collapsible(
        Edges {
            left: false,
            ..Default::default()
        },
        cx,
    );
});
```

**Screenshot**
<img width="1300" alt="image"
src="https://github.com/user-attachments/assets/a01e427c-50f1-4509-82d1-76cc016aa7b3">
This commit is contained in:
reya 2024-12-05 10:12:08 +07:00 committed by GitHub
parent bc7dfb877b
commit 07a8e70d1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 0 deletions

View file

@ -188,6 +188,9 @@ impl Dock {
} }
}); });
} }
DockItem::Panel { .. } => {
// Not supported
}
} }
} }
@ -367,6 +370,7 @@ impl Render for Dock {
.map(|this| match &self.panel { .map(|this| match &self.panel {
DockItem::Split { view, .. } => this.child(view.clone()), DockItem::Split { view, .. } => this.child(view.clone()),
DockItem::Tabs { view, .. } => this.child(view.clone()), DockItem::Tabs { view, .. } => this.child(view.clone()),
DockItem::Panel { view, .. } => this.child(view.clone().view()),
}) })
.child(self.render_resize_handle(cx)) .child(self.render_resize_handle(cx))
.child(DockElement { .child(DockElement {

View file

@ -68,17 +68,21 @@ pub struct DockArea {
/// DockItem is a tree structure that represents the layout of the dock. /// DockItem is a tree structure that represents the layout of the dock.
#[derive(Clone)] #[derive(Clone)]
pub enum DockItem { pub enum DockItem {
/// Split layout
Split { Split {
axis: gpui::Axis, axis: gpui::Axis,
items: Vec<DockItem>, items: Vec<DockItem>,
sizes: Vec<Option<Pixels>>, sizes: Vec<Option<Pixels>>,
view: View<StackPanel>, view: View<StackPanel>,
}, },
/// Tab layout
Tabs { Tabs {
items: Vec<Arc<dyn PanelView>>, items: Vec<Arc<dyn PanelView>>,
active_ix: usize, active_ix: usize,
view: View<TabPanel>, view: View<TabPanel>,
}, },
/// Panel layout
Panel { view: Arc<dyn PanelView> },
} }
impl DockItem { impl DockItem {
@ -140,6 +144,11 @@ impl DockItem {
} }
} }
/// Create DockItem with panel layout
pub fn panel(panel: Arc<dyn PanelView>) -> Self {
Self::Panel { view: panel }
}
/// Create DockItem with tabs layout, items are displayed as tabs. /// Create DockItem with tabs layout, items are displayed as tabs.
/// ///
/// The `active_ix` is the index of the active tab, if `None` the first tab is active. /// The `active_ix` is the index of the active tab, if `None` the first tab is active.
@ -192,6 +201,7 @@ impl DockItem {
match self { match self {
Self::Split { view, .. } => Arc::new(view.clone()), Self::Split { view, .. } => Arc::new(view.clone()),
Self::Tabs { view, .. } => Arc::new(view.clone()), Self::Tabs { view, .. } => Arc::new(view.clone()),
Self::Panel { view, .. } => view.clone(),
} }
} }
@ -202,6 +212,7 @@ impl DockItem {
items.iter().find_map(|item| item.find_panel(panel.clone())) items.iter().find_map(|item| item.find_panel(panel.clone()))
} }
Self::Tabs { items, .. } => items.iter().find(|item| *item == &panel).cloned(), Self::Tabs { items, .. } => items.iter().find(|item| *item == &panel).cloned(),
Self::Panel { view } => Some(view.clone()),
} }
} }
@ -237,6 +248,7 @@ impl DockItem {
stack_panel.add_panel(new_item.view(), None, dock_area.clone(), cx); stack_panel.add_panel(new_item.view(), None, dock_area.clone(), cx);
}); });
} }
Self::Panel { .. } => {}
} }
} }
@ -253,6 +265,7 @@ impl DockItem {
item.set_collapsed(collapsed, cx); item.set_collapsed(collapsed, cx);
} }
} }
DockItem::Panel { .. } => {}
} }
} }
@ -261,6 +274,7 @@ impl DockItem {
match self { match self {
DockItem::Tabs { view, .. } => Some(view.clone()), DockItem::Tabs { view, .. } => Some(view.clone()),
DockItem::Split { view, .. } => view.read(cx).left_top_tab_panel(true, cx), DockItem::Split { view, .. } => view.read(cx).left_top_tab_panel(true, cx),
DockItem::Panel { .. } => None,
} }
} }
@ -269,6 +283,7 @@ impl DockItem {
match self { match self {
DockItem::Tabs { view, .. } => Some(view.clone()), DockItem::Tabs { view, .. } => Some(view.clone()),
DockItem::Split { view, .. } => view.read(cx).right_top_tab_panel(true, cx), DockItem::Split { view, .. } => view.read(cx).right_top_tab_panel(true, cx),
DockItem::Panel { .. } => None,
} }
} }
} }
@ -640,6 +655,9 @@ impl DockArea {
DockItem::Tabs { .. } => { DockItem::Tabs { .. } => {
// We subscribe to the tab panel event in StackPanel's insert_panel // We subscribe to the tab panel event in StackPanel's insert_panel
} }
DockItem::Panel { .. } => {
// Not supported
}
} }
} }
@ -707,6 +725,7 @@ impl DockArea {
match &self.items { match &self.items {
DockItem::Split { view, .. } => view.clone().into_any_element(), DockItem::Split { view, .. } => view.clone().into_any_element(),
DockItem::Tabs { view, .. } => view.clone().into_any_element(), DockItem::Tabs { view, .. } => view.clone().into_any_element(),
DockItem::Panel { view, .. } => view.clone().view().into_any_element(),
} }
} }