From 495a02d1a12e0f7ecf3aeacde0f2b505253f526b Mon Sep 17 00:00:00 2001 From: Florian Thienel Date: Sat, 9 Dec 2023 20:39:42 +0100 Subject: [PATCH] add a new button type to switch pages --- cmd/root.go | 1 + pkg/hamdeck/buttons.go | 41 ++++++++++++++++++ pkg/hamdeck/config.go | 2 +- pkg/hamdeck/factory.go | 51 ++++++++++++++++++++++ pkg/hamdeck/hamdeck_test.go | 2 + pkg/hamdeck/pages_test.go | 40 ++++++++++++++++++ pkg/hamdeck/testdata/testEightPages.json | 54 ++++++++++++++++++++++++ 7 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 pkg/hamdeck/buttons.go create mode 100644 pkg/hamdeck/factory.go create mode 100644 pkg/hamdeck/testdata/testEightPages.json diff --git a/cmd/root.go b/cmd/root.go index d700ace..2968a21 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -94,6 +94,7 @@ func run(cmd *cobra.Command, args []string) { device.SetBrightness(rootFlags.brightness) deck := hamdeck.New(device) + deck.RegisterFactory(hamdeck.NewButtonFactory(deck)) deck.RegisterFactory(pulse.NewButtonFactory()) if rootFlags.hamlibAddress != "" { deck.RegisterFactory(hamlib.NewButtonFactory(rootFlags.hamlibAddress)) diff --git a/pkg/hamdeck/buttons.go b/pkg/hamdeck/buttons.go new file mode 100644 index 0000000..d5c03aa --- /dev/null +++ b/pkg/hamdeck/buttons.go @@ -0,0 +1,41 @@ +package hamdeck + +import "image" + +/* + PageButton +*/ + +type PageButton struct { + BaseButton + image image.Image + + pageSwitcher PageSwitcher + id string + label string +} + +func NewPageButton(pageSwitcher PageSwitcher, id string, label string) *PageButton { + return &PageButton{ + pageSwitcher: pageSwitcher, + id: id, + label: label, + } +} + +func (b *PageButton) Image(gc GraphicContext, redrawImages bool) image.Image { + if b.image == nil || redrawImages { + gc.SetForeground(White) + gc.SetBackground(Black) + b.image = gc.DrawSingleLineTextButton(b.label) + } + return b.image +} + +func (b *PageButton) Pressed() { + b.pageSwitcher.AttachPage(b.id) +} + +func (b *PageButton) Released() { + // nop +} diff --git a/pkg/hamdeck/config.go b/pkg/hamdeck/config.go index cf0fbed..ad4330c 100644 --- a/pkg/hamdeck/config.go +++ b/pkg/hamdeck/config.go @@ -137,7 +137,7 @@ func (d *HamDeck) loadButtons(configuration []any) ([]Button, error) { log.Printf("buttons[%d] has no valid index", i) continue } - if buttonIndex <= 0 || buttonIndex >= len(d.buttons) { + if buttonIndex < 0 || buttonIndex >= len(d.buttons) { log.Printf("%d is not a valid button index in [0, %d])", buttonIndex, len(d.buttons)) } diff --git a/pkg/hamdeck/factory.go b/pkg/hamdeck/factory.go new file mode 100644 index 0000000..fe62323 --- /dev/null +++ b/pkg/hamdeck/factory.go @@ -0,0 +1,51 @@ +package hamdeck + +import "log" + +const ( + ConfigPage = "page" + ConfigLabel = "label" +) + +const ( + PageButtonType = "hamdeck.Page" +) + +type Factory struct { + pageSwitcher PageSwitcher +} + +type PageSwitcher interface { + AttachPage(string) error +} + +func NewButtonFactory(pageSwitcher PageSwitcher) *Factory { + return &Factory{ + pageSwitcher: pageSwitcher, + } +} + +func (f *Factory) Close() { + // nop +} + +func (f *Factory) CreateButton(config map[string]any) Button { + switch config[ConfigType] { + case PageButtonType: + return f.createPageButton(config) + default: + return nil + } +} + +func (f *Factory) createPageButton(config map[string]any) Button { + id, haveID := ToString(config[ConfigPage]) + label, haveLabel := ToString(config[ConfigLabel]) + if !haveID { + log.Print("A hamdeck.Page button must have a page field.") + } + if !haveLabel { + log.Print("A hamdeck.Page button must have a label field.") + } + return NewPageButton(f.pageSwitcher, id, label) +} diff --git a/pkg/hamdeck/hamdeck_test.go b/pkg/hamdeck/hamdeck_test.go index 1b546ca..900df5a 100644 --- a/pkg/hamdeck/hamdeck_test.go +++ b/pkg/hamdeck/hamdeck_test.go @@ -41,6 +41,7 @@ func runWithConfigFile(t *testing.T, filename string, f func(*testing.T, *HamDec device := newDefaultTestDevice() deck := New(device) deck.RegisterFactory(new(testButtonFactory)) + deck.RegisterFactory(NewButtonFactory(deck)) reader, err := openTestConfigFile(filename) require.NoError(t, err) @@ -70,6 +71,7 @@ func runWithConfigString(t *testing.T, config string, f func(*testing.T, *HamDec device := newDefaultTestDevice() deck := New(device) deck.RegisterFactory(new(testButtonFactory)) + deck.RegisterFactory(NewButtonFactory(deck)) reader, err := openTestConfigString(config) require.NoError(t, err) diff --git a/pkg/hamdeck/pages_test.go b/pkg/hamdeck/pages_test.go index 09061e2..318be35 100644 --- a/pkg/hamdeck/pages_test.go +++ b/pkg/hamdeck/pages_test.go @@ -126,3 +126,43 @@ func TestAttachPage(t *testing.T) { assert.Same(t, deck.noButton, deck.buttons[1]) }) } + +func TestPageButton(t *testing.T) { + runWithConfigString(t, `{ + "pages": { + "main": { + "buttons": [ + { "type": "hamdeck.Page", "index": 0, "page": "", "label": "Back" } + ] + } + }, + "buttons": [ + { "type": "hamdeck.Page", "index": 0, "page": "main", "label": "Main" } + ] +}`, func(t *testing.T, deck *HamDeck, device *testDevice, _ chan struct{}) { + assert.Equal(t, legacyPageID, deck.startPageID) + assert.Equal(t, 2, len(deck.pages)) + + mainPage := deck.pages["main"] + require.Equal(t, len(deck.buttons), len(mainPage.buttons)) + mainButton, ok := mainPage.buttons[0].(*PageButton) + require.True(t, ok) + assert.Equal(t, "Back", mainButton.label) + + legacyPage := deck.pages[legacyPageID] + require.Equal(t, len(deck.buttons), len(legacyPage.buttons)) + legacyButton, ok := legacyPage.buttons[0].(*PageButton) + require.True(t, ok) + assert.Equal(t, "Main", legacyButton.label) + + assert.Same(t, legacyButton, deck.buttons[0]) + + device.Press(0) + device.WaitForLastKey() + assert.Same(t, mainButton, deck.buttons[0]) + + device.Press(0) + device.WaitForLastKey() + assert.Same(t, legacyButton, deck.buttons[0]) + }) +} diff --git a/pkg/hamdeck/testdata/testEightPages.json b/pkg/hamdeck/testdata/testEightPages.json new file mode 100644 index 0000000..17debb3 --- /dev/null +++ b/pkg/hamdeck/testdata/testEightPages.json @@ -0,0 +1,54 @@ +{ + "buttons": [ + {"type": "hamdeck.Page", "index": 0, "page": "1", "label": "1"}, + {"type": "hamdeck.Page", "index": 1, "page": "2", "label": "2"}, + {"type": "hamdeck.Page", "index": 2, "page": "3", "label": "3"}, + {"type": "hamdeck.Page", "index": 3, "page": "4", "label": "4"}, + {"type": "hamdeck.Page", "index": 4, "page": "5", "label": "5"}, + {"type": "hamdeck.Page", "index": 5, "page": "6", "label": "6"}, + {"type": "hamdeck.Page", "index": 6, "page": "7", "label": "7"}, + {"type": "hamdeck.Page", "index": 7, "page": "8", "label": "8"} + ], + "pages": { + "1": { + "buttons": [ + {"type": "hamdeck.Page", "index": 0, "page": "", "label": "Back"} + ] + }, + "2": { + "buttons": [ + {"type": "hamdeck.Page", "index": 1, "page": "", "label": "Back"} + ] + }, + "3": { + "buttons": [ + {"type": "hamdeck.Page", "index": 2, "page": "", "label": "Back"} + ] + }, + "4": { + "buttons": [ + {"type": "hamdeck.Page", "index": 3, "page": "", "label": "Back"} + ] + }, + "5": { + "buttons": [ + {"type": "hamdeck.Page", "index": 4, "page": "", "label": "Back"} + ] + }, + "6": { + "buttons": [ + {"type": "hamdeck.Page", "index": 5, "page": "", "label": "Back"} + ] + }, + "7": { + "buttons": [ + {"type": "hamdeck.Page", "index": 6, "page": "", "label": "Back"} + ] + }, + "8": { + "buttons": [ + {"type": "hamdeck.Page", "index": 7, "page": "", "label": "Back"} + ] + } + } +} \ No newline at end of file