Skip to main content

ferroui_controls/shapes/
rectangle.rs

1use super::{Shape, ShapeImpl};
2use crate::ControlImpl;
3use ferroui_base::input::InputElementImpl;
4use ferroui_base::interactivity::InteractiveImpl;
5use ferroui_base::layout::LayoutableImpl;
6use ferroui_base::media::{Geometry, RectangleGeometry};
7use ferroui_base::{
8    ferro_class, ferro_impl_classes, ferro_property, instantiate, FerroObjectImpl, FerroProperty,
9    Rect, Ref, Size, StyledElementImpl, StyledProperty, Visual, VisualImpl,
10};
11
12/// Represents a rectangle with optional rounded corners.
13#[repr(C)]
14pub struct Rectangle {
15    base: Shape,
16}
17
18ferro_class!(Rectangle: Shape);
19ferroui_base::ferro_class_info!(Rectangle { new: Rectangle::new });
20ferro_impl_classes!(Rectangle: StyledElementImpl, VisualImpl, InteractiveImpl, InputElementImpl, ControlImpl);
21
22ferroui_base::ferro_impl_classes!(Rectangle: FerroObjectImpl);
23
24impl ShapeImpl for Rectangle {
25    fn create_defining_geometry(this: &Self) -> Option<Ref<Geometry>> {
26        let rect = Rect::from_size(this.bounds().size()).deflate(this.stroke_thickness() / 2.0);
27
28        Some(RectangleGeometry::with_rect_and_radii(rect, this.radius_x(), this.radius_y()).upcast())
29    }
30}
31
32impl LayoutableImpl for Rectangle {
33    fn measure_override(this: &Self, _available_size: Size) -> Size {
34        Size::new(this.stroke_thickness(), this.stroke_thickness())
35    }
36}
37
38ferroui_base::ferro_properties! { impl Rectangle {
39    ferro_property!(
40        /// Defines the `RadiusX` property.
41        pub fn radius_x_property() -> StyledProperty<f64> {
42            FerroProperty::register::<Rectangle, _>("RadiusX", 0.0)
43        }
44    );
45
46    ferro_property!(
47        /// Defines the `RadiusY` property.
48        pub fn radius_y_property() -> StyledProperty<f64> {
49            FerroProperty::register::<Rectangle, _>("RadiusY", 0.0)
50        }
51    );
52} }
53
54impl Rectangle {
55    fn static_constructor() {
56        Shape::affects_geometry::<Rectangle>(&[
57            Visual::bounds_property().as_property(),
58            Self::radius_x_property().as_property(),
59            Self::radius_y_property().as_property(),
60            Shape::stroke_thickness_property().as_property(),
61        ]);
62    }
63
64    /// Creates the class data; see [`ferroui_base::FerroObject::construct`].
65    pub fn construct() -> Self {
66        Self { base: Shape::construct() }
67    }
68
69    pub fn new() -> Ref<Self> {
70        instantiate(Self::construct())
71    }
72
73    /// Gets the radius in the X-axis of the ellipse that rounds the corners
74    /// of the rectangle.
75    pub fn radius_x(&self) -> f64 {
76        self.get_value(Self::radius_x_property())
77    }
78
79    /// Sets the radius in the X-axis of the ellipse that rounds the corners
80    /// of the rectangle.
81    pub fn set_radius_x(&self, value: f64) {
82        self.set_value(Self::radius_x_property(), value)
83    }
84
85    /// Gets the radius in the Y-axis of the ellipse that rounds the corners
86    /// of the rectangle.
87    pub fn radius_y(&self) -> f64 {
88        self.get_value(Self::radius_y_property())
89    }
90
91    /// Sets the radius in the Y-axis of the ellipse that rounds the corners
92    /// of the rectangle.
93    pub fn set_radius_y(&self, value: f64) {
94        self.set_value(Self::radius_y_property(), value)
95    }
96}