use std::{future::Future, sync::RwLock};
use web_sys::Element;
mod class;
pub mod div_handle;
pub mod error;
pub mod global;
mod pane;
mod state;
mod storage;
mod style;
mod utils;
pub use class::*;
pub use div_handle::*;
pub use error::*;
pub use global::*;
use state::*;
use storage::{ClassStorage, PaneHashMap, PaneStorage};
use style::*;
pub use utils::doc;
pub fn init() -> Result<(), DivError> {
init_ex(None, (0, 0), None)
}
pub fn init_to(id: &str) -> Result<(), DivError> {
init_ex(Some(id), (0, 0), None)
}
pub fn init_ex_with_element(
root: Element,
pos: (i32, i32),
size: Option<(u32, u32)>,
) -> Result<(), DivError> {
state::set_state(GlobalState {
root,
nodes: PaneHashMap::default(),
pos,
size,
zoom: (1.0, 1.0),
classes: JsClassStorage::default(),
})?;
add_div_styles_to_document()?;
init_div_rs();
Ok(())
}
pub fn init_ex(
id: Option<&str>,
pos: (i32, i32),
size: Option<(u32, u32)>,
) -> Result<(), DivError> {
let root = get_root(id)?;
init_ex_with_element(root, pos, size)
}
fn get_root(id: Option<&str>) -> Result<Element, DivError> {
let element = if id.is_some() {
doc()?
.get_element_by_id(id.unwrap())
.ok_or(DivError::MissingRoot(id.unwrap().to_owned()))?
} else {
doc()?.body().ok_or(DivError::MissingBody)?.into()
};
Ok(element)
}
pub fn new(x: i32, y: i32, w: u32, h: u32, html: &str) -> Result<DivHandle, DivError> {
let css = "";
let classes = "";
state::exec_mut(|state| state.new_pane(x, y, w, h, html, css, classes))
}
pub fn new_styled<'a, C, CSS, S1, S2, S3>(
x: i32,
y: i32,
w: u32,
h: u32,
html: &str,
classes: C,
css: CSS,
) -> Result<DivHandle, DivError>
where
C: IntoIterator<Item = &'a S1>,
CSS: IntoIterator<Item = &'a (S2, S3)>,
S1: AsRef<str> + 'a,
S2: AsRef<str> + 'a,
S3: AsRef<str> + 'a,
{
let css_str = css
.into_iter()
.map(|(attr, val)| attr.as_ref().to_owned() + ": " + val.as_ref() + ";")
.collect::<Vec<_>>()
.join(" ");
let classes_str = classes
.into_iter()
.map(AsRef::as_ref)
.collect::<Vec<_>>()
.join(" ");
state::exec_mut(|state| state.new_pane(x, y, w, h, html, &classes_str, &css_str))
}
pub fn load_js_class(
name: &str,
src: &str,
) -> Result<impl Future<Output = JsClassHandle>, DivError> {
let classes = load_js_classes(&[name], src)?;
Ok(async { classes.await[0] })
}
pub fn load_js_classes(
classes: &[&str],
src: &str,
) -> Result<impl Future<Output = Vec<JsClassHandle>>, DivError> {
let future = state::exec_mut(|state| state.classes.load(classes, src))?;
Ok(future)
}
pub fn from_js_class(
x: i32,
y: i32,
w: u32,
h: u32,
class_handle: JsClassHandle,
) -> Result<DivHandle, DivError> {
let ph = new(x, y, w, h, "")?;
let node = ph.parent_element()?;
let class = state::get_class(class_handle)?;
class.attach_new_instance(&node);
Ok(ph)
}
impl JsClass {
pub fn preregistered(name: &str) -> Option<JsClassHandle> {
state::exec_mut(|state| Ok(state.classes.preloaded(name))).unwrap()
}
}