[squeak-dev] Review Request: pluggableSlider.6.cs

christoph.thiede at student.hpi.uni-potsdam.de christoph.thiede at student.hpi.uni-potsdam.de
Wed Dec 28 19:33:47 UTC 2022


=============== Summary ===============

Change Set:        pluggableSlider
Date:            28 December 2022
Author:            Christoph Thiede

Adds a simple slider widget to the ToolBuilder and connects it to the existing implementation in Morphic. An MVC implementation is not provided at this point. Adds a demo model for using the slider to MorphicExtras-Demo. Also makes some improvements to the existing Morphic Slider hierarchy:

* Don't reset a scroll bar when changing its extent (ScrollBar>>#updateSlider). This issue was only observable when the scroll bar was not contained in a ScrollPane which would change the scroll bar value manually.
* Add getQuantumSelector to Slider.
* Prevent Slider construction from implicitly resetting the slider value.

Treats ToolBuilder-Kernel-ct.139 and ToolBuilder-Morphic-ct.254.

=============== Diff ===============

MorphicToolBuilder>>buildPluggableSlider: {widgets required} · ct 12/28/2022 18:18
+ buildPluggableSlider: spec
+ 
+     | widget |
+     widget := self sliderClass
+         on: spec model
+         getValue: spec getValue
+         setValue: spec setValue
+         min: spec minValue
+         max: spec maxValue
+         quantum: spec quantum.
+     self register: widget id: spec name.
+     
+     spec interval ifNotNil: [:interval | widget interval: interval].
+     spec color ifNotNil: [:color | widget color: color].
+     self buildHelpFor: widget spec: spec.
+     self setFrame: spec frame in: widget.
+     self setLayoutHintsFor: widget spec: spec.
+     parent ifNotNil: [self add: widget to: parent].
+     ^ widget

MorphicToolBuilder>>sliderClass {widget classes} · ct 12/28/2022 20:06
+ sliderClass
+ 
+     ^ ScrollBar

PluggableSliderSpec
+ PluggableWidgetSpec subclass: #PluggableSliderSpec
+     instanceVariableNames: 'getValue setValue minValue maxValue quantum interval'
+     classVariableNames: ''
+     poolDictionaries: ''
+     category: 'ToolBuilder-Kernel'
+ 
+ PluggableSliderSpec class 
+     instanceVariableNames: ''
+ 
+ "A slider to choose a numeric value from a concrete or discrete 1-dimensional range."

PluggableSliderSpec>>buildWith: {building} · ct 2/10/2020 11:12
+ buildWith: builder
+ 
+     ^ builder buildPluggableSlider: self

PluggableSliderSpec>>getValue {accessing} · ct 2/10/2020 11:10
+ getValue
+     "Answer the selector for getting the slider's value."
+     ^ getValue

PluggableSliderSpec>>getValue: {accessing} · ct 2/10/2020 11:11
+ getValue: aSymbol
+     "Set the selector for getting the slider's value."
+     getValue := aSymbol

PluggableSliderSpec>>initialize {initialize-release} · ct 12/28/2022 18:15
+ initialize
+ 
+     super initialize.
+     
+     interval := 0.

PluggableSliderSpec>>interval {accessing} · ct 12/28/2022 20:04
+ interval
+     "Answer the interval for the slider extent, a number. 0 for automatic minimal extent."
+     ^ interval

PluggableSliderSpec>>interval: {accessing} · ct 12/28/2022 20:04
+ interval: aNumber
+     "Set the interval for the slider extent. 0 for automatic minimal extent."
+     interval := aNumber

PluggableSliderSpec>>maxValue {accessing} · ct 12/28/2022 18:13
+ maxValue
+     "Answer the maximum slider value, a number or symbol."
+     ^ maxValue

PluggableSliderSpec>>maxValue: {accessing} · ct 12/28/2022 18:13
+ maxValue: aNumberOrSymbol
+     "Set the maximum slider value."
+     maxValue := aNumberOrSymbol

PluggableSliderSpec>>minValue {accessing} · ct 12/28/2022 18:13
+ minValue
+     "Answer the minimum slider value, a number or symbol."
+     ^ minValue

PluggableSliderSpec>>minValue: {accessing} · ct 12/28/2022 18:13
+ minValue: aNumberOrSymbol
+     "Set the minimum slider value."
+     minValue := aNumberOrSymbol

PluggableSliderSpec>>quantum {accessing} · ct 12/28/2022 18:12
+ quantum
+     "Answer the rounding quantum for the slider value, a symbol or number."
+     ^ quantum

PluggableSliderSpec>>quantum: {accessing} · ct 12/28/2022 18:13
+ quantum: aNumberOrSymbol
+     "Set the rounding quantum for the slider value."
+     quantum := aNumberOrSymbol

PluggableSliderSpec>>setValue {accessing} · ct 2/10/2020 11:12
+ setValue
+     "Answer the selector for setting the slider's value."
+     ^ setValue

PluggableSliderSpec>>setValue: {accessing} · ct 2/10/2020 11:12
+ setValue: aSymbol
+     "Set the selector for setting the slider's value."
+     setValue := aSymbol

ScrollBar>>updateSlider {updating} · ct 12/28/2022 18:03 (changed)
updateSlider

    | imagesNeedUpdate |
    imagesNeedUpdate := upButton width ~= (self orientation == #horizontal ifTrue: [self height] ifFalse: [self width]).
    
    self menuButton
        visible: (self orientation == #horizontal or: [self class scrollBarsWithoutMenuButton]) not;
        disableLayout: self menuButton visible not;
        bounds: self boundsForMenuButton.
    self upButton
        visible: self class scrollBarsWithoutArrowButtons not;
        disableLayout: self upButton visible not;
        bounds: self boundsForUpButton.
    self downButton
        visible: self class scrollBarsWithoutArrowButtons not;
        disableLayout: self downButton visible not;
        bounds: self boundsForDownButton.

-     super updateSlider.
- 
-     pagingArea bounds: self totalSliderArea.
+     self orientation == #horizontal
+         ifTrue: [slider height: self totalSliderArea height]
+         ifFalse: [slider width: self totalSliderArea width].
    self expandSlider.
+     sliderShadow bounds: slider bounds.
+     pagingArea bounds: self totalSliderArea.
+     self computeSlider.

    imagesNeedUpdate ifTrue: [
        self menuButton visible ifTrue: [self updateMenuButtonImage].
        self upButton visible ifTrue: [self updateUpButtonImage].
        self downButton visible ifTrue: [self updateDownButtonImage]].

Slider (changed)
MorphicModel subclass: #Slider
-     instanceVariableNames: 'slider value setValueSelector getValueSelector sliderShadow sliderColor descending minimumValue maximumValue quantum getMinimumValueSelector getMaximumValueSelector orientation'
+     instanceVariableNames: 'slider value setValueSelector getValueSelector sliderShadow sliderColor descending minimumValue maximumValue quantum getMinimumValueSelector getMaximumValueSelector getQuantumSelector orientation'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'Morphic-Windows'

Slider class 
    instanceVariableNames: ''

"I am a widget that helps users enter a numerically bounded value. I have a minimum and a maximum value. My thumb indicates my current value. My orientation can be vertical or horizontal, which is usually determined by the ratio of my extent. Nevertheless, you can force me to use a specific orientation,

Note that I can be pluggable and get data from a model."

Slider class>>on:getValue:setValue:min:max:quantum: {instance creation} · ct 12/28/2022 17:29 (changed)
- on: anObject getValue: getSel setValue: setSel min: min max: max quantum: quantum
-     "Answer a new instance of the receiver with
-     the given selectors as the interface."
+ on: anObject getValue: getSel setValue: setSel min: minValueOrSel max: maxValueOrSel quantum: quantumValueOrSel

-     | instance |
-     instance := self new
-         quantum: quantum;
+     ^ self new
        on: anObject
        getValue: getSel
-         setValue: setSel.
-     min isSymbol
-         ifTrue: [instance getMinimumValueSelector: min]
-         ifFalse: [instance minimumValue: min].
-     max isSymbol
-         ifTrue: [instance getMaximumValueSelector: max]
-         ifFalse: [instance maximumValue: max].
-     ^ instance
+         setValue: setSel
+         min: minValueOrSel
+         max: maxValueOrSel
+         quantum: quantumValueOrSel

Slider>>getQuantum {model access} · ct 12/28/2022 17:02
+ getQuantum
+     
+     self getQuantumSelector ifNotNil: [:selector |
+         self quantum: (model perform: selector)].
+     ^ self quantum

Slider>>getQuantumSelector {accessing - model} · ct 12/28/2022 17:00
+ getQuantumSelector
+ 
+     ^ getQuantumSelector

Slider>>getQuantumSelector: {accessing - model} · ct 12/28/2022 17:01
+ getQuantumSelector: aSymbol
+ 
+     getQuantumSelector := aSymbol.

Slider>>maximumValue: {accessing} · ct 12/28/2022 18:06 (changed)
maximumValue: aNumber
    
    maximumValue := aNumber.
-     self setValue: self value.
+     self setValue: self value.
+     self computeSlider.

Slider>>minimumValue: {accessing} · ct 12/28/2022 18:06 (changed)
minimumValue: aNumber

    minimumValue := aNumber.
-     self setValue: self value.
+     self setValue: self value.
+     self computeSlider.

Slider>>on:getValue:setValue:min:max:quantum: {initialization} · ct 12/28/2022 17:37
+ on: anObject getValue: getSel setValue: setSel min: minValueOrSel max: maxValueOrSel quantum: quantumValueOrSel
+ 
+     self
+         model: anObject;
+         getValueSelector: getSel;
+         setValueSelector: setSel.
+     minimumValue := Float negativeInfinity.
+     maximumValue := Float infinity.
+     quantum := nil.
+     value :=  model perform: getValueSelector.
+     
+     minValueOrSel isSymbol
+         ifTrue: [self getMinimumValueSelector: minValueOrSel; getMinimumValue]
+         ifFalse: [self minimumValue: minValueOrSel].
+     maxValueOrSel isSymbol
+         ifTrue: [self getMaximumValueSelector: maxValueOrSel; getMaximumValue]
+         ifFalse: [self maximumValue: maxValueOrSel].
+     quantumValueOrSel isSymbol
+         ifTrue: [self getQuantumSelector: quantumValueOrSel; getQuantum]
+         ifFalse: [self quantum: quantumValueOrSel].
+     self setValue: self getValue.
+     
+     self computeSlider.

Slider>>update: {updating} · ct 12/28/2022 17:01 (changed)
update: aSymbol
    "Update the value."
    
    super update: aSymbol.
    
    aSymbol = self getValueSelector ifTrue: [self getValue. ^ self].
    aSymbol = self getMinimumValueSelector ifTrue: [self getMinimumValue. ^ self].
-     aSymbol = self getMaximumValueSelector ifTrue: [self getMaximumValue. ^ self].
+     aSymbol = self getMaximumValueSelector ifTrue: [self getMaximumValue. ^ self].
+     aSymbol = self getQuantumSelector ifTrue: [self getQuantum. ^ self].

SliderDemoModel
+ Model subclass: #SliderDemoModel
+     instanceVariableNames: 'value minValue maxValue quantum'
+     classVariableNames: ''
+     poolDictionaries: ''
+     category: 'MorphicExtras-Demo-ToolBuilder'
+ 
+ SliderDemoModel class 
+     instanceVariableNames: ''
+ 
+ "I demonstrate how to use the PluggableSliderSpec."

SliderDemoModel class>>open {opening} · ct 12/28/2022 20:20
+ open
+ 
+     ^ self new open

SliderDemoModel>>buildWith: {toolbuilder} · ct 12/28/2022 18:18
+ buildWith: aBuilder
+ 
+     | spec |
+     spec := self buildWindowWith: aBuilder specs: {
+         (0 @ 0 rect: 1 @ 0.1) -> [aBuilder pluggableSliderSpec new
+             model: self;
+             getValue: #currentValue;
+             setValue: #currentValue:;
+             minValue: #minValue;
+             maxValue: #maxValue;
+             quantum: #quantum;
+             interval: 0.1;
+             help: 'slider';
+             color: Color blue;
+             yourself].
+         (0 @ 0.1 rect: 1 / 4 @ 0.2) -> [aBuilder pluggableTextSpec new
+             model: self;
+             getText: #valueText;
+             setText: #valueText:;
+             help: 'value';
+             yourself].
+         (1 / 4 @ 0.1 rect: 2 / 4 @ 0.2) -> [aBuilder pluggableTextSpec new
+             model: self;
+             getText: #minValueText;
+             setText: #minValueText:;
+             help: 'min';
+             yourself].
+         (2 / 4 @ 0.1 rect: 3 / 4 @ 0.2) -> [aBuilder pluggableTextSpec new
+             model: self;
+             getText: #maxValueText;
+             setText: #maxValueText:;
+             help: 'max';
+             yourself].
+         (3 / 4 @ 0.1 rect: 4 / 4 @ 0.2) -> [aBuilder pluggableTextSpec new
+             model: self;
+             getText: #quantumText;
+             setText: #quantumText:;
+             help: 'quantum';
+             yourself] }.
+     ^ aBuilder build: spec

SliderDemoModel>>currentValue {accessing} · ct 12/28/2022 16:55
+ currentValue
+ 
+     ^ value

SliderDemoModel>>currentValue: {accessing} · ct 12/28/2022 17:13
+ currentValue: aNumber
+ 
+     value := aNumber.
+     self changed: #currentValue; changed: #valueText.

SliderDemoModel>>initialize {initialize-release} · ct 12/28/2022 17:14
+ initialize
+ 
+     super initialize.
+     value := 15.
+     minValue := 10.
+     maxValue := 20.
+     quantum := 0.1.

SliderDemoModel>>maxValue {accessing} · ct 12/28/2022 17:03
+ maxValue
+ 
+     ^ maxValue

SliderDemoModel>>maxValue: {accessing} · ct 12/28/2022 17:07
+ maxValue: aNumber
+ 
+     maxValue := aNumber.
+     self changed: #maxValue; changed: #maxValueText.

SliderDemoModel>>maxValueText {accessing - text} · ct 12/28/2022 17:02
+ maxValueText
+ 
+     ^ self maxValue asString

SliderDemoModel>>maxValueText: {accessing - text} · ct 12/28/2022 17:07
+ maxValueText: aStringOrText
+ 
+     self maxValue: aStringOrText asNumber.
+     ^ true

SliderDemoModel>>minValue {accessing} · ct 12/28/2022 17:02
+ minValue
+ 
+     ^ minValue

SliderDemoModel>>minValue: {accessing} · ct 12/28/2022 17:08
+ minValue: aNumber
+ 
+     minValue := aNumber.
+     self changed: #minValue; changed: #minValueText.

SliderDemoModel>>minValueText {accessing - text} · ct 12/28/2022 17:02
+ minValueText
+ 
+     ^ self minValue asString

SliderDemoModel>>minValueText: {accessing - text} · ct 12/28/2022 17:08
+ minValueText: aStringOrText
+ 
+     self minValue: aStringOrText asNumber.
+     ^ true

SliderDemoModel>>open {toolbuilder} · ct 12/28/2022 20:20
+ open
+ 
+     ^ ToolBuilder default open: self

SliderDemoModel>>quantum {accessing} · ct 12/28/2022 17:03
+ quantum
+ 
+     ^ quantum

SliderDemoModel>>quantum: {accessing} · ct 12/28/2022 17:09
+ quantum: aNumber
+ 
+     quantum := aNumber.
+     self changed: #quantum; changed: #quantumText.

SliderDemoModel>>quantumText {accessing - text} · ct 12/28/2022 17:03
+ quantumText
+ 
+     ^ self quantum asString

SliderDemoModel>>quantumText: {accessing - text} · ct 12/28/2022 17:09
+ quantumText: aStringOrText
+ 
+     self quantum: aStringOrText asNumber.
+     ^ true

SliderDemoModel>>valueText {accessing - text} · ct 12/28/2022 17:06
+ valueText
+ 
+     ^ self currentValue printShowingDecimalPlaces: 2

SliderDemoModel>>valueText: {accessing - text} · ct 12/28/2022 16:56
+ valueText: aStringOrText
+ 
+     self currentValue: aStringOrText asNumber.
+     ^ true

ToolBuilder>>buildPluggableSlider: {widgets required} · ct 12/28/2022 20:06
+ buildPluggableSlider: spec
+ 
+     ^ self subclassResponsibility

ToolBuilder>>pluggableSliderSpec {defaults} · ct 2/10/2020 11:14
+ pluggableSliderSpec
+     ^ PluggableSliderSpec

---
Sent from Squeak Inbox Talk
["pluggableSlider.6.cs"]
["SliderDemoModel.png"]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20221228/c1e5136b/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pluggableSlider.6.cs
Type: application/octet-stream
Size: 12495 bytes
Desc: not available
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20221228/c1e5136b/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SliderDemoModel.png
Type: image/png
Size: 14077 bytes
Desc: not available
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20221228/c1e5136b/attachment.png>


More information about the Squeak-dev mailing list