native_windows_gui/controls/
plotters.rs1use winapi::um::winuser::{WS_CHILD, WS_VISIBLE, WS_CLIPCHILDREN, WS_CLIPSIBLINGS};
2use crate::win32::base_helper::check_hwnd;
3use crate::win32::window_helper as wh;
4use crate::NwgError;
5use super::{ControlBase, ControlHandle};
6
7use plotters::prelude::DrawingArea;
8use plotters::coord::Shift;
9pub use crate::win32::plotters_d2d::{PlottersError, PlottersBackend};
10use std::ops::Deref;
11
12const NOT_BOUND: &'static str = "Plotters control is not yet bound to a winapi object";
13const BAD_HANDLE: &'static str = "INTERNAL ERROR: Plotters control handle is not HWND!";
14
15
16pub struct PlottersDrawingArea<'a> {
23 inner: &'a Plotters,
24 area: DrawingArea<&'a PlottersBackend, Shift>
25}
26
27impl<'a> PlottersDrawingArea<'a> {
28
29 pub fn new(inner: &'a Plotters) -> Result<PlottersDrawingArea<'a>, PlottersError> {
30 let backend = inner.d2d_backend.as_ref().unwrap();
31
32 backend.rebuild(inner.handle.hwnd().unwrap())?;
33 backend.begin_draw();
34 backend.clear();
35
36 let area = PlottersDrawingArea {
37 inner: inner,
38 area: backend.into(),
39 };
40
41 Ok(area)
42 }
43
44}
45
46impl<'a> Deref for PlottersDrawingArea<'a> {
47 type Target = DrawingArea<&'a PlottersBackend, Shift>;
48
49 fn deref(&self) -> &Self::Target {
50 &self.area
51 }
52}
53
54impl<'a> Drop for PlottersDrawingArea<'a> {
55 fn drop(&mut self) {
56 self.inner.d2d_backend.as_ref()
57 .unwrap()
58 .end_draw();
59 }
60}
61
62#[derive(Default)]
67pub struct Plotters {
68 pub handle: ControlHandle,
69 d2d_backend: Option<PlottersBackend>,
70}
71
72impl Plotters {
73
74 pub fn builder() -> PlottersBuilder {
75 PlottersBuilder {
76 size: (500, 500),
77 position: (0, 0),
78 ex_flags: 0,
79 parent: None,
80 }
81 }
82
83 pub fn draw<'a>(&'a self) -> Result<PlottersDrawingArea<'a>, PlottersError> {
86 check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
87 PlottersDrawingArea::new(self)
88 }
89
90 pub fn focus(&self) -> bool {
92 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
93 unsafe { wh::get_focus(handle) }
94 }
95
96 pub fn set_focus(&self) {
98 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
99 unsafe { wh::set_focus(handle); }
100 }
101
102 pub fn enabled(&self) -> bool {
104 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
105 unsafe { wh::get_window_enabled(handle) }
106 }
107
108 pub fn set_enabled(&self, v: bool) {
110 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
111 unsafe { wh::set_window_enabled(handle, v) }
112 }
113
114 pub fn visible(&self) -> bool {
117 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
118 unsafe { wh::get_window_visibility(handle) }
119 }
120
121 pub fn set_visible(&self, v: bool) {
123 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
124 unsafe { wh::set_window_visibility(handle, v) }
125 }
126
127 pub fn size(&self) -> (u32, u32) {
129 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
130 unsafe { wh::get_window_size(handle) }
131 }
132
133 pub fn physical_size(&self) -> (u32, u32) {
135 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
136 unsafe { wh::get_window_physical_size(handle) }
137 }
138
139 pub fn set_size(&self, x: u32, y: u32) {
141 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
142 unsafe { wh::set_window_size(handle, x, y, true) }
143 }
144
145 pub fn position(&self) -> (i32, i32) {
147 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
148 unsafe { wh::get_window_position(handle) }
149 }
150
151 pub fn set_position(&self, x: i32, y: i32) {
153 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
154 unsafe { wh::set_window_position(handle, x, y) }
155 }
156
157 pub fn class_name(&self) -> &'static str {
159 "NWG_EXTERN_CANVAS"
160 }
161
162 pub fn flags(&self) -> u32 {
164 WS_CHILD | WS_VISIBLE
165 }
166
167 pub fn forced_flags(&self) -> u32 {
169 WS_CLIPCHILDREN | WS_CLIPSIBLINGS
170 }
171
172
173}
174
175impl PartialEq for Plotters {
176 fn eq(&self, other: &Self) -> bool {
177 self.handle == other.handle
178 }
179}
180
181pub struct PlottersBuilder {
182 parent: Option<ControlHandle>,
183 size: (i32, i32),
184 position: (i32, i32),
185 ex_flags: u32,
186}
187
188impl PlottersBuilder {
189
190 pub fn ex_flags(mut self, flags: u32) -> PlottersBuilder {
191 self.ex_flags = flags;
192 self
193 }
194
195 pub fn size(mut self, size: (i32, i32)) -> PlottersBuilder {
196 self.size = size;
197 self
198 }
199
200 pub fn position(mut self, pos: (i32, i32)) -> PlottersBuilder {
201 self.position = pos;
202 self
203 }
204
205 pub fn parent<C: Into<ControlHandle>>(mut self, p: C) -> PlottersBuilder {
206 self.parent = Some(p.into());
207 self
208 }
209
210 pub fn build(self, out: &mut Plotters) -> Result<(), NwgError> {
211 *out = Default::default();
212
213 out.handle = ControlBase::build_hwnd()
214 .class_name(out.class_name())
215 .forced_flags(out.forced_flags())
216 .flags(out.flags())
217 .ex_flags(self.ex_flags)
218 .size(self.size)
219 .position(self.position)
220 .text("")
221 .parent(self.parent)
222 .build()?;
223
224 let handle = out.handle.hwnd().unwrap();
225 match PlottersBackend::init(handle) {
226 Ok(b) => {
227 out.d2d_backend = Some(b);
228 Ok(())
229 },
230 Err(e) => {
231 *out = Default::default();
232 Err(NwgError::from(e))
233 }
234 }
235 }
236
237}