Trees
Tree widgets allow showing items in a tree! There's no tree trait, all methods belong to the Tree type. Items are added using the add method:
use fltk::{prelude::*, *}; fn main() { let a = app::App::default(); let mut win = window::Window::default().with_size(400, 300); let mut tree = tree::Tree::default().with_size(390, 290).center_of_parent(); tree.add("Item 1"); tree.add("Item 2"); tree.add("Item 3"); win.end(); win.show(); a.run().unwrap(); }
Sub-items are added by using the forward slash separator:
use fltk::{prelude::*, *}; fn main() { let a = app::App::default(); let mut win = window::Window::default().with_size(400, 300); let mut tree = tree::Tree::default().with_size(390, 290).center_of_parent(); tree.add("Item 1"); tree.add("Item 2"); tree.add("Item 3"); tree.add("Item 3/Subitem 1"); tree.add("Item 3/Subitem 2"); tree.add("Item 3/Subitem 3"); win.end(); win.show(); a.run().unwrap(); }
If you try the above code, you'll see that the root item is always indicated by the label "ROOT". This can be changed using the set_root_label() method:
use fltk::{prelude::*, *}; fn main() { let a = app::App::default(); let mut win = window::Window::default().with_size(400, 300); let mut tree = tree::Tree::default().with_size(390, 290).center_of_parent(); tree.set_root_label("My Tree"); tree.add("Item 1"); tree.add("Item 2"); tree.add("Item 3"); tree.add("Item 3/Subitem 1"); tree.add("Item 3/Subitem 2"); tree.add("Item 3/Subitem 3"); win.end(); win.show(); a.run().unwrap(); }
Or even hidden using the set_show_root(false) method.
Items can be queried using the first_selected_item() method:
use fltk::{prelude::*, *}; fn main() { let a = app::App::default(); let mut win = window::Window::default().with_size(400, 300); let mut tree = tree::Tree::default().with_size(390, 290).center_of_parent(); tree.set_show_root(false); tree.add("Item 1"); tree.add("Item 2"); tree.add("Item 3"); tree.add("Item 3/Subitem 1"); tree.add("Item 3/Subitem 2"); tree.add("Item 3/Subitem 3"); win.end(); win.show(); tree.set_callback(|t| { if let Some(item) = t.first_selected_item() { println!("{} selected", item.label().unwrap()); } }); a.run().unwrap(); }
Currently our tree only allow single selection, let's change it to multiple (we'll also change the connector style while we're at it):
use fltk::{prelude::*, *}; fn main() { let a = app::App::default(); let mut win = window::Window::default().with_size(400, 300); let mut tree = tree::Tree::default().with_size(390, 290).center_of_parent(); tree.set_select_mode(tree::TreeSelect::Multi); tree.set_connector_style(tree::TreeConnectorStyle::Solid); tree.set_connector_color(enums::Color::Red.inactive()); tree.set_show_root(false); tree.add("Item 1"); tree.add("Item 2"); tree.add("Item 3"); tree.add("Item 3/Subitem 1"); tree.add("Item 3/Subitem 2"); tree.add("Item 3/Subitem 3"); win.end(); win.show(); tree.set_callback(|t| { if let Some(item) = t.first_selected_item() { println!("{} selected", item.label().unwrap()); } }); a.run().unwrap(); }
The problem now is that we need to get the whole selection instead only of the first selected item, so we'll use the get_selected_items() method which returns an optional Vec, and instead of just getting the label, we'll get the whole path of the item:
use fltk::{prelude::*, *}; fn main() { let a = app::App::default(); let mut win = window::Window::default().with_size(400, 300); let mut tree = tree::Tree::default().with_size(390, 290).center_of_parent(); tree.set_select_mode(tree::TreeSelect::Multi); tree.set_connector_style(tree::TreeConnectorStyle::Solid); tree.set_connector_color(enums::Color::Red.inactive()); tree.set_show_root(false); tree.add("Item 1"); tree.add("Item 2"); tree.add("Item 3"); tree.add("Item 3/Subitem 1"); tree.add("Item 3/Subitem 2"); tree.add("Item 3/Subitem 3"); win.end(); win.show(); tree.set_callback(|t| { if let Some(items) = t.get_selected_items() { for i in items { println!("{} selected", t.item_pathname(&i).unwrap()); } } }); a.run().unwrap(); }