Today we look at the ProgressBar and have some fun.
Design
We'll create three ProgressBars, top, middle and bottom, each showing different aspects of a ProgressBar attributes. We'll add a Button at the bottom of the window, which we'll label GO, and have it kick off animating the three ProgressBars.
As always, we start of with a subclass of UserInterface:
Smalltalk defineClass: #ProgressBarWork
superclass: #{Widgetry.UserInterface}
indexedType: #none
private: false
instanceVariableNames: 'topBar middleBar bottomBar goButton '
classInstanceVariableNames: ''
imports: 'private Widgetry.*'
category: '(none)'
Now we'll add our three ProgressBars and the Button in our #createInterface:
createInterface
topBar := ProgressBar new.
topBar frame: (FractionalFrame
fractionLeft: 0.05
right: 0.95
top: 0.2
bottom: 0.2).
(topBar frame)
topOffset: -13;
bottomOffset: 13.
self addComponent: topBar.
middleBar := ProgressBar new.
middleBar frame: (FractionalFrame
fractionLeft: 0.05
right: 0.95
top: 0.4
bottom: 0.4).
(middleBar frame)
topOffset: -13;
bottomOffset: 13.
self addComponent: middleBar.
bottomBar := ProgressBar new.
bottomBar frame: (FractionalFrame
fractionLeft: 0.05
right: 0.95
top: 0.6
bottom: 0.6).
(bottomBar frame)
topOffset: -13;
bottomOffset: 13.
self addComponent: bottomBar.
goButton := Button new.
goButton frame: (FractionalFrame
fractionLeft: 0.05
right: 0.95
top: 0.8
bottom: 0.8).
(goButton frame)
topOffset: -13;
bottomOffset: 13.
goButton addComponent: ((DisplayLabel string: 'GO') frame: AlignmentFrame new).
self addComponent: goButton.
When we execute ProgressBarWork open, this is what we see:
Wild West
Before we show the various features, lets make our progress bars do something. A ProgressBar will show values from 0 to 100 in percent, based on a value between 0 and 1. You set the value, and the ProgressBar will automatically update itself by sending a value to the #percent: method.
We'll do some fun stuff. First, we'll connect the Clicked announcement to a method that will do the work in our #hookupInterface method:
hookupInterface
goButton when: Clicked send: #goBars to: self.
Now we write our #goBars method:
goBars
0 to: 1.001 by: 0.005 do:
[:index |
(Delay forMilliseconds: 10) wait.
topBar percent: index.
middleBar percent: (index - 1) abs.
bottomBar percent: index]
And here is what it looks like when its running:
Thousand Points Of Light
For now we'll leave our top ProgressBar as an example of the basics.
One of the things we can do, is turn off (or on) the percent display. We'll do that on our bottom progress bar.
hookupInterface
goButton when: Clicked send: #goBars to: self.
bottomBar displayPercentDone: false
Another thing we can do is to display not just integer percents, but the percent in tenths. We'll do that on the middle bar:
hookupInterface
goButton when: Clicked send: #goBars to: self.
bottomBar displayPercentDone: false.
middleBar displayPercentTenths: true
And here is what it looks like now when it is running:
Colors Galore
There are four color values we can set for a ProgressBar. The bar color, the background color, the label color when it is displayed on the bar, and the label color when it is displayed on the background.
You see in our samples, that in the XP Look, the bar has that familiar green vertical bar that Windows XP uses. If instead, we give it a color, it won't just change to a colored bar, but solid fill of that color. Indeed here is what the default looks like when we change to the MacOSX Look, Motif Look and Win9x Look respectively:
If you're playing along at home, you'll notice that the MacOSX bar does not do the ripple effect. On the Motif look, the colors are all black and background gray. On the Win9x look, the colors are selection color (yes, my selection color on my machine is dark brown, not the default blue... You may have noticed this before in the Grid, TreeView and ListBox work we've done) and for the label, either black or background.
Let's make it so that for the top bar, the label color when it is in the bar area, be dark magenta. For the WinXP look, this will make it stand out a bit better:
hookupInterface
goButton when: Clicked send: #goBars to: self.
bottomBar displayPercentDone: false.
middleBar displayPercentTenths: true.
topBar labelOnBarColor: ColorValue darkMagenta.
Notice how the label on the background is still black... You might have to look hard though.
For the middle bar, let's really go all out. Lets make the bar color red, the background pink, the label color green when it is on the background, and yellow when it is on the bar:
hookupInterface
goButton when: Clicked send: #goBars to: self.
bottomBar displayPercentDone: false.
middleBar displayPercentTenths: true.
topBar labelOnBarColor: ColorValue darkMagenta.
middleBar background: ColorValue pink.
middleBar barColor: ColorValue darkRed.
middleBar labelOnBackgroundColor: ColorValue darkGreen.
middleBar labelOnBarColor: ColorValue yellow
As you see, we get what we pay for.
Extra Credit
An interesting feature of the VisualWorks graphics system, is that pretty much anywhere you can specify a ColorValue, you can also/instead specify a Pattern. A Pattern is an image of some sort that when made into a Pattern object, can be used as the brush. It automatically tiles x and y based on the size of the underlying image.
So, I have captured the smiley image from my IRC client, imported it as a resource on my ProgressBarWork class (you can download it here: ProgressBarWork-smile.st). Then with a single line of code:
hookupInterface
goButton when: Clicked send: #goBars to: self.
bottomBar displayPercentDone: false.
middleBar displayPercentTenths: true.
topBar labelOnBarColor: ColorValue darkMagenta.
middleBar background: ColorValue pink.
middleBar barColor: ColorValue darkRed.
middleBar labelOnBackgroundColor: ColorValue darkGreen.
middleBar labelOnBarColor: ColorValue yellow.
bottomBar barColor: (self class smile asPattern)
We get:
Isn't that pretty?
And So It GoesSames