Skip to main content

ferroui_base/media/
geometry_drawing.rs

1use crate::media::immutable::ImmutablePen;
2use crate::media::{Brushes, Colors, Drawing, DrawingContext, DrawingImpl, Geometry, IBrush, IPen};
3use crate::{
4    ferro_class, ferro_impl_classes, ferro_property, instantiate, FerroObjectImpl, FerroProperty, Nullable, Rect, Ref,
5    StyledProperty,
6};
7use std::rc::Rc;
8
9/// Represents a drawing of a [`Geometry`] with a brush and a pen.
10#[repr(C)]
11pub struct GeometryDrawing {
12    base: Drawing,
13}
14
15ferro_class!(GeometryDrawing: Drawing);
16crate::ferro_class_info!(GeometryDrawing { new: GeometryDrawing::new });
17ferro_impl_classes!(GeometryDrawing: FerroObjectImpl);
18
19impl DrawingImpl for GeometryDrawing {
20    fn draw_core(this: &Self, context: &mut DrawingContext) {
21        if let Some(geometry) = this.geometry() {
22            context.draw_geometry(this.brush().as_ref(), this.pen().as_ref(), &geometry);
23        }
24    }
25
26    fn get_bounds(this: &Self) -> Rect {
27        let Some(geometry) = this.geometry() else { return Rect::default() };
28        match this.pen() {
29            Some(pen) => geometry.get_render_bounds(&*pen),
30            // Adding the pen's stroke thickness here could yield wrong
31            // results due to transforms.
32            None => geometry.get_render_bounds(&ImmutablePen::from_uint32(Colors::BLACK.to_uint32(), 0.0)),
33        }
34    }
35}
36
37crate::ferro_properties! { impl GeometryDrawing {
38    ferro_property!(
39        /// Defines the `Geometry` property.
40        pub fn geometry_property() -> StyledProperty<Option<Ref<Geometry>>> {
41            FerroProperty::register::<GeometryDrawing, _>("Geometry", None)
42        }
43    );
44
45    ferro_property!(
46        /// Defines the `Brush` property.
47        pub fn brush_property() -> StyledProperty<Option<Rc<dyn IBrush>>> {
48            FerroProperty::register::<GeometryDrawing, _>("Brush", Some(Brushes::transparent() as Rc<dyn IBrush>))
49        }
50    );
51
52    ferro_property!(
53        /// Defines the `Pen` property.
54        pub fn pen_property() -> StyledProperty<Option<Rc<dyn IPen>>> {
55            FerroProperty::register::<GeometryDrawing, _>("Pen", None)
56        }
57    );
58} }
59
60impl GeometryDrawing {
61    /// Creates the class data.
62    pub fn construct() -> Self {
63        Self { base: Drawing::construct() }
64    }
65
66    pub fn new() -> Ref<Self> {
67        instantiate(Self::construct())
68    }
69
70    /// The geometry that describes the shape of this drawing.
71    pub fn geometry(&self) -> Option<Ref<Geometry>> {
72        self.get_value(Self::geometry_property())
73    }
74
75    pub fn set_geometry(&self, value: impl Into<Nullable<Geometry>>) {
76        self.set_value(Self::geometry_property(), value.into().0)
77    }
78
79    /// The brush used to fill the interior of the shape described by this
80    /// drawing.
81    pub fn brush(&self) -> Option<Rc<dyn IBrush>> {
82        self.get_value(Self::brush_property())
83    }
84
85    pub fn set_brush(&self, value: Option<Rc<dyn IBrush>>) {
86        self.set_value(Self::brush_property(), value)
87    }
88
89    /// The pen used to stroke this drawing.
90    pub fn pen(&self) -> Option<Rc<dyn IPen>> {
91        self.get_value(Self::pen_property())
92    }
93
94    pub fn set_pen(&self, value: Option<Rc<dyn IPen>>) {
95        self.set_value(Self::pen_property(), value)
96    }
97}