use crate::layout_struct::layout_states::LayoutElement;
use crate::layout_struct::layout_tree::{LayoutTree, LayoutTreeCursorBorrow, LayoutTreeIndex};
use crate::layout_struct::{
RenderCommandClipEnd, RenderCommandClipStart, RenderCommandOutput, RenderCommandOutputElement,
TextDrawPayload,
};
use cotis::utils::ElementId;
use std::collections::{HashMap, VecDeque};
pub fn calculate_render_commands<Config>(
tree: &'_ LayoutTree,
current_tree_index: LayoutTreeIndex,
open_nodes: &mut VecDeque<LayoutTreeIndex>,
render_commands: &mut Vec<RenderCommandOutput<Config>>,
configs: &mut HashMap<ElementId, Config>,
text_fragments: &HashMap<ElementId, TextDrawPayload>,
) {
let self_node = LayoutTreeCursorBorrow::new_from_index(tree, ¤t_tree_index).unwrap();
let self_node = self_node.get_local();
let is_layout_root_node = current_tree_index.len() == 1;
if !is_layout_root_node {
render_commands.push(self_node.self_element.to_commands(configs, text_fragments));
}
if self_node.self_element.config.clip.horizontal || self_node.self_element.config.clip.vertical
{
let mut render_commands_inside = Vec::new();
let mut open_nodes_inside = VecDeque::new();
render_commands.push(RenderCommandOutput::ClipStart(RenderCommandClipStart {
bounds: self_node.self_element.info.to_bounding_box(),
id: self_node.self_element.id,
z_index: self_node.self_element.config.floating.z_index,
}));
for node in self_node.children_elements.iter() {
let mut index = current_tree_index.clone();
index.push(node.id);
open_nodes_inside.push_back(index);
}
while let Some(node) = open_nodes_inside.pop_front() {
calculate_render_commands(
tree,
node,
&mut open_nodes_inside,
&mut render_commands_inside,
configs,
text_fragments,
);
}
sort_commands(
&mut render_commands_inside,
self_node.self_element.config.floating.z_index,
);
render_commands.append(&mut render_commands_inside);
render_commands.push(RenderCommandOutput::ClipEnd(RenderCommandClipEnd {
bounds: self_node.self_element.info.to_bounding_box(),
id: self_node.self_element.id,
z_index: self_node.self_element.config.floating.z_index,
}));
} else {
for node in self_node.children_elements.iter() {
let mut index = current_tree_index.clone();
index.push(node.id);
open_nodes.push_back(index);
}
}
}
pub(crate) fn sort_commands<Config>(
render_commands: &mut [RenderCommandOutput<Config>],
z_index: i32,
) {
render_commands.sort_by(|a, b| {
let z_a = match a {
RenderCommandOutput::Element(a) => a.z_index,
RenderCommandOutput::ClipStart(a) => a.z_index,
RenderCommandOutput::ClipEnd(a) => a.z_index,
};
let z_b = match b {
RenderCommandOutput::Element(a) => a.z_index,
RenderCommandOutput::ClipStart(a) => a.z_index,
RenderCommandOutput::ClipEnd(a) => a.z_index,
};
z_a.cmp(&z_b)
});
for command in render_commands.iter_mut() {
match command {
RenderCommandOutput::Element(c) => {
c.z_index = z_index;
}
RenderCommandOutput::ClipStart(c) => {
c.z_index = z_index;
}
RenderCommandOutput::ClipEnd(c) => {
c.z_index = z_index;
}
}
}
}
impl LayoutElement {
pub fn to_commands<Config>(
&self,
configs: &mut HashMap<ElementId, Config>,
text_fragments: &HashMap<ElementId, TextDrawPayload>,
) -> RenderCommandOutput<Config> {
let text = text_fragments.get(&self.id).cloned();
RenderCommandOutput::Element(RenderCommandOutputElement {
bounds: self.info.to_bounding_box(),
z_index: self.config.floating.z_index,
text,
custom: configs
.remove(&self.id)
.expect("There should be a config for this element"),
})
}
}