Preferences tab added for the internal UI.

This commit is contained in:
Storm Dragon committed 2026-10-29 02:46:41 -04:00
1 parent cf95b17e5d
commit 6fc3416a1b
27 files changed
+858 -434

No files matched your search

+16 -5
View File
@@ -32,12 +32,23 @@ func (c *Control) filter_grid() {
}
}
func describe_grid(c Control) string {
func (s *Session) describe_grid(c Control) string {
matches := c.grid_matches()
for position, index := range matches {
if index == c.Selected {
return i18n.Format("{0}. row {1}, column {2}. {3} of {4}",
choice_label(c.Choices[index]), strconv.Itoa(position/c.Columns+1), strconv.Itoa(position%c.Columns+1), strconv.Itoa(position+1), strconv.Itoa(len(matches)))
label := choice_label(c.Choices[index])
row, column := strconv.Itoa(position/c.Columns+1), strconv.Itoa(position%c.Columns+1)
item, total := strconv.Itoa(position+1), strconv.Itoa(len(matches))
switch {
case s.announceGridCoordinates && s.announceItemPosition:
return i18n.Format("{0}. row {1}, column {2}. {3} of {4}", label, row, column, item, total)
case s.announceGridCoordinates:
return i18n.Format("{0}. row {1}, column {2}", label, row, column)
case s.announceItemPosition:
return i18n.Format("{0}. {1} of {2}", label, item, total)
default:
return label
}
}
}
return i18n.T("No matches")
@@ -72,7 +83,7 @@ func (s *Session) grid(c *Control, key Key) Result {
if c.Text != "" {
query = i18n.Format("Search {0}", c.Text)
}
return Result{Speech: query + ". " + describe_grid(*c)}
return Result{Speech: query + ". " + s.describe_grid(*c)}
}
matches := c.grid_matches()
if len(matches) == 0 {
@@ -113,5 +124,5 @@ func (s *Session) grid(c *Control, key Key) Result {
return Result{}
}
c.Selected = matches[position]
return Result{Speech: describe_grid(*c)}
return Result{Speech: s.describe_grid(*c)}
}
+35
View File
@@ -91,3 +91,38 @@ func TestGridValidation(t *testing.T) {
t.Fatal("duplicate values accepted")
}
}
func TestGridSpeechDetailOptions(t *testing.T) {
for _, trial := range []struct {
coordinates, position bool
want, filtered string
}{
{true, true, "Bat. row 1, column 2. 2 of 7", "Japan. row 1, column 2. 2 of 2"},
{true, false, "Bat. row 1, column 2", "Japan. row 1, column 2"},
{false, true, "Bat. 2 of 7", "Japan. 2 of 2"},
{false, false, "Bat", "Japan"},
} {
session, err := New_session(grid_form())
if err != nil {
t.Fatal(err)
}
session.Configure_grid(trial.coordinates, trial.position)
session.Handle(Key{Name: "tab"})
if got := session.Handle(Key{Name: "right"}).Speech; got != trial.want {
t.Fatalf("%+v: %q", trial, got)
}
if got := session.Describe(); got != "Items grid. "+trial.want {
t.Fatal(got)
}
session.Handle(Key{Text: "j"})
if got := session.Handle(Key{Name: "right"}).Speech; got != trial.filtered {
t.Fatal(got)
}
if got := session.Handle(Key{Name: "enter"}).Action; got != "choose" {
t.Fatal(got)
}
if got := session.Handle(Key{Text: "zzz"}).Speech; got != "Search jzzz. No matches" {
t.Fatal(got)
}
}
}
+1 -1
View File
@@ -46,7 +46,7 @@ func (s *Session) Describe() string {
case List:
return label + " " + control.Items[control.Selected]
case Grid:
return i18n.Format("{0} grid. {1}", label, describe_grid(control))
return i18n.Format("{0} grid. {1}", label, s.describe_grid(control))
case ComboBox:
return i18n.Format("{0} combo box {1}", label, describe_choice(control))
case Button:
+10 -4
View File
@@ -25,9 +25,10 @@ import (
)
type Session struct {
form Form
tab, focus, cursor int // focus -1 is the tab strip.
selectAll bool
form Form
tab, focus, cursor int // focus -1 is the tab strip.
announceGridCoordinates, announceItemPosition bool
selectAll bool
}
func New_session(form Form) (*Session, error) {
@@ -90,7 +91,12 @@ func New_session(form Form) (*Session, error) {
}
}
}
return &Session{form: form, focus: -1}, nil
return &Session{form: form, focus: -1, announceGridCoordinates: true, announceItemPosition: true}, nil
}
// Configure_grid controls spoken detail without changing grid navigation or filtering.
func (s *Session) Configure_grid(coordinates, position bool) {
s.announceGridCoordinates, s.announceItemPosition = coordinates, position
}
// Values returns a copy suitable for validation or submission by the host.