From a5a72fcb5a105e7cf2d16bbf38b0f13f0dc509bb Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Fri, 13 Dec 2024 11:23:00 +0800 Subject: [PATCH] panel: Avoid render panel when TabPanel is collapsed. (#492) Close #488 - Fix `collapsed` sync to `TabPanel` when load state. --- crates/ui/src/dock/dock.rs | 5 +++ crates/ui/src/dock/mod.rs | 23 ++++++++++++++ crates/ui/src/dock/tab_panel.rs | 56 +++++++++++++++++++-------------- crates/ui/src/tab/tab.rs | 13 ++++++-- 4 files changed, 70 insertions(+), 27 deletions(-) diff --git a/crates/ui/src/dock/dock.rs b/crates/ui/src/dock/dock.rs index 274dfc92..54b8718d 100644 --- a/crates/ui/src/dock/dock.rs +++ b/crates/ui/src/dock/dock.rs @@ -144,6 +144,11 @@ impl Dock { panel.set_collapsed(true, cx); }); } + DockItem::Split { items, .. } => { + for item in items { + item.set_collapsed(true, cx); + } + } _ => {} } } diff --git a/crates/ui/src/dock/mod.rs b/crates/ui/src/dock/mod.rs index 672cceea..910f071d 100644 --- a/crates/ui/src/dock/mod.rs +++ b/crates/ui/src/dock/mod.rs @@ -85,6 +85,29 @@ pub enum DockItem { Panel { view: Arc }, } +impl std::fmt::Debug for DockItem { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + DockItem::Split { + axis, items, sizes, .. + } => f + .debug_struct("Split") + .field("axis", axis) + .field("items", &items.len()) + .field("sizes", sizes) + .finish(), + DockItem::Tabs { + items, active_ix, .. + } => f + .debug_struct("Tabs") + .field("items", &items.len()) + .field("active_ix", active_ix) + .finish(), + DockItem::Panel { .. } => f.debug_struct("Panel").finish(), + } + } +} + impl DockItem { /// Create DockItem with split layout, each item of panel have equal size. pub fn split( diff --git a/crates/ui/src/dock/tab_panel.rs b/crates/ui/src/dock/tab_panel.rs index 8c2aa1f5..427122e8 100644 --- a/crates/ui/src/dock/tab_panel.rs +++ b/crates/ui/src/dock/tab_panel.rs @@ -560,6 +560,7 @@ impl TabPanel { ) .children(self.panels.iter().enumerate().map(|(ix, panel)| { let mut active = ix == self.active_ix; + let disabled = self.is_collapsed; // Always not show active tab style, if the panel is collapsed if self.is_collapsed { @@ -569,31 +570,34 @@ impl TabPanel { Tab::new(("tab", ix), panel.title(cx)) .py_2() .selected(active) - .on_click(cx.listener(move |view, _, cx| { - view.set_active_ix(ix, cx); - })) - .when(state.draggable, |this| { - this.on_drag( - DragPanel::new(panel.clone(), view.clone()), - |drag, _, cx| { - cx.stop_propagation(); - cx.new_view(|_| drag.clone()) - }, - ) - }) - .when(state.droppable, |this| { - this.drag_over::(|this, _, cx| { - this.rounded_l_none() - .border_l_2() - .border_r_0() - .border_color(cx.theme().drag_border) + .disabled(disabled) + .when(!disabled, |this| { + this.on_click(cx.listener(move |view, _, cx| { + view.set_active_ix(ix, cx); + })) + .when(state.draggable, |this| { + this.on_drag( + DragPanel::new(panel.clone(), view.clone()), + |drag, _, cx| { + cx.stop_propagation(); + cx.new_view(|_| drag.clone()) + }, + ) + }) + .when(state.droppable, |this| { + this.drag_over::(|this, _, cx| { + this.rounded_l_none() + .border_l_2() + .border_r_0() + .border_color(cx.theme().drag_border) + }) + .on_drop(cx.listener( + move |this, drag: &DragPanel, cx| { + this.will_split_placement = None; + this.on_drop(drag, Some(ix), true, cx) + }, + )) }) - .on_drop(cx.listener( - move |this, drag: &DragPanel, cx| { - this.will_split_placement = None; - this.on_drop(drag, Some(ix), true, cx) - }, - )) }) })) .child( @@ -637,6 +641,10 @@ impl TabPanel { } fn render_active_panel(&self, state: TabState, cx: &mut ViewContext) -> impl IntoElement { + if self.is_collapsed { + return Empty {}.into_any_element(); + } + self.active_panel() .map(|panel| { div() diff --git a/crates/ui/src/tab/tab.rs b/crates/ui/src/tab/tab.rs index df3521d4..89ea53ad 100644 --- a/crates/ui/src/tab/tab.rs +++ b/crates/ui/src/tab/tab.rs @@ -42,6 +42,12 @@ impl Tab { self.suffix = Some(suffix.into()); self } + + /// Set disabled state to the tab + pub fn disabled(mut self, disabled: bool) -> Self { + self.disabled = disabled; + self + } } impl Selectable for Tab { @@ -72,9 +78,11 @@ impl Styled for Tab { impl RenderOnce for Tab { fn render(self, cx: &mut WindowContext) -> impl IntoElement { let (text_color, bg_color) = match (self.selected, self.disabled) { - (true, _) => (cx.theme().tab_active_foreground, cx.theme().tab_active), - (false, true) => (cx.theme().tab_foreground.opacity(0.5), cx.theme().tab), + (true, false) => (cx.theme().tab_active_foreground, cx.theme().tab_active), (false, false) => (cx.theme().muted_foreground, cx.theme().tab), + // disabled + (true, true) => (cx.theme().muted_foreground, cx.theme().tab_active), + (false, true) => (cx.theme().muted_foreground, cx.theme().tab), }; self.base @@ -89,7 +97,6 @@ impl RenderOnce for Tab { .border_color(cx.theme().transparent) .when(self.selected, |this| this.border_color(cx.theme().border)) .text_sm() - .when(self.disabled, |this| this) .when_some(self.prefix, |this, prefix| { this.child(prefix).text_color(text_color) })