use nalgebra_glm::{Vec2, Vec4};

use crate::ecs::ui::builder::UiTreeBuilder;
use crate::ecs::ui::components::{DataGridColumn, DragValueConfig, SliderConfig, TextSpan};
use crate::ecs::ui::theme::UiTheme;
use crate::ecs::ui::types::Rect;

use crate::prelude::*;
pub struct Ui<'t, 'w> {
    tree: &'t mut UiTreeBuilder<'w>,
    parent: freecs::Entity,
}

impl<'t, 'w> Ui<'t, 'w> {
    fn scoped<R>(&mut self, f: impl FnOnce(&mut UiTreeBuilder<'w>) -> R) -> R {
        let needs_push = self.tree.current_parent() != self.parent;
        if needs_push {
            self.tree.push_parent(self.parent);
        }
        let result = f(&mut *self.tree);
        if needs_push {
            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 = ui_widget_content(self.tree.world_mut(), entity).unwrap_or(entity);
        let mut child_ui = Ui {
            tree: &mut *self.tree,
            parent: content,
        };
        f(&mut child_ui);
        entity
    }

    pub fn tree(&mut self) -> &mut UiTreeBuilder<'w> {
        self.tree
    }

    pub fn within<R>(&mut self, parent: freecs::Entity, f: impl FnOnce(&mut Ui<'_, 'w>) -> R) -> R {
        let mut child = Ui {
            tree: &mut *self.tree,
            parent,
        };
        f(&mut child)
    }

    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) {
        ui_set_test_id(self.tree.world_mut(), 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) {
        ui_set_visible(self.tree.world_mut(), entity, visible);
    }

    pub fn set_disabled(&mut self, entity: freecs::Entity, disabled: bool) {
        ui_set_disabled(self.tree.world_mut(), entity, disabled);
    }

    pub fn set_disabled_recursive(&mut self, entity: freecs::Entity, disabled: bool) {
        ui_set_disabled_recursive(self.tree.world_mut(), entity, disabled);
    }

    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, min: f32, max: f32, initial: f32) -> freecs::Entity {
        self.scoped(|tree| tree.add_slider(min, max, initial))
    }

    pub fn slider_logarithmic(&mut self, min: f32, max: f32, initial: f32) -> freecs::Entity {
        self.scoped(|tree| tree.add_slider_logarithmic(min, max, initial))
    }

    pub fn slider_configured(&mut self, config: SliderConfig<'_>) -> freecs::Entity {
        self.scoped(|tree| tree.add_slider_configured(config))
    }

    pub fn canvas(&mut self, size: Vec2) -> freecs::Entity {
        self.scoped(|tree| tree.add_canvas(size))
    }

    pub fn toggle(&mut self, initial: bool) -> freecs::Entity {
        self.scoped(|tree| tree.add_toggle(initial))
    }

    pub fn checkbox(&mut self, label: &str, initial: bool) -> freecs::Entity {
        self.scoped(|tree| tree.add_checkbox(label, initial))
    }

    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 progress_bar(&mut self, initial: f32) -> freecs::Entity {
        self.scoped(|tree| tree.add_progress_bar(initial))
    }

    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, min: f32, max: f32, initial: f32, test_id: &str) -> freecs::Entity {
        let entity = self.slider(min, max, initial);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn toggle_id(&mut self, initial: bool, test_id: &str) -> freecs::Entity {
        let entity = self.toggle(initial);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn checkbox_id(&mut self, label: &str, initial: bool, test_id: &str) -> freecs::Entity {
        let entity = self.checkbox(label, initial);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn text_input_id(&mut self, placeholder: &str, test_id: &str) -> freecs::Entity {
        let entity = self.text_input(placeholder);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn dropdown_id(
        &mut self,
        options: &[&str],
        initial: usize,
        test_id: &str,
    ) -> freecs::Entity {
        let entity = self.dropdown(options, initial);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn drag_value_id(
        &mut self,
        min: f32,
        max: f32,
        initial: f32,
        test_id: &str,
    ) -> freecs::Entity {
        let entity = self.drag_value(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, initial: f32, test_id: &str) -> freecs::Entity {
        let entity = self.progress_bar(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, labels: &[&str], initial: usize, test_id: &str) -> freecs::Entity {
        let entity = self.tab_bar(labels, initial);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn color_picker_id(&mut self, initial_color: Vec4, test_id: &str) -> freecs::Entity {
        let entity = self.color_picker(initial_color);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn color_picker_hsv_id(&mut self, initial_color: Vec4, test_id: &str) -> freecs::Entity {
        let entity = self.color_picker_hsv(initial_color);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn range_slider_id(
        &mut self,
        min: f32,
        max: f32,
        initial_low: f32,
        initial_high: f32,
        test_id: &str,
    ) -> freecs::Entity {
        let entity = self.range_slider(min, max, initial_low, initial_high);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn selectable_label_id(
        &mut self,
        text: &str,
        group_id: Option<u32>,
        test_id: &str,
    ) -> freecs::Entity {
        let entity = self.selectable_label(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,
        direction: crate::ecs::ui::components::SplitDirection,
        initial_ratio: f32,
        test_id: &str,
    ) -> freecs::Entity {
        let entity = self.splitter(direction, initial_ratio);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn text_area_id(
        &mut self,
        placeholder: &str,
        rows: usize,
        test_id: &str,
    ) -> freecs::Entity {
        let entity = self.text_area(placeholder, rows);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn text_area_with_value_id(
        &mut self,
        placeholder: &str,
        rows: usize,
        initial_text: &str,
        test_id: &str,
    ) -> freecs::Entity {
        let entity = self.text_area_with_value(placeholder, rows, initial_text);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn text_input_max_length_id(
        &mut self,
        placeholder: &str,
        max_length: usize,
        test_id: &str,
    ) -> freecs::Entity {
        let entity = self.text_input_max_length(placeholder, max_length);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn slider_logarithmic_id(
        &mut self,
        min: f32,
        max: f32,
        initial: f32,
        test_id: &str,
    ) -> freecs::Entity {
        let entity = self.slider_logarithmic(min, max, initial);
        self.set_test_id(entity, test_id);
        entity
    }

    pub fn dropdown_searchable_id(
        &mut self,
        options: &[&str],
        initial: usize,
        test_id: &str,
    ) -> freecs::Entity {
        let entity = self.dropdown_searchable(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, placeholder: &str) -> freecs::Entity {
        self.scoped(|tree| tree.add_text_input(placeholder))
    }

    pub fn text_input_max_length(
        &mut self,
        placeholder: &str,
        max_length: usize,
    ) -> freecs::Entity {
        self.scoped(|tree| tree.add_text_input_max_length(placeholder, max_length))
    }

    pub fn text_area(&mut self, placeholder: &str, rows: usize) -> freecs::Entity {
        self.scoped(|tree| tree.add_text_area(placeholder, rows))
    }

    pub fn text_area_with_value(
        &mut self,
        placeholder: &str,
        rows: usize,
        initial_text: &str,
    ) -> freecs::Entity {
        self.scoped(|tree| tree.add_text_area_with_value(placeholder, rows, initial_text))
    }

    pub fn dropdown(&mut self, options: &[&str], initial: usize) -> freecs::Entity {
        self.scoped(|tree| tree.add_dropdown(options, initial))
    }

    pub fn dropdown_searchable(&mut self, options: &[&str], initial: usize) -> freecs::Entity {
        self.scoped(|tree| tree.add_dropdown_searchable(options, initial))
    }

    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, initial_color: Vec4) -> freecs::Entity {
        self.scoped(|tree| tree.add_color_picker(initial_color))
    }

    pub fn color_picker_hsv(&mut self, initial_color: Vec4) -> freecs::Entity {
        self.scoped(|tree| tree.add_color_picker_hsv(initial_color))
    }

    pub fn color_wheel(&mut self, initial_color: Vec4) -> freecs::Entity {
        self.scoped(|tree| tree.add_color_wheel(initial_color))
    }

    pub fn splitter(
        &mut self,
        direction: crate::ecs::ui::components::SplitDirection,
        initial_ratio: f32,
    ) -> freecs::Entity {
        self.scoped(|tree| tree.add_splitter(direction, initial_ratio))
    }

    pub fn range_slider(
        &mut self,
        min: f32,
        max: f32,
        initial_low: f32,
        initial_high: f32,
    ) -> freecs::Entity {
        self.scoped(|tree| tree.add_range_slider(min, max, initial_low, initial_high))
    }

    pub fn selectable_label(&mut self, text: &str, group_id: Option<u32>) -> freecs::Entity {
        self.scoped(|tree| tree.add_selectable_label(text, group_id))
    }

    pub fn drag_value(&mut self, min: f32, max: f32, initial: f32) -> freecs::Entity {
        self.scoped(|tree| tree.add_drag_value(min, max, initial))
    }

    pub fn drag_value_configured(&mut self, config: DragValueConfig<'_>) -> freecs::Entity {
        self.scoped(|tree| tree.add_drag_value_configured(config))
    }

    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, labels: &[&str], initial: usize) -> freecs::Entity {
        self.scoped(|tree| tree.add_tab_bar(labels, initial))
    }

    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 spinner(&mut self) -> freecs::Entity {
        self.scoped(|tree| tree.add_spinner())
    }

    pub fn breadcrumb(&mut self, segments: &[&str]) -> freecs::Entity {
        self.scoped(|tree| tree.add_breadcrumb(segments))
    }

    pub fn virtual_list(&mut self, item_height: f32, pool_size: usize) -> freecs::Entity {
        self.scoped(|tree| tree.add_virtual_list(item_height, pool_size))
    }

    pub fn rich_text_editor(&mut self, placeholder: &str, rows: usize) -> freecs::Entity {
        self.scoped(|tree| tree.add_rich_text_editor(placeholder, rows))
    }

    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 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,
        label: &str,
        default_open: bool,
        f: impl FnOnce(&mut Ui<'_, 'w>),
    ) -> freecs::Entity {
        self.container(|tree| tree.add_collapsing_header(label, default_open), f)
    }

    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,
        id: &str,
        title: &str,
        rect: Rect,
        f: impl FnOnce(&mut Ui<'_, 'w>),
    ) -> freecs::Entity {
        let id = id.to_string();
        let title = title.to_string();
        self.container(move |tree| tree.add_floating_panel(&id, &title, rect), f)
    }

    pub fn docked_panel_left(
        &mut self,
        id: &str,
        title: &str,
        default_width: f32,
        f: impl FnOnce(&mut Ui<'_, 'w>),
    ) -> freecs::Entity {
        let id = id.to_string();
        let title = title.to_string();
        self.container(
            move |tree| tree.add_docked_panel_left(&id, &title, default_width),
            f,
        )
    }

    pub fn docked_panel_right(
        &mut self,
        id: &str,
        title: &str,
        default_width: f32,
        f: impl FnOnce(&mut Ui<'_, 'w>),
    ) -> freecs::Entity {
        let id = id.to_string();
        let title = title.to_string();
        self.container(
            move |tree| tree.add_docked_panel_right(&id, &title, default_width),
            f,
        )
    }

    pub fn docked_panel_top(
        &mut self,
        id: &str,
        title: &str,
        default_height: f32,
        f: impl FnOnce(&mut Ui<'_, 'w>),
    ) -> freecs::Entity {
        let id = id.to_string();
        let title = title.to_string();
        self.container(
            move |tree| tree.add_docked_panel_top(&id, &title, default_height),
            f,
        )
    }

    pub fn docked_panel_bottom(
        &mut self,
        id: &str,
        title: &str,
        default_height: f32,
        f: impl FnOnce(&mut Ui<'_, 'w>),
    ) -> freecs::Entity {
        let id = id.to_string();
        let title = title.to_string();
        self.container(
            move |tree| tree.add_docked_panel_bottom(&id, &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 = ui_widget_content(self.tree.world_mut(), container).unwrap_or(container);
        let mut child_ui = Ui {
            tree: &mut *self.tree,
            parent: content,
        };
        f(&mut child_ui);
        if !enabled {
            ui_set_disabled_recursive(self.tree.world_mut(), container, true);
        }
        container
    }
}

impl<'w> UiTreeBuilder<'w> {
    pub fn build_ui(&mut self, parent: freecs::Entity, f: impl FnOnce(&mut Ui<'_, 'w>)) {
        let needs_push = self.current_parent() != parent;
        if needs_push {
            self.push_parent(parent);
        }
        let mut ui = Ui { tree: self, parent };
        f(&mut ui);
        if needs_push {
            ui.tree.pop_parent();
        }
    }
}
