#![windows_subsystem = "windows"]
use anyhow::{Error, Result};
use fui_app::*;
use fui_controls::*;
use fui_core::*;
use fui_macros::ui;
use std::cell::{Cell, RefCell};
use std::rc::Rc;
use tokio::task::LocalSet;
use typemap::TypeMap;
#[derive(Clone)]
struct ItemViewModel {
pub id: i32,
pub name: String,
}
impl ItemViewModel {
pub fn new(id: i32, name: String) -> Rc<Self> {
Rc::new(ItemViewModel { id, name })
}
}
struct MainViewModel {
pub items: RefCell<ObservableVec<Rc<ItemViewModel>>>,
counter: Cell<i32>,
}
impl MainViewModel {
pub fn new() -> Rc<Self> {
let main_vm = Rc::new(MainViewModel {
items: RefCell::new(ObservableVec::new()),
counter: Cell::new(0),
});
main_vm.add_n(4);
main_vm
}
pub fn add(self: &Rc<Self>) {
let new_item = ItemViewModel::new(
self.counter.get(),
format!("Element {}", self.counter.get()),
);
self.counter.set(self.counter.get() + 1);
println!("Add {}!", new_item.name);
self.items.borrow_mut().push(new_item);
}
pub fn add_n(self: &Rc<Self>, n: i32) {
for _ in 0..n {
self.add();
}
}
pub fn remove_all(self: &Rc<Self>) {
println!("Remove all!");
self.items.borrow_mut().clear();
}
pub fn delete(self: &Rc<Self>, item: &Rc<ItemViewModel>) {
println!("Delete {}!", item.id);
self.items.borrow_mut().retain(|i| !Rc::ptr_eq(i, item));
}
}
impl ViewModel for MainViewModel {
fn create_view(self: &Rc<Self>) -> Rc<RefCell<dyn ControlObject>> {
ui!(
Grid {
columns: 1,
heights: vec![(0, Length::Auto)],
Vertical {
Margin: Thickness::all(5.0f32),
Button {
clicked: cb!(self, add),
Text { text: "Add" },
},
Button {
clicked: cb!(self, add_n(100)),
Text { text: "Add 100" },
},
Button {
clicked: cb!(self, remove_all),
Text { text: "Remove all" },
},
},
ScrollViewer {
Vertical {
Margin: Thickness::all(5.0f32),
Text { text: "The dynamic list can be mixed with static controls." },
Grid {
columns: 3,
self.items.borrow().flat_map({
let view_model = self.clone();
move |item| {
let item = item.clone();
vec![
ui!(Text { text: "Flat map!" }),
ui!(Text { text: &item.name }),
ui!(Button {
Margin: Thickness::new(5.0f32, 0.0f32, 0.0f32, 0.0f32),
clicked: cb!(&view_model, delete(&item)),
Text { text: "Delete" },
}),
]
}}),
self.items.borrow().map(|item| {
ui!(Text { text: format!("Simple map! ({})", item.id) })
})
},
Text { text: "This is the end." },
},
}
}
)
}
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
LocalSet::new()
.run_until(async {
let app = Application::new("Example: list").await?;
let mut window = Window::create(
WindowOptions::new()
.with_title("Example: list")
.with_size(800, 600),
)
.await?;
window.set_vm(MainViewModel::new());
app.run().await?;
Ok::<(), Error>(())
})
.await
}