use nalgebra_glm::{Vec2, Vec4};
use crate::ecs::ui::builder::UiTreeBuilder;
use crate::ecs::ui::components::{DataGridColumn, DragValueConfig, SliderConfig, TextSpan};
use crate::ecs::ui::composite::CompositeWidget;
use crate::ecs::ui::resources::{FromPropertyValue, IntoPropertyValue};
use crate::ecs::ui::theme::UiTheme;
use crate::ecs::ui::types::Rect;
pub struct Ui<'t, 'w> {
tree: &'t mut UiTreeBuilder<'w>,
parent: freecs::Entity,
prefix: Option<String>,
}
impl<'t, 'w> Ui<'t, 'w> {
fn scoped<R>(&mut self, f: impl FnOnce(&mut UiTreeBuilder<'w>) -> R) -> R {
self.tree.push_parent(self.parent);
let result = f(&mut *self.tree);
self.tree.pop_parent();
result
}
fn container(
&mut self,
add_fn: impl FnOnce(&mut UiTreeBuilder<'w>) -> freecs::Entity,
f: impl FnOnce(&mut Ui<'_, 'w>),
) -> freecs::Entity {
let entity = self.scoped(add_fn);
let content = self
.tree
.world_mut()
.ui_widget_content(entity)
.unwrap_or(entity);
let mut child_ui = Ui {
tree: &mut *self.tree,
parent: content,
prefix: self.prefix.clone(),
};
f(&mut child_ui);
entity
}
fn full_name(&self, name: &str) -> String {
match &self.prefix {
Some(prefix) => format!("{prefix}{name}"),
None => name.to_string(),
}
}
fn register_named<T: IntoPropertyValue>(
&mut self,
name: &str,
entity: freecs::Entity,
initial: T,
) {
if !name.is_empty() {
let full = self.full_name(name);
let property_id = self.tree.world_mut().ui_create_property(entity, initial);
self.tree
.world_mut()
.resources
.retained_ui
.register_named_property(&full, property_id);
}
}
pub fn tree(&mut self) -> &mut UiTreeBuilder<'w> {
self.tree
}
pub fn parent(&self) -> freecs::Entity {
self.parent
}
pub fn world_mut(&mut self) -> &mut crate::ecs::world::World {
self.tree.world_mut()
}
pub fn theme(&self) -> &UiTheme {
self.tree.active_theme()
}
pub fn set_test_id(&mut self, entity: freecs::Entity, test_id: &str) {
self.tree.world_mut().ui_set_test_id(entity, test_id);
}
pub fn set_flex_grow(&mut self, entity: freecs::Entity, weight: f32) {
if let Some(node) = self.tree.world_mut().ui.get_ui_layout_node_mut(entity) {
node.flex_grow = Some(weight);
}
}
pub fn set_visible(&mut self, entity: freecs::Entity, visible: bool) {
self.tree.world_mut().ui_set_visible(entity, visible);
}
pub fn set_disabled(&mut self, entity: freecs::Entity, disabled: bool) {
self.tree.world_mut().ui_set_disabled(entity, disabled);
}
pub fn set_disabled_recursive(&mut self, entity: freecs::Entity, disabled: bool) {
self.tree
.world_mut()
.ui_set_disabled_recursive(entity, disabled);
}
pub fn react<T, F>(&mut self, name: &str, handler: F)
where
T: FromPropertyValue + 'static,
F: FnMut(T, &mut crate::ecs::world::World) + 'static,
{
let full = self.full_name(name);
self.tree.world_mut().ui_react::<T, F>(&full, handler);
}
pub fn scope(&mut self, name: &str, f: impl FnOnce(&mut Ui<'_, 'w>)) {
let new_prefix = match &self.prefix {
Some(prefix) => format!("{prefix}{name}."),
None => format!("{name}."),
};
let mut child_ui = Ui {
tree: &mut *self.tree,
parent: self.parent,
prefix: Some(new_prefix),
};
f(&mut child_ui);
}
pub fn react_clicked<F>(&mut self, entity: freecs::Entity, handler: F)
where
F: FnMut(&mut crate::ecs::world::World) + 'static,
{
self.tree.world_mut().ui_react_clicked(entity, handler);
}
pub fn react_submitted<F>(&mut self, entity: freecs::Entity, handler: F)
where
F: FnMut(String, &mut crate::ecs::world::World) + 'static,
{
self.tree.world_mut().ui_react_submitted(entity, handler);
}
pub fn react_confirmed<F>(&mut self, entity: freecs::Entity, handler: F)
where
F: FnMut(bool, &mut crate::ecs::world::World) + 'static,
{
self.tree.world_mut().ui_react_confirmed(entity, handler);
}
pub fn react_menu_selected<F>(&mut self, entity: freecs::Entity, handler: F)
where
F: FnMut(usize, &mut crate::ecs::world::World) + 'static,
{
self.tree
.world_mut()
.ui_react_menu_selected(entity, handler);
}
pub fn react_command<F>(&mut self, entity: freecs::Entity, handler: F)
where
F: FnMut(usize, &mut crate::ecs::world::World) + 'static,
{
self.tree.world_mut().ui_react_command(entity, handler);
}
pub fn react_tree_selected<F>(&mut self, entity: freecs::Entity, handler: F)
where
F: FnMut(freecs::Entity, &mut crate::ecs::world::World) + 'static,
{
self.tree
.world_mut()
.ui_react_tree_selected(entity, handler);
}
pub fn react_tree_context_menu<F>(&mut self, entity: freecs::Entity, handler: F)
where
F: FnMut(freecs::Entity, nalgebra_glm::Vec2, &mut crate::ecs::world::World) + 'static,
{
self.tree
.world_mut()
.ui_react_tree_context_menu(entity, handler);
}
pub fn cleanup_entity(&mut self, entity: freecs::Entity) {
self.tree.world_mut().ui_cleanup_entity(entity);
}
pub fn remove_property(&mut self, name: &str) {
let full = self.full_name(name);
self.tree.world_mut().ui_remove_property(&full);
}
pub fn react_multi_select_changed<F>(&mut self, entity: freecs::Entity, handler: F)
where
F: FnMut(Vec<usize>, &mut crate::ecs::world::World) + 'static,
{
self.tree
.world_mut()
.ui_react_multi_select_changed(entity, handler);
}
pub fn react_date_changed<F>(&mut self, entity: freecs::Entity, handler: F)
where
F: FnMut(i32, u32, u32, &mut crate::ecs::world::World) + 'static,
{
self.tree.world_mut().ui_react_date_changed(entity, handler);
}
pub fn react_changed<F>(&mut self, entity: freecs::Entity, handler: F)
where
F: FnMut(&mut crate::ecs::world::World) + 'static,
{
self.tree.world_mut().ui_react_changed(entity, handler);
}
pub fn react_any<F>(&mut self, names: &[&str], handler: F)
where
F: FnMut(&mut crate::ecs::world::World) + 'static,
{
let full_names: Vec<String> = names.iter().map(|name| self.full_name(name)).collect();
let refs: Vec<&str> = full_names.iter().map(|s| s.as_str()).collect();
self.tree.world_mut().ui_react_any(&refs, handler);
}
pub fn label(&mut self, text: &str) -> freecs::Entity {
self.scoped(|tree| tree.add_label(text))
}
pub fn label_with_slot(&mut self, slot: usize) -> freecs::Entity {
self.scoped(|tree| tree.add_label_with_slot(slot))
}
pub fn label_colored(&mut self, text: &str, color: Vec4) -> freecs::Entity {
self.scoped(|tree| tree.add_label_colored(text, color))
}
pub fn heading(&mut self, text: &str) -> freecs::Entity {
self.scoped(|tree| tree.add_heading(text))
}
pub fn separator(&mut self) -> freecs::Entity {
self.scoped(|tree| tree.add_separator())
}
pub fn spacing(&mut self, amount: f32) -> freecs::Entity {
self.scoped(|tree| tree.add_spacing(amount))
}
pub fn spring(&mut self) -> freecs::Entity {
self.scoped(|tree| tree.add_spring())
}
pub fn button(&mut self, text: &str) -> freecs::Entity {
self.scoped(|tree| tree.add_button(text))
}
pub fn button_colored(&mut self, text: &str, color: Vec4) -> freecs::Entity {
self.scoped(|tree| tree.add_button_colored(text, color))
}
pub fn icon_button(
&mut self,
texture_index: u32,
icon_size: Vec2,
text: &str,
) -> freecs::Entity {
self.scoped(|tree| tree.add_icon_button(texture_index, icon_size, text))
}
pub fn button_rich(&mut self, spans: &[TextSpan]) -> freecs::Entity {
self.scoped(|tree| tree.add_button_rich(spans))
}
pub fn slider(&mut self, name: &str, min: f32, max: f32, initial: f32) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_slider(min, max, initial));
self.register_named(name, entity, initial);
entity
}
pub fn slider_logarithmic(
&mut self,
name: &str,
min: f32,
max: f32,
initial: f32,
) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_slider_logarithmic(min, max, initial));
self.register_named(name, entity, initial);
entity
}
pub fn slider_configured(&mut self, name: &str, config: SliderConfig<'_>) -> freecs::Entity {
let initial = config.initial;
let entity = self.scoped(|tree| tree.add_slider_configured(config));
self.register_named(name, entity, initial);
entity
}
pub fn canvas(&mut self, size: Vec2) -> freecs::Entity {
self.scoped(|tree| tree.add_canvas(size))
}
pub fn toggle(&mut self, name: &str, initial: bool) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_toggle(initial));
self.register_named(name, entity, initial);
entity
}
pub fn checkbox(&mut self, name: &str, label: &str, initial: bool) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_checkbox(label, initial));
self.register_named(name, entity, initial);
entity
}
pub fn radio(&mut self, label: &str, group_id: u32, option_index: usize) -> freecs::Entity {
self.scoped(|tree| tree.add_radio(label, group_id, option_index))
}
pub fn radio_group(&mut self, name: &str, group_id: u32) {
if name.is_empty() {
return;
}
let members = self
.tree
.world_mut()
.resources
.retained_ui
.radio_groups
.get(&group_id)
.cloned()
.unwrap_or_default();
let Some(&first) = members.first() else {
return;
};
let initial = self
.tree
.world_mut()
.ui_radio_group_value(group_id)
.unwrap_or(0);
self.register_named(name, first, initial);
}
pub fn progress_bar(&mut self, name: &str, initial: f32) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_progress_bar(initial));
self.register_named(name, entity, initial);
entity
}
pub fn label_id(&mut self, text: &str, test_id: &str) -> freecs::Entity {
let entity = self.label(text);
self.set_test_id(entity, test_id);
entity
}
pub fn button_id(&mut self, text: &str, test_id: &str) -> freecs::Entity {
let entity = self.button(text);
self.set_test_id(entity, test_id);
entity
}
pub fn slider_id(
&mut self,
name: &str,
min: f32,
max: f32,
initial: f32,
test_id: &str,
) -> freecs::Entity {
let entity = self.slider(name, min, max, initial);
self.set_test_id(entity, test_id);
entity
}
pub fn toggle_id(&mut self, name: &str, initial: bool, test_id: &str) -> freecs::Entity {
let entity = self.toggle(name, initial);
self.set_test_id(entity, test_id);
entity
}
pub fn checkbox_id(
&mut self,
name: &str,
label: &str,
initial: bool,
test_id: &str,
) -> freecs::Entity {
let entity = self.checkbox(name, label, initial);
self.set_test_id(entity, test_id);
entity
}
pub fn text_input_id(
&mut self,
name: &str,
placeholder: &str,
test_id: &str,
) -> freecs::Entity {
let entity = self.text_input(name, placeholder);
self.set_test_id(entity, test_id);
entity
}
pub fn dropdown_id(
&mut self,
name: &str,
options: &[&str],
initial: usize,
test_id: &str,
) -> freecs::Entity {
let entity = self.dropdown(name, options, initial);
self.set_test_id(entity, test_id);
entity
}
pub fn drag_value_id(
&mut self,
name: &str,
min: f32,
max: f32,
initial: f32,
test_id: &str,
) -> freecs::Entity {
let entity = self.drag_value(name, min, max, initial);
self.set_test_id(entity, test_id);
entity
}
pub fn heading_id(&mut self, text: &str, test_id: &str) -> freecs::Entity {
let entity = self.heading(text);
self.set_test_id(entity, test_id);
entity
}
pub fn progress_bar_id(&mut self, name: &str, initial: f32, test_id: &str) -> freecs::Entity {
let entity = self.progress_bar(name, initial);
self.set_test_id(entity, test_id);
entity
}
pub fn radio_id(
&mut self,
label: &str,
group_id: u32,
option_index: usize,
test_id: &str,
) -> freecs::Entity {
let entity = self.radio(label, group_id, option_index);
self.set_test_id(entity, test_id);
entity
}
pub fn tab_bar_id(
&mut self,
name: &str,
labels: &[&str],
initial: usize,
test_id: &str,
) -> freecs::Entity {
let entity = self.tab_bar(name, labels, initial);
self.set_test_id(entity, test_id);
entity
}
pub fn color_picker_id(
&mut self,
name: &str,
initial_color: Vec4,
test_id: &str,
) -> freecs::Entity {
let entity = self.color_picker(name, initial_color);
self.set_test_id(entity, test_id);
entity
}
pub fn color_picker_hsv_id(
&mut self,
name: &str,
initial_color: Vec4,
test_id: &str,
) -> freecs::Entity {
let entity = self.color_picker_hsv(name, initial_color);
self.set_test_id(entity, test_id);
entity
}
pub fn range_slider_id(
&mut self,
name: &str,
min: f32,
max: f32,
initial_low: f32,
initial_high: f32,
test_id: &str,
) -> freecs::Entity {
let entity = self.range_slider(name, min, max, initial_low, initial_high);
self.set_test_id(entity, test_id);
entity
}
pub fn selectable_label_id(
&mut self,
name: &str,
text: &str,
group_id: Option<u32>,
test_id: &str,
) -> freecs::Entity {
let entity = self.selectable_label(name, text, group_id);
self.set_test_id(entity, test_id);
entity
}
pub fn multi_select_id(&mut self, options: &[&str], test_id: &str) -> freecs::Entity {
let entity = self.multi_select(options);
self.set_test_id(entity, test_id);
entity
}
pub fn date_picker_id(
&mut self,
year: i32,
month: u32,
day: u32,
test_id: &str,
) -> freecs::Entity {
let entity = self.date_picker(year, month, day);
self.set_test_id(entity, test_id);
entity
}
pub fn menu_id(&mut self, label: &str, items: &[&str], test_id: &str) -> freecs::Entity {
let entity = self.menu(label, items);
self.set_test_id(entity, test_id);
entity
}
pub fn splitter_id(
&mut self,
name: &str,
direction: crate::ecs::ui::components::SplitDirection,
initial_ratio: f32,
test_id: &str,
) -> freecs::Entity {
let entity = self.splitter(name, direction, initial_ratio);
self.set_test_id(entity, test_id);
entity
}
pub fn text_area_id(
&mut self,
name: &str,
placeholder: &str,
rows: usize,
test_id: &str,
) -> freecs::Entity {
let entity = self.text_area(name, placeholder, rows);
self.set_test_id(entity, test_id);
entity
}
pub fn text_area_with_value_id(
&mut self,
name: &str,
placeholder: &str,
rows: usize,
initial_text: &str,
test_id: &str,
) -> freecs::Entity {
let entity = self.text_area_with_value(name, placeholder, rows, initial_text);
self.set_test_id(entity, test_id);
entity
}
pub fn text_input_max_length_id(
&mut self,
name: &str,
placeholder: &str,
max_length: usize,
test_id: &str,
) -> freecs::Entity {
let entity = self.text_input_max_length(name, placeholder, max_length);
self.set_test_id(entity, test_id);
entity
}
pub fn slider_logarithmic_id(
&mut self,
name: &str,
min: f32,
max: f32,
initial: f32,
test_id: &str,
) -> freecs::Entity {
let entity = self.slider_logarithmic(name, min, max, initial);
self.set_test_id(entity, test_id);
entity
}
pub fn dropdown_searchable_id(
&mut self,
name: &str,
options: &[&str],
initial: usize,
test_id: &str,
) -> freecs::Entity {
let entity = self.dropdown_searchable(name, options, initial);
self.set_test_id(entity, test_id);
entity
}
pub fn canvas_id(&mut self, size: Vec2, test_id: &str) -> freecs::Entity {
let entity = self.canvas(size);
self.set_test_id(entity, test_id);
entity
}
pub fn image_node_id(
&mut self,
texture_index: u32,
size: Vec2,
test_id: &str,
) -> freecs::Entity {
let entity = self.image_node(texture_index, size);
self.set_test_id(entity, test_id);
entity
}
pub fn confirm_dialog_id(
&mut self,
title: &str,
message: &str,
test_id: &str,
) -> freecs::Entity {
let entity = self.confirm_dialog(title, message);
self.set_test_id(entity, test_id);
entity
}
pub fn data_grid_id(
&mut self,
columns: &[DataGridColumn],
pool_size: usize,
test_id: &str,
) -> freecs::Entity {
let entity = self.data_grid(columns, pool_size);
self.set_test_id(entity, test_id);
entity
}
pub fn table_id(&mut self, headers: &[&str], widths: &[f32], test_id: &str) -> freecs::Entity {
let entity = self.table(headers, widths);
self.set_test_id(entity, test_id);
entity
}
pub fn command_palette_id(&mut self, pool_size: usize, test_id: &str) -> freecs::Entity {
let entity = self.command_palette(pool_size);
self.set_test_id(entity, test_id);
entity
}
pub fn tile_container_id(&mut self, size: Vec2, test_id: &str) -> freecs::Entity {
let entity = self.tile_container(size);
self.set_test_id(entity, test_id);
entity
}
pub fn text_input(&mut self, name: &str, placeholder: &str) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_text_input(placeholder));
self.register_named(name, entity, String::new());
entity
}
pub fn text_input_max_length(
&mut self,
name: &str,
placeholder: &str,
max_length: usize,
) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_text_input_max_length(placeholder, max_length));
self.register_named(name, entity, String::new());
entity
}
pub fn text_area(&mut self, name: &str, placeholder: &str, rows: usize) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_text_area(placeholder, rows));
self.register_named(name, entity, String::new());
entity
}
pub fn text_area_with_value(
&mut self,
name: &str,
placeholder: &str,
rows: usize,
initial_text: &str,
) -> freecs::Entity {
let entity =
self.scoped(|tree| tree.add_text_area_with_value(placeholder, rows, initial_text));
self.register_named(name, entity, initial_text.to_string());
entity
}
#[cfg(feature = "syntax_highlighting")]
pub fn text_area_with_syntax(
&mut self,
name: &str,
placeholder: &str,
rows: usize,
language: &str,
) -> freecs::Entity {
let entity =
self.scoped(|tree| tree.add_text_area_with_syntax(placeholder, rows, language));
self.register_named(name, entity, String::new());
entity
}
#[cfg(feature = "syntax_highlighting")]
pub fn text_area_with_syntax_and_value(
&mut self,
name: &str,
placeholder: &str,
rows: usize,
language: &str,
initial_text: &str,
) -> freecs::Entity {
let entity = self.scoped(|tree| {
tree.add_text_area_with_syntax_and_value(placeholder, rows, language, initial_text)
});
self.register_named(name, entity, initial_text.to_string());
entity
}
pub fn dropdown(&mut self, name: &str, options: &[&str], initial: usize) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_dropdown(options, initial));
self.register_named(name, entity, initial);
entity
}
pub fn dropdown_searchable(
&mut self,
name: &str,
options: &[&str],
initial: usize,
) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_dropdown_searchable(options, initial));
self.register_named(name, entity, initial);
entity
}
pub fn multi_select(&mut self, options: &[&str]) -> freecs::Entity {
self.scoped(|tree| tree.add_multi_select(options))
}
pub fn date_picker(&mut self, year: i32, month: u32, day: u32) -> freecs::Entity {
self.scoped(|tree| tree.add_date_picker(year, month, day))
}
pub fn menu(&mut self, label: &str, items: &[&str]) -> freecs::Entity {
self.scoped(|tree| tree.add_menu(label, items))
}
pub fn color_picker(&mut self, name: &str, initial_color: Vec4) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_color_picker(initial_color));
self.register_named(name, entity, initial_color);
entity
}
pub fn color_picker_hsv(&mut self, name: &str, initial_color: Vec4) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_color_picker_hsv(initial_color));
self.register_named(name, entity, initial_color);
entity
}
pub fn splitter(
&mut self,
name: &str,
direction: crate::ecs::ui::components::SplitDirection,
initial_ratio: f32,
) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_splitter(direction, initial_ratio));
self.register_named(name, entity, initial_ratio);
entity
}
pub fn range_slider(
&mut self,
name: &str,
min: f32,
max: f32,
initial_low: f32,
initial_high: f32,
) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_range_slider(min, max, initial_low, initial_high));
self.register_named(name, entity, Vec4::new(initial_low, initial_high, 0.0, 0.0));
entity
}
pub fn selectable_label(
&mut self,
name: &str,
text: &str,
group_id: Option<u32>,
) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_selectable_label(text, group_id));
self.register_named(name, entity, false);
entity
}
pub fn drag_value(&mut self, name: &str, min: f32, max: f32, initial: f32) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_drag_value(min, max, initial));
self.register_named(name, entity, initial);
entity
}
pub fn drag_value_configured(
&mut self,
name: &str,
config: DragValueConfig<'_>,
) -> freecs::Entity {
let initial = config.initial;
let entity = self.scoped(|tree| tree.add_drag_value_configured(config));
self.register_named(name, entity, initial);
entity
}
pub fn context_menu(&mut self, items: &[(&str, Option<&str>)]) -> freecs::Entity {
self.scoped(|tree| tree.add_context_menu(items))
}
pub fn context_menu_from_builder(
&mut self,
builder: crate::ecs::ui::widgets::ContextMenuBuilder,
) -> freecs::Entity {
self.scoped(|tree| tree.add_context_menu_from_builder(builder))
}
pub fn tab_bar(&mut self, name: &str, labels: &[&str], initial: usize) -> freecs::Entity {
let entity = self.scoped(|tree| tree.add_tab_bar(labels, initial));
self.register_named(name, entity, initial);
entity
}
pub fn image_node(&mut self, texture_index: u32, size: Vec2) -> freecs::Entity {
self.scoped(|tree| tree.add_image_node(texture_index, size))
}
pub fn theme_dropdown(&mut self) -> freecs::Entity {
self.scoped(|tree| tree.add_theme_dropdown())
}
pub fn rich_text(&mut self, spans: &[TextSpan]) -> freecs::Entity {
self.scoped(|tree| tree.add_rich_text(spans))
}
pub fn data_grid(&mut self, columns: &[DataGridColumn], pool_size: usize) -> freecs::Entity {
self.scoped(|tree| tree.add_data_grid(columns, pool_size))
}
pub fn table(&mut self, headers: &[&str], widths: &[f32]) -> freecs::Entity {
self.scoped(|tree| tree.add_table(headers, widths))
}
pub fn confirm_dialog(&mut self, title: &str, message: &str) -> freecs::Entity {
self.scoped(|tree| tree.add_confirm_dialog(title, message))
}
pub fn command_palette(&mut self, pool_size: usize) -> freecs::Entity {
self.scoped(|tree| tree.add_command_palette(pool_size))
}
pub fn property_grid(&mut self, label_width: f32) -> freecs::Entity {
self.scoped(|tree| tree.add_property_grid(label_width))
}
pub fn property_row(
&mut self,
grid: freecs::Entity,
parent: freecs::Entity,
label: &str,
) -> freecs::Entity {
self.tree.add_property_row(grid, parent, label)
}
pub fn property_section(&mut self, parent: freecs::Entity, label: &str) -> freecs::Entity {
self.tree.add_property_section(parent, label)
}
pub fn tree_node(
&mut self,
tree_entity: freecs::Entity,
parent_container: freecs::Entity,
label: &str,
depth: usize,
user_data: u64,
) -> freecs::Entity {
self.tree
.add_tree_node(tree_entity, parent_container, label, depth, user_data)
}
pub fn tree_node_lazy(
&mut self,
tree_entity: freecs::Entity,
parent_container: freecs::Entity,
label: &str,
depth: usize,
user_data: u64,
) -> freecs::Entity {
self.tree
.add_tree_node_lazy(tree_entity, parent_container, label, depth, user_data)
}
pub fn composite<T: CompositeWidget>(&mut self) -> freecs::Entity {
self.scoped(|tree| tree.add_composite::<T>())
}
pub fn row(&mut self, f: impl FnOnce(&mut Ui<'_, 'w>)) -> freecs::Entity {
self.container(|tree| tree.add_row(), f)
}
pub fn column(&mut self, f: impl FnOnce(&mut Ui<'_, 'w>)) -> freecs::Entity {
self.container(|tree| tree.add_column(), f)
}
pub fn collapsing_header(
&mut self,
name: &str,
label: &str,
default_open: bool,
f: impl FnOnce(&mut Ui<'_, 'w>),
) -> freecs::Entity {
let entity = self.container(|tree| tree.add_collapsing_header(label, default_open), f);
self.register_named(name, entity, default_open);
entity
}
pub fn scroll_area(&mut self, size: Vec2, f: impl FnOnce(&mut Ui<'_, 'w>)) -> freecs::Entity {
self.container(|tree| tree.add_scroll_area(size), f)
}
pub fn scroll_area_fill(
&mut self,
padding: f32,
spacing: f32,
f: impl FnOnce(&mut Ui<'_, 'w>),
) -> freecs::Entity {
self.container(|tree| tree.add_scroll_area_fill(padding, spacing), f)
}
pub fn floating_panel(
&mut self,
title: &str,
rect: Rect,
f: impl FnOnce(&mut Ui<'_, 'w>),
) -> freecs::Entity {
self.container(|tree| tree.add_floating_panel(title, rect), f)
}
pub fn docked_panel_left(
&mut self,
title: &str,
default_width: f32,
f: impl FnOnce(&mut Ui<'_, 'w>),
) -> freecs::Entity {
self.container(|tree| tree.add_docked_panel_left(title, default_width), f)
}
pub fn docked_panel_right(
&mut self,
title: &str,
default_width: f32,
f: impl FnOnce(&mut Ui<'_, 'w>),
) -> freecs::Entity {
self.container(|tree| tree.add_docked_panel_right(title, default_width), f)
}
pub fn docked_panel_top(
&mut self,
title: &str,
default_height: f32,
f: impl FnOnce(&mut Ui<'_, 'w>),
) -> freecs::Entity {
self.container(|tree| tree.add_docked_panel_top(title, default_height), f)
}
pub fn docked_panel_bottom(
&mut self,
title: &str,
default_height: f32,
f: impl FnOnce(&mut Ui<'_, 'w>),
) -> freecs::Entity {
self.container(
|tree| tree.add_docked_panel_bottom(title, default_height),
f,
)
}
pub fn modal_dialog(
&mut self,
title: &str,
width: f32,
height: f32,
f: impl FnOnce(&mut Ui<'_, 'w>),
) -> freecs::Entity {
self.container(|tree| tree.add_modal_dialog(title, width, height), f)
}
pub fn tree_view(
&mut self,
multi_select: bool,
f: impl FnOnce(&mut Ui<'_, 'w>),
) -> freecs::Entity {
self.container(|tree| tree.add_tree_view(multi_select), f)
}
pub fn tile_container(&mut self, size: Vec2) -> freecs::Entity {
self.scoped(|tree| tree.add_tile_container(size))
}
pub fn build_tiles(
&mut self,
container: freecs::Entity,
f: impl FnOnce(&mut crate::ecs::ui::widgets::TileBuilder<'_, 'w>),
) {
self.tree.build_tiles(container, f);
}
pub fn enabled(&mut self, enabled: bool, f: impl FnOnce(&mut Ui<'_, 'w>)) -> freecs::Entity {
let container = self.scoped(|tree| tree.add_column());
let content = self
.tree
.world_mut()
.ui_widget_content(container)
.unwrap_or(container);
let mut child_ui = Ui {
tree: &mut *self.tree,
parent: content,
prefix: self.prefix.clone(),
};
f(&mut child_ui);
if !enabled {
self.tree
.world_mut()
.ui_set_disabled_recursive(container, true);
}
container
}
}
impl<'w> UiTreeBuilder<'w> {
pub fn build_ui(&mut self, parent: freecs::Entity, f: impl FnOnce(&mut Ui<'_, 'w>)) {
let mut ui = Ui {
tree: self,
parent,
prefix: None,
};
f(&mut ui);
}
}