1use super::{ControlBase, ControlHandle};
7use crate::NwgError;
8use crate::win32::base_helper::check_hwnd;
9use crate::win32::window_helper as wh;
10use std::ops::Range;
11use winapi::um::commctrl::{PBS_MARQUEE, PBS_SMOOTH, PBS_SMOOTHREVERSE, PBS_VERTICAL};
12use winapi::um::winuser::{WS_DISABLED, WS_VISIBLE};
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
17bitflags! {
18 pub struct ProgressBarFlags: u32 {
19 const VISIBLE = WS_VISIBLE;
20 const DISABLED = WS_DISABLED;
21 const VERTICAL = PBS_VERTICAL;
22 const MARQUEE = PBS_MARQUEE;
23 const SMOOTH = PBS_SMOOTH;
24 const SMOOTHREVERSE = PBS_SMOOTHREVERSE;
25 }
26}
27
28#[derive(Copy, Clone, Debug, PartialEq, Eq)]
29#[repr(u8)]
30pub enum ProgressBarState {
31 Normal,
32 Error,
33 Paused,
34}
35
36#[derive(Default, PartialEq, Eq)]
74pub struct ProgressBar {
75 pub handle: ControlHandle,
76}
77
78impl ProgressBar {
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_ERROR, PBST_NORMAL, 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::shared::minwindef::WPARAM;
112 use winapi::um::commctrl::{PBM_SETSTATE, PBST_ERROR, PBST_NORMAL, PBST_PAUSED};
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::shared::minwindef::WPARAM;
136 use winapi::um::commctrl::PBM_DELTAPOS;
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::shared::minwindef::WPARAM;
153 use winapi::um::commctrl::PBM_SETSTEP;
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::shared::minwindef::WPARAM;
171 use winapi::um::commctrl::PBM_SETPOS;
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::shared::minwindef::{LPARAM, WPARAM};
192 use winapi::um::commctrl::PBM_SETRANGE32;
193
194 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
195 wh::send_message(
196 handle,
197 PBM_SETRANGE32,
198 range.start as WPARAM,
199 range.end as LPARAM,
200 );
201 }
202
203 pub fn set_marquee(&self, enable: bool, update_interval: u32) {
205 use winapi::shared::minwindef::{LPARAM, WPARAM};
206 use winapi::um::commctrl::PBM_SETMARQUEE;
207
208 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
209 wh::send_message(
210 handle,
211 PBM_SETMARQUEE,
212 enable as WPARAM,
213 update_interval as LPARAM,
214 );
215 }
216
217 pub fn add_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 remove_flags(&self, styles: ProgressBarFlags) {
229 let styles = styles.bits() as u32;
230
231 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
232 let active_styles = wh::get_style(handle);
233
234 wh::set_style(handle, active_styles & !styles);
235 }
236
237 pub fn focus(&self) -> bool {
239 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
240 wh::get_focus(handle)
241 }
242
243 pub fn set_focus(&self) {
245 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
246
247 wh::set_focus(handle);
248 }
249
250 pub fn enabled(&self) -> bool {
252 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
253 wh::get_window_enabled(handle)
254 }
255
256 pub fn set_enabled(&self, v: bool) {
258 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
259 wh::set_window_enabled(handle, v)
260 }
261
262 pub fn visible(&self) -> bool {
265 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
266 wh::get_window_visibility(handle)
267 }
268
269 pub fn set_visible(&self, v: bool) {
271 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
272 wh::set_window_visibility(handle, v)
273 }
274
275 pub fn size(&self) -> (u32, u32) {
277 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
278 wh::get_window_size(handle)
279 }
280
281 pub fn set_size(&self, x: u32, y: u32) {
283 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
284 wh::set_window_size(handle, x, y, false)
285 }
286
287 pub fn position(&self) -> (i32, i32) {
289 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
290 wh::get_window_position(handle)
291 }
292
293 pub fn set_position(&self, x: i32, y: i32) {
295 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
296 wh::set_window_position(handle, x, y)
297 }
298
299 pub fn class_name(&self) -> &'static str {
301 "msctls_progress32"
302 }
303
304 pub fn flags(&self) -> u32 {
306 ::winapi::um::winuser::WS_VISIBLE
307 }
308
309 pub fn forced_flags(&self) -> u32 {
311 use winapi::um::winuser::WS_CHILD;
312
313 WS_CHILD
314 }
315}
316
317impl Drop for ProgressBar {
318 fn drop(&mut self) {
319 self.handle.destroy();
320 }
321}
322
323pub struct ProgressBarBuilder {
324 size: (i32, i32),
325 position: (i32, i32),
326 flags: Option<ProgressBarFlags>,
327 ex_flags: u32,
328 state: ProgressBarState,
329 step: u32,
330 pos: u32,
331 range: Range<u32>,
332 marquee_enable: bool,
333 marquee_update: u32,
334 parent: Option<ControlHandle>,
335}
336
337impl ProgressBarBuilder {
338 pub fn flags(mut self, flags: ProgressBarFlags) -> ProgressBarBuilder {
339 self.flags = Some(flags);
340 self
341 }
342
343 pub fn ex_flags(mut self, flags: u32) -> ProgressBarBuilder {
344 self.ex_flags = flags;
345 self
346 }
347
348 pub fn size(mut self, size: (i32, i32)) -> ProgressBarBuilder {
349 self.size = size;
350 self
351 }
352
353 pub fn position(mut self, pos: (i32, i32)) -> ProgressBarBuilder {
354 self.position = pos;
355 self
356 }
357
358 pub fn state(mut self, state: ProgressBarState) -> ProgressBarBuilder {
359 self.state = state;
360 self
361 }
362
363 pub fn step(mut self, step: u32) -> ProgressBarBuilder {
364 self.step = step;
365 self
366 }
367
368 pub fn pos(mut self, pos: u32) -> ProgressBarBuilder {
369 self.pos = pos;
370 self
371 }
372
373 pub fn range(mut self, range: Range<u32>) -> ProgressBarBuilder {
374 self.range = range;
375 self
376 }
377
378 pub fn marquee(mut self, enable: bool) -> ProgressBarBuilder {
379 self.marquee_enable = enable;
380 self
381 }
382
383 pub fn marquee_update(mut self, update_interval: u32) -> ProgressBarBuilder {
384 self.marquee_update = update_interval;
385 self
386 }
387
388 pub fn parent<C: Into<ControlHandle>>(mut self, p: C) -> ProgressBarBuilder {
389 self.parent = Some(p.into());
390 self
391 }
392
393 pub fn build(self, out: &mut ProgressBar) -> Result<(), NwgError> {
394 let flags = self.flags.map(|f| f.bits()).unwrap_or(out.flags());
395
396 let parent = match self.parent {
397 Some(p) => Ok(p),
398 None => Err(NwgError::no_parent("Progress Bar")),
399 }?;
400
401 *out = Default::default();
402
403 out.handle = ControlBase::build_hwnd()
404 .class_name(out.class_name())
405 .forced_flags(out.forced_flags())
406 .flags(flags)
407 .ex_flags(self.ex_flags)
408 .size(self.size)
409 .position(self.position)
410 .parent(Some(parent))
411 .build()?;
412
413 out.set_state(self.state);
414 out.set_step(self.step);
415 out.set_pos(self.pos);
416 out.set_range(self.range);
417 out.set_marquee(self.marquee_enable, self.marquee_update);
418
419 Ok(())
420 }
421}