Tree: select_node and secondary label

This commit is contained in:
Cecile Tonglet 2020-09-14 20:43:07 +02:00
parent e3ad2d2ed2
commit 8af689609e
2 changed files with 65 additions and 19 deletions

View file

@ -1,7 +1,7 @@
use crate::buttons::Button;
use crate::collapse::Collapse;
use crate::forms::controls::Switch;
use crate::icon::IconName;
use crate::icon::*;
use crate::tree::*;
use crate::Intent;
use yew::prelude::*;
@ -24,6 +24,7 @@ pub enum Msg {
ToggleLight,
ToggleCollapse,
ExpandNode(NodeId),
SelectNode(NodeId),
}
impl Component for App {
@ -39,12 +40,11 @@ impl Component for App {
icon_color: None,
icon_intent: None,
label: "".into(),
secondary_label: None,
is_selected: false,
is_expanded: false,
has_caret: true,
disabled: false,
on_collapse: None,
on_expand: None,
data: 0,
}),
InsertBehavior::AsRoot,
@ -57,12 +57,11 @@ impl Component for App {
icon_color: None,
icon_intent: None,
label: "Directory 1".into(),
secondary_label: None,
is_selected: false,
is_expanded: false,
has_caret: true,
disabled: false,
on_collapse: Some(link.callback(|(node_id, _)| Msg::ExpandNode(node_id))),
on_expand: Some(link.callback(|(node_id, _)| Msg::ExpandNode(node_id))),
data: 1,
}),
InsertBehavior::UnderNode(&root_id),
@ -74,12 +73,11 @@ impl Component for App {
icon_color: None,
icon_intent: None,
label: "File 1".into(),
secondary_label: None,
is_selected: false,
is_expanded: false,
has_caret: false,
disabled: false,
on_collapse: None,
on_expand: None,
data: 2,
}),
InsertBehavior::UnderNode(&root_id),
@ -91,12 +89,11 @@ impl Component for App {
icon_color: None,
icon_intent: Some(Intent::Primary),
label: "File 2".into(),
secondary_label: Some(html!(<Icon icon=IconName::EyeOpen />)),
is_selected: false,
is_expanded: false,
has_caret: false,
disabled: false,
on_collapse: None,
on_expand: None,
data: 3,
}),
InsertBehavior::UnderNode(&dir1),
@ -120,7 +117,18 @@ impl Component for App {
Msg::ExpandNode(node_id) => {
let mut tree = self.tree.borrow_mut();
let node = tree.get_mut(&node_id).unwrap();
node.data_mut().is_expanded ^= true;
let data = node.data_mut();
data.is_expanded ^= true;
data.icon = Some(if data.is_expanded {
IconName::FolderOpen
} else {
IconName::FolderClose
})
}
Msg::SelectNode(node_id) => {
let mut tree = self.tree.borrow_mut();
let node = tree.get_mut(&node_id).unwrap();
node.data_mut().is_selected ^= true;
}
}
true
@ -183,7 +191,12 @@ impl Component for App {
</Collapse>
</div>
<div>
<Tree<i32> tree=self.tree.clone() />
<Tree<i32>
tree=self.tree.clone()
on_collapse=Some(self.link.callback(|(node_id, _)| Msg::ExpandNode(node_id)))
on_expand=Some(self.link.callback(|(node_id, _)| Msg::ExpandNode(node_id)))
onclick=Some(self.link.callback(|(node_id, _)| Msg::SelectNode(node_id)))
/>
</div>
</div>
}

View file

@ -47,6 +47,12 @@ pub struct Props<T: Clone> {
#[prop_or_default]
pub is_expanded: bool,
pub tree: TreeData<T>,
#[prop_or_default]
pub on_collapse: Option<Callback<(id_tree::NodeId, MouseEvent)>>,
#[prop_or_default]
pub on_expand: Option<Callback<(id_tree::NodeId, MouseEvent)>>,
#[prop_or_default]
pub onclick: Option<Callback<(id_tree::NodeId, MouseEvent)>>,
}
pub struct NodeData<T> {
@ -58,8 +64,7 @@ pub struct NodeData<T> {
pub is_expanded: bool,
pub is_selected: bool,
pub label: yew::virtual_dom::VNode,
pub on_collapse: Option<Callback<(id_tree::NodeId, MouseEvent)>>,
pub on_expand: Option<Callback<(id_tree::NodeId, MouseEvent)>>,
pub secondary_label: Option<yew::virtual_dom::VNode>,
pub data: T,
}
@ -111,13 +116,26 @@ impl<T: Clone> Tree<T> {
let data = node.data();
let on_collapse = {
let node_id = node_id.clone();
data.on_collapse
.clone()
.map(move |x| x.reform(move |event| (node_id.clone(), event)))
self.props.on_collapse.clone().map(move |x| {
x.reform(move |event: MouseEvent| {
event.stop_propagation();
(node_id.clone(), event)
})
})
};
let on_expand = {
let node_id = node_id.clone();
data.on_expand
self.props.on_expand.clone().map(move |x| {
x.reform(move |event: MouseEvent| {
event.stop_propagation();
(node_id.clone(), event)
})
})
};
let onclick = {
let node_id = node_id.clone();
self.props
.onclick
.clone()
.map(move |x| x.reform(move |event| (node_id.clone(), event)))
};
@ -133,8 +151,10 @@ impl<T: Clone> Tree<T> {
is_expanded=data.is_expanded
is_selected=data.is_selected
label=data.label.clone()
secondary_label=data.secondary_label.clone()
on_collapse=on_collapse
on_expand=on_expand
onclick=onclick
depth=depth
>
{inner_nodes}
@ -164,8 +184,10 @@ pub struct TreeNodeProps {
pub is_expanded: bool,
pub is_selected: bool,
pub label: yew::virtual_dom::VNode,
pub secondary_label: Option<yew::virtual_dom::VNode>,
pub on_collapse: Option<Callback<MouseEvent>>,
pub on_expand: Option<Callback<MouseEvent>>,
pub onclick: Option<Callback<MouseEvent>>,
pub children: html::Children,
pub depth: u32,
}
@ -192,12 +214,16 @@ impl Component for TreeNode {
}
fn view(&self) -> Html {
let mut container_class = Classes::from("bp3-tree-node");
if self.props.is_selected {
container_class.push("bp3-tree-node-selected");
}
let mut content_class = Classes::from("bp3-tree-node-content");
content_class.push(&format!("bp3-tree-node-content-{}", self.props.depth));
html! {
<li class="bp3-tree-node">
<div class=content_class>
<li class=container_class>
<div class=content_class onclick?={self.props.onclick.clone()}>
{
if self.props.has_caret {
let mut class = Classes::from("bp3-tree-node-caret");
@ -235,6 +261,13 @@ impl Component for TreeNode {
intent=self.props.icon_intent,
/>
<span class="bp3-tree-node-label">{self.props.label.clone()}</span>
{
if let Some(label) = self.props.secondary_label.clone() {
html!(<span class="bp3-tree-node-secondary-label">{label}</span>)
} else {
html!()
}
}
</div>
<Collapse is_open=self.props.is_expanded>
{self.props.children.clone()}