102 lines
2.2 KiB
Rust
102 lines
2.2 KiB
Rust
use crate::{
|
|
primitive::{Painter, Primitives},
|
|
util::{IDTracker, ID},
|
|
HashMap, Widget, WidgetId, WidgetLike, WidgetRef,
|
|
};
|
|
use std::{
|
|
any::{Any, TypeId},
|
|
cell::RefCell,
|
|
rc::Rc,
|
|
};
|
|
|
|
pub struct UI {
|
|
ids: IDTracker,
|
|
base: Option<WidgetId>,
|
|
pub widgets: Widgets,
|
|
}
|
|
|
|
pub struct Widgets(HashMap<ID, Box<dyn Widget>>);
|
|
|
|
#[derive(Clone)]
|
|
pub struct UIBuilder {
|
|
ui: Rc<RefCell<UI>>,
|
|
}
|
|
|
|
impl From<UI> for UIBuilder {
|
|
fn from(ui: UI) -> Self {
|
|
UIBuilder {
|
|
ui: Rc::new(RefCell::new(ui)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl UIBuilder {
|
|
pub fn add<W: Widget>(&mut self, w: W) -> WidgetRef<W> {
|
|
WidgetRef::new(self.clone(), [self.push(w)])
|
|
}
|
|
|
|
pub fn push<W: Widget>(&mut self, w: W) -> WidgetId {
|
|
let mut ui = self.ui.borrow_mut();
|
|
let id = ui.ids.next();
|
|
ui.widgets.insert(id.duplicate(), w);
|
|
WidgetId::new(id, TypeId::of::<W>())
|
|
}
|
|
|
|
pub fn finish<W: WidgetLike>(mut self, base: W) -> UI {
|
|
let base = base.add(&mut self).erase_type();
|
|
let mut ui = Rc::into_inner(self.ui).unwrap().into_inner();
|
|
ui.base = Some(base);
|
|
ui
|
|
}
|
|
}
|
|
|
|
impl UI {
|
|
pub fn build() -> UIBuilder {
|
|
Self::empty().into()
|
|
}
|
|
|
|
pub fn empty() -> Self {
|
|
Self {
|
|
ids: IDTracker::new(),
|
|
base: None,
|
|
widgets: Widgets::new(),
|
|
}
|
|
}
|
|
|
|
pub fn to_primitives(&self) -> Primitives {
|
|
let mut painter = Painter::new(&self.widgets);
|
|
if let Some(base) = &self.base {
|
|
painter.draw(base);
|
|
}
|
|
painter.finish()
|
|
}
|
|
}
|
|
|
|
impl Widgets {
|
|
fn new() -> Self {
|
|
Self(HashMap::new())
|
|
}
|
|
|
|
pub fn get(&self, id: &WidgetId) -> &dyn Widget {
|
|
self.0.get(&id.id).unwrap().as_ref()
|
|
}
|
|
|
|
pub fn get_mut<W: Widget>(&mut self, id: &WidgetId<W>) -> Option<&mut W> {
|
|
self.0.get_mut(&id.id).unwrap().as_any_mut().downcast_mut()
|
|
}
|
|
|
|
pub fn insert(&mut self, id: ID, widget: impl Widget) {
|
|
self.0.insert(id, Box::new(widget));
|
|
}
|
|
|
|
pub fn insert_any(&mut self, id: ID, widget: Box<dyn Widget>) {
|
|
self.0.insert(id, widget);
|
|
}
|
|
}
|
|
|
|
impl dyn Widget {
|
|
pub fn as_any_mut(&mut self) -> &mut dyn Any {
|
|
self
|
|
}
|
|
}
|