dock: Add set_dock_collapsible to support setting the Docks to be collapsible or not. (#445)

Close #442 

In this case, the left Dock is not collapsible:

<img width="1165" alt="image"
src="https://github.com/user-attachments/assets/21422cdd-d686-4931-9285-925b8e8d3343">
This commit is contained in:
Jason Lee 2024-11-27 21:34:44 +08:00 committed by GitHub
parent 7fe91e4e12
commit 36dcc53824
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 80 additions and 17 deletions

View file

@ -204,6 +204,15 @@ impl StoryWorkspace {
dock_area.update(cx, |dock_area, cx| {
dock_area.load(state, cx).context("load layout")?;
dock_area.set_dock_collapsible(
Edges {
left: true,
bottom: true,
right: true,
..Default::default()
},
cx,
);
Ok::<(), anyhow::Error>(())
})

View file

@ -65,6 +65,11 @@ pub struct Dock {
/// The size is means the width or height of the Dock, if the placement is left or right, the size is width, otherwise the size is height.
pub(super) size: Pixels,
pub(super) open: bool,
/// Whether the Dock is collapsible, default: true
pub(super) collapsible: bool,
// Runtime state
/// Whether the Dock is resizing
is_resizing: bool,
}
@ -93,6 +98,7 @@ impl Dock {
dock_area,
panel,
open: true,
collapsible: true,
size: px(200.0),
is_resizing: false,
}
@ -110,6 +116,17 @@ impl Dock {
Self::new(dock_area, DockPlacement::Right, cx)
}
/// Update the Dock to be collapsible or not.
///
/// And if the Dock is not collapsible, it will be open.
pub fn set_collapsible(&mut self, collapsible: bool, cx: &mut ViewContext<Self>) {
self.collapsible = collapsible;
if !collapsible {
self.open = true
}
cx.notify();
}
pub(super) fn from_state(
dock_area: WeakView<DockArea>,
placement: DockPlacement,
@ -137,6 +154,7 @@ impl Dock {
panel,
open,
size,
collapsible: true,
is_resizing: false,
}
}

View file

@ -435,6 +435,55 @@ impl DockArea {
}
}
/// Set the dock at the given placement to be open or closed.
///
/// Only the left, bottom, right dock can be toggled.
pub fn set_dock_collapsible(
&mut self,
collapsible_edges: Edges<bool>,
cx: &mut ViewContext<Self>,
) {
if let Some(left_dock) = self.left_dock.as_ref() {
left_dock.update(cx, |dock, cx| {
dock.set_collapsible(collapsible_edges.left, cx);
});
}
if let Some(bottom_dock) = self.bottom_dock.as_ref() {
bottom_dock.update(cx, |dock, cx| {
dock.set_collapsible(collapsible_edges.bottom, cx);
});
}
if let Some(right_dock) = self.right_dock.as_ref() {
right_dock.update(cx, |dock, cx| {
dock.set_collapsible(collapsible_edges.right, cx);
});
}
}
/// Determine if the dock at the given placement is collapsible.
pub fn is_dock_collapsible(&self, placement: DockPlacement, cx: &AppContext) -> bool {
match placement {
DockPlacement::Left => self
.left_dock
.as_ref()
.map(|dock| dock.read(cx).collapsible)
.unwrap_or(false),
DockPlacement::Bottom => self
.bottom_dock
.as_ref()
.map(|dock| dock.read(cx).collapsible)
.unwrap_or(false),
DockPlacement::Right => self
.right_dock
.as_ref()
.map(|dock| dock.read(cx).collapsible)
.unwrap_or(false),
DockPlacement::Center => false,
}
}
pub fn toggle_dock(&self, placement: DockPlacement, cx: &mut ViewContext<Self>) {
let dock = match placement {
DockPlacement::Left => &self.left_dock,

View file

@ -57,11 +57,6 @@ pub trait Panel: EventEmitter<PanelEvent> + FocusableView {
true
}
/// Return true if the panel is collapsible, default is `false`.
fn collapsible(&self, _cx: &WindowContext) -> bool {
false
}
/// The addition popup menu of the panel, default is `None`.
fn popup_menu(&self, this: PopupMenu, _cx: &WindowContext) -> PopupMenu {
this
@ -84,7 +79,6 @@ pub trait PanelView: 'static + Send + Sync {
fn title_style(&self, _cx: &WindowContext) -> Option<TitleStyle>;
fn closeable(&self, cx: &WindowContext) -> bool;
fn zoomable(&self, cx: &WindowContext) -> bool;
fn collapsible(&self, cx: &WindowContext) -> bool;
fn popup_menu(&self, menu: PopupMenu, cx: &WindowContext) -> PopupMenu;
fn toolbar_buttons(&self, cx: &WindowContext) -> Vec<Button>;
fn view(&self) -> AnyView;
@ -113,10 +107,6 @@ impl<T: Panel> PanelView for View<T> {
self.read(cx).zoomable(cx)
}
fn collapsible(&self, cx: &WindowContext) -> bool {
self.read(cx).collapsible(cx)
}
fn popup_menu(&self, menu: PopupMenu, cx: &WindowContext) -> PopupMenu {
self.read(cx).popup_menu(menu, cx)
}

View file

@ -109,12 +109,6 @@ impl Panel for TabPanel {
.unwrap_or(false)
}
fn collapsible(&self, cx: &WindowContext) -> bool {
self.active_panel()
.map(|panel| panel.collapsible(cx))
.unwrap_or(false)
}
fn popup_menu(&self, menu: PopupMenu, cx: &WindowContext) -> PopupMenu {
if let Some(panel) = self.active_panel() {
panel.popup_menu(menu, cx)
@ -383,9 +377,12 @@ impl TabPanel {
return None;
}
let view_entity_id = cx.view().entity_id();
let dock_area = self.dock_area.upgrade()?.read(cx);
if !dock_area.is_dock_collapsible(placement, cx) {
return None;
}
let view_entity_id = cx.view().entity_id();
let toggle_button_panels = dock_area.toggle_button_panels;
// Check if current TabPanel's entity_id matches the one stored in DockArea for this placement