-
Notifications
You must be signed in to change notification settings - Fork 5
Description
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 ToDoList
s and their child ToDoItem
s , 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