Files
voice-cat/clients/windows/VoiceCat.App/Forms/MainForm.Designer.cs
Talon 725bd8e925 fix(windows): screen-reader accessibility for context menus and channel tree
- ContextMenuStrip: select first item on Opened so keyboard-invoked menus
  (Shift+F10 / Apps key) raise the UIA focus event immediately instead of
  staying silent until the first arrow key.
- Name the SplitContainer/SplitterPanel containers so screen readers announce
  orientation instead of a stack of anonymous pane nodes.
- Take the resize splitters out of the Tab cycle (TabStop = false) so focus
  moves control-to-control.
- RefreshChannelTree: restore keyboard focus and re-announce the current node
  after a Nodes.Clear()/rebuild, so the tree no longer loses focus when
  channels/users change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 13:34:26 +02:00

392 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

namespace VoiceCat.App.Forms;
partial class MainForm
{
private System.ComponentModel.IContainer components = null!;
// Menu bar + toolbar
private MenuStrip menuStrip = null!;
private ToolStrip toolStrip = null!;
private ToolStripButton tsbJoinVoice = null!;
private ToolStripButton tsbScreenShare = null!;
// Status bar
private Label lblStatus = null!;
// Main left/right split
private SplitContainer splitMain = null!;
// Left panel: channel tree on top, user list on bottom
private SplitContainer splitLeft = null!;
private Label lblChannels = null!;
private TreeView tvChannels = null!;
private Label lblUsers = null!;
private ListBox lstUsers = null!;
// Right panel: unified log, compose row, output volume
private TableLayoutPanel tblRight = null!;
private Label lblLog = null!;
private RichTextBox rtbLog = null!;
private TableLayoutPanel tblCompose = null!;
private TextBox txtCompose = null!;
private Button btnSend = null!;
private Label lblOutputVolume = null!;
private TrackBar trkOutputVolume = null!;
// Voice control panel (docked Bottom)
private Panel pnlVoice = null!;
private FlowLayoutPanel flpVoiceTop = null!;
private FlowLayoutPanel flpVoiceBottom = null!;
private CheckBox chkMute = null!;
private CheckBox chkDeafen = null!;
private RadioButton radioVad = null!;
private RadioButton radioPtt = null!;
private RadioButton radioAlwaysOn = null!;
private Label lblPttKey = null!;
private Button btnChangePtt = null!;
private Label lblInputDevice = null!;
private ComboBox cboInputDevice = null!;
private Button btnRefreshDevices = null!;
private Label lblLevel = null!;
private ProgressBar pbLevel = null!;
private Label lblVadThreshold = null!;
private TrackBar trkVadThreshold = null!;
protected override void Dispose(bool disposing)
{
if (disposing) components?.Dispose();
base.Dispose(disposing);
}
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
lblStatus = new Label();
splitMain = new SplitContainer();
splitLeft = new SplitContainer();
lblChannels = new Label();
tvChannels = new TreeView();
lblUsers = new Label();
lstUsers = new ListBox();
tblRight = new TableLayoutPanel();
lblLog = new Label();
rtbLog = new RichTextBox();
tblCompose = new TableLayoutPanel();
txtCompose = new TextBox();
btnSend = new Button();
lblOutputVolume = new Label();
trkOutputVolume = new TrackBar();
pnlVoice = new Panel();
flpVoiceTop = new FlowLayoutPanel();
flpVoiceBottom = new FlowLayoutPanel();
chkMute = new CheckBox();
chkDeafen = new CheckBox();
radioVad = new RadioButton();
radioPtt = new RadioButton();
radioAlwaysOn = new RadioButton();
lblPttKey = new Label();
btnChangePtt = new Button();
lblInputDevice = new Label();
cboInputDevice = new ComboBox();
btnRefreshDevices = new Button();
lblLevel = new Label();
pbLevel = new ProgressBar();
lblVadThreshold = new Label();
trkVadThreshold = new TrackBar();
menuStrip = new MenuStrip();
toolStrip = new ToolStrip();
tsbJoinVoice = new ToolStripButton();
tsbScreenShare = new ToolStripButton();
// ── Status label ──────────────────────────────────────────────────────
lblStatus.AccessibleName = "Connection status";
lblStatus.Dock = DockStyle.Top;
lblStatus.AutoSize = true;
lblStatus.Padding = new Padding(6, 4, 6, 4);
lblStatus.TabIndex = 0;
lblStatus.Text = "Connecting...";
// ── Channel tree ──────────────────────────────────────────────────────
lblChannels.Text = "Channels:";
lblChannels.Dock = DockStyle.Top;
lblChannels.AutoSize = true;
lblChannels.Padding = new Padding(4, 4, 4, 2);
tvChannels.AccessibleName = "Channel list";
tvChannels.AccessibleDescription =
"Double-click or press Enter to join a channel. " +
"Channels marked [password] require a password.";
tvChannels.Dock = DockStyle.Fill;
tvChannels.HideSelection = false;
tvChannels.TabIndex = 0;
// ── User list ─────────────────────────────────────────────────────────
lblUsers.Text = "Users in channel:";
lblUsers.Dock = DockStyle.Top;
lblUsers.AutoSize = true;
lblUsers.Padding = new Padding(4, 4, 4, 2);
lstUsers.AccessibleName = "Users in current channel";
lstUsers.AccessibleDescription =
"People in the same channel. Double-click or press Enter for per-user volume settings. " +
"Talking users are marked (talking).";
lstUsers.Dock = DockStyle.Fill;
lstUsers.TabIndex = 1;
// ── Left split (channels top, users bottom) ───────────────────────────
splitLeft.Orientation = Orientation.Horizontal;
splitLeft.Dock = DockStyle.Fill;
splitLeft.Panel1MinSize = 100;
splitLeft.Panel2MinSize = 80;
splitLeft.TabIndex = 0;
// Keep the resize splitter out of the Tab cycle so focus moves control-to-control.
splitLeft.TabStop = false;
// Name the otherwise-anonymous "pane" containers so screen readers announce
// orientation instead of a stack of unnamed panes.
splitLeft.AccessibleName = "Channels and users";
splitLeft.Panel1.AccessibleName = "Channels";
splitLeft.Panel2.AccessibleName = "Users";
splitLeft.Panel1.Controls.Add(tvChannels);
splitLeft.Panel1.Controls.Add(lblChannels);
splitLeft.Panel2.Controls.Add(lstUsers);
splitLeft.Panel2.Controls.Add(lblUsers);
// ── Unified log ───────────────────────────────────────────────────────
lblLog.Text = "Chat & Activity:";
lblLog.AutoSize = true;
lblLog.Padding = new Padding(2, 2, 2, 1);
rtbLog.AccessibleName = "Chat and activity log";
rtbLog.AccessibleDescription = "Combined history of chat messages (normal) and activity events (gray).";
rtbLog.Dock = DockStyle.Fill;
rtbLog.ReadOnly = true;
rtbLog.ScrollBars = RichTextBoxScrollBars.Vertical;
rtbLog.BackColor = SystemColors.Window;
rtbLog.TabIndex = 0;
// ── Compose row ───────────────────────────────────────────────────────
txtCompose.AccessibleName = "Message text";
txtCompose.AccessibleDescription = "Type your channel message. Press Enter or click Send to send.";
txtCompose.Dock = DockStyle.Fill;
txtCompose.TabIndex = 1;
btnSend.Text = "&Send";
btnSend.Dock = DockStyle.Fill;
btnSend.TabIndex = 2;
tblCompose.ColumnCount = 2;
tblCompose.RowCount = 1;
tblCompose.Dock = DockStyle.Fill;
tblCompose.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
tblCompose.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 68F));
tblCompose.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
tblCompose.Padding = new Padding(0, 3, 0, 0);
tblCompose.Controls.Add(txtCompose, 0, 0);
tblCompose.Controls.Add(btnSend, 1, 0);
// ── Output volume row ─────────────────────────────────────────────────
lblOutputVolume.Text = "Output volume:";
lblOutputVolume.AutoSize = true;
lblOutputVolume.Padding = new Padding(2, 6, 4, 0);
trkOutputVolume.AccessibleName = "Output volume";
trkOutputVolume.AccessibleDescription = "Global playback volume for all incoming audio.";
trkOutputVolume.Minimum = 0;
trkOutputVolume.Maximum = 100;
trkOutputVolume.Value = 80;
trkOutputVolume.TickFrequency = 10;
trkOutputVolume.SmallChange = 1;
trkOutputVolume.LargeChange = 10;
trkOutputVolume.Dock = DockStyle.Fill;
trkOutputVolume.TabIndex = 3;
// ── Right table layout ────────────────────────────────────────────────
tblRight.ColumnCount = 1;
tblRight.RowCount = 5;
tblRight.Dock = DockStyle.Fill;
tblRight.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
tblRight.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // row 0: lblLog
tblRight.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); // row 1: rtbLog
tblRight.RowStyles.Add(new RowStyle(SizeType.Absolute, 34F)); // row 2: compose
tblRight.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // row 3: vol label
tblRight.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F)); // row 4: vol slider
tblRight.Controls.Add(lblLog, 0, 0);
tblRight.Controls.Add(rtbLog, 0, 1);
tblRight.Controls.Add(tblCompose, 0, 2);
tblRight.Controls.Add(lblOutputVolume, 0, 3);
tblRight.Controls.Add(trkOutputVolume, 0, 4);
// ── Main split ────────────────────────────────────────────────────────
splitMain.Dock = DockStyle.Fill;
splitMain.Panel1MinSize = 150;
splitMain.TabIndex = 1;
splitMain.TabStop = false;
splitMain.AccessibleName = "Main";
splitMain.Panel1.AccessibleName = "Channels and users";
splitMain.Panel2.AccessibleName = "Chat and activity";
splitMain.Panel1.Controls.Add(splitLeft);
splitMain.Panel2.Controls.Add(tblRight);
// ── Voice control panel ───────────────────────────────────────────────
chkMute.Text = "&Mute mic";
chkMute.AutoSize = true;
chkMute.Enabled = false;
chkMute.Margin = new Padding(0, 4, 6, 0);
chkMute.TabIndex = 1;
chkDeafen.Text = "&Deafen";
chkDeafen.AutoSize = true;
chkDeafen.Enabled = false;
chkDeafen.Margin = new Padding(0, 4, 12, 0);
chkDeafen.TabIndex = 2;
var lblMode = new Label { Text = "Mode:", AutoSize = true, Margin = new Padding(0, 5, 4, 0) };
radioVad.Text = "&Voice activation";
radioVad.AutoSize = true;
radioVad.Checked = true;
radioVad.Enabled = false;
radioVad.Margin = new Padding(0, 4, 6, 0);
radioVad.TabIndex = 3;
radioPtt.Text = "&Push to talk";
radioPtt.AutoSize = true;
radioPtt.Enabled = false;
radioPtt.Margin = new Padding(0, 4, 4, 0);
radioPtt.TabIndex = 4;
radioAlwaysOn.Text = "A&lways on";
radioAlwaysOn.AutoSize = true;
radioAlwaysOn.Enabled = false;
radioAlwaysOn.Margin = new Padding(0, 4, 12, 0);
radioAlwaysOn.TabIndex = 5;
lblPttKey.Text = "(F8)";
lblPttKey.AutoSize = true;
lblPttKey.Margin = new Padding(2, 5, 4, 0);
lblPttKey.Visible = false;
btnChangePtt.Text = "Change key...";
btnChangePtt.AutoSize = true;
btnChangePtt.Margin = new Padding(0, 2, 0, 0);
btnChangePtt.Visible = false;
btnChangePtt.TabIndex = 6;
flpVoiceTop.Dock = DockStyle.Top;
flpVoiceTop.Height = 34;
flpVoiceTop.AutoSize = false;
flpVoiceTop.Padding = new Padding(4, 2, 4, 0);
flpVoiceTop.Controls.Add(chkMute);
flpVoiceTop.Controls.Add(chkDeafen);
flpVoiceTop.Controls.Add(lblMode);
flpVoiceTop.Controls.Add(radioVad);
flpVoiceTop.Controls.Add(radioPtt);
flpVoiceTop.Controls.Add(radioAlwaysOn);
flpVoiceTop.Controls.Add(lblPttKey);
flpVoiceTop.Controls.Add(btnChangePtt);
// Bottom row: device picker + level meter
lblInputDevice.Text = "Input:";
lblInputDevice.AutoSize = true;
lblInputDevice.Margin = new Padding(0, 5, 4, 0);
cboInputDevice.AccessibleName = "Input device";
cboInputDevice.AccessibleDescription = "Select which microphone or audio device to use.";
cboInputDevice.DropDownStyle = ComboBoxStyle.DropDownList;
cboInputDevice.Width = 200;
cboInputDevice.Margin = new Padding(0, 2, 4, 0);
cboInputDevice.TabIndex = 7;
btnRefreshDevices.Text = "Re&fresh";
btnRefreshDevices.AutoSize = true;
btnRefreshDevices.Margin = new Padding(0, 2, 12, 0);
btnRefreshDevices.TabIndex = 8;
lblLevel.Text = "Level:";
lblLevel.AutoSize = true;
lblLevel.Margin = new Padding(0, 5, 4, 0);
pbLevel.AccessibleName = "Microphone level";
pbLevel.AccessibleDescription = "Current input level from the microphone.";
pbLevel.Width = 120;
pbLevel.Height = 16;
pbLevel.Maximum = 100;
pbLevel.Margin = new Padding(0, 6, 0, 0);
pbLevel.Style = ProgressBarStyle.Continuous;
pbLevel.TabStop = false;
lblVadThreshold.Text = "Sensitivity:";
lblVadThreshold.AutoSize = true;
lblVadThreshold.Margin = new Padding(12, 5, 4, 0);
lblVadThreshold.Visible = true;
trkVadThreshold.AccessibleName = "VAD sensitivity";
trkVadThreshold.AccessibleDescription =
"Voice detection sensitivity. Higher = more sensitive (triggers on quieter sounds). " +
"Range 1100; default 25.";
trkVadThreshold.Minimum = 1;
trkVadThreshold.Maximum = 100;
trkVadThreshold.Value = 76;
trkVadThreshold.TickFrequency = 10;
trkVadThreshold.SmallChange = 1;
trkVadThreshold.LargeChange = 10;
trkVadThreshold.Width = 120;
trkVadThreshold.Margin = new Padding(0, 2, 0, 0);
trkVadThreshold.TabIndex = 9;
trkVadThreshold.Visible = true;
flpVoiceBottom.Dock = DockStyle.Fill;
flpVoiceBottom.Padding = new Padding(4, 0, 4, 2);
flpVoiceBottom.Controls.Add(lblInputDevice);
flpVoiceBottom.Controls.Add(cboInputDevice);
flpVoiceBottom.Controls.Add(btnRefreshDevices);
flpVoiceBottom.Controls.Add(lblLevel);
flpVoiceBottom.Controls.Add(pbLevel);
flpVoiceBottom.Controls.Add(lblVadThreshold);
flpVoiceBottom.Controls.Add(trkVadThreshold);
pnlVoice.Dock = DockStyle.Bottom;
pnlVoice.Height = 68;
pnlVoice.BorderStyle = BorderStyle.FixedSingle;
pnlVoice.Padding = new Padding(0);
pnlVoice.Controls.Add(flpVoiceBottom); // Fill — added first
pnlVoice.Controls.Add(flpVoiceTop); // Top — added last
// ── Toolbar ───────────────────────────────────────────────────────────
tsbJoinVoice.Text = "Join Voice";
tsbJoinVoice.DisplayStyle = ToolStripItemDisplayStyle.Text;
tsbJoinVoice.CheckOnClick = false;
tsbScreenShare.Text = "Share Screen Audio";
tsbScreenShare.DisplayStyle = ToolStripItemDisplayStyle.Text;
tsbScreenShare.CheckOnClick = false;
toolStrip.Dock = DockStyle.Top;
toolStrip.Items.Add(tsbJoinVoice);
toolStrip.Items.Add(new ToolStripSeparator());
toolStrip.Items.Add(tsbScreenShare);
toolStrip.TabIndex = 1;
toolStrip.AccessibleName = "Toolbar";
// ── Menu strip ────────────────────────────────────────────────────────
menuStrip.AccessibleName = "Main menu";
menuStrip.Dock = DockStyle.Top;
menuStrip.TabIndex = 0;
MainMenuStrip = menuStrip;
// ── Form ──────────────────────────────────────────────────────────────
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(960, 680);
MinimumSize = new Size(700, 540);
KeyPreview = true;
Controls.Add(splitMain); // DockStyle.Fill
Controls.Add(pnlVoice); // DockStyle.Bottom
Controls.Add(lblStatus); // DockStyle.Top
Controls.Add(toolStrip); // DockStyle.Top (above status)
Controls.Add(menuStrip); // DockStyle.Top (topmost)
StartPosition = FormStartPosition.CenterScreen;
Text = "VoiceCat";
}
}