Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 118 additions & 2 deletions UI/MainForm.Mode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,43 @@ private void InitializeModeChrome()
}
};

_modeLanguageSelector = new ComboBox
{
DropDownStyle = ComboBoxStyle.DropDownList,
Width = ScaleX(110),
Margin = new Padding(0, 4, 8, 4),
AccessibleName = "Quick language selector"
};
_modeLanguageSelector.SelectedIndexChanged += (s, e) =>
{
if (_syncingModeLanguageSelector || _modeLanguageSelector.SelectedItem is not LangItem selected) return;

for (int i = 0; i < _languageSelector.Items.Count; i++)
{
if (_languageSelector.Items[i] is LangItem item &&
item.Code.Equals(selected.Code, StringComparison.OrdinalIgnoreCase))
{
_languageSelector.SelectedIndex = i;
break;
}
}
};

var rightActions = new FlowLayoutPanel
{
AutoSize = true,
WrapContents = false,
FlowDirection = FlowDirection.LeftToRight,
Margin = new Padding(0),
Padding = new Padding(0)
};
rightActions.Controls.Add(_modeLanguageSelector);
rightActions.Controls.Add(_modeSwitchButton);

leftStack.Controls.Add(_modeStatusLabel, 0, 0);
leftStack.Controls.Add(_modeHintLabel, 0, 1);
layout.Controls.Add(leftStack, 0, 0);
layout.Controls.Add(_modeSwitchButton, 1, 0);
layout.Controls.Add(rightActions, 1, 0);
_modeChrome.Controls.Add(layout);

Controls.Add(_modeChrome);
Expand All @@ -94,10 +127,30 @@ private void EnsureModeChromeDockOrder()
{
if (_modeChrome == null) return;

_modeChrome.SendToBack();
// Keep the mode chrome above the main content and reserve layout space.
_modeChrome.BringToFront();
Controls.SetChildIndex(_modeChrome, 0);
ApplyModeChromeLayoutCompensation();
PerformLayout();
}

private void ApplyModeChromeLayoutCompensation()
{
if (_mainVerticalSplitHost == null) return;

int topOffset = (_modeChrome != null && _modeChrome.Visible)
? _modeChrome.Bottom
: 0;

_mainVerticalSplitHost.Dock = DockStyle.None;
_mainVerticalSplitHost.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
_mainVerticalSplitHost.Location = new Point(0, topOffset);
_mainVerticalSplitHost.Size = new Size(
Math.Max(200, ClientSize.Width),
Math.Max(160, ClientSize.Height - topOffset));
_mainVerticalSplitHost.PerformLayout();
}

private void EnsureModeSelectorOverlay()
{
if (_modeSelectorOverlay != null) return;
Expand Down Expand Up @@ -140,6 +193,7 @@ private void ShowModeSelector()
_modeSelectorOverlay.Visible = true;
_modeSelectorOverlay.BringToFront();
if (_modeChrome != null) _modeChrome.Visible = false;
ApplyModeChromeLayoutCompensation();
_modeSelectorOverlay.Focus();
}

Expand All @@ -154,6 +208,7 @@ private void HideModeSelector()
_modeChrome.Visible = true;
EnsureModeChromeDockOrder();
}
ApplyModeChromeLayoutCompensation();
}

private void ToggleUiMode()
Expand Down Expand Up @@ -270,6 +325,7 @@ private void ApplyUiMode(UiMode mode, bool persist)
}

HideModeSelector();
ApplyModeChromeLayoutCompensation();
UpdateModePresentation();

BeginInvoke(new Action(() =>
Expand Down Expand Up @@ -326,6 +382,8 @@ private void UpdateModePresentation()
_modeSwitchButton.Text = TMode("Mode_Switch_Button", "Switch mode");
}

SyncModeLanguageSelector();

if (_modeChrome != null)
{
bool dark = _darkModeToggle.Checked;
Expand All @@ -343,6 +401,11 @@ private void UpdateModePresentation()
_modeSwitchButton.BackColor = dark ? Color.FromArgb(54, 62, 72) : Color.White;
_modeSwitchButton.ForeColor = dark ? Color.WhiteSmoke : Color.FromArgb(28, 28, 28);
}
if (_modeLanguageSelector != null)
{
_modeLanguageSelector.BackColor = dark ? Color.FromArgb(54, 62, 72) : Color.White;
_modeLanguageSelector.ForeColor = dark ? Color.WhiteSmoke : Color.FromArgb(28, 28, 28);
}
}

_modeSelectorOverlay?.UpdatePresentation(_translationService, _darkModeToggle.Checked);
Expand All @@ -358,6 +421,47 @@ private void SetVisible(bool visible, params Control[] controls)
}
}

private void SyncModeLanguageSelector()
{
if (_modeLanguageSelector == null) return;

_syncingModeLanguageSelector = true;
try
{
_modeLanguageSelector.Items.Clear();
foreach (var item in _languageSelector.Items)
{
if (item is LangItem lang)
{
_modeLanguageSelector.Items.Add(lang);
}
}

if (_languageSelector.SelectedItem is LangItem selected)
{
for (int i = 0; i < _modeLanguageSelector.Items.Count; i++)
{
if (_modeLanguageSelector.Items[i] is LangItem lang &&
lang.Code.Equals(selected.Code, StringComparison.OrdinalIgnoreCase))
{
_modeLanguageSelector.SelectedIndex = i;
break;
}
}
}
else if (_modeLanguageSelector.Items.Count > 0)
{
_modeLanguageSelector.SelectedIndex = 0;
}

_modeLanguageSelector.Enabled = _modeLanguageSelector.Items.Count > 0;
}
finally
{
_syncingModeLanguageSelector = false;
}
}

private void EnsureProfessionalCoreControlsVisible()
{
EnsureControlSectionExpanded("_topControls");
Expand All @@ -371,6 +475,18 @@ private void EnsureControlSectionExpanded(string controlName)
if (control == null) return;

control.Visible = true;
if (control is FlowLayoutPanel flow)
{
flow.AutoSize = true;
flow.AutoSizeMode = AutoSizeMode.GrowAndShrink;
flow.WrapContents = true;
flow.AutoScroll = true;
foreach (Control child in flow.Controls)
{
child.Visible = true;
}
flow.PerformLayout();
}

var current = control.Parent;
while (current != null)
Expand Down
12 changes: 12 additions & 0 deletions UI/MainForm.Patient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ private void EnsurePatientShell()
_patientShell.RunCheckRequested += () => CheckButton_Click(this, EventArgs.Empty);
_patientShell.StepChanged += OnPatientStepChanged;
_patientShell.RestartRequested += RestartPatientWizard;
_patientShell.ModeSwitchRequested += OnPatientModeSwitchRequested;

_mainVerticalSplitHost.Panel1.Controls.Add(_patientShell);
_patientShell.BringToFront();
Expand Down Expand Up @@ -331,5 +332,16 @@ private void RestartPatientWizard()
_settingsService.Save();
}
}

private void OnPatientModeSwitchRequested()
{
if (_settingsService?.Settings.UiMode == null)
{
ShowModeSelector();
return;
}

ToggleUiMode();
}
}
}
12 changes: 12 additions & 0 deletions UI/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ public GroupHeader(string canonicalCategory, string display)
private Panel? _modeChrome;
private Label? _modeStatusLabel;
private Label? _modeHintLabel;
private ComboBox? _modeLanguageSelector;
private Button? _modeSwitchButton;
private bool _syncingModeLanguageSelector;
private UiMode? _activeUiMode;
// UI: collapse toggle
private Button? _collapseBtn;
Expand Down Expand Up @@ -227,6 +229,7 @@ public MainForm()
vs.SplitterDistance = targetV;
}
ApplyProfessionalShellLayout();
ApplyModeChromeLayoutCompensation();
}
catch { }
_filterBox.Focus();
Expand All @@ -251,6 +254,7 @@ public MainForm()
vs.SplitterDistance = target;
}
ApplyProfessionalShellLayout();
ApplyModeChromeLayoutCompensation();
}
catch { }
};
Expand Down Expand Up @@ -507,10 +511,12 @@ private void InitializeLayout()
{
Dock = DockStyle.Top,
AutoSize = true,
AutoSizeMode = AutoSizeMode.GrowAndShrink,
WrapContents = true,
AutoScroll = true,
FlowDirection = FlowDirection.LeftToRight,
Padding = new Padding(3),
Margin = new Padding(0),
Name = "_topControls"
};
var vitalsRow = new FlowLayoutPanel { Dock = DockStyle.Fill, AutoSize = true, WrapContents = true, Name = "_vitalsRow" };
Expand Down Expand Up @@ -826,6 +832,12 @@ private void InitializeLayout()
_lblPerf.AutoSize = true; _lblPerf.Padding = new Padding(10,6,0,0); _lblPerf.Text = ""; _lblPerf.AccessibleName = "Performance timing"; topControls.Controls.Add(_lblPerf);
// Top bar (models etc.)
rightPanel.Controls.Add(topControls, 0, 0);
topControls.Resize += (s, e) =>
{
// Keep wrapping stable across DPI/scaling changes.
int maxWidth = Math.Max(240, rightPanel.ClientSize.Width - SystemInformation.VerticalScrollBarWidth - 6);
topControls.MaximumSize = new Size(maxWidth, 0);
};
// Vitals row
vitalsRow.Controls.Add(_lblVitals);
vitalsRow.Controls.Add(_lblTemp);
Expand Down
11 changes: 11 additions & 0 deletions UI/PatientShell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public SymptomItem(string canonical, string display)
private readonly Button _backButton = new();
private readonly Button _nextButton = new();
private readonly Button _restartButton = new();
private readonly Button _switchModeButton = new();

private TranslationService? _translationService;
private bool _darkMode;
Expand All @@ -95,6 +96,7 @@ public SymptomItem(string canonical, string display)
public event Action<PatientVitalsState>? VitalsChanged;
public event Action? RunCheckRequested;
public event Action? RestartRequested;
public event Action? ModeSwitchRequested;

public int CurrentStep => _currentStep;
public FlowLayoutPanel ResultCardsHost => _resultsCards;
Expand Down Expand Up @@ -134,6 +136,7 @@ public void UpdatePresentation(TranslationService? translationService, bool dark

_backButton.Text = T("Patient_Back", "Back");
_restartButton.Text = T("Patient_Restart", "Start over");
_switchModeButton.Text = T("Mode_Switch_Button", "Switch mode");
_nextButton.Text = _currentStep == 3
? T("Patient_RunCheck", "Show results")
: T("Patient_Next", "Next");
Expand Down Expand Up @@ -330,9 +333,16 @@ private void BuildLayout()
_restartButton.Padding = new Padding(12, 7, 12, 7);
_restartButton.Click += (s, e) => RestartRequested?.Invoke();

_switchModeButton.AutoSize = true;
_switchModeButton.FlatStyle = FlatStyle.Flat;
_switchModeButton.Padding = new Padding(12, 7, 12, 7);
_switchModeButton.AccessibleName = "Switch mode";
_switchModeButton.Click += (s, e) => ModeSwitchRequested?.Invoke();

_navigationBar.Controls.Add(_nextButton);
_navigationBar.Controls.Add(_backButton);
_navigationBar.Controls.Add(_restartButton);
_navigationBar.Controls.Add(_switchModeButton);

_root.Controls.Add(_header, 0, 0);
_root.Controls.Add(_contentHost, 0, 1);
Expand Down Expand Up @@ -718,6 +728,7 @@ private void ApplyTheme()

StyleNavigationButton(_backButton, secondary: true);
StyleNavigationButton(_restartButton, secondary: true);
StyleNavigationButton(_switchModeButton, secondary: true);
StyleNavigationButton(_nextButton, secondary: false);
}

Expand Down
Loading