use crate::component::Component;
use crate::component_dirt::ComponentDirt;
use crate::core::{Core, CoreContext, Object, ObjectRef, OnAdded, Property, TryFromU64};
use crate::drawable::Drawable;
use crate::dyn_vec::DynVec;
use crate::option_cell::OptionCell;
use crate::shapes::ClippingShape;
use crate::status_code::StatusCode;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DrawTargetPlacement {
Before,
After,
}
impl Default for DrawTargetPlacement {
fn default() -> Self {
Self::Before
}
}
impl TryFromU64 for DrawTargetPlacement {
fn try_from(val: u64) -> Option<Self> {
match val {
0 => Some(Self::Before),
1 => Some(Self::After),
_ => None,
}
}
}
#[derive(Debug)]
pub struct DrawTarget {
component: Component,
drawable_id: Property<u64>,
placement: Property<DrawTargetPlacement>,
drawable: OptionCell<Object<Drawable>>,
pub(crate) first: OptionCell<Object<Drawable>>,
pub(crate) last: OptionCell<Object<Drawable>>,
clipping_shapes: DynVec<Object<ClippingShape>>,
}
impl ObjectRef<'_, DrawTarget> {
pub fn drawable_id(&self) -> u64 {
self.drawable_id.get()
}
pub fn set_drawable_id(&self, drawable_id: u64) {
self.drawable_id.set(drawable_id);
}
pub fn placement(&self) -> DrawTargetPlacement {
self.placement.get()
}
pub fn set_placement(&self, placement: DrawTargetPlacement) {
if self.placement() == placement {
return;
}
self.placement.set(placement);
if let Some(artboard) = self.component.artboard() {
artboard.cast::<Component>().as_ref().add_dirt(ComponentDirt::DRAW_ORDER, false);
}
}
}
impl ObjectRef<'_, DrawTarget> {
pub fn drawable(&self) -> Option<Object<Drawable>> {
self.drawable.get()
}
pub fn push_clipping_shape(&self, clipping_shape: Object<ClippingShape>) {
self.clipping_shapes.push(clipping_shape);
}
pub fn clipping_shapes(&self) -> impl Iterator<Item = Object<ClippingShape>> + '_ {
self.clipping_shapes.iter()
}
}
impl Core for DrawTarget {
parent_types![(component, Component)];
properties![(119, drawable_id, set_drawable_id), (120, placement, set_placement), component];
}
impl OnAdded for ObjectRef<'_, DrawTarget> {
on_added!([on_added_clean, import], Component);
fn on_added_dirty(&self, context: &dyn CoreContext) -> StatusCode {
let code = self.cast::<Component>().on_added_dirty(context);
if code != StatusCode::Ok {
return code;
}
if let Some(drawable) =
context.resolve(self.drawable_id() as usize).and_then(|core| core.try_cast())
{
self.drawable.set(Some(drawable));
StatusCode::Ok
} else {
StatusCode::MissingObject
}
}
}
impl Default for DrawTarget {
fn default() -> Self {
Self {
component: Component::default(),
drawable_id: Property::new(0),
placement: Property::new(DrawTargetPlacement::Before),
drawable: OptionCell::new(),
first: OptionCell::new(),
last: OptionCell::new(),
clipping_shapes: DynVec::new(),
}
}
}