diff --git a/src/vvedit.rs b/src/vvedit.rs index 169801e..8854cc0 100644 --- a/src/vvedit.rs +++ b/src/vvedit.rs @@ -7,6 +7,7 @@ use crate::vvlib::oct_asset::{self, OctAssetMarker, OctTreeAsset}; mod editor_bevy_input_shim; pub mod editor_ui; mod orbit_camera; +pub mod ui_extensions; pub fn setup(app: &mut App) -> &mut App { app.add_plugins(DefaultPlugins.set(WindowPlugin { diff --git a/src/vvedit/editor_ui.rs b/src/vvedit/editor_ui.rs index 3027d2d..f0a6644 100644 --- a/src/vvedit/editor_ui.rs +++ b/src/vvedit/editor_ui.rs @@ -193,10 +193,3 @@ pub fn round_trip_color() { assert_eq!((color.b() * 255.).floor(), (b * 255.).floor()); } } -#[test] -pub fn test_colors() { - let color = Color::rgb(1., 0., 0.); - //let x = Hsva::from_srgb() - let hsv = egui_color_from(color); - let conv = rgb_from_hsv((hsv.h, hsv.s, hsv.v)); -} diff --git a/src/vvedit/ui_extensions.rs b/src/vvedit/ui_extensions.rs new file mode 100644 index 0000000..82496d8 --- /dev/null +++ b/src/vvedit/ui_extensions.rs @@ -0,0 +1,287 @@ +#[derive(Default, Debug, Clone)] +pub enum StringTreeElement { + #[default] + None, + Element(String, Box>), +} +impl StringTreeElement { + pub fn is_none(&self) -> bool { + match self { + StringTreeElement::None => true, + _ => false, + } + } + pub fn name_of(&self) -> Option<&String> { + match self { + StringTreeElement::Element(name, _) => Some(name), + _ => None, + } + } + pub fn new(key: &String) -> StringTreeElement { + StringTreeElement::Element(key.clone(), Box::new(Vec::new())) + } +} +#[derive(Default, Debug, Clone)] +pub struct StringTree { + root: Vec, +} +impl StringTree { + pub fn new() -> Self { + StringTree { root: Vec::new() } + } + pub fn add_root_level(&mut self, element: &String) -> bool { + for each in &self.root { + if Self::check_present(each, element) { + return false; + } + } + self.root.push(StringTreeElement::new(element)); + true + } + pub fn add_child(&mut self, child: &String, parent: &String) -> bool { + if !self.is_present(child) { + for each in &mut self.root { + let res = Self::add_child_to_parent(each, child, parent); + if res { + return true; + } + } + } + // returns false if parent not found or string already present + false + } + fn add_child_to_parent( + element: &mut StringTreeElement, + child: &String, + parent: &String, + ) -> bool { + if let StringTreeElement::Element(name, children) = element { + if name == parent { + children.as_mut().push(StringTreeElement::new(child)); + return true; + } + for each in children.as_mut() { + if Self::add_child_to_parent(each, child, parent) { + return true; + } + } + } + false + } + pub fn is_present(&self, key: &String) -> bool { + for each in &self.root { + let res = Self::check_present(each, key); + if res { + return true; + } + } + false + } + fn check_present(element: &StringTreeElement, key: &String) -> bool { + if let StringTreeElement::Element(name, children) = element { + if name.eq(key) { + return true; + } + for each in children.as_ref() { + if Self::check_present(each, key) { + return true; + } + } + } + false + } + pub fn add(&mut self, element: &String, parent: Option<&String>) -> bool { + if let Some(parent) = parent { + return self.add_child(element, parent); + } else { + return self.add_root_level(element); + } + } + + pub fn move_branch(&mut self, element: &String, parent: &String) -> bool { + if self.is_present(parent) { + if let Some(popped) = self.pop_branch(element) { + for each in &mut self.root { + if Self::place_branch(each, parent, &popped) { + return true; + } + } + } + } + false + } + fn place_branch( + subject: &mut StringTreeElement, + target_parent: &String, + element: &StringTreeElement, + ) -> bool { + match subject { + StringTreeElement::Element(name, branch) => { + // + if name == target_parent { + branch.push(element.clone()); + return true; + } + for each in branch.as_mut() { + if Self::place_branch(each, target_parent, element) { + return true; + } + } + } + _ => {} + } + false + } + + fn pop_branch(&mut self, element: &String) -> Option { + let mut index = usize::MAX; + for (ind, each) in (&self.root).iter().enumerate() { + if let Some(el) = each.name_of() { + if el == element { + index = ind; + } + } + } + if index != usize::MAX { + let popped = self.root.remove(index); + return Some(popped); + } else { + for each in &mut self.root { + let x = Self::recursive_branch_find_pop(each, element); + if x.is_some() { + return x; + } + } + } + None + } + fn recursive_branch_find_pop( + iterator: &mut StringTreeElement, + name: &String, + ) -> Option { + // name checked in previous iteration + if let StringTreeElement::Element(_, branch) = iterator { + let mut index = usize::MAX; + for each in branch.as_ref().iter().enumerate() { + if let Some(el_name) = each.1.name_of() { + if el_name == name { + index = each.0; + } + } + } + if index != usize::MAX { + let popped = branch.remove(index); + return Some(popped); + } else { + for each in branch.as_mut() { + let x = Self::recursive_branch_find_pop(each, name); + if x.is_some() { + return x; + } + } + } + } + None + } + + pub fn remove_branch(&mut self, element: &String) -> bool { + return self.pop_branch(element).is_some(); + } + + pub fn remove_element_preserve_branch(&mut self, search: &String) -> bool { + let mut failed_yet = false; + let clone = self.clone(); + let parent = clone.parent_of(search); + if let Some(popped) = self.pop_branch(search) { + let mut popped = popped; + if parent.is_some() { + let parent = parent.unwrap(); + match &mut popped { + StringTreeElement::None => {} + StringTreeElement::Element(_, branch) => { + for each in branch.as_mut() { + for branches in &mut self.root { + let x = Self::place_branch(branches, parent, &each); + if !x { + failed_yet = true; + } + } + } + } + } + } else { + match &mut popped { + StringTreeElement::None => {} + StringTreeElement::Element(_, branch) => { + for each in branch.as_ref() { + self.root.push(each.clone()); + } + } + } + } + } + !failed_yet + } + pub fn parent_of(&self, search: &String) -> Option<&String> { + let mut queue = Vec::new(); + + for each in &self.root { + queue.push(each); + } + while !queue.is_empty() { + let element = queue.pop().unwrap(); + if let StringTreeElement::Element(name, branch) = element { + for each in branch.as_ref() { + if let Some(c_name) = each.name_of() { + if c_name == search { + return Some(name); + } + } + queue.push(each); + } + } + } + None + } + /* iterative variation of is_present + pub fn contains(&self, search: &String) -> bool { + let mut queue = Vec::new(); + + for each in &self.root { + queue.push(each); + } + while !queue.is_empty() { + let element = queue.pop().unwrap(); + if let StringTreeElement::Element(name, branch) = element { + if name == search { + return true; + } + for each in branch.as_ref() { + queue.push(each); + } + } + } + false + } */ +} +#[test] +pub fn test_string_tree() { + let parent = &String::from("parent1"); + let parent2 = &String::from("parent2"); + let child = &String::from("child1"); + let child2 = &String::from("child2"); + let mut tester = StringTree::new(); + tester = dbg!(tester); + assert!(dbg!(tester.add(parent, None))); + tester = dbg!(tester); + assert!(dbg!(tester.add_child(child, parent))); + tester = dbg!(tester); + assert!(dbg!(tester.add_root_level(parent2))); + tester = dbg!(tester); + assert!(!dbg!(tester.add_child(child, parent2))); + tester = dbg!(tester); + assert!(dbg!(tester.add(child2, Some(parent2)))); + tester = dbg!(tester); + assert!(dbg!(tester.move_branch(parent2, parent))); + tester = dbg!(tester); +}