1use serde::{Deserialize, Serialize};
2
3use geom::{trim_f64, Polygon, Pt2D};
4
5use crate::{Canvas, EdgeInsets};
6
7#[derive(Debug, Clone, Copy, PartialEq)]
9pub struct ScreenPt {
10 pub x: f64,
11 pub y: f64,
12}
13
14impl ScreenPt {
15 pub fn new(x: f64, y: f64) -> ScreenPt {
16 ScreenPt { x, y }
17 }
18
19 pub fn to_pt(self) -> Pt2D {
22 Pt2D::new(self.x, self.y)
23 }
24
25 pub fn zero() -> Self {
26 Self { x: 0.0, y: 0.0 }
27 }
28
29 pub fn translated(&self, x: f64, y: f64) -> Self {
30 Self {
31 x: self.x + x,
32 y: self.y + y,
33 }
34 }
35}
36
37impl From<winit::dpi::LogicalPosition<f64>> for ScreenPt {
38 fn from(lp: winit::dpi::LogicalPosition<f64>) -> ScreenPt {
39 ScreenPt { x: lp.x, y: lp.y }
40 }
41}
42
43#[derive(Clone, Debug)]
45pub struct ScreenRectangle {
46 pub x1: f64,
47 pub y1: f64,
48 pub x2: f64,
49 pub y2: f64,
50}
51
52impl ScreenRectangle {
53 pub fn top_left(top_left: ScreenPt, dims: ScreenDims) -> ScreenRectangle {
54 ScreenRectangle {
55 x1: top_left.x,
56 y1: top_left.y,
57 x2: top_left.x + dims.width,
58 y2: top_left.y + dims.height,
59 }
60 }
61
62 pub fn placeholder() -> ScreenRectangle {
63 ScreenRectangle {
64 x1: 0.0,
65 y1: 0.0,
66 x2: 0.0,
67 y2: 0.0,
68 }
69 }
70
71 pub fn contains(&self, pt: ScreenPt) -> bool {
72 pt.x >= self.x1 && pt.x <= self.x2 && pt.y >= self.y1 && pt.y <= self.y2
73 }
74
75 pub fn pt_to_percent(&self, pt: ScreenPt) -> Option<(f64, f64)> {
76 if self.contains(pt) {
77 Some((
78 (pt.x - self.x1) / self.width(),
79 (pt.y - self.y1) / self.height(),
80 ))
81 } else {
82 None
83 }
84 }
85 pub fn percent_to_pt(&self, x: f64, y: f64) -> ScreenPt {
86 ScreenPt::new(self.x1 + x * self.width(), self.y1 + y * self.height())
87 }
88
89 pub fn width(&self) -> f64 {
91 self.x2 - self.x1
92 }
93
94 pub fn height(&self) -> f64 {
95 self.y2 - self.y1
96 }
97
98 pub fn dims(&self) -> ScreenDims {
99 ScreenDims::new(self.x2 - self.x1, self.y2 - self.y1)
100 }
101
102 pub fn center(&self) -> ScreenPt {
103 ScreenPt::new((self.x1 + self.x2) / 2.0, (self.y1 + self.y2) / 2.0)
104 }
105
106 pub fn to_polygon(&self) -> Polygon {
107 Polygon::rectangle(self.width(), self.height()).translate(self.x1, self.y1)
108 }
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
114pub struct ScreenDims {
115 pub width: f64,
116 pub height: f64,
117}
118
119impl ScreenDims {
120 pub fn new(width: f64, height: f64) -> ScreenDims {
121 ScreenDims {
122 width: trim_f64(width),
123 height: trim_f64(height),
124 }
125 }
126
127 pub fn zero() -> Self {
128 ScreenDims {
129 width: 0.0,
130 height: 0.0,
131 }
132 }
133
134 pub fn square(square: f64) -> Self {
135 Self::new(square, square)
136 }
137
138 pub fn pad(&self, edge_insets: EdgeInsets) -> Self {
139 Self {
140 width: self.width + edge_insets.left + edge_insets.right,
141 height: self.height + edge_insets.top + edge_insets.bottom,
142 }
143 }
144
145 pub fn top_left_for_corner(&self, corner: ScreenPt, canvas: &Canvas) -> ScreenPt {
146 if corner.x + self.width < canvas.window_width {
148 if corner.y + self.height < canvas.window_height {
150 corner
152 } else {
153 ScreenPt::new(corner.x, corner.y - self.height)
155 }
156 } else {
157 if corner.y + self.height < canvas.window_height {
159 ScreenPt::new(corner.x - self.width, corner.y)
161 } else {
162 ScreenPt::new(corner.x - self.width, corner.y - self.height)
164 }
165 }
166 }
167}
168
169impl From<winit::dpi::LogicalSize<f64>> for ScreenDims {
170 fn from(size: winit::dpi::LogicalSize<f64>) -> ScreenDims {
171 ScreenDims {
172 width: size.width,
173 height: size.height,
174 }
175 }
176}
177
178impl From<ScreenDims> for winit::dpi::LogicalSize<f64> {
179 fn from(dims: ScreenDims) -> winit::dpi::LogicalSize<f64> {
180 winit::dpi::LogicalSize::new(dims.width, dims.height)
181 }
182}
183
184impl From<f64> for ScreenDims {
185 fn from(square: f64) -> ScreenDims {
186 ScreenDims::square(square)
187 }
188}
189
190impl From<i64> for ScreenDims {
191 fn from(square: i64) -> ScreenDims {
192 ScreenDims::square(square as f64)
193 }
194}
195
196impl From<(f64, f64)> for ScreenDims {
198 fn from(width_and_height: (f64, f64)) -> ScreenDims {
199 ScreenDims::new(width_and_height.0, width_and_height.1)
200 }
201}
202
203impl From<geom::Bounds> for ScreenDims {
204 fn from(bounds: geom::Bounds) -> Self {
205 ScreenDims::new(bounds.width(), bounds.height())
206 }
207}
208
209impl From<ScreenDims> for taffy::geometry::Size<taffy::style::Dimension> {
210 fn from(dims: ScreenDims) -> Self {
211 Self {
212 width: taffy::style::Dimension::Points(dims.width as f32),
213 height: taffy::style::Dimension::Points(dims.height as f32),
214 }
215 }
216}