4 Commits

Author SHA1 Message Date
d3c428efd8 Change label justification
All checks were successful
Deploy to Gitea Releases / deploy-to-gitea-releases (push) Successful in 56s
2026-03-06 17:13:03 -05:00
019781b2f4 Update floating status window lib
All checks were successful
Deploy to Gitea Releases / deploy-to-gitea-releases (push) Successful in 2m34s
- Pad labels
2026-03-02 18:21:44 -05:00
5bb26c1c3f Improve startup
All checks were successful
Deploy to Gitea Releases / deploy-to-gitea-releases (push) Successful in 48s
2026-02-27 16:06:23 -05:00
f8aa7c9118 Show sensor value when adding/editing sensors
All checks were successful
Deploy to Gitea Releases / deploy-to-gitea-releases (push) Successful in 49s
2026-02-27 14:34:43 -05:00
9 changed files with 93 additions and 28 deletions

View File

@@ -17,7 +17,7 @@ internal static class Data
internal static ObservableCollection<SensorEntry> SensorEntries { get; set; } = []; internal static ObservableCollection<SensorEntry> SensorEntries { get; set; } = [];
internal static async Task LoadComputer() private static async Task LoadComputer()
{ {
try try
{ {
@@ -30,8 +30,11 @@ internal static class Data
} }
} }
internal static void RefreshComputer() internal static async Task RefreshComputer()
{ {
if (_pipeClient is not { State: PipeState.Connected })
await LoadComputer();
_hardware = _pipeClient.InvokeAsync(service => service.GetHardware()).Result; _hardware = _pipeClient.InvokeAsync(service => service.GetHardware()).Result;
} }

View File

@@ -169,6 +169,15 @@ namespace HardwareMonitorStatusWindow.StatusWindow {
} }
} }
/// <summary>
/// Looks up a localized string similar to Current Value.
/// </summary>
public static string CurrentValueWatermark {
get {
return ResourceManager.GetString("CurrentValueWatermark", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Delete. /// Looks up a localized string similar to Delete.
/// </summary> /// </summary>

View File

@@ -248,4 +248,7 @@ Would you like to download and install it now?</value>
<data name="ServiceNotStarted" xml:space="preserve"> <data name="ServiceNotStarted" xml:space="preserve">
<value>Waiting for service to start...</value> <value>Waiting for service to start...</value>
</data> </data>
<data name="CurrentValueWatermark" xml:space="preserve">
<value>Current Value</value>
</data>
</root> </root>

View File

@@ -1,11 +1,11 @@
using System; using HardwareMonitorStatusWindow.Service;
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using HardwareMonitorStatusWindow.Service;
namespace HardwareMonitorStatusWindow.StatusWindow; namespace HardwareMonitorStatusWindow.StatusWindow;
@@ -18,7 +18,7 @@ public class SensorEntry : INotifyDataErrorInfo, INotifyPropertyChanged
_dataErrorDictionary.ErrorsChanged += DataErrorDictionaryErrorsChanged; _dataErrorDictionary.ErrorsChanged += DataErrorDictionaryErrorsChanged;
} }
public string? Label public string Label
{ {
get; get;
set set
@@ -28,7 +28,7 @@ public class SensorEntry : INotifyDataErrorInfo, INotifyPropertyChanged
SetField(ref field, value); SetField(ref field, value);
} }
} } = string.Empty;
public string? HardwareId public string? HardwareId
{ {
@@ -51,7 +51,7 @@ public class SensorEntry : INotifyDataErrorInfo, INotifyPropertyChanged
} }
[JsonIgnore] [JsonIgnore]
public Hardware? Hardware => Data.ComputerHardware?.FirstOrDefault(h => h.Identifier.ToString() == HardwareId); public Hardware? Hardware => Data.ComputerHardware.FirstOrDefault(h => h.Identifier.ToString() == HardwareId);
[JsonIgnore] [JsonIgnore]
public Sensor? Sensor => Hardware?.Sensors.FirstOrDefault(s => s.Identifier.ToString() == SensorId); public Sensor? Sensor => Hardware?.Sensors.FirstOrDefault(s => s.Identifier.ToString() == SensorId);
@@ -88,17 +88,16 @@ public class SensorEntry : INotifyDataErrorInfo, INotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{ {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} }
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null) private void SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{ {
if (EqualityComparer<T>.Default.Equals(field, value)) return false; if (EqualityComparer<T>.Default.Equals(field, value)) return;
field = value; field = value;
OnPropertyChanged(propertyName); OnPropertyChanged(propertyName);
return true;
} }
public string SensorValueFormat public string SensorValueFormat

View File

@@ -67,13 +67,13 @@ public partial class HardwareSettingsPanel
EditSelectedSensor(); EditSelectedSensor();
} }
private void AddSensor() private async void AddSensor()
{ {
var sensorEntry = new SensorEntry(); var sensorEntry = new SensorEntry();
var sensorWindow = new SensorWindow(); var sensorWindow = new SensorWindow();
var result = sensorWindow.Display(sensorEntry, Window.GetWindow(this)); var result = await sensorWindow.Display(sensorEntry, Window.GetWindow(this));
if (!result.HasValue || !result.Value) if (!result.HasValue || !result.Value)
return; return;
@@ -83,7 +83,7 @@ public partial class HardwareSettingsPanel
SetSensorButtonStates(); SetSensorButtonStates();
} }
private void EditSelectedSensor() private async void EditSelectedSensor()
{ {
if (SensorDataGrid.SelectedItem == null) if (SensorDataGrid.SelectedItem == null)
return; return;
@@ -92,7 +92,7 @@ public partial class HardwareSettingsPanel
var sensorWindow = new SensorWindow(); var sensorWindow = new SensorWindow();
sensorWindow.Display(sensorEntry, Window.GetWindow(this)); await sensorWindow.Display(sensorEntry, Window.GetWindow(this));
} }
private void DeleteSelectedSensors() private void DeleteSelectedSensors()

View File

@@ -68,8 +68,14 @@
DisplayMemberPath="Name" DisplayMemberPath="Name"
VirtualizingPanel.IsVirtualizing="False" VirtualizingPanel.IsVirtualizing="False"
mah:TextBoxHelper.UseFloatingWatermark="True" mah:TextBoxHelper.UseFloatingWatermark="True"
mah:TextBoxHelper.Watermark="{x:Static hardwareMonitorStatusWindow:Resources.SensorWatermark}"> mah:TextBoxHelper.Watermark="{x:Static hardwareMonitorStatusWindow:Resources.SensorWatermark}"
SelectionChanged="SensorComboBox_SelectionChanged">
</ComboBox> </ComboBox>
<TextBox Name="CurrentValueTextBox"
mah:TextBoxHelper.UseFloatingWatermark="True"
mah:TextBoxHelper.Watermark="{x:Static hardwareMonitorStatusWindow:Resources.CurrentValueWatermark}"
mah:TextBoxHelper.SelectAllOnFocus="True"
IsReadOnly="True" />
</StackPanel> </StackPanel>
<StackPanel Grid.Column="0" <StackPanel Grid.Column="0"
Grid.Row="1" Grid.Row="1"

View File

@@ -1,22 +1,28 @@
using System.Linq; using System;
using System.Windows;
using ChrisKaczor.Wpf.Validation; using ChrisKaczor.Wpf.Validation;
using HardwareMonitorStatusWindow.Service; using HardwareMonitorStatusWindow.Service;
using System.Linq;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Threading;
namespace HardwareMonitorStatusWindow.StatusWindow.SettingsWindow; namespace HardwareMonitorStatusWindow.StatusWindow.SettingsWindow;
public partial class SensorWindow public partial class SensorWindow
{ {
private readonly DispatcherTimer _timer = new();
public SensorWindow() public SensorWindow()
{ {
InitializeComponent(); InitializeComponent();
} }
public bool? Display(SensorEntry sensorEntry, Window? owner) public async Task<bool?> Display(SensorEntry sensorEntry, Window? owner)
{ {
DataContext = sensorEntry; DataContext = sensorEntry;
Data.RefreshComputer(); await Data.RefreshComputer();
HardwareTypeComboBox.ItemsSource = Data.ComputerHardware.Where(h => h.Sensors.Any()).DistinctBy(h => h.Type).Select(s => new HardwareTypeItem(s.Type)).OrderBy(s => s.Name); HardwareTypeComboBox.ItemsSource = Data.ComputerHardware.Where(h => h.Sensors.Any()).DistinctBy(h => h.Type).Select(s => new HardwareTypeItem(s.Type)).OrderBy(s => s.Name);
@@ -32,9 +38,18 @@ public partial class SensorWindow
Owner = owner; Owner = owner;
_timer.Interval = TimeSpan.FromSeconds(1);
_timer.Tick += TimerOnTick;
_timer.Start();
return ShowDialog(); return ShowDialog();
} }
private void TimerOnTick(object? sender, EventArgs e)
{
UpdateCurrentSensorValue();
}
private void HandleOkayButtonClick(object sender, RoutedEventArgs e) private void HandleOkayButtonClick(object sender, RoutedEventArgs e)
{ {
if (!this.IsValid()) if (!this.IsValid())
@@ -95,4 +110,26 @@ public partial class SensorWindow
SensorComboBox.ItemsSource = hardware.Sensors.Where(s => s.Type == sensorType.Value); SensorComboBox.ItemsSource = hardware.Sensors.Where(s => s.Type == sensorType.Value);
} }
private void SensorComboBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
UpdateCurrentSensorValue();
}
private void UpdateCurrentSensorValue()
{
var sensor = (Sensor)SensorComboBox.SelectedItem;
if (sensor?.Value == null)
{
CurrentValueTextBox.Text = string.Empty;
return;
}
var hardware = (Hardware)HardwareComboBox.SelectedItem;
var displaySensorEntry = new SensorEntry { HardwareId = hardware.Identifier, SensorId = sensor.Identifier };
CurrentValueTextBox.Text = string.Format(displaySensorEntry.SensorValueFormat, displaySensorEntry.Sensor!.Value);
}
} }

View File

@@ -28,7 +28,7 @@
<PackageReference Include="ChrisKaczor.Wpf.Controls.Link" Version="1.0.4" /> <PackageReference Include="ChrisKaczor.Wpf.Controls.Link" Version="1.0.4" />
<PackageReference Include="ChrisKaczor.Wpf.Validation" Version="1.0.4" /> <PackageReference Include="ChrisKaczor.Wpf.Validation" Version="1.0.4" />
<PackageReference Include="ChrisKaczor.Wpf.Windows.CategoryWindow" Version="1.0.2" /> <PackageReference Include="ChrisKaczor.Wpf.Windows.CategoryWindow" Version="1.0.2" />
<PackageReference Include="ChrisKaczor.Wpf.Windows.FloatingStatusWindow" Version="2.0.0.8" /> <PackageReference Include="ChrisKaczor.Wpf.Windows.FloatingStatusWindow" Version="2.0.0.9" />
<PackageReference Include="gong-wpf-dragdrop" Version="4.0.0" /> <PackageReference Include="gong-wpf-dragdrop" Version="4.0.0" />
<PackageReference Include="PipeMethodCalls" Version="4.0.3" /> <PackageReference Include="PipeMethodCalls" Version="4.0.3" />
<PackageReference Include="Serilog" Version="4.3.1" /> <PackageReference Include="Serilog" Version="4.3.1" />

View File

@@ -9,6 +9,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -139,7 +140,7 @@ internal class WindowSource : IWindowSource, IDisposable
return true; return true;
} }
private async Task Start(bool hasUpdate) private void Start(bool hasUpdate)
{ {
Log.Information("Start: hasUpdate={hasUpdate}", hasUpdate); Log.Information("Start: hasUpdate={hasUpdate}", hasUpdate);
@@ -148,7 +149,7 @@ internal class WindowSource : IWindowSource, IDisposable
Log.Information("Load"); Log.Information("Load");
await Load(); Load();
Log.Information("Starting timer"); Log.Information("Starting timer");
@@ -157,10 +158,8 @@ internal class WindowSource : IWindowSource, IDisposable
_timer.Enabled = true; _timer.Enabled = true;
} }
private static async Task Load() private static void Load()
{ {
await Data.LoadComputer();
Data.Load(); Data.Load();
} }
@@ -227,19 +226,26 @@ internal class WindowSource : IWindowSource, IDisposable
if (existingTask == null) if (existingTask == null)
{ {
_dispatcher.Invoke(() => _floatingStatusWindow.SetText(Resources.ServiceNotInstalled)); _dispatcher.Invoke(() => _floatingStatusWindow.SetText(Resources.ServiceNotInstalled));
_timer.Start();
return; return;
} }
if (existingTask.State != TaskState.Running) if (existingTask.State != TaskState.Running)
{ {
_dispatcher.Invoke(() => _floatingStatusWindow.SetText(Resources.ServiceNotStarted)); _dispatcher.Invoke(() => _floatingStatusWindow.SetText(Resources.ServiceNotStarted));
existingTask.Run();
_timer.Start();
return; return;
} }
} }
var text = new StringBuilder(); var text = new StringBuilder();
Data.RefreshComputer(); Data.RefreshComputer().Wait();
var labelLength = Data.SensorEntries.Max(x => x.Label.Length);
foreach (var sensorEntry in Data.SensorEntries) foreach (var sensorEntry in Data.SensorEntries)
{ {
@@ -249,7 +255,9 @@ internal class WindowSource : IWindowSource, IDisposable
if (text.Length > 0) if (text.Length > 0)
text.AppendLine(); text.AppendLine();
text.Append($"{sensorEntry.Label}: {string.Format(sensorEntry.SensorValueFormat, sensorEntry.Sensor.Value)}"); var label = $"{sensorEntry.Label}:";
text.Append($"{label.PadRight(labelLength + 1)} {string.Format(sensorEntry.SensorValueFormat, sensorEntry.Sensor.Value)}");
} }
_dispatcher.Invoke(() => _floatingStatusWindow.SetText(text.ToString())); _dispatcher.Invoke(() => _floatingStatusWindow.SetText(text.ToString()));