mirror of
https://github.com/yewprint/yewprint
synced 2025-02-16 12:08:25 +00:00
Tree: select_node and secondary label
This commit is contained in:
parent
e3ad2d2ed2
commit
8af689609e
2 changed files with 65 additions and 19 deletions
35
src/app.rs
35
src/app.rs
|
@ -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>
|
||||
}
|
||||
|
|
49
src/tree.rs
49
src/tree.rs
|
@ -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()}
|
||||
|
|
Loading…
Add table
Reference in a new issue