use core_graphics::base::CGFloat;
use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId;
use crate::foundation::{id, nil, NSInteger};
use crate::layout::constraint::LayoutConstraint;
use super::attributes::{LayoutAttribute, LayoutRelation};
#[derive(Clone, Debug, Default)]
pub struct LayoutAnchorDimension2(pub Option<ShareId<Object>>);
#[derive(Clone, Debug)]
pub enum LayoutAnchorDimension {
Uninitialized,
Width(ShareId<Object>),
Height(ShareId<Object>)
}
impl Default for LayoutAnchorDimension {
fn default() -> Self {
Self::Uninitialized
}
}
impl LayoutAnchorDimension {
pub(crate) fn width(view: id) -> Self {
Self::Width(unsafe { ShareId::from_ptr(msg_send![view, widthAnchor]) })
}
pub(crate) fn height(view: id) -> Self {
Self::Height(unsafe { ShareId::from_ptr(msg_send![view, heightAnchor]) })
}
pub fn constraint_equal_to_constant(&self, constant: f64) -> LayoutConstraint {
if let Self::Width(obj) | Self::Height(obj) = self {
return LayoutConstraint::new(unsafe {
let value = constant as CGFloat;
msg_send![*obj, constraintEqualToConstant: value]
});
}
panic!("Attempted to create a constant constraint with an uninitialized anchor.");
}
pub fn constraint_greater_than_or_equal_to_constant(&self, constant: f64) -> LayoutConstraint {
if let Self::Width(obj) | Self::Height(obj) = self {
return LayoutConstraint::new(unsafe {
let value = constant as CGFloat;
msg_send![*obj, constraintGreaterThanOrEqualToConstant: value]
});
}
panic!("Attempted to create a constraint (>=) with an uninitialized anchor.");
}
pub fn constraint_less_than_or_equal_to_constant(&self, constant: f64) -> LayoutConstraint {
if let Self::Width(obj) | Self::Height(obj) = self {
return LayoutConstraint::new(unsafe {
let value = constant as CGFloat;
msg_send![*obj, constraintLessThanOrEqualToConstant: value]
});
}
panic!("Attempted to create a constraint (<=) with an uninitialized anchor.");
}
fn constraint_with<F>(&self, anchor_to: &LayoutAnchorDimension, handler: F) -> LayoutConstraint
where
F: Fn(&ShareId<Object>, &ShareId<Object>) -> id
{
match (self, anchor_to) {
(Self::Width(from), Self::Width(to))
| (Self::Width(from), Self::Height(to))
| (Self::Height(from), Self::Width(to))
| (Self::Height(from), Self::Height(to)) => LayoutConstraint::new(handler(from, to)),
(Self::Uninitialized, Self::Uninitialized) => {
panic!("Attempted to create constraints with an uninitialized \"from\" and \"to\" dimension anchor.");
},
(Self::Uninitialized, _) => {
panic!("Attempted to create constraints with an uninitialized \"from\" dimension anchor.");
},
(_, Self::Uninitialized) => {
panic!("Attempted to create constraints with an uninitialized \"to\" dimension anchor.");
}
}
}
pub fn constraint_equal_to(&self, anchor_to: &LayoutAnchorDimension) -> LayoutConstraint {
self.constraint_with(anchor_to, |from, to| unsafe {
msg_send![*from, constraintEqualToAnchor:&**to]
})
}
pub fn constraint_greater_than_or_equal_to(&self, anchor_to: &LayoutAnchorDimension) -> LayoutConstraint {
self.constraint_with(anchor_to, |from, to| unsafe {
msg_send![*from, constraintGreaterThanOrEqualToAnchor:&**to]
})
}
pub fn constraint_less_than_or_equal_to(&self, anchor_to: &LayoutAnchorDimension) -> LayoutConstraint {
self.constraint_with(anchor_to, |from, to| unsafe {
msg_send![*from, constraintLessThanOrEqualToAnchor:&**to]
})
}
}