Skip to content

Commit 2442bcb

Browse files
author
rj
committed
Added a slider widget, with an implementation for WIN32. Implementation for GTK will need to follow. Small fixes to formatting of doc comments.
1 parent 4c5b55f commit 2442bcb

File tree

9 files changed

+366
-8
lines changed

9 files changed

+366
-8
lines changed

intinput.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ var (
1111
// IntInput describes a widget that users input or update a single integer value.
1212
// The model for the value is a int64.
1313
type IntInput struct {
14-
Value int64 // Values is the current string for the field
14+
Value int64 // Value is the current value for the field
1515
Placeholder string // Placeholder is a descriptive text that can be displayed when the field is empty
1616
Disabled bool // Disabled is a flag indicating that the user cannot interact with this field
1717
OnChange func(value int64) // OnChange will be called whenever the user changes the value for this field

label.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func (*Label) Kind() *base.Kind {
2020
}
2121

2222
// Mount creates a label control in the GUI.
23-
// The newly created widget will be a child of the widget specified by parent.
23+
// The newly created widget will be a child of the widget specified by parent.
2424
func (w *Label) Mount(parent base.Control) (base.Element, error) {
2525
// Forward to the platform-dependant code
2626
return w.mount(parent)

label_windows.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import (
1010
)
1111

1212
var (
13-
staticClassName []uint16
14-
oldStaticWindowProc uintptr
13+
staticClassName []uint16
1514
)
1615

1716
func init() {

mainwindow_windows.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,16 @@ func windowWindowProc(hwnd win.HWND, msg uint32, wParam uintptr, lParam uintptr)
596596
// Defer to the default window proc
597597

598598
case win.WM_HSCROLL:
599-
windowGetPtr(hwnd).setScrollPos(win.SB_HORZ, wParam)
599+
if lParam == 0 {
600+
// Message was sent by a standard scroll bar. Need to adjust the
601+
// scroll position for the window.
602+
windowGetPtr(hwnd).setScrollPos(win.SB_HORZ, wParam)
603+
} else {
604+
// Message was sent by a child window. As for all other controls
605+
// that notify the parent, resend to the child with the expectation
606+
// that the child has been subclassed.
607+
win.SendMessage(win.HWND(lParam), win.WM_HSCROLL, wParam, 0)
608+
}
600609
return 0
601610

602611
case win.WM_VSCROLL:

progress.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ var (
1414
// If both Min and Max are zero, then Max will be updated to 100. Other cases
1515
// where Min == Max are not allowed.
1616
type Progress struct {
17-
Value int
18-
Min, Max int
17+
Value int // Value is the current value to be displayed
18+
Min, Max int // Min and Max set the range of Value
1919
}
2020

2121
// Kind returns the concrete type for use in the Widget interface.

slider.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package goey
2+
3+
import (
4+
"bitbucket.org/rj/goey/base"
5+
)
6+
7+
var (
8+
sliderKind = base.NewKind("bitbucket.org/rj/goey.Slider")
9+
)
10+
11+
// Slider describes a widget that users input or update a single real value.
12+
// The model for the value is a float64.
13+
//
14+
// If both Min and Max are zero, then Max will be updated to 100. Other cases
15+
// where Min == Max are not allowed.
16+
type Slider struct {
17+
Value float64 // Value is the current value for the field
18+
Disabled bool // Disabled is a flag indicating that the user cannot interact with this field
19+
Min, Max float64 // Min and Max set the range of Value
20+
OnChange func(float64) // OnChange will be called whenever the user changes the value for this field
21+
OnFocus func() // OnFocus will be called whenever the slider receives the keyboard focus.
22+
OnBlur func() // OnBlur will be called whenever the slider loses the keyboard focus.
23+
}
24+
25+
// Kind returns the concrete type for use in the Widget interface.
26+
// Users should not need to use this method directly.
27+
func (*Slider) Kind() *base.Kind {
28+
return &sliderKind
29+
}
30+
31+
// Mount creates a slider control in the GUI.
32+
// The newly created widget will be a child of the widget specified by parent.
33+
func (w *Slider) Mount(parent base.Control) (base.Element, error) {
34+
// Fill in default values for the range.
35+
w.UpdateRange()
36+
37+
// Forward to the platform-dependant code
38+
return w.mount(parent)
39+
}
40+
41+
// UpdateRange sets a default range when Min and Max are uninitialized.
42+
func (w *Slider) UpdateRange() {
43+
if w.Min == 0 && w.Max == 0 {
44+
w.Max = 100
45+
}
46+
}
47+
48+
func (*sliderElement) Kind() *base.Kind {
49+
return &sliderKind
50+
}
51+
52+
func (w *sliderElement) UpdateProps(data base.Widget) error {
53+
slider := data.(*Slider)
54+
55+
// Fill in default values for the range.
56+
slider.UpdateRange()
57+
// Forward to the platform-dependant code
58+
return w.updateProps(slider)
59+
}

slider_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package goey
2+
3+
import (
4+
"bitbucket.org/rj/goey/base"
5+
"fmt"
6+
"strconv"
7+
"testing"
8+
)
9+
10+
func ExampleSlider() {
11+
value := 0.0
12+
13+
// In a full application, this variable would be updated to point to
14+
// the main window for the application.
15+
var mainWindow *Window
16+
// These functions are used to update the GUI. See below
17+
var update func()
18+
var render func() base.Widget
19+
20+
// Update function
21+
update = func() {
22+
err := mainWindow.SetChild(render())
23+
if err != nil {
24+
panic(err)
25+
}
26+
}
27+
28+
// Render function generates a tree of Widgets to describe the desired
29+
// state of the GUI.
30+
render = func() base.Widget {
31+
// Prep - text for the button
32+
text := "Value: " + strconv.FormatFloat(value, 'f', 1, 64)
33+
// The GUI contains a single widget, this button.
34+
return &VBox{
35+
AlignMain: MainCenter,
36+
AlignCross: CrossCenter,
37+
Children: []base.Widget{
38+
&Label{Text: text},
39+
&Slider{
40+
Value: value,
41+
OnChange: func(v float64) {
42+
value = v
43+
update()
44+
},
45+
},
46+
},
47+
}
48+
}
49+
50+
err := Run(func() error {
51+
w, err := NewWindow("Slider", render())
52+
if err != nil {
53+
return err
54+
}
55+
56+
mainWindow = w
57+
return nil
58+
})
59+
if err != nil {
60+
fmt.Println("Error:", err)
61+
} else {
62+
fmt.Println("OK")
63+
}
64+
65+
// Output:
66+
// OK
67+
}
68+
69+
func TestSliderCreate(t *testing.T) {
70+
testingRenderWidgets(t,
71+
&Slider{Value: 50},
72+
&Slider{Value: 50, Disabled: true},
73+
&Slider{Value: 500, Max: 1000},
74+
)
75+
}
76+
77+
func TestSliderClose(t *testing.T) {
78+
testingCloseWidgets(t,
79+
&Slider{Value: 50},
80+
&Slider{Value: 50, Disabled: true},
81+
&Slider{Value: 500, Max: 1000},
82+
)
83+
}
84+
85+
func TestSliderFocus(t *testing.T) {
86+
testingCheckFocusAndBlur(t,
87+
&Slider{Value: 50},
88+
&Slider{Value: 50},
89+
&Slider{Value: 500, Max: 1000},
90+
)
91+
}
92+
93+
func TestSliderUpdate(t *testing.T) {
94+
testingUpdateWidgets(t, []base.Widget{
95+
&Slider{Value: 50},
96+
&Slider{Value: 50, Disabled: true},
97+
&Slider{Value: 500, Max: 1000},
98+
}, []base.Widget{
99+
&Slider{Value: 50},
100+
&Slider{Value: 50, Min: 10, Max: 60},
101+
&Slider{Value: 500, Max: 1000, Disabled: true},
102+
})
103+
}

0 commit comments

Comments
 (0)