using System;
using Gtk;
using System.Collections.Generic;
using UI = Gtk.Builder.ObjectAttribute;
public class SettingsWindow
{
[UI] private Label ComPortLabel = null;
[UI] private ComboBoxText ComPortComboBox = null;
[UI] private Button ConnectButton = null;
[UI] private Button AutoConnectButton = null;
[UI] private Button RefreshButton = null;
[UI] private Button SettingBackButton = null;
[UI] private Label StatusLabel = null;
[UI] private Label LogLabel = null;
[UI] private TextView LogtextBox = null;
// private readonly Dictionary<string, Button> _buttonsById;
// private readonly Dictionary<string, Label> _labelsById;
// internal Language _Language;
private readonly Language _lang;
private bool _connected;
private const int MaxLogLines = 500;
private readonly ArduinoConnection _arduino;
private string[] _ports = new string[0];
/// <summary>Raised after the window hides itself, so the caller can re-show the main window.</summary>
public event EventHandler BackRequested;
public SettingsWindow(Builder builder, ArduinoConnection arduino, Language language)
{
builder.Autoconnect(this);
_arduino = arduino;
_lang = language;
// Title = "Settings";
// ComPortLabel.Text = "COM Port";
// LogLabel.Text = "Log";
LogtextBox.Editable = false;
LogtextBox.WrapMode = WrapMode.WordChar;
RefreshButton.Clicked += (s, e) => RefreshPorts();
ConnectButton.Clicked += OnConnectClicked;
AutoConnectButton.Clicked += OnAutoConnectClicked;
SettingBackButton.Clicked += OnBackClicked;
// DeleteEvent += (o, a) => { a.RetVal = true; OnBackClicked(o, EventArgs.Empty); };
_arduino.Log += AppendLog;
_arduino.LineReceived += OnLineReceived;
_arduino.ConnectionChanged += OnConnectionChanged;
_lang.Register("ComPortLabel", ComPortLabel);
_lang.Register("LogLabel", LogLabel);
_lang.Register("AutoConnectButton", AutoConnectButton);
_lang.Register("RefreshButton", RefreshButton);
_lang.Register("SettingBackButton", SettingBackButton);
_lang.RegisterDynamic("ConnectButton", ConnectButton); // set in OnConnectionChanged
_lang.RegisterDynamic("StatusLabel", StatusLabel);
_lang.Changed += (s, e) => OnConnectionChanged(_connected);
// _buttonsById = new Dictionary<string, Button>
// {
// { "ConnectButton", ConnectButton },
// { "AutoConnectButton", AutoConnectButton },
// { "RefreshButton", RefreshButton },
// { "BackButton", BackButton },
// };
// // CSS ID selectors (#Option1Button etc.) need the widget Name set explicitly
// foreach (var kvp in _buttonsById)
// kvp.Value.Name = kvp.Key;
// _Language = new Language(_buttonsById);
// // _Language.ApplyLanguages(Language.LanguageSwitchValue);
RefreshPorts();
OnConnectionChanged(_arduino.IsOpen);
}
// ---------- UI actions ----------
private void RefreshPorts()
{
ComPortComboBox.RemoveAll();
_ports = ArduinoConnection.ListPorts();
foreach (string p in _ports)
ComPortComboBox.AppendText(p);
if (_ports.Length > 0)
{
ComPortComboBox.Active = 0;
AppendLog(_lang.Format("Log.PortsFound", _ports.Length));
}
else
{
AppendLog(_lang["Log.NoPorts"]);
}
}
private void OnConnectClicked(object sender, EventArgs e)
{
if (_arduino.IsOpen)
{
_arduino.Disconnect();
return;
}
string port = ComPortComboBox.ActiveText;
if (string.IsNullOrEmpty(port))
{
AppendLog(_lang["Log.SelectPort"]);
return;
}
_arduino.Connect(port);
}
private async void OnAutoConnectClicked(object sender, EventArgs e)
{
AutoConnectButton.Sensitive = false;
ConnectButton.Sensitive = false;
AppendLog(_lang["Log.Scanning"]);
string found = await _arduino.DetectPortAsync();
if (found != null)
{
RefreshPorts();
SelectPort(found);
_arduino.Connect(found);
}
else
{
AppendLog(_lang["Log.DeviceNotFound"]);
}
AutoConnectButton.Sensitive = true;
ConnectButton.Sensitive = true;
}
private void OnBackClicked(object sender, EventArgs e)
{
// Hide();
BackRequested?.Invoke(this, EventArgs.Empty);
}
private void SelectPort(string portName)
{
for (int i = 0; i < _ports.Length; i++)
{
if (_ports[i] == portName)
{
ComPortComboBox.Active = i;
return;
}
}
}
// ---------- device events ----------
private void OnConnectionChanged(bool connected)
{
_connected = connected;
ConnectButton.Label = connected
? _lang["ConnectButton.Disconnect"]
: _lang["ConnectButton.Connect"];
StatusLabel.Text = connected
? _lang.Format("StatusLabel.Connected", _arduino.PortName)
: _lang["StatusLabel.Disconnected"];
ComPortComboBox.Sensitive = !connected;
RefreshButton.Sensitive = !connected;
StyleContext ctx = StatusLabel.StyleContext;
ctx.RemoveClass(connected ? "status-off" : "status-on");
ctx.AddClass(connected ? "status-on" : "status-off");
}
private void OnLineReceived(string line)
{
// Same filtering Form2.cs applied before parsing.
if (line.StartsWith("Send Status:")) return;
if (line.StartsWith("\u2713") || line.StartsWith("\u2717")) return;
if (line.Contains("ESPNOW_CONNECTED")) { AppendLog(_lang["Log.EspNowConnected"]); return; }
if (line.Contains("ESPNOW_DISCONNECTED")) { AppendLog(_lang["Log.EspNowDisconnected"]); return; }
AppendLog(line);
}
// ---------- log ----------
public void AppendLog(string message)
{
TextBuffer buf = LogtextBox.Buffer;
TextIter end = buf.EndIter;
buf.Insert(ref end, $"[{DateTime.Now:HH:mm:ss.fff}] {message}\n");
if (buf.LineCount > MaxLogLines)
{
TextIter start = buf.StartIter;
TextIter cut = buf.GetIterAtLine(buf.LineCount - MaxLogLines);
buf.Delete(ref start, ref cut);
}
TextMark mark = buf.CreateMark(null, buf.EndIter, false);
LogtextBox.ScrollToMark(mark, 0, false, 0, 0);
buf.DeleteMark(mark);
}
}