// Fenrir console screen reader. // Copyright (c) 2026 Storm Dragon // SPDX-License-Identifier: GPL-3.0-or-later // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation, either version 3 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU General Public License along with // this program. If not, see . package interaction import ( "strconv" "git.stormux.org/storm/fenrir/internal/i18n" ) func (s *Session) Open() string { return i18n.T(s.form.Title) + ". " + s.Describe() } func (s *Session) Describe() string { tab := s.form.Tabs[s.tab] if s.focus == -1 { return i18n.Format("{0} tab", i18n.T(tab.Label)) } control := tab.Controls[s.focus] label := i18n.T(control.Label) switch control.Kind { case CheckBox: state := "unchecked" if control.Checked { state = "checked" } return label + " " + i18n.T(state) case Number: return label + " " + strconv.FormatFloat(control.Number, 'f', -1, 64) case Entry: return i18n.Format("{0} entry {1}", label, control.Text) case List: return label + " " + control.Items[control.Selected] case Grid: 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: return i18n.Format("{0} button", label) } return label } func describe_choice(control Control) string { choice := control.Choices[control.Selected] text := choice_label(choice) if choice.Unavailable != "" { text += ". " + i18n.T("unavailable") + ": " + choice.Unavailable } return text } func choice_label(choice Choice) string { if choice.Literal { return choice.Label } return i18n.T(choice.Label) } func (s *Session) focused_group() string { if s.focus < 0 { return "" } return s.form.Tabs[s.tab].Controls[s.focus].Group } func (s *Session) describe_focus(previousGroup string) string { if group := s.focused_group(); group != "" && group != previousGroup { return i18n.T(group) + ". " + s.Describe() } return s.Describe() }