This commit is contained in:
2026-10-30 14:12:09 +07:00
parent f23c582c16
commit 8be5ac91ec
6 changed files with 790 additions and 3 deletions
+153
View File
@@ -24,6 +24,7 @@ use gpui_native_core::toast::{Toast, ToastSeverity, Toasts, ToastsView};
use gpui_native_core::toggle::Toggle;
use gpui_native_core::tooltip::Tooltip;
use gpui_native_data::list::{List, ListItem};
use gpui_native_data::tree::{Tree, TreeItem};
use gpui_native_icons::{IconAssets, IconRole, icon};
use gpui_native_theme::{ActiveTheme as _, Theme};
use gpui_platform::application;
@@ -43,6 +44,66 @@ struct Gallery {
toasts: Entity<Toasts>,
scroll: gpui::ScrollHandle,
list_selected: Option<usize>,
tree_nodes: Vec<GalleryNode>,
tree_selected: Option<usize>,
}
/// A demo model for the tree section: the app owns the real tree and its
/// expansion set, and flattens the visible nodes for the component.
#[derive(Clone)]
struct GalleryNode {
label: SharedString,
icon: Option<IconRole>,
expanded: bool,
children: Vec<GalleryNode>,
}
fn flatten_tree(
nodes: &[GalleryNode],
depth: usize,
prefix: &[usize],
items: &mut Vec<TreeItem>,
paths: &mut Vec<Vec<usize>>,
) {
for (index, node) in nodes.iter().enumerate() {
let mut path = prefix.to_vec();
path.push(index);
let mut item = TreeItem::new(node.label.clone())
.depth(depth)
.expandable(!node.children.is_empty())
.expanded(node.expanded);
if let Some(role) = node.icon {
item = item.icon(role);
}
items.push(item);
paths.push(path.clone());
if node.expanded {
flatten_tree(&node.children, depth + 1, &path, items, paths);
}
}
}
fn toggle_tree_path(nodes: &mut [GalleryNode], path: &[usize]) {
let Some(index) = path.first() else { return };
let Some(node) = nodes.get_mut(*index) else {
return;
};
if path.len() == 1 {
node.expanded = !node.expanded;
} else {
toggle_tree_path(&mut node.children, &path[1..]);
}
}
/// The visible-row paths of the current tree state, matching the flat index
/// the tree component reports.
fn tree_paths(nodes: &[GalleryNode]) -> Vec<Vec<usize>> {
let mut items = Vec::new();
let mut paths = Vec::new();
flatten_tree(nodes, 0, &[], &mut items, &mut paths);
paths
}
impl Render for Gallery {
@@ -377,6 +438,40 @@ impl Render for Gallery {
.child(format!("selected: {:?}", self.list_selected)),
),
)
.child(
v_flex()
.gap_2()
.child(section_label(
"tree · native refs — NSOutlineView, WinUI TreeView, Adwaita expander rows, Breeze",
colors,
))
.child({
let gallery = gallery.clone();
let disclosure_gallery = gallery.clone();
let mut items = Vec::new();
let mut paths = Vec::new();
flatten_tree(&self.tree_nodes, 0, &[], &mut items, &mut paths);
Tree::new("gallery-tree")
.selected(self.tree_selected)
.on_change(move |selected, _, cx| {
gallery.update(cx, |gallery, cx| {
gallery.tree_selected = selected;
cx.notify();
});
})
.on_disclosure(move |index, _, cx| {
disclosure_gallery.update(cx, |gallery, cx| {
let paths = tree_paths(&gallery.tree_nodes);
if let Some(path) = paths.get(index) {
toggle_tree_path(&mut gallery.tree_nodes, path);
}
cx.notify();
});
})
.items(move |_, _| items.clone())
}),
)
.child(
v_flex()
.gap_2()
@@ -996,6 +1091,64 @@ fn main() {
toasts,
scroll: gpui::ScrollHandle::new(),
list_selected: None,
tree_selected: None,
tree_nodes: vec![
GalleryNode {
label: "Workspace".into(),
icon: Some(IconRole::Folder),
expanded: true,
children: vec![GalleryNode {
label: "gpui-native-kit".into(),
icon: Some(IconRole::Folder),
expanded: true,
children: vec![
GalleryNode {
label: "crates".into(),
icon: Some(IconRole::Folder),
expanded: true,
children: vec![
GalleryNode {
label: "theme".into(),
icon: None,
expanded: false,
children: Vec::new(),
},
GalleryNode {
label: "core".into(),
icon: None,
expanded: false,
children: Vec::new(),
},
GalleryNode {
label: "data".into(),
icon: None,
expanded: false,
children: Vec::new(),
},
],
},
GalleryNode {
label: "docs".into(),
icon: Some(IconRole::Folder),
expanded: false,
children: Vec::new(),
},
GalleryNode {
label: "Cargo.toml".into(),
icon: None,
expanded: false,
children: Vec::new(),
},
],
}],
},
GalleryNode {
label: "Archive.zip".into(),
icon: None,
expanded: false,
children: Vec::new(),
},
],
}
})
},