1use std::ffi::{c_ulong, c_void};
2use std::fmt;
3use std::marker::PhantomData;
4use std::rc::Rc;
5
6use crate::{backend, EventLoop, Result};
7
8#[derive(Copy, Clone, Debug, PartialEq)]
9pub struct Point {
10 pub x: f64,
11 pub y: f64,
12}
13
14impl Point {
15 #[inline]
16 pub fn new(x: f64, y: f64) -> Point {
17 Point { x, y }
18 }
19
20 #[inline]
21 pub fn scale(self, scale: f64) -> Point {
22 Point::new(self.x * scale, self.y * scale)
23 }
24}
25
26#[derive(Copy, Clone, Debug, PartialEq)]
27pub struct Size {
28 pub width: f64,
29 pub height: f64,
30}
31
32impl Size {
33 #[inline]
34 pub fn new(width: f64, height: f64) -> Size {
35 Size { width, height }
36 }
37
38 #[inline]
39 pub fn scale(self, scale: f64) -> Size {
40 Size::new(self.width * scale, self.height * scale)
41 }
42}
43
44#[derive(Copy, Clone, Debug, PartialEq)]
45pub struct Rect {
46 pub x: f64,
47 pub y: f64,
48 pub width: f64,
49 pub height: f64,
50}
51
52impl Rect {
53 #[inline]
54 pub fn new(x: f64, y: f64, width: f64, height: f64) -> Rect {
55 Rect {
56 x,
57 y,
58 width,
59 height,
60 }
61 }
62
63 #[inline]
64 pub fn scale(self, scale: f64) -> Rect {
65 Rect::new(
66 self.x * scale,
67 self.y * scale,
68 self.width * scale,
69 self.height * scale,
70 )
71 }
72}
73
74pub struct Bitmap<'a> {
75 data: &'a [u32],
76 width: usize,
77 height: usize,
78}
79
80impl<'a> Bitmap<'a> {
81 #[inline]
82 pub fn new(data: &'a [u32], width: usize, height: usize) -> Bitmap<'a> {
83 assert!(width * height == data.len(), "invalid bitmap dimensions");
84
85 Bitmap {
86 data,
87 width,
88 height,
89 }
90 }
91
92 #[inline]
93 pub fn data(&self) -> &'a [u32] {
94 self.data
95 }
96
97 #[inline]
98 pub fn width(&self) -> usize {
99 self.width
100 }
101
102 #[inline]
103 pub fn height(&self) -> usize {
104 self.height
105 }
106}
107
108#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
109pub enum MouseButton {
110 Left,
111 Middle,
112 Right,
113 Back,
114 Forward,
115}
116
117#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
118pub enum Cursor {
119 Arrow,
120 Crosshair,
121 Hand,
122 IBeam,
123 No,
124 SizeNs,
125 SizeWe,
126 SizeNesw,
127 SizeNwse,
128 Wait,
129 None,
130}
131
132#[derive(Copy, Clone, Debug, PartialEq)]
133pub enum Event<'a> {
134 Expose(&'a [Rect]),
135 Frame,
136 Close,
137 GainFocus,
138 LoseFocus,
139 MouseEnter,
140 MouseExit,
141 MouseMove(Point),
142 MouseDown(MouseButton),
143 MouseUp(MouseButton),
144 Scroll(Point),
145}
146
147#[derive(Copy, Clone, Debug, Eq, PartialEq)]
148pub enum Response {
149 Capture,
150 Ignore,
151}
152
153#[derive(Copy, Clone, Debug)]
154pub enum RawWindow {
155 Win32(*mut c_void),
156 AppKit(*mut c_void),
157 X11(c_ulong),
158}
159
160#[derive(Clone, Debug)]
161pub struct WindowOptions {
162 pub(crate) title: String,
163 pub(crate) position: Option<Point>,
164 pub(crate) size: Size,
165 pub(crate) parent: Option<RawWindow>,
166}
167
168impl Default for WindowOptions {
169 fn default() -> Self {
170 WindowOptions {
171 title: String::new(),
172 position: None,
173 size: Size::new(0.0, 0.0),
174 parent: None,
175 }
176 }
177}
178
179impl WindowOptions {
180 pub fn new() -> WindowOptions {
181 Self::default()
182 }
183
184 pub fn title<S: AsRef<str>>(&mut self, title: S) -> &mut Self {
185 self.title = title.as_ref().to_string();
186 self
187 }
188
189 pub fn position(&mut self, position: Point) -> &mut Self {
190 self.position = Some(position);
191 self
192 }
193
194 pub fn size(&mut self, size: Size) -> &mut Self {
195 self.size = size;
196 self
197 }
198
199 pub unsafe fn raw_parent(&mut self, parent: RawWindow) -> &mut Self {
200 self.parent = Some(parent);
201 self
202 }
203
204 pub fn open<F>(&self, event_loop: &EventLoop, handler: F) -> Result<Window>
205 where
206 F: FnMut(Event) -> Response + 'static,
207 {
208 Ok(Window {
209 state: backend::WindowState::open(self, event_loop, handler)?,
210 _marker: PhantomData,
211 })
212 }
213}
214
215pub struct Window {
216 pub(crate) state: Rc<backend::WindowState>,
217 _marker: PhantomData<*mut ()>,
219}
220
221impl Window {
222 pub fn show(&self) {
223 self.state.show();
224 }
225
226 pub fn hide(&self) {
227 self.state.hide();
228 }
229
230 pub fn size(&self) -> Size {
231 self.state.size()
232 }
233
234 pub fn scale(&self) -> f64 {
235 self.state.scale()
236 }
237
238 pub fn present(&self, bitmap: Bitmap) {
239 self.state.present(bitmap);
240 }
241
242 pub fn present_partial(&self, bitmap: Bitmap, rects: &[Rect]) {
243 self.state.present_partial(bitmap, rects);
244 }
245
246 pub fn set_cursor(&self, cursor: Cursor) {
247 self.state.set_cursor(cursor);
248 }
249
250 pub fn set_mouse_position(&self, position: Point) {
251 self.state.set_mouse_position(position);
252 }
253
254 pub fn as_raw(&self) -> Result<RawWindow> {
255 self.state.as_raw()
256 }
257}
258
259impl Drop for Window {
260 fn drop(&mut self) {
261 self.state.close();
262 }
263}
264
265impl fmt::Debug for Window {
266 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
267 fmt.debug_struct("Window").finish_non_exhaustive()
268 }
269}