Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More Complex Examples #2

Open
wyhinton opened this issue Jul 13, 2021 · 0 comments
Open

More Complex Examples #2

wyhinton opened this issue Jul 13, 2021 · 0 comments

Comments

@wyhinton
Copy link

wyhinton commented Jul 13, 2021

Hello,

Thanks for the wonderful work on this crate! I'm thinking about using vec-tree to manage widgets in my rust GUI (made with fltk-rs).

I appreciate the large number of examples shown in the tests, but I was wondering if some examples which demonstrate more complex/component based design might be added. Primarily, I think one of the design challenges in using vec-tree for my gui is figuring out how I could insert a component into a tree, then have that component insert new items into that same tree.

For example, what if we wanted to create a Drag and Drop Todo list app in rust, similar to this example made with React: https://codesandbox.io/s/ym3rvj1z71. I thought a tree would be a good data structure for representing the different ToDoLists and their child ToDoItems , but it's not quite as simple as I thought. If we want our ToDoList to generate a ToDoItem, how could we add that to our Ui tree?

While we could wrap the tree in an Rc<RefCell<>>> and pass it through the constructors of all of the ToDoList, the whole point of using a tree as the owner of the data is removing such interior mutability patterns.

Now, for a lot of reasons it seems like a bad idea to give child nodes a mutable access to their parent tree. Just wondering how we might get around such a circular reference.

Currently all the examples represent somewhat "static" tree's whose nodes don't really interact with one another. A slightly more "real world" example would go a long way, I think.

use vec_tree::{VecTree, Index};
use fltk::{app::*, enums::*, frame::Frame, group::*, prelude::*, window::Window};
use std::borrow::{Cow};
#[derive(Clone)]
enum UiItem<'a>{
    Window(Window),
    ToDo(ToDoItem<'a>),
    ToDoList(ToDoList),
}

#[derive(Clone)]
pub struct ToDoItem<'a>{
    widg: Frame,
    body: Cow<'a, str>,
    //from the todo item we might want to know something about the parent node, so 
    //we track the Index of the parent node
    parent: Index,
}

impl <'a> ToDoItem<'a>{
    pub fn new(body: &'a str, parent: Index)->Self{
        let label = String::from(body);
        let mut frame= Frame::new(0,0,200,200,None);
        frame.set_label(&label);
        ToDoItem{
            widg: frame,
            body: Cow::from(body),
            parent: parent,
        }
    }
}

//ToDoList doens't own a list of ToDoItems, just a list of their indexes in the tree
#[derive(Clone)]
pub struct ToDoList{
    index: Index, 
    group: Pack, 
    items: Vec<Index>
}

impl ToDoList{
    pub fn new(node_id: Index)->Self{
        let mut container= Pack::new(0,0,100,200,"to do list");
        let mut test= Frame::new(0,0,50,50,"myframe");
        container.end();
        ToDoList{
            index: node_id, 
            group: container,
            items: vec![],
        }
    }
    //We want our ToDoLists to be able to generate new ToDoItems, perhaps on clicking the list
    pub fn add_todo<'a>(&mut self, body: &'a str){
        let new_todo = ToDoItem::new(body, self.index);
        //but what would we do with our new ToDoItem? We don't want to store it in this struct, 
        //and we don't have access to our tree to insert it
    }
}

fn main() {
    let app = App::default();
    let mut tree: VecTree<UiItem> = VecTree::new();
    let mut wind = Window::new(100,100,300,300, None);
    //window is the root of the tree
    let root_node = tree.insert_root(UiItem::Window(wind.clone()));
    //insert first todo list
    let mut to_do_list_1 = ToDoList::new(root_node);
    to_do_list_1.add_todo("first todo");
    //insert second todo list
    let mut to_do_list_2 = ToDoList::new(root_node);
    to_do_list_2.add_todo("another todo");

    wind.end();
    wind.show();
    tree.insert(UiItem::ToDoList(to_do_list_1), root_node);
    tree.insert(UiItem::ToDoList(to_do_list_2), root_node);
    app.run().unwrap();
}

For reference, froggy, a component graph system, has a neet demo app: https://github.com/kvark/froggy/tree/master/demos/cubes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant