Skip to content

More Complex Examples #2

@wyhinton

Description

@wyhinton

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions