Skip to content

Instantly share code, notes, and snippets.

@lisael
Created June 24, 2021 06:31
Show Gist options
  • Save lisael/35aa7a13d4bb583f924acb832b9ef30a to your computer and use it in GitHub Desktop.
Save lisael/35aa7a13d4bb583f924acb832b9ef30a to your computer and use it in GitHub Desktop.
use std::fmt;
use druid::im::Vector;
use druid::widget::{Button, Either, Flex, Label, Scroll, TextBox};
use druid::{AppLauncher, Data, Lens, LocalizedString, Widget, WidgetExt, WindowDesc};
use druid_widget_nursery::{Tree, TreeNode};
#[derive(Clone, Lens, Data)]
struct Taxonomy {
name: String,
editing: bool,
children: Vector<Taxonomy>, // this makes use of im::Vector now (can derive Data)
}
/// We use Taxonomy as a tree node, implementing both the Data and TreeNode traits.
impl Taxonomy {
fn new(name: &'static str) -> Self {
Taxonomy {
name: name.to_string(),
editing: false,
children: Vector::new(),
}
}
fn add_child(mut self, child: Self) -> Self {
self.children.push_back(child);
self
}
// ADDITION: add a child on a ref (as passed to the on_click closures)
fn add_child_ref(&mut self, child: Self) {
self.children.push_back(child);
}
}
impl Default for Taxonomy {
fn default() -> Self {
Taxonomy {
name: "Life".to_string(),
editing: false,
children: Vector::new(),
}
}
}
impl TreeNode for Taxonomy {
fn children_count(&self) -> usize {
self.children.len()
}
fn get_child(&self, index: usize) -> &Taxonomy {
&self.children[index]
}
fn get_child_mut(&mut self, index: usize) -> &mut Taxonomy {
&mut self.children[index]
}
}
impl fmt::Display for Taxonomy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.name)
}
}
pub fn main() {
// Create the main window
let main_window = WindowDesc::new(ui_builder())
.title(LocalizedString::new("tree-demo-window-title").with_placeholder("Tree Demo"));
// Set our initial data.
// This is an extract from https://en.wikipedia.org/wiki/Linnaean_taxonomy
let taxonomy = Taxonomy::new("Life")
.add_child(
Taxonomy::new("Animalia")
.add_child(
Taxonomy::new("Aves")
.add_child(Taxonomy::new("Accipitres"))
.add_child(Taxonomy::new("Picae"))
.add_child(Taxonomy::new("Passeres")),
)
.add_child(
Taxonomy::new("Amphibia")
.add_child(Taxonomy::new("Reptiles"))
.add_child(Taxonomy::new("Serpentes"))
.add_child(Taxonomy::new("Nantes")),
)
.add_child(Taxonomy::new("Pisces"))
.add_child(Taxonomy::new("Insecta")),
)
.add_child(
Taxonomy::new("Vegetalia")
.add_child(Taxonomy::new("Monandria"))
.add_child(Taxonomy::new("Diandria"))
.add_child(Taxonomy::new("Heptandria")),
)
.add_child(
Taxonomy::new("Mineralia")
.add_child(Taxonomy::new("Petræ"))
.add_child(Taxonomy::new("Fossilia"))
.add_child(Taxonomy::new("Vitamentra")),
);
// start the application
AppLauncher::with_window(main_window)
.log_to_console()
.launch(taxonomy)
.expect("launch failed");
}
fn ui_builder() -> impl Widget<Taxonomy> {
Scroll::new(Tree::new(|t: &Taxonomy| {
// ADDITION: use an Either to build the inner widget, bound to the editing status
Either::new(
|data, _env| (*data).editing,
Flex::row()
.with_child(
TextBox::new()
.with_placeholder("new item")
.lens(Taxonomy::name),
)
.with_child(
Button::new("Add").on_click(|ctx, data: &mut Taxonomy, _env| {
println!("save {}", data.name);
data.editing = false;
// ctx.children_changed();
// ctx.request_paint();
println!("done.");
}),
),
Flex::row()
.with_child(Label::new(t.name.as_str()))
.with_child(
Button::new("Add child").on_click(|ctx, data: &mut Taxonomy, _env| {
println!("create child of {}", data.name);
data.add_child_ref({
let mut child = Taxonomy::new("");
child.editing = true;
child
});
// I tried to request_* almost anything here
// ctx.children_changed();
// ctx.request_paint();
println!("done.");
}),
),
)
}))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment