buffer_graphics_lib/
drawable.rs1use crate::shapes::CreateDrawable;
2use graphics_shapes::coord::Coord;
3use graphics_shapes::{IntersectsContains, Shape};
4use ici_files::prelude::*;
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9#[derive(Debug, Clone, Copy, Eq, PartialEq)]
10pub enum DrawType {
11 Stroke(Color),
12 Fill(Color),
13}
14
15impl DrawType {
16 pub fn is_stroke(&self) -> bool {
17 matches!(self, DrawType::Stroke(_))
18 }
19
20 #[inline]
21 pub fn color(&self) -> Color {
22 *match self {
23 DrawType::Stroke(c) => c,
24 DrawType::Fill(c) => c,
25 }
26 }
27}
28
29#[inline]
30pub fn fill(color: Color) -> DrawType {
31 DrawType::Fill(color)
32}
33
34#[inline]
35pub fn stroke(color: Color) -> DrawType {
36 DrawType::Stroke(color)
37}
38
39#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
41#[derive(Debug, Eq, PartialEq, Clone)]
42pub struct Drawable<T: Clone> {
43 obj: T,
44 draw_type: DrawType,
45 drawing_points: Vec<Coord>,
46}
47
48impl<T: Clone> Drawable<T> {
49 #[inline]
50 pub fn obj(&self) -> &T {
51 &self.obj
52 }
53 #[inline]
54 pub fn draw_type(&self) -> DrawType {
55 self.draw_type
56 }
57 #[inline]
58 pub fn drawing_points(&self) -> &Vec<Coord> {
59 &self.drawing_points
60 }
61}
62
63impl<T: Clone> Drawable<T> {
64 #[inline]
65 pub fn new(obj: T, draw_type: DrawType, drawing_points: Vec<Coord>) -> Drawable<T> {
66 Self {
67 obj,
68 draw_type,
69 drawing_points,
70 }
71 }
72}
73
74impl<T: Clone> Drawable<T> {
75 pub fn with_draw_type(&self, draw_type: DrawType) -> Drawable<T> {
76 Drawable::new(self.obj.clone(), draw_type, self.drawing_points.clone())
77 }
78}
79
80impl<T> Drawable<T>
81where
82 Self: CreateDrawable<T>,
83 T: Shape + Clone,
84{
85 pub fn with_translation<P: Into<Coord>>(&self, delta: P) -> Drawable<T> {
86 let moved = self.obj.translate_by(delta.into());
87 Drawable::from_obj(moved, self.draw_type)
88 }
89
90 pub fn with_move<P: Into<Coord>>(&self, xy: P) -> Drawable<T> {
91 let moved = self.obj.move_to(xy.into());
92 Drawable::from_obj(moved, self.draw_type)
93 }
94
95 pub fn with_move_center<P: Into<Coord>>(&self, xy: P) -> Drawable<T> {
96 let moved = self.obj.move_center_to(xy.into());
97 Drawable::from_obj(moved, self.draw_type)
98 }
99
100 pub fn with_scale(&self, scale: f32) -> Drawable<T> {
101 let moved = self.obj.scale(scale);
102 Drawable::from_obj(moved, self.draw_type)
103 }
104
105 pub fn with_scale_around<P: Into<Coord>>(&self, scale: f32, point: P) -> Drawable<T> {
106 let moved = self.obj.scale_around(scale, point.into());
107 Drawable::from_obj(moved, self.draw_type)
108 }
109
110 pub fn with_rotation(&self, degrees: isize) -> Drawable<T> {
111 let rotated = self.obj.rotate(degrees);
112 Drawable::from_obj(rotated, self.draw_type)
113 }
114
115 pub fn with_rotation_around<P: Into<Coord>>(&self, degrees: isize, point: P) -> Drawable<T> {
116 let rotated = self.obj.rotate_around(degrees, point.into());
117 Drawable::from_obj(rotated, self.draw_type)
118 }
119
120 pub fn left(&self) -> isize {
121 self.obj.left()
122 }
123
124 pub fn right(&self) -> isize {
125 self.obj.right()
126 }
127
128 pub fn top(&self) -> isize {
129 self.obj.top()
130 }
131
132 pub fn bottom(&self) -> isize {
133 self.obj.bottom()
134 }
135}
136
137impl<T> Drawable<T>
138where
139 Self: CreateDrawable<T>,
140 T: IntersectsContains + Clone,
141{
142 pub fn intersects_shape(&self, shape: &dyn Shape) -> Option<bool> {
143 self.obj.intersects_shape(shape)
144 }
145
146 pub fn contains_shape(&self, shape: &dyn Shape) -> Option<bool> {
147 self.obj.contains_shape(shape)
148 }
149
150 pub fn intersects_drawable<S: Shape + Clone>(&self, drawable: &Drawable<S>) -> Option<bool> {
151 self.obj.intersects_shape(&drawable.obj)
152 }
153
154 pub fn contains_drawable<S: Shape + Clone>(&self, drawable: &Drawable<S>) -> Option<bool> {
155 self.obj.contains_shape(&drawable.obj)
156 }
157}