use core::ptr::NonNull;
use std::ffi::{CString, c_void};
use crate::binding::Boxed;
use crate::ffi::{
noesis_gui_get_application_resources, noesis_gui_register_default_styles,
noesis_gui_set_application_resources, noesis_resource_dictionary_add,
noesis_resource_dictionary_add_merged, noesis_resource_dictionary_contains,
noesis_resource_dictionary_count, noesis_resource_dictionary_create,
noesis_resource_dictionary_destroy, noesis_resource_dictionary_find,
noesis_resource_dictionary_parse, noesis_resource_dictionary_set_source,
};
pub struct ResourceDictionary {
ptr: NonNull<c_void>,
}
unsafe impl Send for ResourceDictionary {}
impl Default for ResourceDictionary {
fn default() -> Self {
Self::new()
}
}
impl ResourceDictionary {
#[must_use]
pub fn new() -> Self {
let ptr = unsafe { noesis_resource_dictionary_create() };
Self {
ptr: NonNull::new(ptr).expect("noesis_resource_dictionary_create returned null"),
}
}
#[must_use]
pub fn parse(xaml: &str) -> Option<Self> {
let c = CString::new(xaml).expect("xaml contained interior NUL");
let ptr = unsafe { noesis_resource_dictionary_parse(c.as_ptr()) };
NonNull::new(ptr).map(|ptr| Self { ptr })
}
#[must_use]
pub(crate) unsafe fn from_owned(ptr: NonNull<c_void>) -> Self {
Self { ptr }
}
#[must_use]
pub fn raw(&self) -> *mut c_void {
self.ptr.as_ptr()
}
#[must_use]
pub fn len(&self) -> usize {
unsafe { noesis_resource_dictionary_count(self.ptr.as_ptr()) as usize }
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub unsafe fn add(&mut self, key: &str, value: *mut c_void) -> bool {
let c = CString::new(key).expect("resource key contained interior NUL");
unsafe { noesis_resource_dictionary_add(self.ptr.as_ptr(), c.as_ptr(), value) }
}
pub fn add_string(&mut self, key: &str, value: &str) -> bool {
let boxed = crate::binding::box_string(value);
unsafe { self.add(key, boxed.raw()) }
}
pub fn add_boxed(&mut self, key: &str, value: &Boxed) -> bool {
unsafe { self.add(key, value.raw()) }
}
pub fn add_brush(&mut self, key: &str, brush: &impl crate::brushes::Brush) -> bool {
unsafe { self.add(key, brush.brush_raw()) }
}
#[must_use]
pub fn contains(&self, key: &str) -> bool {
let c = CString::new(key).expect("resource key contained interior NUL");
unsafe { noesis_resource_dictionary_contains(self.ptr.as_ptr(), c.as_ptr()) }
}
#[must_use]
pub fn find(&self, key: &str) -> Option<NonNull<c_void>> {
let c = CString::new(key).expect("resource key contained interior NUL");
let p = unsafe { noesis_resource_dictionary_find(self.ptr.as_ptr(), c.as_ptr()) };
NonNull::new(p)
}
pub fn add_merged(&mut self, other: &ResourceDictionary) -> bool {
unsafe { noesis_resource_dictionary_add_merged(self.ptr.as_ptr(), other.raw()) }
}
pub fn set_source(&mut self, uri: &str) -> bool {
let c = CString::new(uri).expect("resource dictionary URI contained interior NUL");
unsafe { noesis_resource_dictionary_set_source(self.ptr.as_ptr(), c.as_ptr()) }
}
}
impl Drop for ResourceDictionary {
fn drop(&mut self) {
unsafe { noesis_resource_dictionary_destroy(self.ptr.as_ptr()) }
}
}
pub fn set_application_resources(dict: &ResourceDictionary) {
unsafe { noesis_gui_set_application_resources(dict.raw()) }
}
#[must_use]
pub fn application_resources_present() -> bool {
!unsafe { noesis_gui_get_application_resources() }.is_null()
}
#[must_use]
pub fn application_resources_contains(key: &str) -> bool {
let app = unsafe { noesis_gui_get_application_resources() };
if app.is_null() {
return false;
}
let c = CString::new(key).expect("resource key contained interior NUL");
unsafe { noesis_resource_dictionary_contains(app, c.as_ptr()) }
}
#[must_use]
pub fn register_default_styles(uri: &str) -> bool {
let c = CString::new(uri).expect("uri contained interior NUL");
unsafe { noesis_gui_register_default_styles(c.as_ptr()) }
}