vixevoxerust/src/vvedit/ui_extensions.rs

310 lines
9.6 KiB
Rust

#[derive(Default, Debug, Clone)]
pub enum StringTreeElement {
#[default]
None,
Element(String, Box<Vec<StringTreeElement>>),
}
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 {
pub root: Vec<StringTreeElement>,
}
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<StringTreeElement> {
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<StringTreeElement> {
// 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
} */
pub fn list_of_elements(&self) -> Vec<String> {
let mut list: Vec<String> = Vec::new();
let mut to_search = Vec::new();
for each in &self.root {
to_search.push(each);
}
while !to_search.is_empty() {
let next = to_search.pop();
if let Some(next) = next {
if let Some(name) = next.name_of() {
list.push(name.clone());
}
if let StringTreeElement::Element(_, children) = next {
for each in children.as_ref() {
to_search.push(each);
}
}
}
}
return list;
}
}
#[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)));
dbg!(tester);
}