using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Gtk;
using UI = Gtk.Builder.ObjectAttribute;
using System.Runtime.InteropServices;
public class MainWindow : Window
{
// ---- stack + pages (new all-in-one glade) ----
[UI] private Notebook RootNoteBook = null;
private const int PageSplash = 0;
private const int PageSettings = 1;
// ---- splash page widgets ----
[UI] private Button Option1Button = null;
[UI] private Button Option2Button = null;
[UI] private Button Option3Button = null;
// [UI] private Switch LanguageSwitch = null;
[UI] private ToggleButton LanguageToggle = null;
[UI] private Label LanguageLabel = null;
[UI] private Button CloseButton = null;
[UI] private Button SettingButton = null;
[UI] private Image ConnectionIcon = null; // was GtkIconView in the old glade
private CssProvider _scaleCssProvider;
// private CssProvider _languageCssProvider;
private int _lastAppliedWidth = -1;
private const int BaseWidth = 1920;
private const int BaseHeight = 1080;
// private const string EngCssPath = "lang_eng.css";
// private const string JpnCssPath = "lang_jpn.css";
// private Dictionary<string, string> _engText;
// private Dictionary<string, string> _jpnText;
// private Dictionary<string, Button> _buttonsById;
private bool _connected;
private readonly ArduinoConnection _arduino = new ArduinoConnection();
internal SettingsWindow _settingsWindow;
internal Language _Language;
public MainWindow() : this(CreateBuilder()) { }
private static Builder CreateBuilder()
{
var builder = new Builder();
builder.AddFromFile("homepageall.glade");
return builder;
}
private MainWindow(Builder builder) : base(builder.GetObject("Root").Handle)
{
builder.Autoconnect(this);
_scaleCssProvider = new CssProvider();
// _languageCssProvider = new CssProvider();
StyleContext.AddProviderForScreen(Gdk.Screen.Default, _scaleCssProvider, 600);
// StyleContext.AddProviderForScreen(Gdk.Screen.Default, _Language._languageCssProvider, 600);
// make it full screen
this.Fullscreen();
// RootStack.TransitionType = StackTransitionType.None;
// RootStack.TransitionType = StackTransitionType.SlideLeftRight;
// RootStack.TransitionDuration = 150;
Option1Button.Clicked += OnNormalSessionClicked;
Option2Button.Clicked += OnPositionRecordingClicked;
Option3Button.Clicked += OnExamModeClicked;
CloseButton.Clicked += OnCloseClicked;
SettingButton.Clicked += OnSettingClicked;
// LanguageSwitch.AddNotification("active", OnLanguageSwitchNotify);
LanguageToggle.Toggled += OnLanguageToggled;
DeleteEvent += OnDeleteEvent;
SizeAllocated += OnWindowSizeAllocated;
_arduino.ConnectionChanged += OnArduinoConnectionChanged;
// // _buttonsById = new Dictionary<string, Button>
// // {
// // { "Option1Button", Option1Button },
// // { "Option2Button", Option2Button },
// // { "Option3Button", Option3Button },
// // { "CloseButton", CloseButton },
// // { "SettingButton", SettingButton },
// // };
// // CSS ID selectors (#Option1Button etc.) need the widget Name set explicitly
// foreach (var kvp in _buttonsById)
// kvp.Value.Name = kvp.Key;
// // _engText = LoadButtonText("info_eng.csv");
// // _jpnText = LoadButtonText("info_jpn.csv");
// _Language = new Language(_buttonsById,LanguageLabel);
// // _Language.ApplyLanguage(LanguageSwitch.Active);
_Language = new Language(LanguageToggle.Active);
_Language.Register("Option1Button", Option1Button);
_Language.Register("Option2Button", Option2Button);
_Language.Register("Option3Button", Option3Button);
_Language.Register("CloseButton", CloseButton);
_Language.Register("SettingButton", SettingButton);
_Language.Register("LanguageLabel", LanguageLabel);
_Language.Register("LanguageToggle", LanguageToggle);
_Language.RegisterDynamic("ConnectionIcon", ConnectionIcon);
_settingsWindow = new SettingsWindow(builder, _arduino, _Language);
_settingsWindow.BackRequested += OnSettingsClosed;
_Language.Changed += (s, e) => OnArduinoConnectionChanged(_connected);
_Language.Apply(LanguageToggle.Active);
// // single source of truth: the toggle drives both pages
// ApplyLanguageEverywhere(LanguageToggle.Active);
RootNoteBook.ShowTabs = false;
RootNoteBook.ShowBorder = false;
RootNoteBook.CurrentPage = PageSplash;
OnArduinoConnectionChanged(false);
}
// ---------- settings panel ----------
private void OnSettingClicked(object sender, EventArgs e)
{
// if (_settingsWindow == null)
// {
// // _settingsWindow = new SettingsWindow(_arduino);
// // _settingsWindow.BackRequested += OnSettingsClosed;
// // _settingsWindow.ShowAll(); // build it fullscreen once, up front
// // _settingsWindow.Fullscreen();
// RootNoteBook.CurrentPage = PageSettings;
// }
// _settingsWindow.ShowAll();
// _settingsWindow.Present();
// this.Hide();
RootNoteBook.CurrentPage = PageSettings;
}
private void OnSettingsClosed(object sender, EventArgs e)
{
// this.ShowAll();
// this.Present();
// _settingsWindow.Hide();
RootNoteBook.CurrentPage = PageSplash;
}
private void OnArduinoConnectionChanged(bool connected)
{
_connected = connected;
if (ConnectionIcon == null) return;
ConnectionIcon.SetFromIconName(
connected ? "network-transmit-receive" : "network-offline",
IconSize.Dnd);
ConnectionIcon.TooltipText = connected
? _Language.Format("ConnectionIcon.Connected", _arduino.PortName)
: _Language["ConnectionIcon.Disconnected"];
}
// ---------- localisation ----------
// private Dictionary<string, string> LoadButtonText(string path)
// {
// var result = new Dictionary<string, string>();
// if (!File.Exists(path))
// {
// Console.WriteLine($"Warning: text file not found: {path}");
// return result;
// }
// var lines = File.ReadAllLines(path);
// for (int i = 1; i < lines.Length; i++) // skip header row
// {
// var line = lines[i].Trim();
// if (string.IsNullOrEmpty(line)) continue;
// var parts = line.Split(new[] { ',' }, 2);
// if (parts.Length < 2) continue;
// result[parts[0]] = parts[1];
// }
// return result;
// }
// private void ApplyLanguage(bool isEnglish)
// {
// var text = isEnglish ? _engText : _jpnText;
// string cssPath = isEnglish ? EngCssPath : JpnCssPath;
// foreach (var kvp in _buttonsById)
// {
// if (text.TryGetValue(kvp.Key, out var buttonText))
// kvp.Value.Label = buttonText;
// }
// if (File.Exists(cssPath))
// _languageCssProvider.LoadFromPath(cssPath);
// else
// Console.WriteLine($"Warning: CSS file not found: {cssPath}");
// LanguageLabel.Text = isEnglish ? "あ" : "A";
// }
// ---------- scaling ----------
private void OnWindowSizeAllocated(object o, SizeAllocatedArgs args)
{
int width = args.Allocation.Width;
int height = args.Allocation.Height;
if (width == _lastAppliedWidth) return;
_lastAppliedWidth = width;
double scaleX = (double)width / BaseWidth;
double scaleY = (double)height / BaseHeight;
ApplyScale(Math.Min(scaleX, scaleY));
}
private void ApplyScale(double scale)
{
int fontSize = Math.Max(10, (int)(20 * scale));
int buttonPadV = Math.Max(4, (int)(12 * scale));
int buttonPadH = Math.Max(8, (int)(24 * scale));
int switchWidth = Math.Max(30, (int)(40 * scale));
int switchHeight= Math.Max(18, (int)(24 * scale));
// NOTE: integers + InvariantCulture. Interpolating a double here emitted
// "40,5px" under ja_JP / de_DE locales and GTK silently dropped the rule.
string css = string.Format(CultureInfo.InvariantCulture, @"
grid, label, button, switch {{
font-size: {0}px;
}}
button {{
padding: {1}px {2}px;
}}
switch {{
min-width: {3}px;
min-height: {4}px;
}}
", fontSize, buttonPadV, buttonPadH, switchWidth, switchHeight);
_scaleCssProvider.LoadFromData(css);
}
// ---------- lifecycle ----------
private void OnDeleteEvent(object sender, DeleteEventArgs a)
{
Shutdown();
a.RetVal = true;
}
private void OnCloseClicked(object sender, EventArgs e)
{
Shutdown();
}
private void Shutdown()
{
_arduino.Disconnect();
_arduino.Dispose();
// _settingsWindow?.Destroy();
Application.Quit();
}
private void OnNormalSessionClicked(object sender, EventArgs e)
{
Console.WriteLine("Normal Session selected");
}
private void OnPositionRecordingClicked(object sender, EventArgs e)
{
Console.WriteLine("Position Recording Mode selected");
}
private void OnExamModeClicked(object sender, EventArgs e)
{
Console.WriteLine("Exam Mode selected");
}
private void OnLanguageToggled(object sender, EventArgs e)
{
_Language.Apply(LanguageToggle.Active);
}
// private void ApplyLanguageEverywhere(bool isEnglish)
// {
// Language.LanguageSwitchValue = isEnglish;
// _Language.ApplyLanguage(isEnglish);
// _settingsWindow?._Language?.ApplyLanguages(isEnglish);
// }
}