Today we show how to work with Sliders, and show the rather odd Region widget.
Design
We'll create two Sliders, one vertical, along the right side of the window, and another horizontal along the top edge of the window. Then we'll put a Region in the remaining area. With the vertical slider, we'll control the size of a black edge in the Region. With the horizontal slider, we'll control the hue of the color in the interior of the Region.
As always, we start with a subclass of UserInterface:
Smalltalk defineClass: #SliderWork
superclass: #{Widgetry.UserInterface}
indexedType: #none
private: false
instanceVariableNames: 'hueSlider thicknessSlider region '
classInstanceVariableNames: ''
imports: 'private Widgetry.*'
category: '(none)'
Now, we fill our #createInterface with our panes:
createInterface
hueSlider := Slider new.
hueSlider frame: (FractionalFrame
fractionLeft: 0.05
right: 0.8
top: 0.05
bottom: 0.2).
self addComponent: hueSlider.
thicknessSlider := Slider new.
thicknessSlider frame: (FractionalFrame
fractionLeft: 0.8
right: 0.95
top: 0.2
bottom: 0.95).
self addComponent: thicknessSlider.
region := Region new.
region frame: (FractionalFrame
fractionLeft: 0.1
right: 0.7
top: 0.3
bottom: 0.9).
self addComponent: region
And this is what it looks like when we execute SliderWork open:
Clean Up In Aisle 5
Well, that's ugly, isn't it?
By default, a Slider is horizontal. You can change that by sending either #beVertical or #beHorizontal: with a boolean. We'll go simple, and start our #hookupInterface:
hookupInterface
thicknessSlider beVertical.
And the result looks like this:
That's better.
Home On The Range
By default, a Slider has a range between 0.0 and 1.0, and moving the slider, from minimum to maximum position, changes the model's value to some value in between relative to its position. This makes changing the hue (just a ColorValue) of the Region easy. We just hook up the ValueChanged announcement, and push the color to the region from there using the #fillColor: method of Region.
hookupInterface
thicknessSlider beVertical.
hueSlider when: ValueChanged send: #updateRegionHue to: self.
updateRegionHue
region fillColor: (ColorValue
hue: hueSlider model value
saturation: 0.4
brightness: 0.7)
Here's what it looks like somewhere along the hue scale:
If you're following along at home, you'll notice that the value and the color of the Region changes quite smoothly.
Heads Up
Now we want to hook up our vertical slider to control the thickness of a black line around our Region. We want that to be a value from 1 to 10. And instead of being a smooth series of values, we want it to stop at each whole value. Finally, we want to show ticks for each intermediate stop, as well as at both ends.
Fortunately, the Slider has method to do this easily
To change from the 0.0 to 1.0 fully variable range, we use the Slider's #start:stop:step: method.
To have it show tick marks, we use the #showTicks: method:
hookupInterface
thicknessSlider beVertical.
hueSlider when: ValueChanged send: #updateRegionHue to: self.
thicknessSlider start: 1 stop: 10 step: 1.
thicknessSlider showTicks: true.
Edge Of Our Seats
Finally, we hook up the value of the thickness Slider to the #lineThickness: of the Region.
Some extra notes about the Region. We have to turn on the edge line of the Region, which by default is off, which we do with #displayEdgeLine:. Also, by default, the edge color is white. To make it more visible here, we'll make it black by using the #lineColor: method.
Here's our updated #hookupInterface
hookupInterface
thicknessSlider beVertical.
hueSlider when: ValueChanged send: #updateRegionHue to: self.
thicknessSlider start: 1 stop: 10 step: 1.
thicknessSlider showTicks: true.
region displayEdgeLine: true.
region lineColor: ColorValue black.
thicknessSlider when: ValueChanged send: #updateRegionEdge to: self.
And here's our simple #updateRegionEdge method:
updateRegionEdge
region lineThickness: thicknessSlider model value
Extra Credit
If you have been playing along at home, you probably notice that when the window opens, the Region is just a black box. That is the default fill color for a Region (just as white is the default edge color). Once we move the hue slider its hard to see the initial black edge because the default value of 1 is so thin.
So, let's force the color and the thickness to be different on startup:
hookupInterface
thicknessSlider beVertical.
hueSlider when: ValueChanged send: #updateRegionHue to: self.
thicknessSlider start: 1 stop: 10 step: 1.
thicknessSlider showTicks: true.
region displayEdgeLine: true.
region lineColor: ColorValue black.
thicknessSlider when: ValueChanged send: #updateRegionEdge to: self.
thicknessSlider model value: 7.
self updateRegionHue.
self updateRegionEdge
And here is what it looks like when starting up now:
Isn't that pretty?
And So It GoesSames