Skip to content

Commit 61e06ca

Browse files
authored
Merge pull request #64 from NoraCodes/progressbar-improvements
Make ProgressBar API safe and more ergonomic
2 parents 32177a4 + 10f6b51 commit 61e06ca

File tree

4 files changed

+75
-28
lines changed

4 files changed

+75
-28
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
88

99
### Added
1010

11-
- `ProgressBar` control for tracking the completion of a task
11+
- `ProgressBar` control for tracking the completion of a task with automatic value conversions
1212
- `enable()` and `disable()` methods on all controls
1313
- `RadioButtons` control for groups of radio buttons
1414
- `Combobox::selected()` method to retrieve the currently selected index of the combobox

iui/examples/inputs-grid.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
extern crate iui;
55
use iui::prelude::*;
66
use iui::controls::{Label, Spinbox, Slider, Entry, MultilineEntry, LayoutGrid,
7-
GridAlignment, GridExpand, HorizontalSeparator};
7+
GridAlignment, GridExpand, HorizontalSeparator, ProgressBar};
88
use std::rc::Rc;
99
use std::cell::RefCell;
1010

@@ -59,11 +59,12 @@ fn main() {
5959

6060
// Set up the outputs for the application. Organization is very similar to the
6161
// previous setup.
62-
let (add_label, sub_label, text_label, bigtext_label) = {
62+
let (add_label, sub_label, text_label, bigtext_label, progress_bar) = {
6363
let add_label = Label::new(&ui, "");
6464
let sub_label = Label::new(&ui, "");
6565
let text_label = Label::new(&ui, "");
6666
let bigtext_label = Label::new(&ui, "");
67+
let progress_bar = ProgressBar::indeterminate(&ui);
6768
grid.append(&ui, add_label.clone(),
6869
1, 0, 1, 1, GridExpand::Neither, GridAlignment::Fill, GridAlignment::Fill);
6970
grid.append(&ui, sub_label.clone(),
@@ -74,7 +75,9 @@ fn main() {
7475
1, 4, 1, 1, GridExpand::Neither, GridAlignment::Fill, GridAlignment::Fill);
7576
grid.append(&ui, bigtext_label.clone(),
7677
1, 5, 1, 1, GridExpand::Neither, GridAlignment::Fill, GridAlignment::Fill);
77-
(add_label, sub_label, text_label, bigtext_label)
78+
grid.append(&ui, progress_bar.clone(),
79+
0, 6, 2, 1, GridExpand::Neither, GridAlignment::Fill, GridAlignment::Fill);
80+
(add_label, sub_label, text_label, bigtext_label, progress_bar)
7881
};
7982

8083
// The window allows all constituent components to be displayed.
@@ -116,14 +119,16 @@ fn main() {
116119
let mut sub_label = sub_label.clone();
117120
let mut text_label = text_label.clone();
118121
let mut bigtext_label = bigtext_label.clone();
122+
let mut progress_bar = progress_bar.clone();
119123
move || {
120124
let state = state.borrow();
121125

122-
// Update all the labels
126+
// Update all the outputs
123127
add_label.set_text(&ui, &format!("Added: {}", state.slider_val + state.spinner_val));
124128
sub_label.set_text(&ui, &format!("Subtracted: {}", state.slider_val - state.spinner_val));
125129
text_label.set_text(&ui, &format!("Text: {}", state.entry_val));
126130
bigtext_label.set_text(&ui, &format!("Multiline Text: {}", state.multi_val));
131+
progress_bar.set_value(&ui, (state.slider_val + state.spinner_val) as u32);
127132
}
128133
});
129134
event_loop.run(&ui);

iui/examples/inputs.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
extern crate iui;
44
use iui::prelude::*;
5-
use iui::controls::{Label, Spinbox, Slider, Entry, MultilineEntry, VerticalBox, HorizontalBox, HorizontalSeparator, Group, Spacer};
5+
use iui::controls::{Label, Spinbox, Slider, Entry, MultilineEntry, VerticalBox, HorizontalBox, HorizontalSeparator, Group, Spacer, ProgressBar};
66
use std::rc::Rc;
77
use std::cell::RefCell;
88

@@ -52,19 +52,21 @@ fn main() {
5252

5353
// Set up the outputs for the application. Organization is very similar to the
5454
// previous setup.
55-
let (output_group, add_label, sub_label, text_label, bigtext_label) = {
55+
let (output_group, add_label, sub_label, text_label, bigtext_label, progress_bar) = {
5656
let mut output_group = Group::new(&ui, "Outputs");
5757
let mut output_vbox = VerticalBox::new(&ui);
5858
let add_label = Label::new(&ui, "");
5959
let sub_label = Label::new(&ui, "");
6060
let text_label = Label::new(&ui, "");
6161
let bigtext_label = Label::new(&ui, "");
62+
let progress_bar = ProgressBar::indeterminate(&ui);
6263
output_vbox.append(&ui, add_label.clone(), LayoutStrategy::Compact);
6364
output_vbox.append(&ui, sub_label.clone(), LayoutStrategy::Compact);
65+
output_vbox.append(&ui, progress_bar.clone(), LayoutStrategy::Compact);
6466
output_vbox.append(&ui, text_label.clone(), LayoutStrategy::Compact);
6567
output_vbox.append(&ui, bigtext_label.clone(), LayoutStrategy::Stretchy);
6668
output_group.set_child(&ui, output_vbox);
67-
(output_group, add_label, sub_label, text_label, bigtext_label)
69+
(output_group, add_label, sub_label, text_label, bigtext_label, progress_bar)
6870
};
6971

7072
// This horizontal box will arrange the two groups of controls.
@@ -111,14 +113,16 @@ fn main() {
111113
let mut sub_label = sub_label.clone();
112114
let mut text_label = text_label.clone();
113115
let mut bigtext_label = bigtext_label.clone();
116+
let mut progress_bar = progress_bar.clone();
114117
move || {
115118
let state = state.borrow();
116119

117-
// Update all the labels
120+
// Update all the outputs
118121
add_label.set_text(&ui, &format!("Added: {}", state.slider_val + state.spinner_val));
119122
sub_label.set_text(&ui, &format!("Subtracted: {}", state.slider_val - state.spinner_val));
120123
text_label.set_text(&ui, &format!("Text: {}", state.entry_val));
121124
bigtext_label.set_text(&ui, &format!("Multiline Text: {}", state.multi_val));
125+
progress_bar.set_value(&ui, (state.slider_val + state.spinner_val) as u32)
122126
}
123127
});
124128
event_loop.run(&ui);

iui/src/controls/progressbar.rs

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,37 @@ use std::mem;
33
use ui::UI;
44
use ui_sys::{self, uiControl, uiProgressBar};
55

6-
/// An enum representing the value of a `ProgressBar`
6+
/// An enum representing the value of a `ProgressBar`.
7+
///
8+
/// # Values
9+
///
10+
/// A `ProgressBarValue` can be either `Determinate`, a number from 0 up to 100, or
11+
/// `Indeterminate`, representing a process that is still in progress but has no
12+
/// completeness metric availble.
13+
///
14+
/// # Conversions
15+
///
16+
/// A `ProgressBarValue` can be made from a `u32` or an `Option<u32>`, and the relevant functions
17+
/// take a type that is generic over this behavior, so it's easy to set the progress of a bar.
18+
///
19+
/// ```
20+
/// # use iui::prelude::*;
21+
/// # use iui::controls::{ProgressBar, ProgressBarValue};
22+
/// # let ui = UI::init().unwrap();
23+
/// # let mut window = Window::new(&ui, "Test Window", 0, 0, WindowType::NoMenubar);
24+
/// let mut progressbar = ProgressBar::indeterminate(&ui);
25+
/// progressbar.set_value(&ui, 54);
26+
///
27+
/// // Perhaps this is the result of some fallible progress-checking function.
28+
/// let maybe_progress: Option<u32> = None;
29+
/// progressbar.set_value(&ui, maybe_progress);
30+
///
31+
/// // And of course, you can always set it by hand.
32+
/// progressbar.set_value(&ui, ProgressBarValue::Indeterminate);
33+
/// # window.set_child(&ui, progressbar);
34+
/// # ui.quit();
35+
/// # ui.main();
36+
/// ```
737
pub enum ProgressBarValue {
838
/// Represents a set, consistent percentage of the bar to be filled
939
///
@@ -15,6 +45,25 @@ pub enum ProgressBarValue {
1545
Indeterminate,
1646
}
1747

48+
impl From<u32> for ProgressBarValue {
49+
fn from(value: u32) -> ProgressBarValue {
50+
if value <= 100 {
51+
ProgressBarValue::Determinate(value)
52+
} else {
53+
ProgressBarValue::Determinate(100)
54+
}
55+
}
56+
}
57+
58+
impl From<Option<u32>> for ProgressBarValue {
59+
fn from(value: Option<u32>) -> ProgressBarValue {
60+
match value {
61+
Some(v) => v.into(),
62+
None => ProgressBarValue::Indeterminate
63+
}
64+
}
65+
}
66+
1867
define_control! {
1968
/// A bar that fills up with a set percentage, used to show completion of a
2069
///
@@ -34,27 +83,16 @@ impl ProgressBar {
3483
}
3584

3685
/// Create a new indeterminate progress bar
37-
pub fn indeterminate() -> ProgressBar {
86+
pub fn indeterminate(ctx: &UI) -> ProgressBar {
3887
let mut pb = ProgressBar::new();
39-
pb.set_indeterminate();
88+
pb.set_value(ctx, ProgressBarValue::Indeterminate);
4089
pb
4190
}
4291

43-
/// Set the value of the progress bar to a determinate value
44-
///
45-
/// If `value` is larger than 100, than the value will be set to 100.
46-
pub fn set_determinate(&mut self, value: u32) {
47-
self.set_value(ProgressBarValue::Determinate(value));
48-
}
49-
50-
/// Set the value of the progress bar to be indeterminate
51-
pub fn set_indeterminate(&mut self) {
52-
self.set_value(ProgressBarValue::Indeterminate);
53-
}
54-
55-
/// Set the value of the progress bar
56-
pub fn set_value(&mut self, value: ProgressBarValue) {
57-
let sys_value = match value {
92+
/// Set the value of the progress bar. See [`ProgressBarValue`] for the values that can be passed in.
93+
/// [`ProgressBarValue`]: enum.ProgressBarValue.html
94+
pub fn set_value<V: Into<ProgressBarValue>>(&mut self, _ctx: &UI, value: V) {
95+
let sys_value = match value.into() {
5896
ProgressBarValue::Determinate(value) => {
5997
let value = if value > 100 { 100 } else { value };
6098
value as i32
@@ -65,7 +103,7 @@ impl ProgressBar {
65103
}
66104

67105
/// Get the value of the progress bar
68-
pub fn value(&self) -> ProgressBarValue {
106+
pub fn value(&self, _ctx: &UI) -> ProgressBarValue {
69107
let sys_value = unsafe { ui_sys::uiProgressBarValue(self.uiProgressBar) };
70108
if sys_value.is_negative() {
71109
assert!(

0 commit comments

Comments
 (0)