use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet};
use iced::Element;
use iced::Task;
use oxiui_iced::{apply_message, IcedConfig, IcedUiCtx, Message, WidgetState};
use crate::{ContentFn, HookFn, Plugin};
pub struct OxiIcedState {
pub title: String,
pub content: RefCell<Option<ContentFn>>,
pub pending_clicks: RefCell<HashSet<usize>>,
pub widget_state: RefCell<HashMap<usize, WidgetState>>,
pub on_init: RefCell<Vec<HookFn>>,
pub on_frame: RefCell<Vec<HookFn>>,
pub plugins: RefCell<Vec<Box<dyn Plugin>>>,
pub initialised: Cell<bool>,
}
impl OxiIcedState {
pub fn empty() -> Self {
Self {
title: String::new(),
content: RefCell::new(None),
pending_clicks: RefCell::new(HashSet::new()),
widget_state: RefCell::new(HashMap::new()),
on_init: RefCell::new(Vec::new()),
on_frame: RefCell::new(Vec::new()),
plugins: RefCell::new(Vec::new()),
initialised: Cell::new(false),
}
}
}
pub fn update(state: &mut OxiIcedState, msg: Message) -> Task<Message> {
let mut clicks = state.pending_clicks.borrow_mut();
let mut widget_state = state.widget_state.borrow_mut();
apply_message(&mut widget_state, &mut clicks, &msg);
Task::none()
}
pub fn view<'a>(state: &'a OxiIcedState) -> Element<'a, Message> {
let clicks = {
let mut guard = state.pending_clicks.borrow_mut();
std::mem::take(&mut *guard)
};
let widget_state = state.widget_state.borrow().clone();
let config = IcedConfig {
pending_clicks: clicks,
state: widget_state,
spacing: 8.0,
padding: 0.0,
title: state.title.clone(),
spec_capacity_hint: 0,
};
let mut ctx = IcedUiCtx::new(config);
if !state.initialised.get() {
state.initialised.set(true);
if let Ok(mut hooks) = state.on_init.try_borrow_mut() {
for hook in hooks.iter_mut() {
hook(&mut ctx);
}
}
if let Ok(mut plugins) = state.plugins.try_borrow_mut() {
for plugin in plugins.iter_mut() {
plugin.init(&mut ctx);
}
}
}
if let Ok(mut content_guard) = state.content.try_borrow_mut() {
if let Some(ref mut f) = *content_guard {
f(&mut ctx);
}
}
if let Ok(mut hooks) = state.on_frame.try_borrow_mut() {
for hook in hooks.iter_mut() {
hook(&mut ctx);
}
}
if let Ok(mut plugins) = state.plugins.try_borrow_mut() {
for plugin in plugins.iter_mut() {
plugin.update(&mut ctx);
}
}
let elem: Element<'static, Message> = ctx.into_iced_element();
elem
}
pub fn run(state: OxiIcedState, iced_theme: iced::Theme, width: f32, height: f32) -> iced::Result {
let boot_state = std::sync::Mutex::new(Some(state));
let boot = move || {
boot_state
.lock()
.ok()
.and_then(|mut g| g.take())
.unwrap_or_else(OxiIcedState::empty)
};
let title_fn = move |s: &OxiIcedState| s.title.clone();
let theme_fn = move |_: &OxiIcedState| iced_theme.clone();
let _ = width;
let _ = height;
iced::application(boot, update, view)
.title(title_fn)
.theme(theme_fn)
.run()
}