commit a7add69f1840a7737618ba76c1989dd45c44b671
parent 97dc090619eddcccb8162f84d074c8656c1b051c
Author: lash <dev@holbrook.no>
Date: Sat, 8 Apr 2023 11:31:05 +0100
Add menu browse display conditional on state
Diffstat:
4 files changed, 123 insertions(+), 12 deletions(-)
diff --git a/go/resource/resource.go b/go/resource/resource.go
@@ -18,7 +18,6 @@ type Resource interface {
GetTemplate(sym string, sizer *Sizer) (string, error) // Get the template for a given symbol.
GetCode(sym string) ([]byte, error) // Get the bytecode for the given symbol.
PutMenu(string, string) error // Add a menu item.
- ShiftMenu() (string, string, error) // Remove and return the first menu item in list.
SetMenuBrowse(string, string, bool) error // Set menu browser display details.
RenderTemplate(sym string, values map[string]string, idx uint16, sizer *Sizer) (string, error) // Render the given data map using the template of the symbol.
RenderMenu() (string, error) // Render the current state of menu
@@ -30,6 +29,8 @@ type MenuResource struct {
menu [][2]string
next [2]string
prev [2]string
+ canNext bool
+ canPrev bool
sinkValues []string
codeFunc CodeFunc
templateFunc TemplateFunc
@@ -68,12 +69,22 @@ func(m *MenuResource) SetMenuBrowse(selector string, title string, back bool) er
entry := [2]string{selector, title}
if back {
m.prev = entry
+ m.canPrev = true
} else {
m.next = entry
+ m.canNext = true
}
return nil
}
+//func(m *MenuResource) putNext() error {
+// return m.PutMenu(m.next[0], m.next[1])
+//}
+//
+//func(m *MenuResource) putPrevious() error {
+// return m.PutMenu(m.prev[0], m.prev[1])
+//}
+
// PutMenu adds a menu option to the menu rendering.
func(m *MenuResource) PutMenu(selector string, title string) error {
m.menu = append(m.menu, [2]string{selector, title})
@@ -81,10 +92,9 @@ func(m *MenuResource) PutMenu(selector string, title string) error {
return nil
}
-// PutMenu removes and returns the first of remaining menu options.
-//
-// Fails if menu is empty.
-func(m *MenuResource) ShiftMenu() (string, string, error) {
+// removes and returns the first of remaining menu options.
+// fails if menu is empty.
+func(m *MenuResource) shiftMenu() (string, string, error) {
if len(m.menu) == 0 {
return "", "", fmt.Errorf("menu is empty")
}
@@ -93,14 +103,36 @@ func(m *MenuResource) ShiftMenu() (string, string, error) {
return r[0], r[1], nil
}
+// add available browse options.
+func(m *MenuResource) applyPage() error {
+ if m.canNext {
+ err := m.PutMenu(m.next[0], m.next[1])
+ if err != nil {
+ return err
+ }
+ }
+ if m.canPrev {
+ err := m.PutMenu(m.prev[0], m.prev[1])
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
// RenderMenu returns the full current state of the menu as a string.
//
// After this has been executed, the state of the menu will be empty.
func(m *MenuResource) RenderMenu() (string, error) {
+ err := m.applyPage()
+ if err != nil {
+ return "", err
+ }
+
r := ""
for true {
l := len(r)
- choice, title, err := m.ShiftMenu()
+ choice, title, err := m.shiftMenu()
if err != nil {
break
}
diff --git a/go/resource/state.go b/go/resource/state.go
@@ -20,10 +20,25 @@ func NewStateResource(st *state.State) *StateResource {
}
}
-func(s *StateResource) WithState(st *state.State) *StateResource {
- if s.st != nil {
+func(sr *StateResource) WithState(st *state.State) *StateResource {
+ if sr.st != nil {
panic("state already set")
}
- s.st = st
- return s
+ sr.st = st
+ return sr
+}
+
+func(sr *StateResource) SetMenuBrowse(selector string, title string, back bool) error {
+ var err error
+ next, prev := sr.st.Sides()
+
+ if back {
+ if prev {
+ err = sr.Resource.SetMenuBrowse(selector, title, true)
+ }
+ } else if next {
+ err = sr.Resource.SetMenuBrowse(selector, title, false)
+
+ }
+ return err
}
diff --git a/go/resource/state_test.go b/go/resource/state_test.go
@@ -12,3 +12,62 @@ func TestStateResourceInit(t *testing.T) {
_ = ToStateResource(rs).WithState(&st)
_ = NewStateResource(&st)
}
+
+func TestStateBrowse(t *testing.T) {
+ st := state.NewState(0)
+ st.Down("root")
+
+ rs := NewStateResource(&st)
+ rs.PutMenu("1", "foo")
+ rs.PutMenu("2", "bar")
+ err := rs.SetMenuBrowse("11", "next", false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = rs.SetMenuBrowse("22", "prev", true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ s, err := rs.RenderMenu()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ expect := `1:foo
+2:bar
+11:next`
+ if s != expect {
+ t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect, s)
+ }
+
+ idx, err := st.Next()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if idx != 1 {
+ t.Fatalf("expected idx 1, got %v", idx)
+ }
+ rs = NewStateResource(&st)
+ rs.PutMenu("1", "foo")
+ rs.PutMenu("2", "bar")
+ err = rs.SetMenuBrowse("11", "next", false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = rs.SetMenuBrowse("22", "prev", true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ s, err = rs.RenderMenu()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ expect = `1:foo
+2:bar
+11:next
+22:prev`
+ if s != expect {
+ t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect, s)
+ }
+}
diff --git a/go/state/state.go b/go/state/state.go
@@ -204,7 +204,7 @@ func(st State) WithOutputSize(outputSize uint32) State {
}
// Where returns the current active rendering symbol.
-func(st State) Where() (string, uint16) {
+func(st *State) Where() (string, uint16) {
if len(st.execPath) == 0 {
return "", 0
}
@@ -213,11 +213,13 @@ func(st State) Where() (string, uint16) {
}
// Next moves to the next sink page index.
-func(st State) Next() (uint16, error) {
+func(st *State) Next() (uint16, error) {
if len(st.execPath) == 0 {
return 0, fmt.Errorf("state root node not yet defined")
}
st.sizeIdx += 1
+ s, idx := st.Where()
+ log.Printf("next page for %s: %v", s, idx)
return st.sizeIdx, nil
}
@@ -232,6 +234,8 @@ func(st *State) Previous() (uint16, error) {
return 0, fmt.Errorf("already at first index")
}
st.sizeIdx -= 1
+ s, idx := st.Where()
+ log.Printf("previous page for %s: %v", s, idx)
return st.sizeIdx, nil
}
@@ -243,6 +247,7 @@ func(st *State) Sides() (bool, bool) {
return false, false
}
next := true
+ log.Printf("sides %v", st.sizeIdx)
if st.sizeIdx == 0 {
return next, false
}