core_animation/
layer_builder.rs

1//! Builder for `CALayer` (the basic compositing layer).
2
3use crate::color::Color;
4use objc2::rc::Retained;
5use objc2_core_foundation::{CFRetained, CGFloat, CGPoint, CGRect};
6use objc2_core_graphics::CGColor;
7use objc2_quartz_core::{CALayer, CATransform3D};
8
9/// Builder for `CALayer`.
10///
11/// ```ignore
12/// let layer = CALayerBuilder::new()
13///     .bounds(CGRect::new(CGPoint::ZERO, CGSize::new(100.0, 100.0)))
14///     .position(CGPoint::new(50.0, 50.0))
15///     .background_color(Color::DARK_GRAY)
16///     .corner_radius(8.0)
17///     .build();
18/// ```
19#[derive(Default)]
20pub struct CALayerBuilder {
21    bounds: Option<CGRect>,
22    position: Option<CGPoint>,
23    background_color: Option<CFRetained<CGColor>>,
24    corner_radius: Option<CGFloat>,
25    hidden: Option<bool>,
26    transform: Option<CATransform3D>,
27    opacity: Option<f32>,
28}
29
30impl CALayerBuilder {
31    /// Creates a new builder with default values.
32    pub fn new() -> Self {
33        Self::default()
34    }
35
36    /// Sets the bounds rectangle.
37    pub fn bounds(mut self, bounds: CGRect) -> Self {
38        self.bounds = Some(bounds);
39        self
40    }
41
42    /// Sets the position in superlayer coordinates.
43    pub fn position(mut self, position: CGPoint) -> Self {
44        self.position = Some(position);
45        self
46    }
47
48    /// Sets the background color.
49    ///
50    /// Accepts any type that implements `Into<CFRetained<CGColor>>`, including:
51    /// - `Color::RED`, `Color::rgb(1.0, 0.0, 0.0)`
52    /// - `CFRetained<CGColor>` directly
53    ///
54    /// # Example
55    ///
56    /// ```ignore
57    /// .background_color(Color::BLUE)
58    /// .background_color(Color::rgb(0.2, 0.2, 0.2))
59    /// .background_color(Color::WHITE.with_alpha(0.5))
60    /// ```
61    pub fn background_color(mut self, color: impl Into<CFRetained<CGColor>>) -> Self {
62        self.background_color = Some(color.into());
63        self
64    }
65
66    /// Sets the background color from RGBA values (0.0–1.0).
67    pub fn background_rgba(mut self, r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) -> Self {
68        self.background_color = Some(Color::rgba(r, g, b, a).into());
69        self
70    }
71
72    /// Sets the corner radius.
73    pub fn corner_radius(mut self, radius: CGFloat) -> Self {
74        self.corner_radius = Some(radius);
75        self
76    }
77
78    /// Sets whether the layer is hidden.
79    pub fn hidden(mut self, hidden: bool) -> Self {
80        self.hidden = Some(hidden);
81        self
82    }
83
84    /// Sets the 3D transform.
85    pub fn transform(mut self, transform: CATransform3D) -> Self {
86        self.transform = Some(transform);
87        self
88    }
89
90    /// Sets the opacity (0.0–1.0).
91    pub fn opacity(mut self, opacity: f32) -> Self {
92        self.opacity = Some(opacity);
93        self
94    }
95
96    /// Builds and returns the configured `CALayer`.
97    pub fn build(self) -> Retained<CALayer> {
98        let layer = CALayer::new();
99
100        if let Some(bounds) = self.bounds {
101            layer.setBounds(bounds);
102        }
103        if let Some(position) = self.position {
104            layer.setPosition(position);
105        }
106        if let Some(ref color) = self.background_color {
107            layer.setBackgroundColor(Some(&**color));
108        }
109        if let Some(radius) = self.corner_radius {
110            layer.setCornerRadius(radius);
111        }
112        if let Some(hidden) = self.hidden {
113            layer.setHidden(hidden);
114        }
115        if let Some(transform) = self.transform {
116            layer.setTransform(transform);
117        }
118        if let Some(opacity) = self.opacity {
119            layer.setOpacity(opacity);
120        }
121
122        layer
123    }
124}