use crate::ecs::world::World;
use nalgebra_glm::Vec2;
use crate::ecs::ui::layout_types::FlowDirection;
use crate::ecs::ui::state::UiBase;
use super::date_utils::{format_month_year, populate_calendar_grid};
use crate::prelude::*;
pub fn ui_data_grid_enable_filters(world: &mut World, entity: freecs::Entity) {
let columns = if let Some(data) = world.ui.get_ui_data_grid(entity) {
data.columns.clone()
} else {
return;
};
let theme = world.resources.retained_ui.theme_state.active_theme();
let font_size = theme.font_size;
let input_bg = theme.input_background_color;
let text_color = theme.text_color;
let border_color = theme.border_color;
let corner_radius = theme.corner_radius;
let row_height = 28.0;
let header_entity = if let Some(data) = world.ui.get_ui_data_grid(entity) {
data.header_entities
.first()
.and_then(|header| world.core.get_parent(*header).and_then(|p| p.0))
} else {
None
};
let header_parent = if let Some(he) = header_entity {
world.core.get_parent(he).and_then(|p| p.0)
} else {
None
};
let filter_row_parent = header_parent.unwrap_or(entity);
let mut filter_input_entities = Vec::new();
let mut filter_texts = Vec::new();
let filter_row = {
let mut tree = crate::ecs::ui::builder::UiTreeBuilder::new(world);
tree.push_parent(filter_row_parent);
let row_entity = tree
.add_node()
.flow_child(
crate::ecs::ui::units::Rl(Vec2::new(100.0, 0.0))
+ crate::ecs::ui::units::Ab(Vec2::new(0.0, row_height)),
)
.flow(FlowDirection::Horizontal, 0.0, 2.0)
.entity();
tree.push_parent(row_entity);
for column in &columns {
let text_slot = tree.world_mut().resources.text.cache.add_text("");
let input = tree
.add_node()
.flow_child(crate::ecs::ui::units::Ab(Vec2::new(
column.width,
row_height,
)))
.with_rect(corner_radius, 1.0, border_color)
.color_raw::<UiBase>(input_bg)
.with_interaction()
.with_children(|inner| {
inner
.add_node()
.with_text_slot(text_slot, font_size)
.color_raw::<UiBase>(text_color)
.entity();
})
.entity();
filter_input_entities.push(input);
filter_texts.push(String::new());
}
tree.pop_parent();
tree.pop_parent();
row_entity
};
if let Some(data) = world.ui.get_ui_data_grid_mut(entity) {
data.filter_row_entity = Some(filter_row);
data.filter_input_entities = filter_input_entities;
data.filter_texts = filter_texts;
}
}
pub fn ui_data_grid_set_filtered_indices(
world: &mut World,
entity: freecs::Entity,
indices: Option<Vec<usize>>,
) {
if let Some(data) = world.ui.get_ui_data_grid_mut(entity) {
data.filtered_indices = indices;
}
ui_mark_layout_dirty(world);
}
pub fn ui_set_state_active(
world: &mut World,
entity: freecs::Entity,
state_index: usize,
active: bool,
) {
if state_index >= crate::ecs::ui::state::STATE_COUNT {
return;
}
if let Some(weights) = world.ui.get_ui_state_weights_mut(entity) {
weights.targets[state_index] = if active { 1.0 } else { 0.0 };
weights.start_weights[state_index] = weights.weights[state_index];
weights.progress[state_index] = 0.0;
}
}
pub fn ui_clicked(world: &World, entity: freecs::Entity) -> bool {
widget::<crate::ecs::ui::components::UiButtonData>(world, entity).is_some_and(|d| d.clicked)
}
pub fn ui_set_reduced_motion(world: &mut World, enabled: bool) {
world.resources.retained_ui.accessibility.reduced_motion = enabled;
}
pub fn ui_announce(world: &mut World, message: &str) {
world
.resources
.retained_ui
.accessibility
.announce_queue
.push(message.to_string());
}
pub fn ui_announcements(world: &World) -> &[String] {
&world.resources.retained_ui.accessibility.announce_queue
}
pub fn ui_set_accessible_label(world: &mut World, entity: freecs::Entity, label: &str) {
if let Some(interaction) = world.ui.get_ui_node_interaction_mut(entity) {
interaction.accessible_label = Some(label.to_string());
}
}
pub fn ui_multi_select_set_selected(world: &mut World, entity: freecs::Entity, indices: &[usize]) {
let update = if let Some(data) = world.ui.get_ui_multi_select_mut(entity) {
data.selected_indices = indices.iter().copied().collect();
let count = data.selected_indices.len();
let header_slot = data.header_text_slot;
let header_text = format!("{count} selected");
let check_updates: Vec<(freecs::Entity, bool)> = data
.check_entities
.iter()
.enumerate()
.map(|(index, &e)| (e, data.selected_indices.contains(&index)))
.collect();
Some((header_slot, header_text, check_updates))
} else {
None
};
if let Some((header_slot, header_text, check_updates)) = update {
for (check_entity, selected) in check_updates {
let check_text = if selected { "\u{2713}" } else { " " };
if let Some(crate::ecs::ui::components::UiNodeContent::Text { text_slot, .. }) =
world.ui.get_ui_node_content(check_entity)
{
let slot = *text_slot;
world.resources.text.cache.set_text(slot, check_text);
}
}
world
.resources
.text
.cache
.set_text(header_slot, &header_text);
}
}
pub fn ui_date_picker_set_value(
world: &mut World,
entity: freecs::Entity,
year: i32,
month: u32,
day: u32,
) {
let header_text = format!("{year:04}-{month:02}-{day:02}");
let update = world.ui.get_ui_date_picker(entity).map(|data| {
(
data.header_text_slot,
data.month_label_slot,
data.day_text_slots.clone(),
data.day_entities.clone(),
)
});
if let Some((header_slot, month_slot, day_slots, day_ents)) = update {
world
.resources
.text
.cache
.set_text(header_slot, &header_text);
let month_label = format_month_year(year, month);
world
.resources
.text
.cache
.set_text(month_slot, &month_label);
let theme = world.resources.retained_ui.theme_state.active_theme();
let accent_color = theme.accent_color;
populate_calendar_grid(world, year, month, day, &day_slots, &day_ents, accent_color);
if let Some(data) = world.ui.get_ui_date_picker_mut(entity) {
data.year = year;
data.month = month;
data.day = day;
}
}
}