use crate::app::AppInner;
use crate::event::Event;
use crate::sys;
use crate::util::{cstring, ensure_abi, NotThreadSafe};
use std::rc::Rc;
#[derive(Clone, Copy, Debug, Default)]
pub struct DispatchResult {
pub redraw_requested: bool,
pub invalidate_view: bool,
pub defer_widget_changes: bool,
pub layout_changed: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(i32)]
pub enum DocumentScript {
UiControls = 0,
}
enum Owner {
Owned,
App(#[allow(dead_code)] Rc<AppInner>),
}
pub struct Document {
raw: *mut sys::affineui_document,
owner: Owner,
_not_send: NotThreadSafe,
}
impl Drop for Document {
fn drop(&mut self) {
if matches!(self.owner, Owner::Owned) {
unsafe { sys::affineui_document_destroy(self.raw) };
}
}
}
impl Document {
pub fn new() -> Document {
ensure_abi();
Document {
raw: unsafe { sys::affineui_document_create() },
owner: Owner::Owned,
_not_send: NotThreadSafe::default(),
}
}
pub(crate) fn borrowed(raw: *mut sys::affineui_document, app: Rc<AppInner>) -> Document {
Document { raw, owner: Owner::App(app), _not_send: NotThreadSafe::default() }
}
pub fn set_html(&self, html: &str) {
let html = cstring(html);
unsafe { sys::affineui_document_set_html(self.raw, html.as_ptr()) };
}
pub fn set_user_stylesheet(&self, css: &str, base_url: Option<&str>) {
let css = cstring(css);
let base = base_url.map(cstring);
unsafe {
sys::affineui_document_set_user_stylesheet(
self.raw,
css.as_ptr(),
base.as_ref().map_or(std::ptr::null(), |b| b.as_ptr()),
)
};
}
pub fn reload_stylesheets(&self) {
unsafe { sys::affineui_document_reload_stylesheets(self.raw) };
}
pub fn layout(&self, viewport_width: i32, viewport_height: i32) {
unsafe { sys::affineui_document_layout(self.raw, viewport_width, viewport_height) };
}
pub fn content_size(&self) -> (i32, i32) {
let (mut w, mut h) = (0, 0);
unsafe { sys::affineui_document_content_size(self.raw, &mut w, &mut h) };
(w, h)
}
pub fn set_attribute_by_id(&self, elem_id: &str, name: &str, value: &str) -> bool {
let (id, name, value) = (cstring(elem_id), cstring(name), cstring(value));
unsafe {
sys::affineui_document_set_attribute_by_id(self.raw, id.as_ptr(), name.as_ptr(), value.as_ptr()) != 0
}
}
pub fn remove_attribute_by_id(&self, elem_id: &str, name: &str) -> bool {
let (id, name) = (cstring(elem_id), cstring(name));
unsafe { sys::affineui_document_remove_attribute_by_id(self.raw, id.as_ptr(), name.as_ptr()) != 0 }
}
pub fn set_text_by_id(&self, elem_id: &str, text: &str) -> bool {
let (id, text) = (cstring(elem_id), cstring(text));
unsafe { sys::affineui_document_set_text_by_id(self.raw, id.as_ptr(), text.as_ptr()) != 0 }
}
pub fn dispatch(&self, ev: &Event) -> DispatchResult {
let mut out = sys::affineui_dispatch_result::default();
ev.with_sys(|sys_ev| unsafe { sys::affineui_document_dispatch(self.raw, sys_ev, &mut out) });
DispatchResult {
redraw_requested: out.redraw_requested != 0,
invalidate_view: out.invalidate_view != 0,
defer_widget_changes: out.defer_widget_changes != 0,
layout_changed: out.layout_changed != 0,
}
}
pub fn attach_script(&self, script: DocumentScript) {
unsafe { sys::affineui_document_attach_script(self.raw, script as i32) };
}
pub fn detach_script(&self, script: DocumentScript) {
unsafe { sys::affineui_document_detach_script(self.raw, script as i32) };
}
pub fn hovered_cursor(&self) -> i32 {
unsafe { sys::affineui_document_hovered_cursor(self.raw) }
}
}
impl Default for Document {
fn default() -> Document {
Document::new()
}
}