aboutsummaryrefslogtreecommitdiff
path: root/src/element/dynelem.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/element/dynelem.rs')
-rw-r--r--src/element/dynelem.rs84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/element/dynelem.rs b/src/element/dynelem.rs
new file mode 100644
index 0000000..d32c06d
--- /dev/null
+++ b/src/element/dynelem.rs
@@ -0,0 +1,84 @@
+use super::{Drawable, PointCollection};
+use crate::drawing::backend::{BackendCoord, DrawingBackend, DrawingErrorKind};
+
+use std::borrow::Borrow;
+
+trait DynDrawable<DB: DrawingBackend> {
+ fn draw_dyn(
+ &self,
+ points: &mut dyn Iterator<Item = BackendCoord>,
+ backend: &mut DB,
+ parent_dim: (u32, u32),
+ ) -> Result<(), DrawingErrorKind<DB::ErrorType>>;
+}
+
+impl<DB: DrawingBackend, T: Drawable<DB>> DynDrawable<DB> for T {
+ fn draw_dyn(
+ &self,
+ points: &mut dyn Iterator<Item = BackendCoord>,
+ backend: &mut DB,
+ parent_dim: (u32, u32),
+ ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
+ T::draw(self, points, backend, parent_dim)
+ }
+}
+
+/// The container for a dynamically dispatched element
+pub struct DynElement<'a, DB, Coord>
+where
+ DB: DrawingBackend,
+ Coord: Clone,
+{
+ points: Vec<Coord>,
+ drawable: Box<dyn DynDrawable<DB> + 'a>,
+}
+
+impl<'a, 'b: 'a, DB: DrawingBackend, Coord: Clone> PointCollection<'a, Coord>
+ for &'a DynElement<'b, DB, Coord>
+{
+ type Borrow = &'a Coord;
+ type IntoIter = &'a Vec<Coord>;
+ fn point_iter(self) -> Self::IntoIter {
+ &self.points
+ }
+}
+
+impl<'a, DB: DrawingBackend, Coord: Clone> Drawable<DB> for DynElement<'a, DB, Coord> {
+ fn draw<I: Iterator<Item = BackendCoord>>(
+ &self,
+ mut pos: I,
+ backend: &mut DB,
+ parent_dim: (u32, u32),
+ ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
+ self.drawable.draw_dyn(&mut pos, backend, parent_dim)
+ }
+}
+
+/// The trait that makes the conversion from the statically dispatched element
+/// to the dynamically dispatched element
+pub trait IntoDynElement<'a, DB: DrawingBackend, Coord: Clone>
+where
+ Self: 'a,
+{
+ /// Make the conversion
+ fn into_dyn(self) -> DynElement<'a, DB, Coord>;
+}
+
+impl<'b, T, DB, Coord> IntoDynElement<'b, DB, Coord> for T
+where
+ T: Drawable<DB> + 'b,
+ for<'a> &'a T: PointCollection<'a, Coord>,
+ Coord: Clone,
+ DB: DrawingBackend,
+{
+ fn into_dyn(self) -> DynElement<'b, DB, Coord> {
+ DynElement {
+ points: self
+ .point_iter()
+ .into_iter()
+ .map(|x| x.borrow().clone())
+ .collect(),
+ drawable: Box::new(self),
+ }
+ }
+}