use std::fmt;
use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId;
use crate::foundation::{id, nil, NSString, NSUInteger, NO, YES};
mod class;
use class::register_toolbar_class;
mod item;
pub use item::ToolbarItem;
mod traits;
pub use traits::ToolbarDelegate;
mod enums;
pub use enums::{ItemIdentifier, ToolbarDisplayMode, ToolbarSizeMode};
pub(crate) static TOOLBAR_PTR: &str = "cacaoToolbarPtr";
pub struct Toolbar<T = ()> {
pub identifier: String,
pub objc: ShareId<Object>,
pub objc_delegate: ShareId<Object>,
pub delegate: Option<Box<T>>
}
impl<T> Toolbar<T>
where
T: ToolbarDelegate + 'static
{
pub fn new<S: Into<String>>(identifier: S, delegate: T) -> Self {
let identifier = identifier.into();
let cls = register_toolbar_class::<T>(&delegate);
let mut delegate = Box::new(delegate);
let (objc, objc_delegate) = unsafe {
let alloc: id = msg_send![class!(NSToolbar), alloc];
let identifier = NSString::new(&identifier);
let toolbar: id = msg_send![alloc, initWithIdentifier: identifier];
let objc_delegate: id = msg_send![cls, new];
let ptr: *const T = &*delegate;
(&mut *objc_delegate).set_ivar(TOOLBAR_PTR, ptr as usize);
let _: () = msg_send![toolbar, setDelegate: objc_delegate];
(ShareId::from_ptr(toolbar), ShareId::from_ptr(objc_delegate))
};
let _ret = &mut delegate.did_load(Toolbar {
objc: objc.clone(),
objc_delegate: objc_delegate.clone(),
identifier: identifier.clone(),
delegate: None
});
Toolbar {
identifier,
objc,
objc_delegate,
delegate: Some(delegate)
}
}
}
impl<T> Toolbar<T> {
pub fn set_shows_baseline_separator(&self, shows: bool) {
unsafe {
let _: () = msg_send![&*self.objc, setShowsBaselineSeparator:match shows {
true => YES,
false => NO
}];
}
}
pub fn set_display_mode(&self, mode: ToolbarDisplayMode) {
let mode: NSUInteger = mode.into();
unsafe {
let _: () = msg_send![&*self.objc, setDisplayMode: mode];
}
}
pub fn set_size_mode(&self, mode: ToolbarSizeMode) {
let mode: NSUInteger = mode.into();
unsafe {
let _: () = msg_send![&*self.objc, setSizeMode: mode];
}
}
pub fn set_visible(&self, visibility: bool) {
unsafe {
let _: () = msg_send![&*self.objc, setVisible:match visibility {
true => YES,
false => NO
}];
}
}
pub fn set_selected(&self, item_identifier: &str) {
let identifier = NSString::new(item_identifier);
unsafe {
let _: () = msg_send![&*self.objc, setSelectedItemIdentifier:&*identifier];
}
}
}
impl<T> fmt::Debug for Toolbar<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let delegate = match &self.delegate {
Some(d) => format!("Some({:p})", d),
None => "None".to_string()
};
f.debug_struct("Toolbar")
.field("identifier", &self.identifier)
.field("objc", &self.objc)
.field("objc_delegate", &self.objc_delegate)
.field("delegate", &delegate)
.finish()
}
}
impl<T> Drop for Toolbar<T> {
fn drop(&mut self) {
if self.delegate.is_some() {
unsafe {
let _: () = msg_send![&*self.objc, setDelegate: nil];
}
}
}
}