ferroui_base/media/
dash_style.rs1use crate::animation::Animatable;
2use crate::media::immutable::ImmutableDashStyle;
3use crate::media::MediaCollection;
4use crate::reactive::{Disposable, IDisposable};
5use crate::utilities::HandlerList;
6use crate::{
7 ferro_class, ferro_property, instantiate, FerroObjectImpl, FerroObjectImplExt, FerroProperty,
8 FerroPropertyChangedEventArgs, Ref, StyledProperty,
9};
10use std::cell::RefCell;
11use std::rc::Rc;
12
13#[repr(C)]
16pub struct DashStyle {
17 base: Animatable,
18 invalidated: HandlerList<dyn Fn()>,
19 dashes_subscription: RefCell<Option<Rc<dyn IDisposable>>>,
20}
21
22ferro_class!(DashStyle: Animatable);
23crate::ferro_class_info!(DashStyle { new: DashStyle::new, interfaces: [std::rc::Rc<dyn crate::media::IDashStyle>] });
24
25impl FerroObjectImpl for DashStyle {
26 fn on_property_changed(this: &Self, change: &FerroPropertyChangedEventArgs<'_>) {
27 Self::parent_on_property_changed(this, change);
28
29 if change.property() == Self::dashes_property().as_property() {
30 let new_value = change.get_new_value::<Option<MediaCollection<f64>>>();
31
32 if let Some(subscription) = this.dashes_subscription.take() {
33 subscription.dispose();
34 }
35
36 if let Some(new_value) = new_value {
37 let weak = this.to_ref().downgrade();
38 let subscription = new_value.collection_changed(move |_| {
39 if let Some(this) = weak.upgrade() {
40 this.raise_invalidated();
41 }
42 });
43 *this.dashes_subscription.borrow_mut() = Some(subscription);
44 }
45 }
46 }
47}
48
49crate::ferro_properties! { impl DashStyle {
50 ferro_property!(pub fn dashes_property() -> StyledProperty<Option<MediaCollection<f64>>> {
51 FerroProperty::register::<DashStyle, _>("Dashes", None)
52 });
53
54 ferro_property!(pub fn offset_property() -> StyledProperty<f64> {
55 FerroProperty::register::<DashStyle, _>("Offset", 0.0)
56 });
57} }
58
59impl DashStyle {
60 fn static_constructor() {
61 Self::dashes_property().changed().add_class_handler::<DashStyle>(|x, _| x.raise_invalidated());
62 Self::offset_property().changed().add_class_handler::<DashStyle>(|x, _| x.raise_invalidated());
63 }
64
65 pub fn construct() -> Self {
67 Self { base: Animatable::construct(), invalidated: HandlerList::new(), dashes_subscription: RefCell::new(None) }
68 }
69
70 pub fn new() -> Ref<Self> {
72 instantiate(Self::construct())
73 }
74
75 pub fn with_dashes(dashes: Option<&[f64]>, offset: f64) -> Ref<Self> {
77 Self::with_dash_list(MediaCollection::from_items(dashes.unwrap_or(&[]).iter().copied()), offset)
78 }
79
80 pub fn with_dash_list(dashes: MediaCollection<f64>, offset: f64) -> Ref<Self> {
82 let result = Self::new();
83 result.set_dashes(Some(dashes));
84 result.set_offset(offset);
85 result
86 }
87
88 pub fn dash() -> Rc<ImmutableDashStyle> {
90 crate::ferro_thread_local! {
91 static DASH: Rc<ImmutableDashStyle> = Rc::new(ImmutableDashStyle::new(Some(&[2.0, 2.0]), 1.0));
92 }
93 DASH.with(Rc::clone)
94 }
95
96 pub fn dot() -> Rc<ImmutableDashStyle> {
98 crate::ferro_thread_local! {
99 static DOT: Rc<ImmutableDashStyle> = Rc::new(ImmutableDashStyle::new(Some(&[0.0, 2.0]), 0.0));
100 }
101 DOT.with(Rc::clone)
102 }
103
104 pub fn dash_dot() -> Rc<ImmutableDashStyle> {
106 crate::ferro_thread_local! {
107 static DASH_DOT: Rc<ImmutableDashStyle> =
108 Rc::new(ImmutableDashStyle::new(Some(&[2.0, 2.0, 0.0, 2.0]), 1.0));
109 }
110 DASH_DOT.with(Rc::clone)
111 }
112
113 pub fn dash_dot_dot() -> Rc<ImmutableDashStyle> {
115 crate::ferro_thread_local! {
116 static DASH_DOT_DOT: Rc<ImmutableDashStyle> =
117 Rc::new(ImmutableDashStyle::new(Some(&[2.0, 2.0, 0.0, 2.0, 0.0, 2.0]), 1.0));
118 }
119 DASH_DOT_DOT.with(Rc::clone)
120 }
121
122 pub fn dashes(&self) -> Option<MediaCollection<f64>> {
124 self.get_value(Self::dashes_property())
125 }
126
127 pub fn set_dashes(&self, value: Option<MediaCollection<f64>>) {
128 self.set_value(Self::dashes_property(), value)
129 }
130
131 pub fn offset(&self) -> f64 {
133 self.get_value(Self::offset_property())
134 }
135
136 pub fn set_offset(&self, value: f64) {
137 self.set_value(Self::offset_property(), value)
138 }
139
140 pub fn invalidated(&self, handler: impl Fn() + 'static) -> Rc<dyn IDisposable> {
143 let token = self.invalidated.add(Rc::new(handler));
144 let weak = self.to_ref().downgrade();
145 Disposable::create(move || {
146 if let Some(this) = weak.upgrade() {
147 this.invalidated.remove(token);
148 }
149 })
150 }
151
152 fn raise_invalidated(&self) {
153 if self.invalidated.is_empty() {
154 return;
155 }
156 for (_, handler) in self.invalidated.snapshot().iter() {
157 handler();
158 }
159 }
160
161 pub fn to_immutable(&self) -> ImmutableDashStyle {
163 ImmutableDashStyle::new(self.dashes().map(|dashes| dashes.to_vec()).as_deref(), self.offset())
164 }
165}