1325 lines
49 KiB
C#
1325 lines
49 KiB
C#
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
// Copyright (C) LibreHardwareMonitor and Contributors.
|
|
// Partial Copyright (C) Michael Möller <mmoeller@openhardwaremonitor.org> and Contributors.
|
|
// All Rights Reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows.Forms;
|
|
using Aga.Controls.Tree;
|
|
using Aga.Controls.Tree.NodeControls;
|
|
using LibreHardwareMonitor.Hardware;
|
|
using LibreHardwareMonitor.UI.Themes;
|
|
using LibreHardwareMonitor.Utilities;
|
|
using LibreHardwareMonitor.Wmi;
|
|
|
|
namespace LibreHardwareMonitor.UI;
|
|
|
|
public sealed partial class MainForm : Form
|
|
{
|
|
private ToolStripMenuItem _autoThemeMenuItem;
|
|
private readonly UserOption _autoStart;
|
|
private readonly Computer _computer;
|
|
private readonly SensorGadget _gadget;
|
|
private readonly Logger _logger;
|
|
private readonly UserRadioGroup _loggingInterval;
|
|
private readonly UserRadioGroup _updateInterval;
|
|
private readonly UserOption _logSensors;
|
|
private readonly UserOption _minimizeOnClose;
|
|
private readonly UserOption _minimizeToTray;
|
|
private readonly PlotPanel _plotPanel;
|
|
private readonly UserOption _readBatterySensors;
|
|
private readonly UserOption _readCpuSensors;
|
|
private readonly UserOption _readFanControllersSensors;
|
|
private readonly UserOption _readGpuSensors;
|
|
private readonly UserOption _readHddSensors;
|
|
private readonly UserOption _readMainboardSensors;
|
|
private readonly UserOption _readNicSensors;
|
|
private readonly UserOption _readPsuSensors;
|
|
private readonly UserOption _readRamSensors;
|
|
private readonly Node _root;
|
|
private readonly UserOption _runWebServer;
|
|
private readonly UserRadioGroup _sensorValuesTimeWindow;
|
|
private readonly PersistentSettings _settings;
|
|
private readonly UserOption _showGadget;
|
|
private readonly StartupManager _startupManager = new();
|
|
private readonly SystemTray _systemTray;
|
|
private readonly UnitManager _unitManager;
|
|
private readonly UpdateVisitor _updateVisitor = new();
|
|
private readonly WmiProvider _wmiProvider;
|
|
|
|
private int _delayCount;
|
|
private Form _plotForm;
|
|
private UserRadioGroup _plotLocation;
|
|
private UserRadioGroup _splitPanelScalingSetting;
|
|
private bool _selectionDragging;
|
|
private IDictionary<ISensor, Color> _sensorPlotColors = new Dictionary<ISensor, Color>();
|
|
private UserOption _showPlot;
|
|
private UserRadioGroup _strokeThickness;
|
|
private double _plotStrokeThickness = 2;
|
|
|
|
public MainForm()
|
|
{
|
|
InitializeComponent();
|
|
|
|
_settings = new PersistentSettings();
|
|
_settings.Load(Path.ChangeExtension(Application.ExecutablePath, ".config"));
|
|
|
|
_unitManager = new UnitManager(_settings);
|
|
|
|
// make sure the buffers used for double buffering are not disposed
|
|
// after each draw call
|
|
BufferedGraphicsManager.Current.MaximumBuffer = Screen.PrimaryScreen.Bounds.Size;
|
|
|
|
// set the DockStyle here, to avoid conflicts with the MainMenu
|
|
splitContainer.Dock = DockStyle.Fill;
|
|
|
|
Font = SystemFonts.MessageBoxFont;
|
|
treeView.Font = SystemFonts.MessageBoxFont;
|
|
|
|
// Set the bounds immediately, so that our child components can be
|
|
// properly placed.
|
|
Bounds = new Rectangle
|
|
{
|
|
X = _settings.GetValue("mainForm.Location.X", Location.X),
|
|
Y = _settings.GetValue("mainForm.Location.Y", Location.Y),
|
|
Width = _settings.GetValue("mainForm.Width", 470),
|
|
Height = _settings.GetValue("mainForm.Height", 640)
|
|
};
|
|
|
|
Theme setTheme = Theme.All.FirstOrDefault(theme => _settings.GetValue("theme", "auto") == theme.Id);
|
|
if (setTheme != null)
|
|
{
|
|
Theme.Current = setTheme;
|
|
}
|
|
else
|
|
{
|
|
Theme.SetAutoTheme();
|
|
}
|
|
|
|
_plotPanel = new PlotPanel(_settings, _unitManager) { Font = SystemFonts.MessageBoxFont, Dock = DockStyle.Fill };
|
|
|
|
nodeCheckBox.IsVisibleValueNeeded += NodeCheckBox_IsVisibleValueNeeded;
|
|
nodeTextBoxText.DrawText += NodeTextBoxText_DrawText;
|
|
nodeTextBoxValue.DrawText += NodeTextBoxText_DrawText;
|
|
nodeTextBoxMin.DrawText += NodeTextBoxText_DrawText;
|
|
nodeTextBoxMax.DrawText += NodeTextBoxText_DrawText;
|
|
nodeTextBoxText.EditorShowing += NodeTextBoxText_EditorShowing;
|
|
|
|
for (int i = 1; i < treeView.Columns.Count; i++)
|
|
{
|
|
TreeColumn column = treeView.Columns[i];
|
|
column.Width = Math.Max(20, Math.Min(400, _settings.GetValue("treeView.Columns." + column.Header + ".Width", column.Width)));
|
|
}
|
|
|
|
TreeModel treeModel = new();
|
|
_root = new Node(Environment.MachineName) { Image = EmbeddedResources.GetImage("computer.png") };
|
|
|
|
treeModel.Nodes.Add(_root);
|
|
treeView.Model = treeModel;
|
|
|
|
_computer = new Computer(_settings);
|
|
|
|
_systemTray = new SystemTray(_computer, _settings, _unitManager);
|
|
_systemTray.HideShowCommand += HideShowClick;
|
|
_systemTray.ExitCommand += ExitClick;
|
|
|
|
if (Software.OperatingSystem.IsUnix)
|
|
{
|
|
// Unix
|
|
treeView.RowHeight = Math.Max(treeView.RowHeight, 18);
|
|
splitContainer.BorderStyle = BorderStyle.None;
|
|
splitContainer.SplitterWidth = 4;
|
|
treeView.BorderStyle = BorderStyle.Fixed3D;
|
|
_plotPanel.BorderStyle = BorderStyle.Fixed3D;
|
|
gadgetMenuItem.Visible = false;
|
|
minCloseMenuItem.Visible = false;
|
|
minTrayMenuItem.Visible = false;
|
|
startMinMenuItem.Visible = false;
|
|
}
|
|
else
|
|
{
|
|
// Windows
|
|
treeView.RowHeight = Math.Max(treeView.Font.Height + 1, 18);
|
|
_gadget = new SensorGadget(_computer, _settings, _unitManager);
|
|
_gadget.HideShowCommand += HideShowClick;
|
|
_wmiProvider = new WmiProvider(_computer);
|
|
}
|
|
|
|
treeView.ShowNodeToolTips = true;
|
|
NodeToolTipProvider tooltipProvider = new();
|
|
nodeTextBoxText.ToolTipProvider = tooltipProvider;
|
|
nodeTextBoxValue.ToolTipProvider = tooltipProvider;
|
|
_logger = new Logger(_computer);
|
|
|
|
_computer.HardwareAdded += HardwareAdded;
|
|
_computer.HardwareRemoved += HardwareRemoved;
|
|
_computer.Open();
|
|
|
|
backgroundUpdater.DoWork += BackgroundUpdater_DoWork;
|
|
timer.Enabled = true;
|
|
|
|
UserOption showHiddenSensors = new("hiddenMenuItem", false, hiddenMenuItem, _settings);
|
|
showHiddenSensors.Changed += delegate { treeModel.ForceVisible = showHiddenSensors.Value; };
|
|
|
|
UserOption showValue = new("valueMenuItem", true, valueMenuItem, _settings);
|
|
showValue.Changed += delegate { treeView.Columns[1].IsVisible = showValue.Value; };
|
|
|
|
UserOption showMin = new("minMenuItem", false, minMenuItem, _settings);
|
|
showMin.Changed += delegate { treeView.Columns[2].IsVisible = showMin.Value; };
|
|
|
|
UserOption showMax = new("maxMenuItem", true, maxMenuItem, _settings);
|
|
showMax.Changed += delegate { treeView.Columns[3].IsVisible = showMax.Value; };
|
|
|
|
var _ = new UserOption("startMinMenuItem", false, startMinMenuItem, _settings);
|
|
_minimizeToTray = new UserOption("minTrayMenuItem", true, minTrayMenuItem, _settings);
|
|
_minimizeToTray.Changed += delegate { _systemTray.IsMainIconEnabled = _minimizeToTray.Value; };
|
|
|
|
_minimizeOnClose = new UserOption("minCloseMenuItem", false, minCloseMenuItem, _settings);
|
|
|
|
_autoStart = new UserOption(null, _startupManager.Startup, startupMenuItem, _settings);
|
|
_autoStart.Changed += delegate
|
|
{
|
|
try
|
|
{
|
|
_startupManager.Startup = _autoStart.Value;
|
|
}
|
|
catch (InvalidOperationException)
|
|
{
|
|
MessageBox.Show("Updating the auto-startup option failed.",
|
|
"Error",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
|
|
_autoStart.Value = _startupManager.Startup;
|
|
}
|
|
};
|
|
|
|
_readMainboardSensors = new UserOption("mainboardMenuItem", true, mainboardMenuItem, _settings);
|
|
_readMainboardSensors.Changed += delegate { _computer.IsMotherboardEnabled = _readMainboardSensors.Value; };
|
|
|
|
_readCpuSensors = new UserOption("cpuMenuItem", true, cpuMenuItem, _settings);
|
|
_readCpuSensors.Changed += delegate { _computer.IsCpuEnabled = _readCpuSensors.Value; };
|
|
|
|
_readRamSensors = new UserOption("ramMenuItem", true, ramMenuItem, _settings);
|
|
_readRamSensors.Changed += delegate { _computer.IsMemoryEnabled = _readRamSensors.Value; };
|
|
|
|
_readGpuSensors = new UserOption("gpuMenuItem", true, gpuMenuItem, _settings);
|
|
_readGpuSensors.Changed += delegate { _computer.IsGpuEnabled = _readGpuSensors.Value; };
|
|
|
|
_readFanControllersSensors = new UserOption("fanControllerMenuItem", true, fanControllerMenuItem, _settings);
|
|
_readFanControllersSensors.Changed += delegate { _computer.IsControllerEnabled = _readFanControllersSensors.Value; };
|
|
|
|
_readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem, _settings);
|
|
_readHddSensors.Changed += delegate { _computer.IsStorageEnabled = _readHddSensors.Value; };
|
|
|
|
_readNicSensors = new UserOption("nicMenuItem", true, nicMenuItem, _settings);
|
|
_readNicSensors.Changed += delegate { _computer.IsNetworkEnabled = _readNicSensors.Value; };
|
|
|
|
_readPsuSensors = new UserOption("psuMenuItem", true, psuMenuItem, _settings);
|
|
_readPsuSensors.Changed += delegate { _computer.IsPsuEnabled = _readPsuSensors.Value; };
|
|
|
|
_readBatterySensors = new UserOption("batteryMenuItem", true, batteryMenuItem, _settings);
|
|
_readBatterySensors.Changed += delegate { _computer.IsBatteryEnabled = _readBatterySensors.Value; };
|
|
|
|
_showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem, _settings);
|
|
|
|
// Prevent Menu From Closing When UnClicking Hardware Items
|
|
menuItemFileHardware.DropDown.Closing += StopFileHardwareMenuFromClosing;
|
|
|
|
|
|
_showGadget.Changed += delegate
|
|
{
|
|
if (_gadget != null)
|
|
_gadget.Visible = _showGadget.Value;
|
|
};
|
|
|
|
celsiusMenuItem.Checked = _unitManager.TemperatureUnit == TemperatureUnit.Celsius;
|
|
fahrenheitMenuItem.Checked = !celsiusMenuItem.Checked;
|
|
|
|
Server = new HttpServer(_root,
|
|
_settings.GetValue("listenerIp", "?"),
|
|
_settings.GetValue("listenerPort", 8085),
|
|
_settings.GetValue("authenticationEnabled", false),
|
|
_settings.GetValue("authenticationUserName", ""),
|
|
_settings.GetValue("authenticationPassword", ""));
|
|
|
|
if (Server.PlatformNotSupported)
|
|
{
|
|
webMenuItemSeparator.Visible = false;
|
|
webMenuItem.Visible = false;
|
|
}
|
|
|
|
_runWebServer = new UserOption("runWebServerMenuItem", false, runWebServerMenuItem, _settings);
|
|
_runWebServer.Changed += delegate
|
|
{
|
|
if (_runWebServer.Value)
|
|
Server.StartHttpListener();
|
|
else
|
|
Server.StopHttpListener();
|
|
};
|
|
|
|
authWebServerMenuItem.Checked = _settings.GetValue("authenticationEnabled", false);
|
|
|
|
_logSensors = new UserOption("logSensorsMenuItem", false, logSensorsMenuItem, _settings);
|
|
|
|
_loggingInterval = new UserRadioGroup("loggingInterval",
|
|
0,
|
|
new[]
|
|
{
|
|
log1sMenuItem,
|
|
log2sMenuItem,
|
|
log5sMenuItem,
|
|
log10sMenuItem,
|
|
log30sMenuItem,
|
|
log1minMenuItem,
|
|
log2minMenuItem,
|
|
log5minMenuItem,
|
|
log10minMenuItem,
|
|
log30minMenuItem,
|
|
log1hMenuItem,
|
|
log2hMenuItem,
|
|
log6hMenuItem
|
|
},
|
|
_settings);
|
|
|
|
_loggingInterval.Changed += (sender, e) =>
|
|
{
|
|
switch (_loggingInterval.Value)
|
|
{
|
|
case 0:
|
|
_logger.LoggingInterval = new TimeSpan(0, 0, 1);
|
|
break;
|
|
case 1:
|
|
_logger.LoggingInterval = new TimeSpan(0, 0, 2);
|
|
break;
|
|
case 2:
|
|
_logger.LoggingInterval = new TimeSpan(0, 0, 5);
|
|
break;
|
|
case 3:
|
|
_logger.LoggingInterval = new TimeSpan(0, 0, 10);
|
|
break;
|
|
case 4:
|
|
_logger.LoggingInterval = new TimeSpan(0, 0, 30);
|
|
break;
|
|
case 5:
|
|
_logger.LoggingInterval = new TimeSpan(0, 1, 0);
|
|
break;
|
|
case 6:
|
|
_logger.LoggingInterval = new TimeSpan(0, 2, 0);
|
|
break;
|
|
case 7:
|
|
_logger.LoggingInterval = new TimeSpan(0, 5, 0);
|
|
break;
|
|
case 8:
|
|
_logger.LoggingInterval = new TimeSpan(0, 10, 0);
|
|
break;
|
|
case 9:
|
|
_logger.LoggingInterval = new TimeSpan(0, 30, 0);
|
|
break;
|
|
case 10:
|
|
_logger.LoggingInterval = new TimeSpan(1, 0, 0);
|
|
break;
|
|
case 11:
|
|
_logger.LoggingInterval = new TimeSpan(2, 0, 0);
|
|
break;
|
|
case 12:
|
|
_logger.LoggingInterval = new TimeSpan(6, 0, 0);
|
|
break;
|
|
}
|
|
};
|
|
|
|
_updateInterval = new UserRadioGroup("updateIntervalMenuItem",
|
|
2,
|
|
new[]
|
|
{
|
|
updateInterval250msMenuItem,
|
|
updateInterval500msMenuItem,
|
|
updateInterval1sMenuItem,
|
|
updateInterval2sMenuItem,
|
|
updateInterval5sMenuItem,
|
|
updateInterval10sMenuItem
|
|
},
|
|
_settings);
|
|
|
|
_updateInterval.Changed += (sender, e) =>
|
|
{
|
|
switch (_updateInterval.Value)
|
|
{
|
|
case 0:
|
|
timer.Interval = 250;
|
|
break;
|
|
case 1:
|
|
timer.Interval = 500;
|
|
break;
|
|
case 2:
|
|
timer.Interval = 1000;
|
|
break;
|
|
case 3:
|
|
timer.Interval = 2000;
|
|
break;
|
|
case 4:
|
|
timer.Interval = 5000;
|
|
break;
|
|
case 5:
|
|
timer.Interval = 10000;
|
|
break;
|
|
}
|
|
};
|
|
|
|
_sensorValuesTimeWindow = new UserRadioGroup("sensorValuesTimeWindow",
|
|
10,
|
|
new[]
|
|
{
|
|
timeWindow30sMenuItem,
|
|
timeWindow1minMenuItem,
|
|
timeWindow2minMenuItem,
|
|
timeWindow5minMenuItem,
|
|
timeWindow10minMenuItem,
|
|
timeWindow30minMenuItem,
|
|
timeWindow1hMenuItem,
|
|
timeWindow2hMenuItem,
|
|
timeWindow6hMenuItem,
|
|
timeWindow12hMenuItem,
|
|
timeWindow24hMenuItem
|
|
},
|
|
_settings);
|
|
|
|
perSessionFileRotationMenuItem.Checked = _logger.FileRotationMethod == LoggerFileRotation.PerSession;
|
|
dailyFileRotationMenuItem.Checked = _logger.FileRotationMethod == LoggerFileRotation.Daily;
|
|
|
|
_sensorValuesTimeWindow.Changed += (sender, e) =>
|
|
{
|
|
TimeSpan timeWindow = TimeSpan.Zero;
|
|
switch (_sensorValuesTimeWindow.Value)
|
|
{
|
|
case 0:
|
|
timeWindow = new TimeSpan(0, 0, 30);
|
|
break;
|
|
case 1:
|
|
timeWindow = new TimeSpan(0, 1, 0);
|
|
break;
|
|
case 2:
|
|
timeWindow = new TimeSpan(0, 2, 0);
|
|
break;
|
|
case 3:
|
|
timeWindow = new TimeSpan(0, 5, 0);
|
|
break;
|
|
case 4:
|
|
timeWindow = new TimeSpan(0, 10, 0);
|
|
break;
|
|
case 5:
|
|
timeWindow = new TimeSpan(0, 30, 0);
|
|
break;
|
|
case 6:
|
|
timeWindow = new TimeSpan(1, 0, 0);
|
|
break;
|
|
case 7:
|
|
timeWindow = new TimeSpan(2, 0, 0);
|
|
break;
|
|
case 8:
|
|
timeWindow = new TimeSpan(6, 0, 0);
|
|
break;
|
|
case 9:
|
|
timeWindow = new TimeSpan(12, 0, 0);
|
|
break;
|
|
case 10:
|
|
timeWindow = new TimeSpan(24, 0, 0);
|
|
break;
|
|
}
|
|
|
|
_computer.Accept(new SensorVisitor(delegate(ISensor sensor) { sensor.ValuesTimeWindow = timeWindow; }));
|
|
};
|
|
|
|
InitializeTheme();
|
|
InitializePlotForm();
|
|
InitializeSplitter();
|
|
|
|
startupMenuItem.Visible = _startupManager.IsAvailable;
|
|
|
|
if (startMinMenuItem.Checked)
|
|
{
|
|
if (!minTrayMenuItem.Checked)
|
|
{
|
|
WindowState = FormWindowState.Minimized;
|
|
Show();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Show();
|
|
}
|
|
|
|
// Create a handle, otherwise calling Close() does not fire FormClosed
|
|
|
|
// Make sure the settings are saved when the user logs off
|
|
Microsoft.Win32.SystemEvents.SessionEnded += delegate
|
|
{
|
|
_computer.Close();
|
|
SaveConfiguration();
|
|
if (_runWebServer.Value)
|
|
Server.Quit();
|
|
};
|
|
|
|
Microsoft.Win32.SystemEvents.PowerModeChanged += PowerModeChanged;
|
|
}
|
|
|
|
private void StopFileHardwareMenuFromClosing(object sender, ToolStripDropDownClosingEventArgs e)
|
|
{
|
|
if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
|
|
{
|
|
e.Cancel = true;
|
|
}
|
|
}
|
|
|
|
public bool AuthWebServerMenuItemChecked
|
|
{
|
|
get { return authWebServerMenuItem.Checked; }
|
|
set { authWebServerMenuItem.Checked = value; }
|
|
}
|
|
|
|
public HttpServer Server { get; }
|
|
|
|
private void BackgroundUpdater_DoWork(object sender, DoWorkEventArgs e)
|
|
{
|
|
_computer.Accept(_updateVisitor);
|
|
|
|
if (_logSensors != null && _logSensors.Value && _delayCount >= 4)
|
|
_logger.Log();
|
|
|
|
if (_delayCount < 4)
|
|
_delayCount++;
|
|
|
|
_plotPanel.InvalidatePlot();
|
|
}
|
|
|
|
private void PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs eventArgs)
|
|
{
|
|
if (eventArgs.Mode == Microsoft.Win32.PowerModes.Resume)
|
|
{
|
|
_computer.Reset();
|
|
}
|
|
}
|
|
|
|
private void InitializeTheme()
|
|
{
|
|
mainMenu.Renderer = new ThemedToolStripRenderer();
|
|
treeContextMenu.Renderer = new ThemedToolStripRenderer();
|
|
ThemedVScrollIndicator.AddToControl(treeView);
|
|
ThemedHScrollIndicator.AddToControl(treeView);
|
|
|
|
string themeSetting = _settings.GetValue("theme", "auto");
|
|
bool themeSelected = false;
|
|
|
|
void ClearThemeMenu()
|
|
{
|
|
foreach (ToolStripItem x in themeMenuItem.DropDownItems)
|
|
{
|
|
if (x is ToolStripMenuItem tmi)
|
|
{
|
|
tmi.Checked = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Theme.SupportsAutoThemeSwitching())
|
|
{
|
|
_autoThemeMenuItem = new ToolStripMenuItem();
|
|
_autoThemeMenuItem.Text = "Auto";
|
|
_autoThemeMenuItem.Click += (o, e) =>
|
|
{
|
|
ClearThemeMenu();
|
|
_autoThemeMenuItem.Checked = true;
|
|
Theme.SetAutoTheme();
|
|
_settings.SetValue("theme", "auto");
|
|
PlotSelectionChanged(o, e);
|
|
};
|
|
themeMenuItem.DropDownItems.Add(_autoThemeMenuItem);
|
|
}
|
|
|
|
foreach (Theme theme in Theme.All)
|
|
{
|
|
ToolStripMenuItem item = new ToolStripMenuItem();
|
|
item.Text = theme.DisplayName;
|
|
item.Click += (o, e) =>
|
|
{
|
|
ClearThemeMenu();
|
|
item.Checked = true;
|
|
Theme.Current = theme;
|
|
_settings.SetValue("theme", theme.Id);
|
|
PlotSelectionChanged(o, e);
|
|
};
|
|
themeMenuItem.DropDownItems.Add(item);
|
|
|
|
if (themeSetting == theme.Id)
|
|
{
|
|
item.PerformClick();
|
|
themeSelected = true;
|
|
}
|
|
}
|
|
|
|
if (!themeSelected)
|
|
{
|
|
themeMenuItem.DropDownItems[0].PerformClick();
|
|
}
|
|
|
|
Theme.Current.Apply(this);
|
|
}
|
|
|
|
private void InitializeSplitter()
|
|
{
|
|
splitContainer.SplitterDistance = _settings.GetValue("splitContainer.SplitterDistance", 400);
|
|
splitContainer.SplitterMoved += delegate { _settings.SetValue("splitContainer.SplitterDistance", splitContainer.SplitterDistance); };
|
|
}
|
|
|
|
private void InitializePlotForm()
|
|
{
|
|
_plotForm = new Form { FormBorderStyle = FormBorderStyle.SizableToolWindow, ShowInTaskbar = false, StartPosition = FormStartPosition.Manual };
|
|
AddOwnedForm(_plotForm);
|
|
_plotForm.Bounds = new Rectangle
|
|
{
|
|
X = _settings.GetValue("plotForm.Location.X", -100000),
|
|
Y = _settings.GetValue("plotForm.Location.Y", 100),
|
|
Width = _settings.GetValue("plotForm.Width", 600),
|
|
Height = _settings.GetValue("plotForm.Height", 400)
|
|
};
|
|
|
|
_showPlot = new UserOption("plotMenuItem", false, plotMenuItem, _settings);
|
|
_plotLocation = new UserRadioGroup("plotLocation", 0, new[] { plotWindowMenuItem, plotBottomMenuItem, plotRightMenuItem }, _settings);
|
|
_splitPanelScalingSetting = new UserRadioGroup("splitPanelScalingSetting", 0, new[] { splitPanelPercentageScalingMenuItem, splitPanelFixedPlotScalingMenuItem, splitPanelFixedSensorScalingMenuItem }, _settings);
|
|
|
|
_showPlot.Changed += delegate
|
|
{
|
|
if (_plotLocation.Value == 0)
|
|
{
|
|
if (_showPlot.Value && Visible)
|
|
{
|
|
Theme.Current.Apply(_plotForm);
|
|
_plotForm.Show();
|
|
}
|
|
else
|
|
_plotForm.Hide();
|
|
}
|
|
else
|
|
{
|
|
splitContainer.Panel2Collapsed = !_showPlot.Value;
|
|
}
|
|
|
|
treeView.Invalidate();
|
|
};
|
|
|
|
_strokeThickness = new UserRadioGroup("plotStroke", 1, new[] { strokeThickness1ptMenuItem, strokeThickness2ptMenuItem, strokeThickness3ptMenuItem, strokeThickness4ptMenuItem }, _settings);
|
|
|
|
_strokeThickness.Changed += (sender, e) =>
|
|
{
|
|
_plotStrokeThickness = (_strokeThickness.Value >= 0 && _strokeThickness.Value <= 3)
|
|
? _strokeThickness.Value + 1
|
|
: 4;
|
|
_plotPanel.UpdateStrokeThickness(_plotStrokeThickness);
|
|
};
|
|
|
|
_plotLocation.Changed += delegate
|
|
{
|
|
switch (_plotLocation.Value)
|
|
{
|
|
case 0:
|
|
splitContainer.Panel2.Controls.Clear();
|
|
splitContainer.Panel2Collapsed = true;
|
|
_plotForm.Controls.Add(_plotPanel);
|
|
if (_showPlot.Value && Visible)
|
|
_plotForm.Show();
|
|
break;
|
|
case 1:
|
|
_plotForm.Controls.Clear();
|
|
_plotForm.Hide();
|
|
splitContainer.Orientation = Orientation.Horizontal;
|
|
splitContainer.Panel2.Controls.Add(_plotPanel);
|
|
splitContainer.Panel2Collapsed = !_showPlot.Value;
|
|
break;
|
|
case 2:
|
|
_plotForm.Controls.Clear();
|
|
_plotForm.Hide();
|
|
splitContainer.Orientation = Orientation.Vertical;
|
|
splitContainer.Panel2.Controls.Add(_plotPanel);
|
|
splitContainer.Panel2Collapsed = !_showPlot.Value;
|
|
break;
|
|
}
|
|
};
|
|
|
|
_splitPanelScalingSetting.Changed += delegate
|
|
{
|
|
switch (_splitPanelScalingSetting.Value)
|
|
{
|
|
case 0:
|
|
splitContainer.FixedPanel = FixedPanel.None;
|
|
break;
|
|
case 1:
|
|
splitContainer.FixedPanel = FixedPanel.Panel2;
|
|
break;
|
|
case 2:
|
|
splitContainer.FixedPanel = FixedPanel.Panel1;
|
|
break;
|
|
}
|
|
};
|
|
|
|
_plotForm.FormClosing += delegate(object sender, FormClosingEventArgs e)
|
|
{
|
|
if (e.CloseReason == CloseReason.UserClosing)
|
|
{
|
|
// just switch off the plotting when the user closes the form
|
|
if (_plotLocation.Value == 0)
|
|
{
|
|
_showPlot.Value = false;
|
|
}
|
|
|
|
e.Cancel = true;
|
|
}
|
|
};
|
|
|
|
void MoveOrResizePlotForm(object sender, EventArgs e)
|
|
{
|
|
if (_plotForm.WindowState != FormWindowState.Minimized)
|
|
{
|
|
_settings.SetValue("plotForm.Location.X", _plotForm.Bounds.X);
|
|
_settings.SetValue("plotForm.Location.Y", _plotForm.Bounds.Y);
|
|
_settings.SetValue("plotForm.Width", _plotForm.Bounds.Width);
|
|
_settings.SetValue("plotForm.Height", _plotForm.Bounds.Height);
|
|
}
|
|
}
|
|
|
|
_plotForm.Move += MoveOrResizePlotForm;
|
|
_plotForm.Resize += MoveOrResizePlotForm;
|
|
|
|
_plotForm.VisibleChanged += delegate
|
|
{
|
|
Rectangle bounds = new(_plotForm.Location, _plotForm.Size);
|
|
Screen screen = Screen.FromRectangle(bounds);
|
|
Rectangle intersection = Rectangle.Intersect(screen.WorkingArea, bounds);
|
|
if (intersection.Width < Math.Min(16, bounds.Width) ||
|
|
intersection.Height < Math.Min(16, bounds.Height))
|
|
{
|
|
_plotForm.Location = new Point(screen.WorkingArea.Width / 2 - bounds.Width / 2,
|
|
screen.WorkingArea.Height / 2 - bounds.Height / 2);
|
|
}
|
|
};
|
|
|
|
VisibleChanged += delegate
|
|
{
|
|
if (Visible && _showPlot.Value && _plotLocation.Value == 0)
|
|
_plotForm.Show();
|
|
else
|
|
_plotForm.Hide();
|
|
};
|
|
|
|
Theme.Current.Apply(_plotForm);
|
|
}
|
|
|
|
private void InsertSorted(IList<Node> nodes, HardwareNode node)
|
|
{
|
|
int i = 0;
|
|
while (i < nodes.Count && nodes[i] is HardwareNode && ((HardwareNode)nodes[i]).Hardware.HardwareType <= node.Hardware.HardwareType)
|
|
i++;
|
|
|
|
nodes.Insert(i, node);
|
|
}
|
|
|
|
private void SubHardwareAdded(IHardware hardware, Node node)
|
|
{
|
|
HardwareNode hardwareNode = new(hardware, _settings, _unitManager);
|
|
hardwareNode.PlotSelectionChanged += PlotSelectionChanged;
|
|
InsertSorted(node.Nodes, hardwareNode);
|
|
foreach (IHardware subHardware in hardware.SubHardware)
|
|
SubHardwareAdded(subHardware, hardwareNode);
|
|
}
|
|
|
|
private void HardwareAdded(IHardware hardware)
|
|
{
|
|
SubHardwareAdded(hardware, _root);
|
|
PlotSelectionChanged(this, null);
|
|
}
|
|
|
|
private void HardwareRemoved(IHardware hardware)
|
|
{
|
|
List<HardwareNode> nodesToRemove = new();
|
|
foreach (Node node in _root.Nodes)
|
|
{
|
|
if (node is HardwareNode hardwareNode && hardwareNode.Hardware == hardware)
|
|
nodesToRemove.Add(hardwareNode);
|
|
}
|
|
|
|
foreach (HardwareNode hardwareNode in nodesToRemove)
|
|
{
|
|
_root.Nodes.Remove(hardwareNode);
|
|
hardwareNode.PlotSelectionChanged -= PlotSelectionChanged;
|
|
}
|
|
|
|
PlotSelectionChanged(this, null);
|
|
}
|
|
|
|
private void NodeTextBoxText_DrawText(object sender, DrawEventArgs e)
|
|
{
|
|
if (e.Node.Tag is Node node)
|
|
{
|
|
if (node.IsVisible)
|
|
{
|
|
if (plotMenuItem.Checked && node is SensorNode sensorNode && _sensorPlotColors.TryGetValue(sensorNode.Sensor, out Color color))
|
|
e.TextColor = color;
|
|
}
|
|
else
|
|
e.TextColor = Color.DarkGray;
|
|
}
|
|
}
|
|
|
|
private void PlotSelectionChanged(object sender, EventArgs e)
|
|
{
|
|
List<ISensor> selected = new();
|
|
IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
|
|
int colorIndex = 0;
|
|
|
|
foreach (TreeNodeAdv node in treeView.AllNodes)
|
|
{
|
|
if (node.Tag is SensorNode sensorNode)
|
|
{
|
|
if (sensorNode.Plot)
|
|
{
|
|
if (!sensorNode.PenColor.HasValue)
|
|
{
|
|
colors.Add(sensorNode.Sensor,
|
|
Theme.Current.PlotColorPalette[colorIndex % Theme.Current.PlotColorPalette.Length]);
|
|
}
|
|
|
|
selected.Add(sensorNode.Sensor);
|
|
}
|
|
|
|
colorIndex++;
|
|
}
|
|
}
|
|
|
|
// if a sensor is assigned a color that's already being used by another
|
|
// sensor, try to assign it a new color. This is done only after the
|
|
// previous loop sets an unchanging default color for all sensors, so that
|
|
// colors jump around as little as possible as sensors get added/removed
|
|
// from the plot
|
|
var usedColors = new List<Color>();
|
|
foreach (ISensor curSelectedSensor in selected)
|
|
{
|
|
if (!colors.ContainsKey(curSelectedSensor))
|
|
continue;
|
|
|
|
Color curColor = colors[curSelectedSensor];
|
|
if (usedColors.Contains(curColor))
|
|
{
|
|
foreach (Color potentialNewColor in Theme.Current.PlotColorPalette)
|
|
{
|
|
if (!colors.Values.Contains(potentialNewColor))
|
|
{
|
|
colors[curSelectedSensor] = potentialNewColor;
|
|
usedColors.Add(potentialNewColor);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
usedColors.Add(curColor);
|
|
}
|
|
}
|
|
|
|
foreach (TreeNodeAdv node in treeView.AllNodes)
|
|
{
|
|
if (node.Tag is SensorNode sensorNode && sensorNode.Plot && sensorNode.PenColor.HasValue)
|
|
colors.Add(sensorNode.Sensor, sensorNode.PenColor.Value);
|
|
}
|
|
|
|
_sensorPlotColors = colors;
|
|
_plotPanel.SetSensors(selected, colors, _plotStrokeThickness);
|
|
}
|
|
|
|
private void NodeTextBoxText_EditorShowing(object sender, CancelEventArgs e)
|
|
{
|
|
e.Cancel = !(treeView.CurrentNode != null && (treeView.CurrentNode.Tag is SensorNode || treeView.CurrentNode.Tag is HardwareNode));
|
|
}
|
|
|
|
private void NodeCheckBox_IsVisibleValueNeeded(object sender, NodeControlValueEventArgs e)
|
|
{
|
|
e.Value = e.Node.Tag is SensorNode && plotMenuItem.Checked;
|
|
}
|
|
|
|
private void ExitClick(object sender, EventArgs e)
|
|
{
|
|
CloseApplication();
|
|
}
|
|
|
|
private void Timer_Tick(object sender, EventArgs e)
|
|
{
|
|
treeView.Invalidate();
|
|
_systemTray.Redraw();
|
|
_gadget?.Redraw();
|
|
_wmiProvider?.Update();
|
|
|
|
if (!backgroundUpdater.IsBusy)
|
|
backgroundUpdater.RunWorkerAsync();
|
|
|
|
RestoreCollapsedNodeState(treeView);
|
|
}
|
|
|
|
private void SaveConfiguration()
|
|
{
|
|
if (_plotPanel == null || _settings == null)
|
|
return;
|
|
|
|
_plotPanel.SetCurrentSettings();
|
|
|
|
foreach (TreeColumn column in treeView.Columns)
|
|
_settings.SetValue("treeView.Columns." + column.Header + ".Width", column.Width);
|
|
|
|
_settings.SetValue("listenerIp", Server.ListenerIp);
|
|
_settings.SetValue("listenerPort", Server.ListenerPort);
|
|
_settings.SetValue("authenticationEnabled", Server.AuthEnabled);
|
|
_settings.SetValue("authenticationUserName", Server.UserName);
|
|
_settings.SetValue("authenticationPassword", Server.Password);
|
|
|
|
string fileName = Path.ChangeExtension(Application.ExecutablePath, ".config");
|
|
|
|
try
|
|
{
|
|
_settings.Save(fileName);
|
|
}
|
|
catch (UnauthorizedAccessException)
|
|
{
|
|
MessageBox.Show("Access to the path '" +
|
|
fileName +
|
|
"' is denied. " +
|
|
"The current settings could not be saved.",
|
|
"Error",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
}
|
|
catch (IOException)
|
|
{
|
|
MessageBox.Show("The path '" +
|
|
fileName +
|
|
"' is not writeable. " +
|
|
"The current settings could not be saved.",
|
|
"Error",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
|
|
private void MainForm_Load(object sender, EventArgs e)
|
|
{
|
|
Rectangle newBounds = new()
|
|
{
|
|
X = _settings.GetValue("mainForm.Location.X", Location.X),
|
|
Y = _settings.GetValue("mainForm.Location.Y", Location.Y),
|
|
Width = _settings.GetValue("mainForm.Width", 470),
|
|
Height = _settings.GetValue("mainForm.Height", 640)
|
|
};
|
|
|
|
Rectangle fullWorkingArea = new(int.MaxValue, int.MaxValue, int.MinValue, int.MinValue);
|
|
|
|
foreach (Screen screen in Screen.AllScreens)
|
|
fullWorkingArea = Rectangle.Union(fullWorkingArea, screen.Bounds);
|
|
|
|
Rectangle intersection = Rectangle.Intersect(fullWorkingArea, newBounds);
|
|
if (intersection.Width < 20 || intersection.Height < 20 || !_settings.Contains("mainForm.Location.X"))
|
|
{
|
|
newBounds.X = (Screen.PrimaryScreen.WorkingArea.Width / 2) - (newBounds.Width / 2);
|
|
newBounds.Y = (Screen.PrimaryScreen.WorkingArea.Height / 2) - (newBounds.Height / 2);
|
|
}
|
|
|
|
Bounds = newBounds;
|
|
|
|
RestoreCollapsedNodeState(treeView);
|
|
|
|
FormClosed += MainForm_FormClosed;
|
|
}
|
|
|
|
private void RestoreCollapsedNodeState(TreeViewAdv treeViewAdv)
|
|
{
|
|
var collapsedHwNodes = treeViewAdv.AllNodes
|
|
.Where(n => n.IsExpanded && n.Tag is IExpandPersistNode expandPersistNode && !expandPersistNode.Expanded)
|
|
.OrderByDescending(n => n.Level)
|
|
.ToList();
|
|
|
|
foreach (TreeNodeAdv node in collapsedHwNodes)
|
|
{
|
|
node.IsExpanded = false;
|
|
}
|
|
}
|
|
|
|
private void CloseApplication()
|
|
{
|
|
FormClosed -= MainForm_FormClosed;
|
|
|
|
Visible = false;
|
|
_systemTray.IsMainIconEnabled = false;
|
|
timer.Enabled = false;
|
|
_computer.Close();
|
|
SaveConfiguration();
|
|
if (_runWebServer.Value)
|
|
Server.Quit();
|
|
|
|
_systemTray.Dispose();
|
|
timer.Dispose();
|
|
backgroundUpdater.Dispose();
|
|
|
|
Application.Exit();
|
|
}
|
|
|
|
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
|
|
{
|
|
CloseApplication();
|
|
}
|
|
|
|
private void AboutMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
_ = new AboutBox().ShowDialog();
|
|
}
|
|
|
|
private void TreeView_Click(object sender, EventArgs e)
|
|
{
|
|
if (!(e is MouseEventArgs m) || (m.Button != MouseButtons.Left && m.Button != MouseButtons.Right))
|
|
return;
|
|
|
|
NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
|
|
if (m.Button == MouseButtons.Left && info.Node != null)
|
|
{
|
|
if (info.Node.Tag is IExpandPersistNode expandPersistNode)
|
|
{
|
|
expandPersistNode.Expanded = info.Node.IsExpanded;
|
|
}
|
|
return;
|
|
}
|
|
|
|
treeView.SelectedNode = info.Node;
|
|
if (info.Node != null)
|
|
{
|
|
if (info.Node.Tag is SensorNode node && node.Sensor != null)
|
|
{
|
|
treeContextMenu.Items.Clear();
|
|
if (node.Sensor.Parameters.Count > 0)
|
|
{
|
|
ToolStripItem item = new ToolStripMenuItem("Parameters...");
|
|
item.Click += delegate { ShowParameterForm(node.Sensor); };
|
|
treeContextMenu.Items.Add(item);
|
|
}
|
|
|
|
if (nodeTextBoxText.EditEnabled)
|
|
{
|
|
ToolStripItem item = new ToolStripMenuItem("Rename");
|
|
item.Click += delegate { nodeTextBoxText.BeginEdit(); };
|
|
treeContextMenu.Items.Add(item);
|
|
}
|
|
|
|
if (node.IsVisible)
|
|
{
|
|
ToolStripItem item = new ToolStripMenuItem("Hide");
|
|
item.Click += delegate { node.IsVisible = false; };
|
|
treeContextMenu.Items.Add(item);
|
|
}
|
|
else
|
|
{
|
|
ToolStripItem item = new ToolStripMenuItem("Unhide");
|
|
item.Click += delegate { node.IsVisible = true; };
|
|
treeContextMenu.Items.Add(item);
|
|
}
|
|
|
|
treeContextMenu.Items.Add(new ToolStripSeparator());
|
|
{
|
|
ToolStripItem item = new ToolStripMenuItem("Pen Color...");
|
|
item.Click += delegate
|
|
{
|
|
ColorDialog dialog = new() { Color = node.PenColor.GetValueOrDefault() };
|
|
if (dialog.ShowDialog() == DialogResult.OK)
|
|
node.PenColor = dialog.Color;
|
|
};
|
|
|
|
treeContextMenu.Items.Add(item);
|
|
}
|
|
|
|
{
|
|
ToolStripItem item = new ToolStripMenuItem("Reset Pen Color");
|
|
item.Click += delegate { node.PenColor = null; };
|
|
treeContextMenu.Items.Add(item);
|
|
}
|
|
|
|
treeContextMenu.Items.Add(new ToolStripSeparator());
|
|
{
|
|
ToolStripMenuItem item = new("Show in Tray") { Checked = _systemTray.Contains(node.Sensor) };
|
|
item.Click += delegate
|
|
{
|
|
if (item.Checked)
|
|
_systemTray.Remove(node.Sensor);
|
|
else
|
|
_systemTray.Add(node.Sensor, true);
|
|
};
|
|
|
|
treeContextMenu.Items.Add(item);
|
|
}
|
|
|
|
if (_gadget != null)
|
|
{
|
|
ToolStripMenuItem item = new("Show in Gadget") { Checked = _gadget.Contains(node.Sensor) };
|
|
item.Click += delegate
|
|
{
|
|
if (item.Checked)
|
|
{
|
|
_gadget.Remove(node.Sensor);
|
|
}
|
|
else
|
|
{
|
|
_gadget.Add(node.Sensor);
|
|
}
|
|
};
|
|
|
|
treeContextMenu.Items.Add(item);
|
|
}
|
|
|
|
if (node.Sensor.Control != null)
|
|
{
|
|
treeContextMenu.Items.Add(new ToolStripSeparator());
|
|
IControl control = node.Sensor.Control;
|
|
ToolStripMenuItem controlItem = new("Control");
|
|
ToolStripItem defaultItem = new ToolStripMenuItem("Default") { Checked = control.ControlMode == ControlMode.Default };
|
|
controlItem.DropDownItems.Add(defaultItem);
|
|
defaultItem.Click += delegate { control.SetDefault(); };
|
|
ToolStripMenuItem manualItem = new("Manual");
|
|
controlItem.DropDownItems.Add(manualItem);
|
|
manualItem.Checked = control.ControlMode == ControlMode.Software;
|
|
for (int i = 0; i <= 100; i += 5)
|
|
{
|
|
if (i <= control.MaxSoftwareValue &&
|
|
i >= control.MinSoftwareValue)
|
|
{
|
|
ToolStripMenuItem item = new ToolStripRadioButtonMenuItem(i + " %");
|
|
manualItem.DropDownItems.Add(item);
|
|
item.Checked = control.ControlMode == ControlMode.Software && Math.Round(control.SoftwareValue) == i;
|
|
int softwareValue = i;
|
|
item.Click += delegate { control.SetSoftware(softwareValue); };
|
|
}
|
|
}
|
|
|
|
treeContextMenu.Items.Add(controlItem);
|
|
}
|
|
|
|
treeContextMenu.Show(treeView, new Point(m.X, m.Y));
|
|
}
|
|
|
|
if (info.Node.Tag is HardwareNode hardwareNode && hardwareNode.Hardware != null)
|
|
{
|
|
treeContextMenu.Items.Clear();
|
|
|
|
if (nodeTextBoxText.EditEnabled)
|
|
{
|
|
ToolStripItem item = new ToolStripMenuItem("Rename");
|
|
item.Click += delegate { nodeTextBoxText.BeginEdit(); };
|
|
treeContextMenu.Items.Add(item);
|
|
}
|
|
|
|
treeContextMenu.Show(treeView, new Point(m.X, m.Y));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SaveReportMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
string report = _computer.GetReport();
|
|
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
|
{
|
|
using (TextWriter w = new StreamWriter(saveFileDialog.FileName))
|
|
{
|
|
w.Write(report);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SysTrayHideShow()
|
|
{
|
|
Visible = !Visible;
|
|
if (Visible)
|
|
Activate();
|
|
}
|
|
|
|
protected override void WndProc(ref Message m)
|
|
{
|
|
const int WM_SYSCOMMAND = 0x112;
|
|
const int WM_WININICHANGE = 0x001A;
|
|
const int SC_MINIMIZE = 0xF020;
|
|
const int SC_CLOSE = 0xF060;
|
|
|
|
if (_minimizeToTray.Value && m.Msg == WM_SYSCOMMAND && m.WParam.ToInt64() == SC_MINIMIZE)
|
|
{
|
|
SysTrayHideShow();
|
|
}
|
|
else if (m.Msg == WM_WININICHANGE && Marshal.PtrToStringUni(m.LParam) == "ImmersiveColorSet" && _autoThemeMenuItem?.Checked == true)
|
|
{
|
|
Theme.SetAutoTheme();
|
|
}
|
|
else if (_minimizeOnClose.Value && m.Msg == WM_SYSCOMMAND && m.WParam.ToInt64() == SC_CLOSE)
|
|
{
|
|
//Apparently the user wants to minimize rather than close
|
|
//Now we still need to check if we're going to the tray or not
|
|
//Note: the correct way to do this would be to send out SC_MINIMIZE,
|
|
//but since the code here is so simple,
|
|
//that would just be a waste of time.
|
|
if (_minimizeToTray.Value)
|
|
SysTrayHideShow();
|
|
else
|
|
WindowState = FormWindowState.Minimized;
|
|
}
|
|
else
|
|
{
|
|
base.WndProc(ref m);
|
|
}
|
|
}
|
|
|
|
private void HideShowClick(object sender, EventArgs e)
|
|
{
|
|
SysTrayHideShow();
|
|
}
|
|
|
|
private void ShowParameterForm(ISensor sensorForm)
|
|
{
|
|
ParameterForm form = new() { Parameters = sensorForm.Parameters, captionLabel = { Text = sensorForm.Name } };
|
|
form.ShowDialog();
|
|
}
|
|
|
|
private void TreeView_NodeMouseDoubleClick(object sender, TreeNodeAdvMouseEventArgs e)
|
|
{
|
|
if (e.Node.Tag is SensorNode node && node.Sensor != null && node.Sensor.Parameters.Count > 0)
|
|
ShowParameterForm(node.Sensor);
|
|
}
|
|
|
|
private void CelsiusMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
celsiusMenuItem.Checked = true;
|
|
fahrenheitMenuItem.Checked = false;
|
|
_unitManager.TemperatureUnit = TemperatureUnit.Celsius;
|
|
}
|
|
|
|
private void FahrenheitMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
celsiusMenuItem.Checked = false;
|
|
fahrenheitMenuItem.Checked = true;
|
|
_unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
|
|
}
|
|
|
|
private void ResetMinMaxMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
_computer.Accept(new SensorVisitor(delegate(ISensor sensorClick)
|
|
{
|
|
sensorClick.ResetMin();
|
|
sensorClick.ResetMax();
|
|
}));
|
|
}
|
|
|
|
private void resetPlotMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
_computer.Accept(new SensorVisitor(delegate (ISensor sensorClick)
|
|
{
|
|
sensorClick.ClearValues();
|
|
}));
|
|
}
|
|
|
|
private void MainForm_MoveOrResize(object sender, EventArgs e)
|
|
{
|
|
if (WindowState != FormWindowState.Minimized)
|
|
{
|
|
_settings.SetValue("mainForm.Location.X", Bounds.X);
|
|
_settings.SetValue("mainForm.Location.Y", Bounds.Y);
|
|
_settings.SetValue("mainForm.Width", Bounds.Width);
|
|
_settings.SetValue("mainForm.Height", Bounds.Height);
|
|
}
|
|
}
|
|
|
|
private void ResetClick(object sender, EventArgs e)
|
|
{
|
|
// disable the fallback MainIcon during reset, otherwise icon visibility
|
|
// might be lost
|
|
_systemTray.IsMainIconEnabled = false;
|
|
_computer.Reset();
|
|
// restore the MainIcon setting
|
|
_systemTray.IsMainIconEnabled = _minimizeToTray.Value;
|
|
}
|
|
|
|
private void TreeView_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
_selectionDragging &= (e.Button & (MouseButtons.Left | MouseButtons.Right)) > 0;
|
|
if (_selectionDragging)
|
|
treeView.SelectedNode = treeView.GetNodeAt(e.Location);
|
|
}
|
|
|
|
private void TreeView_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
_selectionDragging = true;
|
|
}
|
|
|
|
private void TreeView_MouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
_selectionDragging = false;
|
|
}
|
|
|
|
private void TreeView_SizeChanged(object sender, EventArgs e)
|
|
{
|
|
int newWidth = treeView.Width;
|
|
for (int i = 1; i < treeView.Columns.Count; i++)
|
|
{
|
|
if (treeView.Columns[i].IsVisible)
|
|
newWidth -= treeView.Columns[i].Width;
|
|
}
|
|
treeView.Columns[0].Width = newWidth;
|
|
}
|
|
|
|
private void TreeView_ColumnWidthChanged(TreeColumn column)
|
|
{
|
|
int index = treeView.Columns.IndexOf(column);
|
|
int columnsWidth = 0;
|
|
foreach (TreeColumn treeColumn in treeView.Columns)
|
|
{
|
|
if (treeColumn.IsVisible)
|
|
columnsWidth += treeColumn.Width;
|
|
}
|
|
|
|
int nextColumnIndex = index + 1;
|
|
while (nextColumnIndex < treeView.Columns.Count && treeView.Columns[nextColumnIndex].IsVisible == false)
|
|
nextColumnIndex++;
|
|
|
|
if (nextColumnIndex < treeView.Columns.Count) {
|
|
int diff = treeView.Width - columnsWidth;
|
|
treeView.Columns[nextColumnIndex].Width = Math.Max(20, treeView.Columns[nextColumnIndex].Width + diff);
|
|
}
|
|
}
|
|
|
|
private void ServerInterfacePortMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
new InterfacePortForm(this).ShowDialog();
|
|
}
|
|
|
|
private void AuthWebServerMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
new AuthForm(this).ShowDialog();
|
|
}
|
|
|
|
private void perSessionFileRotationMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
dailyFileRotationMenuItem.Checked = false;
|
|
perSessionFileRotationMenuItem.Checked = true;
|
|
_logger.FileRotationMethod = LoggerFileRotation.PerSession;
|
|
}
|
|
|
|
private void dailyFileRotationMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
dailyFileRotationMenuItem.Checked = true;
|
|
perSessionFileRotationMenuItem.Checked = false;
|
|
_logger.FileRotationMethod = LoggerFileRotation.Daily;
|
|
}
|
|
}
|