dioxus_swdir_tree/
item_view.rs1use std::fmt;
4
5use dioxus::prelude::*;
6use dioxus_swdir_tree_core::keyboard::{Modifiers as CoreMods, TreeKey};
7use dioxus_swdir_tree_core::{ItemDragMsg, ItemTree, ItemTreeEvent};
8
9use crate::item_row::ItemTreeRow;
10use crate::row::{ArcTheme, default_theme};
11use crate::style as s;
12
13#[derive(Props, Clone)]
47pub struct ItemTreeViewProps<T: Clone + fmt::Debug + Send + Sync + 'static> {
48 pub tree: Signal<ItemTree<T>>,
49 pub on_event: EventHandler<ItemTreeEvent>,
50 #[props(optional)]
51 pub theme: Option<ArcTheme>,
52}
53
54impl<T: Clone + fmt::Debug + Send + Sync + 'static> PartialEq for ItemTreeViewProps<T> {
55 fn eq(&self, other: &Self) -> bool {
56 self.tree == other.tree && self.on_event == other.on_event && self.theme == other.theme
58 }
59}
60
61#[allow(non_snake_case)]
62pub fn ItemTreeView<T: Clone + fmt::Debug + Send + Sync + 'static>(
63 props: ItemTreeViewProps<T>,
64) -> Element {
65 let ItemTreeViewProps {
66 tree,
67 on_event,
68 theme,
69 } = props;
70 let theme = theme.unwrap_or_else(default_theme);
71
72 let t = tree.read();
73 let rows = t.visible_rows();
74 let dnd_enabled = t.is_drag_and_drop_enabled();
75 let hover = t.drop_target();
76 let is_dragging = t.is_dragging();
77 drop(t);
78
79 #[cfg(feature = "default-style")]
80 let default_style_css = Some(s::DEFAULT_CSS);
81 #[cfg(not(feature = "default-style"))]
82 let default_style_css: Option<&str> = None;
83
84 let on_keydown = move |evt: KeyboardEvent| {
85 let tree_key = match evt.key() {
86 Key::ArrowUp => TreeKey::Up,
87 Key::ArrowDown => TreeKey::Down,
88 Key::Home => TreeKey::Home,
89 Key::End => TreeKey::End,
90 Key::Enter => TreeKey::Enter,
91 Key::ArrowLeft => TreeKey::Left,
92 Key::ArrowRight => TreeKey::Right,
93 Key::Escape => TreeKey::Escape,
94 Key::Character(ref ch) if ch == " " => TreeKey::Space,
95 _ => return,
96 };
97 let mods = CoreMods {
98 shift: evt.modifiers().shift(),
99 ctrl: evt.modifiers().ctrl(),
100 };
101 if let Some(ev) = tree.read().handle_key(tree_key, mods) {
102 evt.prevent_default();
103 on_event.call(ev);
104 }
105 };
106
107 rsx! {
108 if let Some(css) = default_style_css {
109 style { "{css}" }
110 }
111
112 div {
113 class: s::CLASS_TREE,
114 tabindex: "0",
115 onkeydown: on_keydown,
116 onmouseup: move |_| {
117 if is_dragging {
118 on_event.call(ItemTreeEvent::Drag(ItemDragMsg::Cancelled));
119 }
120 },
121
122 for row in rows {
123 ItemTreeRow {
124 key: "{row.id.0}",
125 row,
126 on_event,
127 theme: theme.clone(),
128 dnd_enabled,
129 hover,
130 }
131 }
132 }
133 }
134}