use std::fmt;
use dioxus::prelude::*;
use dioxus_swdir_tree_core::keyboard::{Modifiers as CoreMods, TreeKey};
use dioxus_swdir_tree_core::{ItemTree, ItemTreeEvent};
use crate::item_row::ItemTreeRow;
use crate::row::{ArcTheme, default_theme};
use crate::style as s;
#[derive(Props, Clone)]
pub struct ItemTreeViewProps<T: Clone + fmt::Debug + Send + Sync + 'static> {
pub tree: Signal<ItemTree<T>>,
pub on_event: EventHandler<ItemTreeEvent>,
#[props(optional)]
pub theme: Option<ArcTheme>,
}
impl<T: Clone + fmt::Debug + Send + Sync + 'static> PartialEq for ItemTreeViewProps<T> {
fn eq(&self, other: &Self) -> bool {
self.tree == other.tree && self.on_event == other.on_event && self.theme == other.theme
}
}
#[allow(non_snake_case)]
pub fn ItemTreeView<T: Clone + fmt::Debug + Send + Sync + 'static>(
props: ItemTreeViewProps<T>,
) -> Element {
let ItemTreeViewProps {
tree,
on_event,
theme,
} = props;
let theme = theme.unwrap_or_else(default_theme);
let t = tree.read();
let rows = t.visible_rows();
drop(t);
#[cfg(feature = "default-style")]
let default_style_css = Some(s::DEFAULT_CSS);
#[cfg(not(feature = "default-style"))]
let default_style_css: Option<&str> = None;
let on_keydown = move |evt: KeyboardEvent| {
let tree_key = match evt.key() {
Key::ArrowUp => TreeKey::Up,
Key::ArrowDown => TreeKey::Down,
Key::Home => TreeKey::Home,
Key::End => TreeKey::End,
Key::Enter => TreeKey::Enter,
Key::ArrowLeft => TreeKey::Left,
Key::ArrowRight => TreeKey::Right,
Key::Escape => TreeKey::Escape,
Key::Character(ref ch) if ch == " " => TreeKey::Space,
_ => return,
};
let mods = CoreMods {
shift: evt.modifiers().shift(),
ctrl: evt.modifiers().ctrl(),
};
if let Some(ev) = tree.read().handle_key(tree_key, mods) {
evt.prevent_default();
on_event.call(ev);
}
};
rsx! {
if let Some(css) = default_style_css {
style { "{css}" }
}
div {
class: s::CLASS_TREE,
tabindex: "0",
onkeydown: on_keydown,
for row in rows {
ItemTreeRow {
key: "{row.id.0}",
row,
on_event,
theme: theme.clone(),
}
}
}
}
}