Allow updating the callback function on an existing button instance.

This commit is contained in:
Jakub Sobon 2020-12-30 00:10:55 -05:00
parent cd7782f3b1
commit d70bcd1afb
No known key found for this signature in database
GPG Key ID: F2451A77FB05D3B7
3 changed files with 66 additions and 1 deletions

View File

@ -60,6 +60,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
main states (up, focused and up, down).
- the `button` widget allows specifying separate fill color values for each of
its main states (up, focused and up, down).
- the `button` widget now has a method `SetCallback` that allows updating the
callback function on an existing `button` instance.
#### Updates to the `textinput` widget

View File

@ -154,6 +154,13 @@ func NewFromChunks(chunks []*TextChunk, cFn CallbackFn, opts ...Option) (*Button
}, nil
}
// SetCallback replaces the callback function of the button with the one provided.
func (b *Button) SetCallback(cFn CallbackFn) {
b.mu.Lock()
defer b.mu.Unlock()
b.callback = cFn
}
// Vars to be replaced from tests.
var (
// Runes to use in cells that contain the button.

View File

@ -45,6 +45,10 @@ type callbackTracker struct {
// count is the number of times the callback was called.
count int
// useSetCallback when set to true instructs the test to set the callback
// via button.SetCallback instead of button.New or button.NewFromChunks.
useSetCallback bool
// mu protects the tracker.
mu sync.Mutex
}
@ -411,7 +415,7 @@ func TestButton(t *testing.T) {
wantCallback: &callbackTracker{},
},
{
desc: "mouse triggered the callback",
desc: "mouse triggered a callback set via the constructor",
callback: &callbackTracker{},
text: "hello",
canvas: image.Rect(0, 0, 8, 4),
@ -451,6 +455,50 @@ func TestButton(t *testing.T) {
count: 1,
},
},
{
desc: "mouse triggered a callback set via SetCallback",
callback: &callbackTracker{
useSetCallback: true,
},
text: "hello",
canvas: image.Rect(0, 0, 8, 4),
meta: &widgetapi.Meta{Focused: false},
events: []*event{
{
ev: &terminalapi.Mouse{Position: image.Point{0, 0}, Button: mouse.ButtonLeft},
meta: &widgetapi.EventMeta{},
},
{
ev: &terminalapi.Mouse{Position: image.Point{0, 0}, Button: mouse.ButtonRelease},
meta: &widgetapi.EventMeta{},
},
},
want: func(size image.Point) *faketerm.Terminal {
ft := faketerm.MustNew(size)
cvs := testcanvas.MustNew(ft.Area())
// Shadow.
testcanvas.MustSetAreaCells(cvs, image.Rect(1, 1, 8, 4), 's', cell.BgColor(cell.ColorNumber(240)))
// Button.
testcanvas.MustSetAreaCells(cvs, image.Rect(0, 0, 7, 3), 'x', cell.BgColor(cell.ColorNumber(117)))
// Text.
testdraw.MustText(cvs, "hello", image.Point{1, 1},
draw.TextCellOpts(
cell.FgColor(cell.ColorBlack),
cell.BgColor(cell.ColorNumber(117))),
)
testcanvas.MustApply(cvs, ft)
return ft
},
wantCallback: &callbackTracker{
called: true,
count: 1,
useSetCallback: true,
},
},
{
desc: "draws button in down state due to a keyboard event, callback triggered",
callback: &callbackTracker{},
@ -1373,6 +1421,10 @@ func TestButton(t *testing.T) {
var cFn CallbackFn
if gotCallback == nil {
cFn = nil
} else if gotCallback.useSetCallback {
// Set an no-op callback via the constructor.
// It will be updated to the real one via SetCallback.
cFn = func() error { return nil }
} else {
cFn = gotCallback.callback
}
@ -1402,6 +1454,10 @@ func TestButton(t *testing.T) {
btn = b
}
if gotCallback.useSetCallback {
btn.SetCallback(gotCallback.callback)
}
{
// Draw once which initializes the mouse state machine with the current canvas area.
c, err := canvas.New(tc.canvas)