1use winapi::um::winuser::{WS_VISIBLE, WS_DISABLED};
7use winapi::um::commctrl::{PBS_MARQUEE, PBS_VERTICAL};
8use crate::win32::window_helper as wh;
9use crate::win32::base_helper::check_hwnd;
10use crate::NwgError;
11use super::{ControlHandle, ControlBase};
12use std::ops::Range;
13
14const NOT_BOUND: &'static str = "Progress bar is not yet bound to a winapi object";
15const BAD_HANDLE: &'static str = "INTERNAL ERROR: Progress bar handle is not HWND!";
16
17
18bitflags! {
19 pub struct ProgressBarFlags: u32 {
20 const VISIBLE = WS_VISIBLE;
21 const DISABLED = WS_DISABLED;
22 const VERTICAL = PBS_VERTICAL;
23 const MARQUEE = PBS_MARQUEE;
24 }
25}
26
27#[derive(Copy, Clone, Debug, PartialEq, Eq)]
28#[repr(u8)]
29pub enum ProgressBarState {
30 Normal,
31 Error,
32 Paused
33}
34
35#[derive(Default, PartialEq, Eq)]
73pub struct ProgressBar {
74 pub handle: ControlHandle
75}
76
77impl ProgressBar {
78
79 pub fn builder() -> ProgressBarBuilder {
80 ProgressBarBuilder {
81 size: (100, 40),
82 position: (0, 0),
83 flags: None,
84 ex_flags: 0,
85 state: ProgressBarState::Normal,
86 step: 1,
87 pos: 0,
88 range: 0..100,
89 marquee_enable: false,
90 marquee_update: 0,
91 parent: None
92 }
93 }
94
95 pub fn state(&self) -> ProgressBarState {
97 use winapi::um::commctrl::{PBM_GETSTATE, PBST_NORMAL, PBST_ERROR, PBST_PAUSED};
98
99 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
100
101 match wh::send_message(handle, PBM_GETSTATE, 0, 0) as i32 {
102 PBST_NORMAL => ProgressBarState::Normal,
103 PBST_ERROR => ProgressBarState::Error,
104 PBST_PAUSED => ProgressBarState::Paused,
105 _ => panic!("Unkown progress bar state")
106 }
107 }
108
109 pub fn set_state(&self, state: ProgressBarState) {
111 use winapi::um::commctrl::{PBM_SETSTATE, PBST_NORMAL, PBST_ERROR, PBST_PAUSED};
112 use winapi::shared::minwindef::WPARAM;
113
114 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
115
116 let state = match state {
117 ProgressBarState::Normal => PBST_NORMAL,
118 ProgressBarState::Error => PBST_ERROR,
119 ProgressBarState::Paused => PBST_PAUSED
120 };
121
122 wh::send_message(handle, PBM_SETSTATE, state as WPARAM, 0);
123 }
124
125 pub fn advance(&self) {
127 use winapi::um::commctrl::PBM_STEPIT;
128
129 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
130 wh::send_message(handle, PBM_STEPIT, 0, 0);
131 }
132
133 pub fn advance_delta(&self, v: u32) {
135 use winapi::um::commctrl::PBM_DELTAPOS;
136 use winapi::shared::minwindef::WPARAM;
137
138 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
139 wh::send_message(handle, PBM_DELTAPOS, v as WPARAM, 0);
140 }
141
142 pub fn step(&self) -> u32 {
144 use winapi::um::commctrl::PBM_GETSTEP;
145
146 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
147 wh::send_message(handle, PBM_GETSTEP, 0, 0) as u32
148 }
149
150 pub fn set_step(&self, s: u32) {
152 use winapi::um::commctrl::PBM_SETSTEP;
153 use winapi::shared::minwindef::WPARAM;
154
155 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
156 wh::send_message(handle, PBM_SETSTEP, s as WPARAM, 0);
157 }
158
159 pub fn pos(&self) -> u32 {
161 use winapi::um::commctrl::PBM_GETPOS;
162
163 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
164 wh::send_message(handle, PBM_GETPOS, 0, 0) as u32
165 }
166
167 pub fn set_pos(&self, p: u32) {
170 use winapi::um::commctrl::PBM_SETPOS;
171 use winapi::shared::minwindef::WPARAM;
172
173 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
174 wh::send_message(handle, PBM_SETPOS, p as WPARAM, 0);
175 }
176
177 pub fn range(&self) -> Range<u32> {
179 use winapi::um::commctrl::PBM_GETRANGE;
180
181 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
182
183 let low = wh::send_message(handle, PBM_GETRANGE, 1, 0) as u32;
184 let high = wh::send_message(handle, PBM_GETRANGE, 0, 0) as u32;
185
186 low..high
187 }
188
189 pub fn set_range(&self, range: Range<u32>) {
191 use winapi::um::commctrl::PBM_SETRANGE32;
192 use winapi::shared::minwindef::{WPARAM, LPARAM};
193
194 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
195 wh::send_message(handle, PBM_SETRANGE32, range.start as WPARAM, range.end as LPARAM);
196 }
197
198 pub fn set_marquee(&self, enable: bool, update_interval: u32) {
200 use winapi::shared::minwindef::{LPARAM, WPARAM};
201 use winapi::um::commctrl::PBM_SETMARQUEE;
202
203 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
204 wh::send_message(handle, PBM_SETMARQUEE, enable as WPARAM, update_interval as LPARAM);
205 }
206
207 pub fn add_flags(&self, styles: ProgressBarFlags) {
209 let styles = styles.bits() as u32;
210
211 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
212 let active_styles = wh::get_style(handle);
213
214 wh::set_style(handle, active_styles | styles);
215 }
216
217 pub fn remove_flags(&self, styles: ProgressBarFlags) {
219 let styles = styles.bits() as u32;
220
221 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
222 let active_styles = wh::get_style(handle);
223
224 wh::set_style(handle, active_styles & !styles);
225 }
226
227 pub fn focus(&self) -> bool {
229 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
230 unsafe { wh::get_focus(handle) }
231 }
232
233 pub fn set_focus(&self) {
235 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
236 unsafe { wh::set_focus(handle); }
237 }
238
239 pub fn enabled(&self) -> bool {
241 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
242 unsafe { wh::get_window_enabled(handle) }
243 }
244
245 pub fn set_enabled(&self, v: bool) {
247 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
248 unsafe { wh::set_window_enabled(handle, v) }
249 }
250
251 pub fn visible(&self) -> bool {
254 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
255 unsafe { wh::get_window_visibility(handle) }
256 }
257
258 pub fn set_visible(&self, v: bool) {
260 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
261 unsafe { wh::set_window_visibility(handle, v) }
262 }
263
264 pub fn size(&self) -> (u32, u32) {
266 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
267 unsafe { wh::get_window_size(handle) }
268 }
269
270 pub fn set_size(&self, x: u32, y: u32) {
272 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
273 unsafe { wh::set_window_size(handle, x, y, false) }
274 }
275
276 pub fn position(&self) -> (i32, i32) {
278 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
279 unsafe { wh::get_window_position(handle) }
280 }
281
282 pub fn set_position(&self, x: i32, y: i32) {
284 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
285 unsafe { wh::set_window_position(handle, x, y) }
286 }
287
288 pub fn class_name(&self) -> &'static str {
290 "msctls_progress32"
291 }
292
293 pub fn flags(&self) -> u32 {
295 ::winapi::um::winuser::WS_VISIBLE
296 }
297
298 pub fn forced_flags(&self) -> u32 {
300 use winapi::um::winuser::{WS_CHILD};
301
302 WS_CHILD
303 }
304
305}
306
307impl Drop for ProgressBar {
308 fn drop(&mut self) {
309 self.handle.destroy();
310 }
311}
312
313pub struct ProgressBarBuilder {
314 size: (i32, i32),
315 position: (i32, i32),
316 flags: Option<ProgressBarFlags>,
317 ex_flags: u32,
318 state: ProgressBarState,
319 step: u32,
320 pos: u32,
321 range: Range<u32>,
322 marquee_enable: bool,
323 marquee_update: u32,
324 parent: Option<ControlHandle>
325}
326
327impl ProgressBarBuilder {
328
329 pub fn flags(mut self, flags: ProgressBarFlags) -> ProgressBarBuilder {
330 self.flags = Some(flags);
331 self
332 }
333
334 pub fn ex_flags(mut self, flags: u32) -> ProgressBarBuilder {
335 self.ex_flags = flags;
336 self
337 }
338
339 pub fn size(mut self, size: (i32, i32)) -> ProgressBarBuilder {
340 self.size = size;
341 self
342 }
343
344 pub fn position(mut self, pos: (i32, i32)) -> ProgressBarBuilder {
345 self.position = pos;
346 self
347 }
348
349 pub fn state(mut self, state: ProgressBarState) -> ProgressBarBuilder {
350 self.state = state;
351 self
352 }
353
354 pub fn step(mut self, step: u32) -> ProgressBarBuilder {
355 self.step = step;
356 self
357 }
358
359 pub fn pos(mut self, pos: u32) -> ProgressBarBuilder {
360 self.pos = pos;
361 self
362 }
363
364 pub fn range(mut self, range: Range<u32>) -> ProgressBarBuilder {
365 self.range = range;
366 self
367 }
368
369 pub fn marquee(mut self, enable: bool) -> ProgressBarBuilder {
370 self.marquee_enable = enable;
371 self
372 }
373
374 pub fn marquee_update(mut self, update_interval: u32) -> ProgressBarBuilder {
375 self.marquee_update = update_interval;
376 self
377 }
378
379 pub fn parent<C: Into<ControlHandle>>(mut self, p: C) -> ProgressBarBuilder {
380 self.parent = Some(p.into());
381 self
382 }
383
384 pub fn build(self, out: &mut ProgressBar) -> Result<(), NwgError> {
385 let flags = self.flags.map(|f| f.bits()).unwrap_or(out.flags());
386
387 let parent = match self.parent {
388 Some(p) => Ok(p),
389 None => Err(NwgError::no_parent("Progress Bar"))
390 }?;
391
392 *out = Default::default();
393
394 out.handle = ControlBase::build_hwnd()
395 .class_name(out.class_name())
396 .forced_flags(out.forced_flags())
397 .flags(flags)
398 .ex_flags(self.ex_flags)
399 .size(self.size)
400 .position(self.position)
401 .parent(Some(parent))
402 .build()?;
403
404 out.set_state(self.state);
405 out.set_step(self.step);
406 out.set_pos(self.pos);
407 out.set_range(self.range);
408 out.set_marquee(self.marquee_enable, self.marquee_update);
409
410 Ok(())
411 }
412
413}