dessin 0.8.23

Build complex drawing for PDF, SVG, Images or Dioxus
Documentation
use crate::prelude::*;
use nalgebra::Transform2;
use std::{
	ops::{Deref, DerefMut},
	sync::{Arc, RwLock},
};

/// Dyn shape
pub type Shaper = dyn Fn() -> Shape + Send + Sync + 'static;

/// Dyn shape
pub trait DynamicShape: std::fmt::Debug {
	/// Dyn shape
	fn as_shape(&self) -> Shape;
}

impl<T: std::fmt::Debug + Clone + Into<Shape>> DynamicShape for T {
	fn as_shape(&self) -> Shape {
		self.clone().into()
	}
}

/// Dyn shape
#[derive(Clone, Debug, Shape)]
pub struct Dynamic<T> {
	#[local_transform]
	local_transform: Transform2<f32>,
	#[shape(skip)]
	shape: T,
	#[shape(skip)]
	_ref: Option<Arc<RwLock<T>>>,
}

impl<T: Default> Default for Dynamic<T> {
	fn default() -> Self {
		Dynamic {
			shape: T::default(),
			local_transform: Default::default(),
			_ref: Default::default(),
		}
	}
}

impl<T> Deref for Dynamic<T> {
	type Target = T;

	#[inline]
	fn deref(&self) -> &Self::Target {
		&self.shape
	}
}

impl<T> DerefMut for Dynamic<T> {
	#[inline]
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.shape
	}
}

impl<T> From<Dynamic<T>> for Shape
where
	T: DynamicShape + Send + Sync + 'static,
{
	fn from(
		Dynamic {
			local_transform,
			shape,
			_ref,
		}: Dynamic<T>,
	) -> Self {
		let _ref = match _ref {
			Some(_ref) => {
				*_ref.write().unwrap() = shape;
				_ref
			}
			None => Arc::new(RwLock::new(shape)),
		};

		Shape::Dynamic {
			local_transform,
			shaper: Arc::new(move || _ref.read().unwrap().as_shape()),
		}
	}
}

impl<T> Dynamic<T> {
	/// Dyn shape
	pub fn _ref(&mut self, _ref: &Arc<RwLock<T>>) -> &mut Self {
		self._ref = Some(_ref.clone());
		self
	}

	/// Dyn shape
	pub fn with_ref(mut self, _ref: &Arc<RwLock<T>>) -> Self {
		self._ref(_ref);
		self
	}
}

#[test]
fn dynamic() {
	use crate::export::{Export, Exporter};
	use nalgebra::Point2;

	struct TestExporter(f32);
	impl Exporter for TestExporter {
		type Error = ();

		fn start_style(&mut self, _style: StylePosition) -> Result<(), Self::Error> {
			unimplemented!()
		}

		fn end_style(&mut self) -> Result<(), Self::Error> {
			unimplemented!()
		}

		fn export_image(&mut self, _image: ImagePosition) -> Result<(), Self::Error> {
			unimplemented!()
		}

		fn export_ellipse(&mut self, ellipse: EllipsePosition) -> Result<(), Self::Error> {
			assert_eq!(ellipse.center, Point2::new(0., 0.));
			assert_eq!(ellipse.semi_major_axis, self.0);
			assert_eq!(ellipse.semi_minor_axis, self.0);
			Ok(())
		}

		fn export_curve(
			&mut self,
			_curve: CurvePosition,
			StylePosition { fill, stroke }: StylePosition,
		) -> Result<(), Self::Error> {
			unimplemented!()
		}

		fn export_text(&mut self, _text: TextPosition) -> Result<(), Self::Error> {
			unimplemented!()
		}
	}

	let my_ref = Default::default();

	let c = dessin!([Dynamic::<Circle>(_ref = &my_ref, radius = 2.,)]);
	c.write_into_exporter(
		&mut TestExporter(2.),
		&Transform2::default(),
		StylePosition {
			fill: None,
			stroke: None,
		},
	)
	.unwrap();

	my_ref.write().unwrap().scale([10., 10.]);
	c.write_into_exporter(
		&mut TestExporter(20.),
		&Transform2::default(),
		StylePosition {
			fill: None,
			stroke: None,
		},
	)
	.unwrap();
}