use super::composition_object_impls::composition_object_impls;
use super::generated::{
CompositionEllipseGeometryHooks, CompositionEllipseGeometryProps, CompositionGeometryHooks,
CompositionGeometryProps, CompositionLineGeometryHooks, CompositionLineGeometryProps,
CompositionPathGeometryHooks, CompositionPathGeometryProps, CompositionRectangleGeometryHooks,
CompositionRectangleGeometryProps, CompositionRoundedRectangleGeometryHooks,
CompositionRoundedRectangleGeometryProps, ServerCompositionEllipseGeometryProps,
ServerCompositionLineGeometryProps, ServerCompositionPathGeometryProps, ServerCompositionRectangleGeometryProps,
ServerCompositionRoundedRectangleGeometryProps,
};
use super::server::{
IServerObject, ServerCompositionEllipseGeometry, ServerCompositionLineGeometry, ServerCompositionPathGeometry,
ServerCompositionRectangleGeometry, ServerCompositionRoundedRectangleGeometry, ServerCompositor, ServerObjectId,
};
use super::{CompositionObject, Compositor};
use crate::media::Geometry;
use crate::platform::IGeometryImpl;
use crate::utilities::FormatError;
use crate::{Rect, Vector};
use std::ops::Deref;
use std::rc::{Rc, Weak};
use std::sync::Arc;
#[derive(Clone)]
pub struct CompositionPath {
geometry: Arc<dyn IGeometryImpl>,
}
impl CompositionPath {
pub fn new(geometry: Arc<dyn IGeometryImpl>) -> CompositionPath {
CompositionPath { geometry }
}
pub fn from_geometry(geometry: &Geometry) -> Option<CompositionPath> {
geometry.platform_impl().map(CompositionPath::new)
}
pub fn parse(data: &str) -> Result<CompositionPath, FormatError> {
let geometry = Geometry::parse(data)?;
let platform = geometry.platform_impl().expect("a parsed stream geometry has a platform geometry");
Ok(CompositionPath::new(platform))
}
pub fn geometry(&self) -> &Arc<dyn IGeometryImpl> {
&self.geometry
}
pub fn bounds(&self) -> Rect {
self.geometry.bounds()
}
}
impl std::fmt::Debug for CompositionPath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CompositionPath").field("bounds", &self.geometry.bounds()).finish()
}
}
pub(crate) enum CompositionGeometryKind {
Rectangle(CompositionRectangleGeometryProps),
RoundedRectangle(CompositionRoundedRectangleGeometryProps),
Ellipse(CompositionEllipseGeometryProps),
Line(CompositionLineGeometryProps),
Path(CompositionPathGeometryProps),
}
pub struct CompositionGeometry {
this: Weak<CompositionGeometry>,
object: CompositionObject,
kind: CompositionGeometryKind,
}
impl CompositionGeometry {
fn create(
compositor: &Rc<Compositor>,
kind: CompositionGeometryKind,
server: impl FnOnce(&Rc<ServerCompositor>) -> Rc<dyn IServerObject> + Send + 'static,
) -> Rc<CompositionGeometry> {
let server = compositor.create_server_object(move |compositor, _| server(compositor));
let geometry = Rc::new_cyclic(|this: &Weak<CompositionGeometry>| CompositionGeometry {
this: this.clone(),
object: CompositionObject::new(compositor, Some(server)),
kind,
});
match &geometry.kind {
CompositionGeometryKind::Rectangle(props) => props.initialize_defaults(&*geometry),
CompositionGeometryKind::RoundedRectangle(props) => props.initialize_defaults(&*geometry),
CompositionGeometryKind::Ellipse(props) => props.initialize_defaults(&*geometry),
CompositionGeometryKind::Line(props) => props.initialize_defaults(&*geometry),
CompositionGeometryKind::Path(props) => props.initialize_defaults(&*geometry),
}
geometry
}
pub fn geometry_props(&self) -> &CompositionGeometryProps {
match &self.kind {
CompositionGeometryKind::Rectangle(props) => props.base(),
CompositionGeometryKind::RoundedRectangle(props) => props.base(),
CompositionGeometryKind::Ellipse(props) => props.base(),
CompositionGeometryKind::Line(props) => props.base(),
CompositionGeometryKind::Path(props) => props.base(),
}
}
pub fn compositor(&self) -> &Rc<Compositor> {
self.object.compositor()
}
pub fn object(&self) -> &CompositionObject {
&self.object
}
pub fn server(&self) -> ServerObjectId {
self.object.required_server()
}
pub fn is_disposed(&self) -> bool {
self.object.is_disposed()
}
pub fn dispose(&self) {
self.object.dispose();
}
pub fn type_name(&self) -> &'static str {
match &self.kind {
CompositionGeometryKind::Rectangle(_) => "CompositionRectangleGeometry",
CompositionGeometryKind::RoundedRectangle(_) => "CompositionRoundedRectangleGeometry",
CompositionGeometryKind::Ellipse(_) => "CompositionEllipseGeometry",
CompositionGeometryKind::Line(_) => "CompositionLineGeometry",
CompositionGeometryKind::Path(_) => "CompositionPathGeometry",
}
}
pub fn trim_end(&self) -> f32 {
self.geometry_props().trim_end()
}
pub fn set_trim_end(&self, value: f32) {
self.geometry_props().set_trim_end(self, value)
}
pub fn trim_offset(&self) -> f32 {
self.geometry_props().trim_offset()
}
pub fn set_trim_offset(&self, value: f32) {
self.geometry_props().set_trim_offset(self, value)
}
pub fn trim_start(&self) -> f32 {
self.geometry_props().trim_start()
}
pub fn set_trim_start(&self, value: f32) {
self.geometry_props().set_trim_start(self, value)
}
}
impl CompositionGeometryHooks for CompositionGeometry {}
impl CompositionRectangleGeometryHooks for CompositionGeometry {}
impl CompositionRoundedRectangleGeometryHooks for CompositionGeometry {}
impl CompositionEllipseGeometryHooks for CompositionGeometry {}
impl CompositionLineGeometryHooks for CompositionGeometry {}
impl CompositionPathGeometryHooks for CompositionGeometry {}
composition_object_impls!(
CompositionGeometry, "CompositionGeometry",
serialize: |this, writer| match &this.kind {
CompositionGeometryKind::Rectangle(props) => props.serialize_changes_core(this, writer),
CompositionGeometryKind::RoundedRectangle(props) => props.serialize_changes_core(this, writer),
CompositionGeometryKind::Ellipse(props) => props.serialize_changes_core(this, writer),
CompositionGeometryKind::Line(props) => props.serialize_changes_core(this, writer),
CompositionGeometryKind::Path(props) => props.serialize_changes_core(this, writer),
},
start_animation: |this, name, animation, final_value| match &this.kind {
CompositionGeometryKind::Rectangle(props) => props.start_animation(this, name, animation, final_value),
CompositionGeometryKind::RoundedRectangle(props) => props.start_animation(this, name, animation, final_value),
CompositionGeometryKind::Ellipse(props) => props.start_animation(this, name, animation, final_value),
CompositionGeometryKind::Line(props) => props.start_animation(this, name, animation, final_value),
CompositionGeometryKind::Path(props) => props.start_animation(this, name, animation, final_value),
},
composition_property: |this, name| match &this.kind {
CompositionGeometryKind::Rectangle(_) => ServerCompositionRectangleGeometryProps::get_composition_property(name),
CompositionGeometryKind::RoundedRectangle(_) => {
ServerCompositionRoundedRectangleGeometryProps::get_composition_property(name)
}
CompositionGeometryKind::Ellipse(_) => ServerCompositionEllipseGeometryProps::get_composition_property(name),
CompositionGeometryKind::Line(_) => ServerCompositionLineGeometryProps::get_composition_property(name),
CompositionGeometryKind::Path(_) => ServerCompositionPathGeometryProps::get_composition_property(name),
},
);
macro_rules! geometry_handle {
($(#[$meta:meta])* $name:ident, $variant:ident, $props:ident, $what:literal) => {
$(#[$meta])*
#[derive(Clone)]
pub struct $name(Rc<CompositionGeometry>);
impl Deref for $name {
type Target = Rc<CompositionGeometry>;
fn deref(&self) -> &Rc<CompositionGeometry> {
&self.0
}
}
impl $name {
#[doc = concat!("The handle of `geometry` as ", $what, ", if it is one.")]
pub fn from_geometry(geometry: &Rc<CompositionGeometry>) -> Option<$name> {
matches!(geometry.kind, CompositionGeometryKind::$variant(_)).then(|| $name(geometry.clone()))
}
pub fn geometry(&self) -> &Rc<CompositionGeometry> {
&self.0
}
fn props(&self) -> &$props {
match &self.0.kind {
CompositionGeometryKind::$variant(props) => props,
_ => unreachable!(concat!("the handle wraps ", $what)),
}
}
}
};
}
geometry_handle!(
CompositionRectangleGeometry,
Rectangle,
CompositionRectangleGeometryProps,
"a rectangle geometry"
);
impl CompositionRectangleGeometry {
pub(crate) fn new(compositor: &Rc<Compositor>) -> CompositionRectangleGeometry {
CompositionRectangleGeometry(CompositionGeometry::create(
compositor,
CompositionGeometryKind::Rectangle(CompositionRectangleGeometryProps::new()),
|c| ServerCompositionRectangleGeometry::new(c),
))
}
pub fn offset(&self) -> Vector {
self.props().offset()
}
pub fn set_offset(&self, value: Vector) {
self.props().set_offset(&*self.0, value)
}
pub fn size(&self) -> Vector {
self.props().size()
}
pub fn set_size(&self, value: Vector) {
self.props().set_size(&*self.0, value)
}
}
geometry_handle!(
CompositionRoundedRectangleGeometry,
RoundedRectangle,
CompositionRoundedRectangleGeometryProps,
"a rounded rectangle geometry"
);
impl CompositionRoundedRectangleGeometry {
pub(crate) fn new(compositor: &Rc<Compositor>) -> CompositionRoundedRectangleGeometry {
CompositionRoundedRectangleGeometry(CompositionGeometry::create(
compositor,
CompositionGeometryKind::RoundedRectangle(CompositionRoundedRectangleGeometryProps::new()),
|c| ServerCompositionRoundedRectangleGeometry::new(c),
))
}
pub fn corner_radius(&self) -> Vector {
self.props().corner_radius()
}
pub fn set_corner_radius(&self, value: Vector) {
self.props().set_corner_radius(&*self.0, value)
}
pub fn offset(&self) -> Vector {
self.props().offset()
}
pub fn set_offset(&self, value: Vector) {
self.props().set_offset(&*self.0, value)
}
pub fn size(&self) -> Vector {
self.props().size()
}
pub fn set_size(&self, value: Vector) {
self.props().set_size(&*self.0, value)
}
}
geometry_handle!(
CompositionEllipseGeometry,
Ellipse,
CompositionEllipseGeometryProps,
"an ellipse geometry"
);
impl CompositionEllipseGeometry {
pub(crate) fn new(compositor: &Rc<Compositor>) -> CompositionEllipseGeometry {
CompositionEllipseGeometry(CompositionGeometry::create(
compositor,
CompositionGeometryKind::Ellipse(CompositionEllipseGeometryProps::new()),
|c| ServerCompositionEllipseGeometry::new(c),
))
}
pub fn center(&self) -> Vector {
self.props().center()
}
pub fn set_center(&self, value: Vector) {
self.props().set_center(&*self.0, value)
}
pub fn radius(&self) -> Vector {
self.props().radius()
}
pub fn set_radius(&self, value: Vector) {
self.props().set_radius(&*self.0, value)
}
}
geometry_handle!(
CompositionLineGeometry,
Line,
CompositionLineGeometryProps,
"a line geometry"
);
impl CompositionLineGeometry {
pub(crate) fn new(compositor: &Rc<Compositor>) -> CompositionLineGeometry {
CompositionLineGeometry(CompositionGeometry::create(
compositor,
CompositionGeometryKind::Line(CompositionLineGeometryProps::new()),
|c| ServerCompositionLineGeometry::new(c),
))
}
pub fn start(&self) -> Vector {
self.props().start()
}
pub fn set_start(&self, value: Vector) {
self.props().set_start(&*self.0, value)
}
pub fn end(&self) -> Vector {
self.props().end()
}
pub fn set_end(&self, value: Vector) {
self.props().set_end(&*self.0, value)
}
}
geometry_handle!(
CompositionPathGeometry,
Path,
CompositionPathGeometryProps,
"a path geometry"
);
impl CompositionPathGeometry {
pub(crate) fn new(compositor: &Rc<Compositor>) -> CompositionPathGeometry {
CompositionPathGeometry(CompositionGeometry::create(
compositor,
CompositionGeometryKind::Path(CompositionPathGeometryProps::new()),
|c| ServerCompositionPathGeometry::new(c),
))
}
pub(crate) fn with_path(compositor: &Rc<Compositor>, path: Option<CompositionPath>) -> CompositionPathGeometry {
let geometry = Self::new(compositor);
geometry.set_path(path);
geometry
}
pub fn path(&self) -> Option<CompositionPath> {
self.props().path().map(|path| (*path).clone())
}
pub fn set_path(&self, value: Option<CompositionPath>) {
self.props().set_path(&*self.0, value.map(Arc::new))
}
}