use nalgebra_glm::{Vec2, Vec4};
use crate::ecs::text::components::{TextAlignment, VerticalAlignment};
use crate::ecs::ui::builder::UiTreeBuilder;
use crate::ecs::ui::components::*;
use crate::ecs::ui::layout_types::FlowDirection;
use crate::ecs::ui::state::{UiBase, UiHover};
use crate::ecs::ui::units::{Ab, Rl};
impl<'a> UiTreeBuilder<'a> {
pub fn add_tree_view(&mut self, multi_select: bool) -> freecs::Entity {
let scroll_entity = self.add_scroll_area_fill(2.0, 0.0);
let content_entity = self
.world_mut()
.widget::<UiScrollAreaData>(scroll_entity)
.map(|d| d.content_entity)
.unwrap_or(scroll_entity);
self.world_mut().ui.set_ui_widget_state(
scroll_entity,
UiWidgetState::TreeView(UiTreeViewData {
selected_nodes: Vec::new(),
multi_select,
node_entities: Vec::new(),
changed: false,
content_entity,
context_menu_node: None,
filter_text: String::new(),
filter_active: false,
pre_filter_expanded: std::collections::HashMap::new(),
}),
);
if let Some(interaction) = self
.world_mut()
.ui
.get_ui_node_interaction_mut(scroll_entity)
{
interaction.accessible_role = Some(AccessibleRole::Tree);
}
scroll_entity
}
pub fn add_tree_node(
&mut self,
tree: freecs::Entity,
parent_container: freecs::Entity,
label: &str,
depth: usize,
user_data: u64,
) -> freecs::Entity {
let theme = self
.world_mut()
.resources
.retained_ui
.theme_state
.active_theme();
let font_size = theme.font_size;
let row_height = font_size * 1.4;
let indent = depth as f32 * 16.0;
let arrow_slot = self.world_mut().resources.text_cache.add_text("\u{25B6}");
let label_slot = self.world_mut().resources.text_cache.add_text(label);
let wrapper_entity = self
.add_node()
.flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, 0.0)))
.flow(FlowDirection::Vertical, 0.0, 0.0)
.without_pointer_events()
.entity();
if let Some(parent) = self.world_mut().core.get_parent_mut(wrapper_entity) {
*parent = crate::ecs::transform::components::Parent(Some(parent_container));
}
self.world_mut().resources.children_cache_valid = false;
self.push_parent(wrapper_entity);
let row_entity = self
.add_node()
.flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, row_height)))
.with_rect(2.0, 0.0, Vec4::new(0.0, 0.0, 0.0, 0.0))
.with_color::<UiBase>(Vec4::new(0.0, 0.0, 0.0, 0.0))
.with_theme_color::<UiHover>(ThemeColor::BackgroundHover)
.with_interaction()
.with_transition::<UiHover>(8.0, 6.0)
.with_cursor_icon(winit::window::CursorIcon::Pointer)
.flow(FlowDirection::Horizontal, 4.0, 2.0)
.entity();
self.push_parent(row_entity);
if indent > 0.0 {
self.add_node()
.flow_child(Ab(Vec2::new(indent, row_height)))
.without_pointer_events()
.done();
}
let arrow_entity = self
.add_node()
.flow_child(Ab(Vec2::new(16.0, row_height)))
.with_text_slot(arrow_slot, font_size * 0.8)
.with_text_alignment(TextAlignment::Center, VerticalAlignment::Middle)
.with_theme_color::<UiBase>(ThemeColor::Text)
.without_pointer_events()
.done();
self.add_node()
.flow_child(Rl(Vec2::new(0.0, 100.0)))
.flex_grow(1.0)
.with_text_slot(label_slot, font_size)
.with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
.with_theme_color::<UiBase>(ThemeColor::Text)
.without_pointer_events()
.done();
self.pop_parent();
let children_container = self
.add_node()
.flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, 0.0)))
.flow(FlowDirection::Vertical, 0.0, 0.0)
.with_visible(false)
.without_pointer_events()
.entity();
self.pop_parent();
let node_entity = row_entity;
let existing_nodes = if let Some(UiWidgetState::TreeView(tree_data)) =
self.world_mut().ui.get_ui_widget_state(tree)
{
tree_data.node_entities.clone()
} else {
Vec::new()
};
let parent_node = existing_nodes.iter().find_map(|&candidate| {
if let Some(UiWidgetState::TreeNode(nd)) =
self.world_mut().ui.get_ui_widget_state(candidate)
&& nd.children_container == parent_container
{
return Some(candidate);
}
None
});
self.world_mut().ui.set_ui_widget_state(
node_entity,
UiWidgetState::TreeNode(UiTreeNodeData {
label: label.to_string(),
text_slot: label_slot,
depth,
expanded: false,
selected: false,
row_entity,
arrow_entity,
arrow_text_slot: arrow_slot,
children_container,
user_data,
parent_node,
wrapper_entity,
lazy: false,
lazy_loaded: false,
}),
);
if let Some(interaction) = self.world_mut().ui.get_ui_node_interaction_mut(node_entity) {
interaction.accessible_role = Some(AccessibleRole::TreeItem);
}
if let Some(UiWidgetState::TreeView(tree_data)) =
self.world_mut().ui.get_ui_widget_state_mut(tree)
{
tree_data.node_entities.push(node_entity);
}
node_entity
}
pub fn add_tree_node_lazy(
&mut self,
tree: freecs::Entity,
parent_container: freecs::Entity,
label: &str,
depth: usize,
user_data: u64,
) -> freecs::Entity {
let node = self.add_tree_node(tree, parent_container, label, depth, user_data);
if let Some(UiWidgetState::TreeNode(data)) =
self.world_mut().ui.get_ui_widget_state_mut(node)
{
data.lazy = true;
}
node
}
}