Skip to main content

ferroui_base/media/
i_dash_style.rs

1use crate::media::immutable::ImmutableDashStyle;
2use crate::media::DashStyle;
3use crate::media::ref_adapter::RefAdapter;
4use crate::{FerroObject, ObjectType, Ref, Upcast};
5use std::any::Any;
6use std::rc::Rc;
7
8/// Represents the sequence of dashes and gaps that will be applied by a pen.
9///
10/// Implemented by [`ImmutableDashStyle`] and, through an adapter, by handles ([`Ref`]) of
11/// [`DashStyle`].
12pub trait IDashStyle: 'static {
13    /// The length of alternating dashes and gaps.
14    fn dashes(&self) -> Option<Vec<f64>>;
15
16    /// How far in the dash sequence the stroke will start.
17    fn offset(&self) -> f64;
18
19    /// The implementing value, for downcasts to [`ImmutableDashStyle`].
20    fn as_any(&self) -> &dyn Any;
21
22    /// The object behind the dash style when it is a mutable [`DashStyle`].
23    fn as_object(&self) -> Option<&FerroObject> {
24        None
25    }
26
27    /// Converts the dash style to an immutable dash style; an immutable dash
28    /// style returns itself.
29    fn into_immutable_dash_style(self: Rc<Self>) -> Rc<ImmutableDashStyle>;
30
31    /// The identity of the dash style, used for reference equality.
32    #[doc(hidden)]
33    fn reference_id(&self) -> *const () {
34        self as *const Self as *const ()
35    }
36
37    /// Whether the dash style equals `other`. Mutable dash styles compare by
38    /// reference, immutable ones structurally.
39    fn equals(&self, other: &dyn IDashStyle) -> bool {
40        self.reference_id() == other.reference_id()
41    }
42}
43
44impl PartialEq for dyn IDashStyle {
45    #[inline]
46    fn eq(&self, other: &Self) -> bool {
47        self.equals(other)
48    }
49}
50
51impl std::fmt::Debug for dyn IDashStyle {
52    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53        f.debug_struct("IDashStyle").field("dashes", &self.dashes()).field("offset", &self.offset()).finish()
54    }
55}
56
57impl<T: ObjectType + Upcast<DashStyle>> IDashStyle for RefAdapter<T> {
58    fn dashes(&self) -> Option<Vec<f64>> {
59        Upcast::<DashStyle>::upcast(&*self.0).dashes().map(|dashes| dashes.to_vec())
60    }
61
62    #[inline]
63    fn offset(&self) -> f64 {
64        Upcast::<DashStyle>::upcast(&*self.0).offset()
65    }
66
67    fn as_any(&self) -> &dyn Any {
68        Upcast::<DashStyle>::upcast(&*self.0)
69    }
70
71    fn as_object(&self) -> Option<&FerroObject> {
72        Some(self.object())
73    }
74
75    fn into_immutable_dash_style(self: Rc<Self>) -> Rc<ImmutableDashStyle> {
76        Rc::new(Upcast::<DashStyle>::upcast(&*self.0).to_immutable())
77    }
78
79    fn reference_id(&self) -> *const () {
80        RefAdapter::reference_id(self)
81    }
82}
83
84impl<T: ObjectType + Upcast<DashStyle>> From<Ref<T>> for Rc<dyn IDashStyle> {
85    #[inline]
86    fn from(value: Ref<T>) -> Self {
87        Rc::new(RefAdapter(value))
88    }
89}
90
91impl<T: ObjectType + Upcast<DashStyle>> From<&Ref<T>> for Rc<dyn IDashStyle> {
92    #[inline]
93    fn from(value: &Ref<T>) -> Self {
94        Rc::new(RefAdapter(value.clone()))
95    }
96}