panel: Avoid render panel when TabPanel is collapsed. (#492)

Close #488

- Fix `collapsed` sync to `TabPanel` when load state.
This commit is contained in:
Jason Lee 2024-12-13 11:23:00 +08:00 committed by GitHub
parent 5630154590
commit a5a72fcb5a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 70 additions and 27 deletions

View file

@ -144,6 +144,11 @@ impl Dock {
panel.set_collapsed(true, cx);
});
}
DockItem::Split { items, .. } => {
for item in items {
item.set_collapsed(true, cx);
}
}
_ => {}
}
}

View file

@ -85,6 +85,29 @@ pub enum DockItem {
Panel { view: Arc<dyn PanelView> },
}
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(

View file

@ -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::<DragPanel>(|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::<DragPanel>(|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<Self>) -> impl IntoElement {
if self.is_collapsed {
return Empty {}.into_any_element();
}
self.active_panel()
.map(|panel| {
div()

View file

@ -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)
})