Add theme and plot thickness options (#847)
* Add theme and plot thickness options * Cleanup * Fixed themes, and made it so the plot colors are updated when the theme is changed * I think supporting themes beyond dark, light, and black is unecessary for the time being. * recall theme from settings before instantiating plot * Check for null setting * committing to merge * Fix * Cleanup * Cleanup * Fix from comments. Thank you kamkie! * Fixing last UI bugs * Fix windowed plot not theming on relaunch, change theme, show plot
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using LibreHardwareMonitor.UI.Themes;
|
||||
|
||||
namespace LibreHardwareMonitor.UI;
|
||||
|
||||
@@ -21,6 +22,7 @@ public sealed partial class AboutBox : Form
|
||||
projectLinkLabel.Links.Add(0, projectLinkLabel.Text.Length, "https://github.com/LibreHardwareMonitor/LibreHardwareMonitor");
|
||||
licenseLinkLabel.Links.Remove(licenseLinkLabel.Links[0]);
|
||||
licenseLinkLabel.Links.Add(0, licenseLinkLabel.Text.Length, "https://www.mozilla.org/en-US/MPL/2.0/");
|
||||
Theme.Current.Apply(this);
|
||||
}
|
||||
|
||||
private void LinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
@@ -31,4 +33,4 @@ public sealed partial class AboutBox : Form
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+59
-2
@@ -87,6 +87,12 @@ namespace LibreHardwareMonitor.UI
|
||||
this.plotWindowMenuItem = new LibreHardwareMonitor.UI.ToolStripRadioButtonMenuItem();
|
||||
this.plotBottomMenuItem = new LibreHardwareMonitor.UI.ToolStripRadioButtonMenuItem();
|
||||
this.plotRightMenuItem = new LibreHardwareMonitor.UI.ToolStripRadioButtonMenuItem();
|
||||
this.themeMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.strokeThicknessMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.strokeThickness1ptMenuItem = new LibreHardwareMonitor.UI.ToolStripRadioButtonMenuItem();
|
||||
this.strokeThickness2ptMenuItem = new LibreHardwareMonitor.UI.ToolStripRadioButtonMenuItem();
|
||||
this.strokeThickness3ptMenuItem = new LibreHardwareMonitor.UI.ToolStripRadioButtonMenuItem();
|
||||
this.strokeThickness4ptMenuItem = new LibreHardwareMonitor.UI.ToolStripRadioButtonMenuItem();
|
||||
this.splitPlotPanelScalingMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.splitPanelPercentageScalingMenuItem = new LibreHardwareMonitor.UI.ToolStripRadioButtonMenuItem();
|
||||
this.splitPanelFixedPlotScalingMenuItem = new LibreHardwareMonitor.UI.ToolStripRadioButtonMenuItem();
|
||||
@@ -440,6 +446,8 @@ namespace LibreHardwareMonitor.UI
|
||||
this.separatorMenuItem,
|
||||
this.temperatureUnitsMenuItem,
|
||||
this.plotLocationMenuItem,
|
||||
this.strokeThicknessMenuItem,
|
||||
this.themeMenuItem,
|
||||
this.splitPlotPanelScalingMenuItem,
|
||||
this.logSeparatorMenuItem,
|
||||
this.logSensorsMenuItem,
|
||||
@@ -537,6 +545,51 @@ namespace LibreHardwareMonitor.UI
|
||||
this.plotRightMenuItem.Size = new System.Drawing.Size(118, 22);
|
||||
this.plotRightMenuItem.Text = "Right";
|
||||
//
|
||||
// themeMenuItem
|
||||
//
|
||||
this.themeMenuItem.Name = "themeMenuItem";
|
||||
this.themeMenuItem.Size = new System.Drawing.Size(278, 22);
|
||||
this.themeMenuItem.Text = "Theme";
|
||||
//
|
||||
// strokeThicknessMenuItem
|
||||
//
|
||||
this.strokeThicknessMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.strokeThickness1ptMenuItem,
|
||||
this.strokeThickness2ptMenuItem,
|
||||
this.strokeThickness3ptMenuItem,
|
||||
this.strokeThickness4ptMenuItem});
|
||||
this.strokeThicknessMenuItem.Name = "strokeThicknessMenuItem";
|
||||
this.strokeThicknessMenuItem.Size = new System.Drawing.Size(278, 22);
|
||||
this.strokeThicknessMenuItem.Text = "Stroke Thickness";
|
||||
//
|
||||
// strokeThickness1ptMenuItem
|
||||
//
|
||||
this.strokeThickness1ptMenuItem.CheckOnClick = true;
|
||||
this.strokeThickness1ptMenuItem.Name = "strokeThickness1ptMenuItem";
|
||||
this.strokeThickness1ptMenuItem.Size = new System.Drawing.Size(224, 22);
|
||||
this.strokeThickness1ptMenuItem.Text = "1pt";
|
||||
//
|
||||
// strokeThickness2ptMenuItem
|
||||
//
|
||||
this.strokeThickness2ptMenuItem.CheckOnClick = true;
|
||||
this.strokeThickness2ptMenuItem.Name = "strokeThickness2ptMenuItem";
|
||||
this.strokeThickness2ptMenuItem.Size = new System.Drawing.Size(224, 22);
|
||||
this.strokeThickness2ptMenuItem.Text = "2pt";
|
||||
//
|
||||
// strokeThickness3ptMenuItem
|
||||
//
|
||||
this.strokeThickness3ptMenuItem.CheckOnClick = true;
|
||||
this.strokeThickness3ptMenuItem.Name = "strokeThickness3ptMenuItem";
|
||||
this.strokeThickness3ptMenuItem.Size = new System.Drawing.Size(224, 22);
|
||||
this.strokeThickness3ptMenuItem.Text = "3pt";
|
||||
//
|
||||
// strokeThickness4ptMenuItem
|
||||
//
|
||||
this.strokeThickness4ptMenuItem.CheckOnClick = true;
|
||||
this.strokeThickness4ptMenuItem.Name = "strokeThickness4ptMenuItem";
|
||||
this.strokeThickness4ptMenuItem.Size = new System.Drawing.Size(224, 26);
|
||||
this.strokeThickness4ptMenuItem.Text = "4pt";
|
||||
//
|
||||
// attachedPlotPanelScalingMenuItem
|
||||
//
|
||||
this.splitPlotPanelScalingMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
@@ -910,8 +963,6 @@ namespace LibreHardwareMonitor.UI
|
||||
//
|
||||
// splitContainer
|
||||
//
|
||||
this.splitContainer.Border3DStyle = System.Windows.Forms.Border3DStyle.Raised;
|
||||
this.splitContainer.Color = System.Drawing.SystemColors.Control;
|
||||
this.splitContainer.Cursor = System.Windows.Forms.Cursors.Default;
|
||||
this.splitContainer.Location = new System.Drawing.Point(12, 12);
|
||||
this.splitContainer.Name = "splitContainer";
|
||||
@@ -1100,6 +1151,12 @@ namespace LibreHardwareMonitor.UI
|
||||
private System.Windows.Forms.ToolStripMenuItem psuMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem batteryMenuItem;
|
||||
private System.ComponentModel.BackgroundWorker backgroundUpdater;
|
||||
private System.Windows.Forms.ToolStripMenuItem themeMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem strokeThicknessMenuItem;
|
||||
private ToolStripRadioButtonMenuItem strokeThickness4ptMenuItem;
|
||||
private ToolStripRadioButtonMenuItem strokeThickness1ptMenuItem;
|
||||
private ToolStripRadioButtonMenuItem strokeThickness2ptMenuItem;
|
||||
private ToolStripRadioButtonMenuItem strokeThickness3ptMenuItem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,12 @@ 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;
|
||||
|
||||
@@ -21,6 +23,7 @@ namespace LibreHardwareMonitor.UI;
|
||||
|
||||
public sealed partial class MainForm : Form
|
||||
{
|
||||
private ToolStripMenuItem _autoThemeMenuItem;
|
||||
private readonly UserOption _autoStart;
|
||||
private readonly Computer _computer;
|
||||
private readonly SensorGadget _gadget;
|
||||
@@ -30,7 +33,6 @@ public sealed partial class MainForm : Form
|
||||
private readonly UserOption _logSensors;
|
||||
private readonly UserOption _minimizeOnClose;
|
||||
private readonly UserOption _minimizeToTray;
|
||||
private readonly Color[] _plotColorPalette;
|
||||
private readonly PlotPanel _plotPanel;
|
||||
private readonly UserOption _readBatterySensors;
|
||||
private readonly UserOption _readCpuSensors;
|
||||
@@ -59,6 +61,8 @@ public sealed partial class MainForm : Form
|
||||
private bool _selectionDragging;
|
||||
private IDictionary<ISensor, Color> _sensorPlotColors = new Dictionary<ISensor, Color>();
|
||||
private UserOption _showPlot;
|
||||
private UserRadioGroup _strokeThickness;
|
||||
private double _plotStrokeThickness = 2;
|
||||
|
||||
public MainForm()
|
||||
{
|
||||
@@ -89,6 +93,16 @@ public sealed partial class MainForm : Form
|
||||
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;
|
||||
@@ -118,7 +132,6 @@ public sealed partial class MainForm : Form
|
||||
// Unix
|
||||
treeView.RowHeight = Math.Max(treeView.RowHeight, 18);
|
||||
splitContainer.BorderStyle = BorderStyle.None;
|
||||
splitContainer.Border3DStyle = Border3DStyle.Adjust;
|
||||
splitContainer.SplitterWidth = 4;
|
||||
treeView.BorderStyle = BorderStyle.Fixed3D;
|
||||
_plotPanel.BorderStyle = BorderStyle.Fixed3D;
|
||||
@@ -142,21 +155,6 @@ public sealed partial class MainForm : Form
|
||||
nodeTextBoxValue.ToolTipProvider = tooltipProvider;
|
||||
_logger = new Logger(_computer);
|
||||
|
||||
_plotColorPalette = new Color[13];
|
||||
_plotColorPalette[0] = Color.Blue;
|
||||
_plotColorPalette[1] = Color.OrangeRed;
|
||||
_plotColorPalette[2] = Color.Green;
|
||||
_plotColorPalette[3] = Color.LightSeaGreen;
|
||||
_plotColorPalette[4] = Color.Goldenrod;
|
||||
_plotColorPalette[5] = Color.DarkViolet;
|
||||
_plotColorPalette[6] = Color.YellowGreen;
|
||||
_plotColorPalette[7] = Color.SaddleBrown;
|
||||
_plotColorPalette[8] = Color.RoyalBlue;
|
||||
_plotColorPalette[9] = Color.DeepPink;
|
||||
_plotColorPalette[10] = Color.MediumSeaGreen;
|
||||
_plotColorPalette[11] = Color.Olive;
|
||||
_plotColorPalette[12] = Color.Firebrick;
|
||||
|
||||
_computer.HardwareAdded += HardwareAdded;
|
||||
_computer.HardwareRemoved += HardwareRemoved;
|
||||
_computer.Open();
|
||||
@@ -432,6 +430,7 @@ public sealed partial class MainForm : Form
|
||||
_computer.Accept(new SensorVisitor(delegate(ISensor sensor) { sensor.ValuesTimeWindow = timeWindow; }));
|
||||
};
|
||||
|
||||
InitializeTheme();
|
||||
InitializePlotForm();
|
||||
InitializeSplitter();
|
||||
|
||||
@@ -501,6 +500,71 @@ public sealed partial class MainForm : Form
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -528,7 +592,10 @@ public sealed partial class MainForm : Form
|
||||
if (_plotLocation.Value == 0)
|
||||
{
|
||||
if (_showPlot.Value && Visible)
|
||||
{
|
||||
Theme.Current.Apply(_plotForm);
|
||||
_plotForm.Show();
|
||||
}
|
||||
else
|
||||
_plotForm.Hide();
|
||||
}
|
||||
@@ -540,6 +607,16 @@ public sealed partial class MainForm : Form
|
||||
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)
|
||||
@@ -632,6 +709,8 @@ public sealed partial class MainForm : Form
|
||||
else
|
||||
_plotForm.Hide();
|
||||
};
|
||||
|
||||
Theme.Current.Apply(_plotForm);
|
||||
}
|
||||
|
||||
private void InsertSorted(IList<Node> nodes, HardwareNode node)
|
||||
@@ -705,7 +784,7 @@ public sealed partial class MainForm : Form
|
||||
if (!sensorNode.PenColor.HasValue)
|
||||
{
|
||||
colors.Add(sensorNode.Sensor,
|
||||
_plotColorPalette[colorIndex % _plotColorPalette.Length]);
|
||||
Theme.Current.PlotColorPalette[colorIndex % Theme.Current.PlotColorPalette.Length]);
|
||||
}
|
||||
|
||||
selected.Add(sensorNode.Sensor);
|
||||
@@ -729,7 +808,7 @@ public sealed partial class MainForm : Form
|
||||
Color curColor = colors[curSelectedSensor];
|
||||
if (usedColors.Contains(curColor))
|
||||
{
|
||||
foreach (Color potentialNewColor in _plotColorPalette)
|
||||
foreach (Color potentialNewColor in Theme.Current.PlotColorPalette)
|
||||
{
|
||||
if (!colors.Values.Contains(potentialNewColor))
|
||||
{
|
||||
@@ -752,7 +831,7 @@ public sealed partial class MainForm : Form
|
||||
}
|
||||
|
||||
_sensorPlotColors = colors;
|
||||
_plotPanel.SetSensors(selected, colors);
|
||||
_plotPanel.SetSensors(selected, colors, _plotStrokeThickness);
|
||||
}
|
||||
|
||||
private void NodeTextBoxText_EditorShowing(object sender, CancelEventArgs e)
|
||||
@@ -909,7 +988,6 @@ public sealed partial class MainForm : Form
|
||||
{
|
||||
expandPersistNode.Expanded = info.Node.IsExpanded;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1065,6 +1143,7 @@ public sealed partial class MainForm : Form
|
||||
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;
|
||||
|
||||
@@ -1072,6 +1151,10 @@ public sealed partial class MainForm : Form
|
||||
{
|
||||
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
|
||||
|
||||
@@ -16,6 +16,7 @@ using OxyPlot.Annotations;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.WindowsForms;
|
||||
using OxyPlot.Series;
|
||||
using LibreHardwareMonitor.UI.Themes;
|
||||
|
||||
namespace LibreHardwareMonitor.UI;
|
||||
|
||||
@@ -48,7 +49,7 @@ public class PlotPanel : UserControl
|
||||
SetDpi();
|
||||
_model = CreatePlotModel();
|
||||
|
||||
_plot = new PlotView { Dock = DockStyle.Fill, Model = _model, BackColor = Color.White, ContextMenuStrip = CreateMenu() };
|
||||
_plot = new PlotView { Dock = DockStyle.Fill, Model = _model, BackColor = Color.Black, ContextMenuStrip = CreateMenu() };
|
||||
_plot.MouseDown += (sender, e) =>
|
||||
{
|
||||
if (e.Button == MouseButtons.Right)
|
||||
@@ -72,6 +73,34 @@ public class PlotPanel : UserControl
|
||||
SuspendLayout();
|
||||
Controls.Add(_plot);
|
||||
ResumeLayout(true);
|
||||
_plot.ShowTracker(new TrackerHitResult());
|
||||
_plot.HideTracker();
|
||||
foreach (Control plotControl in _plot.Controls)
|
||||
{
|
||||
plotControl.BackColor = Theme.Current.PlotBackgroundColor;
|
||||
plotControl.ForeColor = Theme.Current.PlotTextColor;
|
||||
}
|
||||
ApplyTheme();
|
||||
}
|
||||
|
||||
public void ApplyTheme()
|
||||
{
|
||||
_model.Background = Theme.Current.PlotBackgroundColor.ToOxyColor();
|
||||
_model.PlotAreaBorderColor = Theme.Current.PlotBorderColor.ToOxyColor();
|
||||
foreach (Axis axis in _model.Axes)
|
||||
{
|
||||
axis.AxislineColor = Theme.Current.PlotBorderColor.ToOxyColor();
|
||||
axis.MajorGridlineColor = Theme.Current.PlotGridMajorColor.ToOxyColor();
|
||||
axis.MinorGridlineColor = Theme.Current.PlotGridMinorColor.ToOxyColor();
|
||||
axis.TextColor = Theme.Current.PlotTextColor.ToOxyColor();
|
||||
axis.TitleColor = Theme.Current.PlotTextColor.ToOxyColor();
|
||||
axis.MinorTicklineColor = Theme.Current.PlotBorderColor.ToOxyColor();
|
||||
axis.TicklineColor = Theme.Current.PlotBorderColor.ToOxyColor();
|
||||
}
|
||||
foreach (LineAnnotation annotation in _model.Annotations.Select(x => x as LineAnnotation).Where(x => x != null))
|
||||
{
|
||||
annotation.Color = Theme.Current.PlotBorderColor.ToOxyColor();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCurrentSettings()
|
||||
@@ -88,6 +117,7 @@ public class PlotPanel : UserControl
|
||||
private ContextMenuStrip CreateMenu()
|
||||
{
|
||||
ContextMenuStrip menu = new ContextMenuStrip();
|
||||
menu.Renderer = new ThemedToolStripRenderer();
|
||||
menu.Opening += (sender, e) =>
|
||||
{
|
||||
if (_cancelContextMenu)
|
||||
@@ -227,7 +257,7 @@ public class PlotPanel : UserControl
|
||||
ClipByXAxis = false,
|
||||
ClipByYAxis = false,
|
||||
LineStyle = LineStyle.Solid,
|
||||
Color = OxyColors.Black,
|
||||
Color = Theme.Current.PlotBorderColor.ToOxyColor(),
|
||||
YAxisKey = typeName,
|
||||
StrokeThickness = 2,
|
||||
};
|
||||
@@ -275,7 +305,7 @@ public class PlotPanel : UserControl
|
||||
_dpiYScale = _dpiY / defaultDpi;
|
||||
}
|
||||
|
||||
public void SetSensors(List<ISensor> sensors, IDictionary<ISensor, Color> colors)
|
||||
public void SetSensors(List<ISensor> sensors, IDictionary<ISensor, Color> colors, double strokeThickness)
|
||||
{
|
||||
_model.Series.Clear();
|
||||
var types = new HashSet<SensorType>();
|
||||
@@ -304,7 +334,7 @@ public class PlotPanel : UserControl
|
||||
{
|
||||
ItemsSource = sensor.Values.Select(value => CreateDataPoint(sensor.SensorType, value)),
|
||||
Color = colors[sensor].ToOxyColor(),
|
||||
StrokeThickness = 1,
|
||||
StrokeThickness = strokeThickness,
|
||||
YAxisKey = _axes[sensor.SensorType].Key,
|
||||
Title = sensor.Hardware.Name + " " + sensor.Name
|
||||
};
|
||||
@@ -325,6 +355,15 @@ public class PlotPanel : UserControl
|
||||
InvalidatePlot();
|
||||
}
|
||||
|
||||
public void UpdateStrokeThickness(double strokeThickness)
|
||||
{
|
||||
foreach (LineSeries series in _model.Series)
|
||||
{
|
||||
series.StrokeThickness = strokeThickness;
|
||||
}
|
||||
InvalidatePlot();
|
||||
}
|
||||
|
||||
private void UpdateAxesPosition()
|
||||
{
|
||||
if (_stackedAxes.Value)
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using LibreHardwareMonitor.UI.Themes;
|
||||
|
||||
namespace LibreHardwareMonitor.UI;
|
||||
|
||||
public class SplitContainerAdv : SplitContainer
|
||||
{
|
||||
private int _delta;
|
||||
private Border3DStyle _border3DStyle = Border3DStyle.Raised;
|
||||
private Color _bgColor = SystemColors.Control;
|
||||
private bool _mouseOver;
|
||||
|
||||
public SplitContainerAdv()
|
||||
{
|
||||
@@ -32,10 +32,8 @@ public class SplitContainerAdv : SplitContainer
|
||||
Graphics g = e.Graphics;
|
||||
Rectangle r = SplitterRectangle;
|
||||
|
||||
using (SolidBrush brush = new SolidBrush(_bgColor))
|
||||
using (SolidBrush brush = new SolidBrush(_mouseOver ? Theme.Current.SplitterHoverColor : Theme.Current.SplitterColor))
|
||||
g.FillRectangle(brush, r);
|
||||
|
||||
ControlPaint.DrawBorder3D(g, r, _border3DStyle);
|
||||
}
|
||||
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
@@ -73,6 +71,13 @@ public class SplitContainerAdv : SplitContainer
|
||||
IsSplitterFixed = true;
|
||||
}
|
||||
|
||||
protected override void OnMouseEnter(EventArgs e)
|
||||
{
|
||||
base.OnMouseEnter(e);
|
||||
_mouseOver = true;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
if (IsSplitterFixed)
|
||||
@@ -107,6 +112,8 @@ public class SplitContainerAdv : SplitContainer
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
Cursor = Cursors.Default;
|
||||
_mouseOver = false;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseEventArgs e)
|
||||
@@ -115,24 +122,4 @@ public class SplitContainerAdv : SplitContainer
|
||||
IsSplitterFixed = false;
|
||||
Cursor.Current = Cursors.Default;
|
||||
}
|
||||
|
||||
public Border3DStyle Border3DStyle
|
||||
{
|
||||
get { return _border3DStyle; }
|
||||
set
|
||||
{
|
||||
_border3DStyle = value;
|
||||
Invalidate(false);
|
||||
}
|
||||
}
|
||||
|
||||
public Color Color
|
||||
{
|
||||
get { return _bgColor; }
|
||||
set
|
||||
{
|
||||
_bgColor = value;
|
||||
Invalidate(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using Aga.Controls.Tree;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace LibreHardwareMonitor.UI.Themes
|
||||
{
|
||||
public abstract class Theme
|
||||
{
|
||||
private static Theme _current = new LightTheme();
|
||||
public static Theme Current
|
||||
{
|
||||
get { return _current; }
|
||||
set
|
||||
{
|
||||
_current = value;
|
||||
foreach (Form form in Application.OpenForms)
|
||||
{
|
||||
_current.Apply(form);
|
||||
}
|
||||
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Init()
|
||||
{
|
||||
TreeViewAdv.CustomPlusMinusRenderFunc = (g, rect, isExpanded) =>
|
||||
{
|
||||
int x = rect.Left;
|
||||
int y = rect.Top + 5;
|
||||
int size = 8;
|
||||
using (Brush brush = new SolidBrush(Current.BackgroundColor))
|
||||
{
|
||||
g.FillRectangle(brush, x - 1, y - 1, size + 4, size + 4);
|
||||
}
|
||||
using (Pen pen = new Pen(Current.TreeOutlineColor))
|
||||
{
|
||||
|
||||
g.DrawRectangle(pen, x, y, size, size);
|
||||
g.DrawLine(pen, x + 2, y + (size / 2), x + size - 2, y + (size / 2));
|
||||
if (!isExpanded)
|
||||
{
|
||||
g.DrawLine(pen, x + (size / 2), y + 2, x + (size / 2), y + size - 2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TreeViewAdv.CustomCheckRenderFunc = (g, rect, isChecked) =>
|
||||
{
|
||||
int x = rect.Left;
|
||||
int y = rect.Top + 1;
|
||||
int size = 12;
|
||||
using (Brush brush = new SolidBrush(Current.BackgroundColor))
|
||||
{
|
||||
g.FillRectangle(brush, x - 1, y - 1, 12, 12);
|
||||
}
|
||||
using (Pen pen = new Pen(Current.TreeOutlineColor))
|
||||
{
|
||||
g.DrawRectangle(pen, x, y, size, size);
|
||||
if (isChecked)
|
||||
{
|
||||
x += 3;
|
||||
y += 3;
|
||||
g.DrawLine(pen, x, y + 3, x + 2, y + 5);
|
||||
g.DrawLine(pen, x + 2, y + 5, x + 6, y + 1);
|
||||
g.DrawLine(pen, x, y + 4, x + 2, y + 6);
|
||||
g.DrawLine(pen, x + 2, y + 6, x + 6, y + 2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TreeViewAdv.CustomColumnBackgroundRenderFunc = (g, rect, isPressed, isHot) =>
|
||||
{
|
||||
using (Brush brush = new SolidBrush(Current.TreeBackgroundColor))
|
||||
{
|
||||
g.FillRectangle(brush, rect);
|
||||
}
|
||||
using (Pen pen = new Pen(Current.TreeRowSepearatorColor))
|
||||
{
|
||||
g.DrawLine(pen, rect.Left, rect.Top, rect.Right, rect.Top);
|
||||
g.DrawLine(pen, rect.Left, rect.Top + 1, rect.Right, rect.Top + 1);
|
||||
}
|
||||
};
|
||||
|
||||
TreeViewAdv.CustomColumnTextRenderFunc = (g, rect, font, text) =>
|
||||
{
|
||||
TextRenderer.DrawText(g, text, font, rect, Current.TreeTextColor, TextFormatFlags.Left);
|
||||
};
|
||||
|
||||
TreeViewAdv.CustomHorizontalLinePen = new Pen(Current.TreeRowSepearatorColor);
|
||||
TreeViewAdv.CustomSelectedRowBrush = new SolidBrush(Current.TreeSelectedBackgroundColor);
|
||||
TreeViewAdv.CustomSelectedTextColor = Current.TreeSelectedTextColor;
|
||||
}
|
||||
|
||||
private static List<Theme> _all;
|
||||
public static List<Theme> All
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_all == null)
|
||||
{
|
||||
_all = new List<Theme>();
|
||||
foreach (Type type in typeof(Theme).Assembly.GetTypes())
|
||||
{
|
||||
if (type != typeof(Theme) && typeof(Theme).IsAssignableFrom(type))
|
||||
{
|
||||
_all.Add((Theme)type.GetConstructor(new Type[] { }).Invoke(new object[] { }));
|
||||
}
|
||||
}
|
||||
}
|
||||
return _all.OrderBy(x => x.DisplayName).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool SupportsAutoThemeSwitching()
|
||||
{
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", -1) is int useLightTheme)
|
||||
{
|
||||
return useLightTheme != -1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void SetAutoTheme()
|
||||
{
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", 1) is int useLightTheme)
|
||||
{
|
||||
if (useLightTheme > 0)
|
||||
{
|
||||
Current = new LightTheme();
|
||||
}
|
||||
else
|
||||
{
|
||||
Current = new DarkTheme();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback incase registry fails
|
||||
Current = new LightTheme();
|
||||
}
|
||||
}
|
||||
|
||||
public Theme(string id, string displayName)
|
||||
{
|
||||
Id = id;
|
||||
DisplayName = displayName;
|
||||
}
|
||||
|
||||
public string Id { get; }
|
||||
public string DisplayName { get; }
|
||||
public abstract Color BackgroundColor { get; }
|
||||
public abstract Color ForegroundColor { get; }
|
||||
public abstract Color HyperlinkColor { get; }
|
||||
public abstract Color LineColor { get; }
|
||||
public abstract Color StrongLineColor { get; }
|
||||
public abstract Color SelectedBackgroundColor { get; }
|
||||
public abstract Color SelectedForegroundColor { get; }
|
||||
|
||||
// button
|
||||
public virtual Color ButtonBackgroundColor => BackgroundColor;
|
||||
public virtual Color ButtonBorderColor => ForegroundColor;
|
||||
public virtual Color ButtonHoverBackgroundColor => SelectedBackgroundColor;
|
||||
public virtual Color ButtonPressedBackgroundColor => LineColor;
|
||||
public virtual Color ButtonTextColor => ForegroundColor;
|
||||
|
||||
// menu
|
||||
public virtual Color MenuBackgroundColor => BackgroundColor;
|
||||
public virtual Color MenuBorderColor => StrongLineColor;
|
||||
public virtual Color MenuForegroundColor => ForegroundColor;
|
||||
public virtual Color MenuSelectedBackgroundColor => SelectedBackgroundColor;
|
||||
public virtual Color MenuSelectedForegroundColor => SelectedForegroundColor;
|
||||
|
||||
// plot
|
||||
public virtual Color PlotBackgroundColor => BackgroundColor;
|
||||
public virtual Color PlotBorderColor => ForegroundColor;
|
||||
public abstract Color[] PlotColorPalette { get; }
|
||||
public abstract Color PlotGridMajorColor { get; }
|
||||
public abstract Color PlotGridMinorColor { get; }
|
||||
public virtual Color PlotTextColor => ForegroundColor;
|
||||
|
||||
// scrollbar
|
||||
public virtual Color ScrollbarBackground => BackgroundColor;
|
||||
public virtual Color ScrollbarTrack => StrongLineColor;
|
||||
|
||||
// splitter
|
||||
public virtual Color SplitterColor => BackgroundColor;
|
||||
public virtual Color SplitterHoverColor => SelectedBackgroundColor;
|
||||
|
||||
// tree
|
||||
public virtual Color TreeBackgroundColor => BackgroundColor;
|
||||
public virtual Color TreeOutlineColor => ForegroundColor;
|
||||
public virtual Color TreeSelectedBackgroundColor => SelectedBackgroundColor;
|
||||
public virtual Color TreeTextColor => ForegroundColor;
|
||||
public virtual Color TreeSelectedTextColor => SelectedForegroundColor;
|
||||
public virtual Color TreeRowSepearatorColor => LineColor;
|
||||
|
||||
// window
|
||||
public virtual Color WindowTitlebarBackgroundColor => BackgroundColor;
|
||||
public abstract bool WindowTitlebarFallbackToImmersiveDarkMode { get; }
|
||||
public virtual Color WindowTitlebarForegroundColor => ForegroundColor;
|
||||
|
||||
public void Apply(Form form)
|
||||
{
|
||||
if (IsWindows10OrGreater(22000))
|
||||
{
|
||||
// Windows 11, Set the titlebar color based on theme
|
||||
int color = ColorTranslator.ToWin32(WindowTitlebarBackgroundColor);
|
||||
DwmSetWindowAttribute(form.Handle, DWMWA_CAPTION_COLOR, ref color, sizeof(int));
|
||||
color = ColorTranslator.ToWin32(WindowTitlebarForegroundColor);
|
||||
DwmSetWindowAttribute(form.Handle, DWMWA_TEXT_COLOR, ref color, sizeof(int));
|
||||
}
|
||||
else if (IsWindows10OrGreater(17763))
|
||||
{
|
||||
// Windows 10, fallback to using "Immersive Dark Mode" instead
|
||||
var attribute = DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1;
|
||||
if (IsWindows10OrGreater(18985))
|
||||
{
|
||||
// Windows 10 20H1 or later
|
||||
attribute = DWMWA_USE_IMMERSIVE_DARK_MODE;
|
||||
}
|
||||
int useImmersiveDarkMode = WindowTitlebarFallbackToImmersiveDarkMode ? 1 : 0;
|
||||
DwmSetWindowAttribute(form.Handle, (int)attribute, ref useImmersiveDarkMode, sizeof(int));
|
||||
}
|
||||
form.BackColor = BackgroundColor;
|
||||
foreach (Control control in form.Controls)
|
||||
{
|
||||
Apply(control);
|
||||
}
|
||||
}
|
||||
|
||||
public void Apply(Control control)
|
||||
{
|
||||
if (control is Button button)
|
||||
{
|
||||
button.ForeColor = ButtonTextColor;
|
||||
button.FlatStyle = FlatStyle.Flat;
|
||||
button.FlatAppearance.BorderColor = ButtonBorderColor;
|
||||
button.FlatAppearance.MouseOverBackColor = ButtonHoverBackgroundColor;
|
||||
button.FlatAppearance.MouseDownBackColor = ButtonPressedBackgroundColor;
|
||||
}
|
||||
else if (control is LinkLabel linkLabel)
|
||||
{
|
||||
linkLabel.LinkColor = HyperlinkColor;
|
||||
}
|
||||
else if (control is PlotPanel plotPanel)
|
||||
{
|
||||
plotPanel.ApplyTheme();
|
||||
}
|
||||
else if (control is TreeViewAdv treeView)
|
||||
{
|
||||
treeView.BackColor = TreeBackgroundColor;
|
||||
treeView.ForeColor = TreeTextColor;
|
||||
treeView.LineColor = TreeOutlineColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
control.BackColor = BackgroundColor;
|
||||
control.ForeColor = ForegroundColor;
|
||||
}
|
||||
|
||||
foreach (Control child in control.Controls)
|
||||
{
|
||||
Apply(child);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("dwmapi.dll")]
|
||||
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
|
||||
|
||||
private const int DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19;
|
||||
private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
|
||||
private const int DWMWA_BORDER_COLOR = 34;
|
||||
private const int DWMWA_CAPTION_COLOR = 35;
|
||||
private const int DWMWA_TEXT_COLOR = 36;
|
||||
|
||||
private static bool IsWindows10OrGreater(int build = -1)
|
||||
{
|
||||
return !Software.OperatingSystem.IsUnix && Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= build;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
|
||||
namespace LibreHardwareMonitor.UI.Themes
|
||||
{
|
||||
public class BlackTheme : LightTheme
|
||||
{
|
||||
private readonly Color[] _plotColorPalette;
|
||||
public override Color ForegroundColor => Color.FromArgb(218, 218, 218);
|
||||
public override Color BackgroundColor => Color.FromArgb(0, 0, 0);
|
||||
public override Color HyperlinkColor => Color.FromArgb(144, 220, 232);
|
||||
public override Color SelectedForegroundColor => ForegroundColor;
|
||||
public override Color SelectedBackgroundColor => ColorTranslator.FromHtml("#090A17");
|
||||
public override Color LineColor => ColorTranslator.FromHtml("#070A12");
|
||||
public override Color StrongLineColor => ColorTranslator.FromHtml("#091217");
|
||||
public override Color[] PlotColorPalette => _plotColorPalette;
|
||||
public override Color PlotGridMajorColor => Color.FromArgb(73, 73, 73);
|
||||
public override Color PlotGridMinorColor => Color.FromArgb(33, 33, 33);
|
||||
public override bool WindowTitlebarFallbackToImmersiveDarkMode => true;
|
||||
|
||||
public BlackTheme() : base("black", "Black")
|
||||
{
|
||||
string[] colors = {
|
||||
"#FF2525",
|
||||
"#1200FF",
|
||||
"#00FF5B",
|
||||
"#FFE53B",
|
||||
"#00FFFF",
|
||||
"#FF0A6C",
|
||||
"#2D27FF",
|
||||
"#FF2CDF",
|
||||
"#00E1FD",
|
||||
"#0A5057"
|
||||
};
|
||||
|
||||
_plotColorPalette = colors.Select(color => ColorTranslator.FromHtml(color)).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
|
||||
namespace LibreHardwareMonitor.UI.Themes
|
||||
{
|
||||
public class DarkTheme : LightTheme
|
||||
{
|
||||
private readonly Color[] _plotColorPalette;
|
||||
public override Color ForegroundColor => Color.FromArgb(233, 233, 233);
|
||||
public override Color BackgroundColor => Color.FromArgb(30, 30, 30);
|
||||
public override Color HyperlinkColor => Color.FromArgb(144, 220, 232);
|
||||
public override Color SelectedForegroundColor => ForegroundColor;
|
||||
public override Color SelectedBackgroundColor => Color.FromArgb(45, 45, 45);
|
||||
public override Color LineColor => Color.FromArgb(38, 38, 38);
|
||||
public override Color StrongLineColor => Color.FromArgb(53, 53, 53);
|
||||
public override Color[] PlotColorPalette => _plotColorPalette;
|
||||
public override Color PlotGridMajorColor => Color.FromArgb(93, 93, 93);
|
||||
public override Color PlotGridMinorColor => Color.FromArgb(53, 53, 53);
|
||||
public override bool WindowTitlebarFallbackToImmersiveDarkMode => true;
|
||||
|
||||
public DarkTheme() : base("dark", "Dark")
|
||||
{
|
||||
string[] colors = {
|
||||
"#F07178",
|
||||
"#82AAFF",
|
||||
"#C3E88D",
|
||||
"#FFCB6B",
|
||||
"#009688",
|
||||
"#89DDF3",
|
||||
"#FFE082",
|
||||
"#7986CB",
|
||||
"#C792EA",
|
||||
"#FF5370",
|
||||
"#73d1c8",
|
||||
"#F78C6A"
|
||||
};
|
||||
|
||||
_plotColorPalette = colors.Select(color => ColorTranslator.FromHtml(color)).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace LibreHardwareMonitor.UI.Themes
|
||||
{
|
||||
public class LightTheme : Theme
|
||||
{
|
||||
private readonly Color[] _plotColorPalette = new Color[] {
|
||||
Color.Blue,
|
||||
Color.OrangeRed,
|
||||
Color.Green,
|
||||
Color.LightSeaGreen,
|
||||
Color.Goldenrod,
|
||||
Color.DarkViolet,
|
||||
Color.YellowGreen,
|
||||
Color.SaddleBrown,
|
||||
Color.RoyalBlue,
|
||||
Color.DeepPink,
|
||||
Color.MediumSeaGreen,
|
||||
Color.Olive,
|
||||
Color.Firebrick
|
||||
};
|
||||
|
||||
public LightTheme(string id, string displayName) : base(id, displayName) { }
|
||||
public override Color ForegroundColor => Color.FromArgb(0, 0, 0);
|
||||
public override Color BackgroundColor => Color.FromArgb(255, 255, 255);
|
||||
public override Color HyperlinkColor => Color.FromArgb(0, 0, 255);
|
||||
public override Color SelectedForegroundColor => ForegroundColor;
|
||||
public override Color SelectedBackgroundColor => Color.FromArgb(240, 240, 240);
|
||||
public override Color LineColor => Color.FromArgb(247, 247, 247);
|
||||
public override Color StrongLineColor => Color.FromArgb(209, 209, 209);
|
||||
public override Color[] PlotColorPalette => _plotColorPalette;
|
||||
public override Color PlotGridMajorColor => Color.FromArgb(192, 192, 192);
|
||||
public override Color PlotGridMinorColor => Color.FromArgb(232, 232, 232);
|
||||
public override bool WindowTitlebarFallbackToImmersiveDarkMode => false;
|
||||
|
||||
public LightTheme() : base("light", "Light") { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibreHardwareMonitor.UI.Themes
|
||||
{
|
||||
public class ThemedHScrollIndicator : Control
|
||||
{
|
||||
private readonly HScrollBar _scrollbar;
|
||||
|
||||
public static void AddToControl(Control control)
|
||||
{
|
||||
foreach (Control child in control.Controls)
|
||||
{
|
||||
if (child is HScrollBar scrollbar)
|
||||
{
|
||||
control.Controls.Add(new ThemedHScrollIndicator(scrollbar));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ThemedHScrollIndicator(HScrollBar scrollBar)
|
||||
{
|
||||
_scrollbar = scrollBar;
|
||||
|
||||
Height = 8;
|
||||
SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
SetStyle(ControlStyles.UserPaint, true);
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
Left = 0;
|
||||
Top = scrollBar.Parent.Height - Height;
|
||||
Size = new Size(scrollBar.Parent.Width, Height);
|
||||
Anchor = AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Bottom;
|
||||
Visible = scrollBar.Visible;
|
||||
|
||||
scrollBar.VisibleChanged += (s, e) => Visible = (s as ScrollBar).Visible;
|
||||
scrollBar.Scroll += (s, e) => Invalidate();
|
||||
scrollBar.ValueChanged += (s, e) => Invalidate();
|
||||
|
||||
scrollBar.Height = 0;
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
Graphics g = e.Graphics;
|
||||
|
||||
using (SolidBrush brush = new SolidBrush(Theme.Current.ScrollbarBackground))
|
||||
g.FillRectangle(brush, new Rectangle(0, 0, Bounds.Width, Bounds.Height));
|
||||
|
||||
int width = Bounds.Width;
|
||||
int range = _scrollbar.Maximum - _scrollbar.Minimum;
|
||||
|
||||
if (range > 0)
|
||||
{
|
||||
int start = width * (_scrollbar.Value - _scrollbar.Minimum) / range;
|
||||
int end = width * (_scrollbar.Value - _scrollbar.Minimum + _scrollbar.LargeChange) / range;
|
||||
using (SolidBrush brush = new SolidBrush(Theme.Current.ScrollbarTrack))
|
||||
g.FillRectangle(brush, new Rectangle(start, 2, end - start, Bounds.Height - 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibreHardwareMonitor.UI.Themes
|
||||
{
|
||||
public class ThemedToolStripRenderer : ToolStripRenderer
|
||||
{
|
||||
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
|
||||
{
|
||||
if (e.Item is not ToolStripSeparator)
|
||||
{
|
||||
base.OnRenderSeparator(e);
|
||||
return;
|
||||
}
|
||||
|
||||
Rectangle bounds = new(Point.Empty, e.Item.Size);
|
||||
using (Brush brush = new SolidBrush(Theme.Current.MenuBackgroundColor))
|
||||
e.Graphics.FillRectangle(brush, bounds);
|
||||
}
|
||||
|
||||
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
|
||||
{
|
||||
e.ArrowColor = e.Item.Selected ? Theme.Current.MenuSelectedForegroundColor : Theme.Current.MenuForegroundColor;
|
||||
base.OnRenderArrow(e);
|
||||
}
|
||||
|
||||
protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
|
||||
{
|
||||
using (Pen pen = new Pen(e.Item.Selected ? Theme.Current.MenuSelectedForegroundColor : Theme.Current.MenuForegroundColor))
|
||||
{
|
||||
int x = 10;
|
||||
int y = 6;
|
||||
e.Graphics.DrawLine(pen, x, y + 3, x + 2, y + 5);
|
||||
e.Graphics.DrawLine(pen, x + 2, y + 5, x + 6, y + 1);
|
||||
e.Graphics.DrawLine(pen, x, y + 4, x + 2, y + 6);
|
||||
e.Graphics.DrawLine(pen, x + 2, y + 6, x + 6, y + 2);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
|
||||
{
|
||||
e.TextColor = e.Item.Selected ? Theme.Current.MenuSelectedForegroundColor : Theme.Current.MenuForegroundColor;
|
||||
base.OnRenderItemText(e);
|
||||
}
|
||||
|
||||
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
|
||||
{
|
||||
if (e.ToolStrip.Parent is not Form)
|
||||
{
|
||||
Rectangle bounds = new(Point.Empty, new Size(e.ToolStrip.Width - 1, e.ToolStrip.Height - 1));
|
||||
using (Pen pen = new Pen(Theme.Current.MenuBorderColor))
|
||||
e.Graphics.DrawRectangle(pen, bounds);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
|
||||
{
|
||||
Rectangle bounds = new(Point.Empty, e.ToolStrip.Size);
|
||||
using (Brush brush = new SolidBrush(Theme.Current.MenuBackgroundColor))
|
||||
e.Graphics.FillRectangle(brush, bounds);
|
||||
}
|
||||
|
||||
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
|
||||
{
|
||||
Rectangle bounds = new(Point.Empty, e.Item.Size);
|
||||
|
||||
using (Brush brush = new SolidBrush(e.Item.Selected ? Theme.Current.MenuSelectedBackgroundColor : Theme.Current.MenuBackgroundColor))
|
||||
e.Graphics.FillRectangle(brush, bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibreHardwareMonitor.UI.Themes
|
||||
{
|
||||
public class ThemedVScrollIndicator : Control
|
||||
{
|
||||
private readonly VScrollBar _scrollbar;
|
||||
|
||||
public static void AddToControl(Control control)
|
||||
{
|
||||
foreach (Control child in control.Controls)
|
||||
{
|
||||
if (child is VScrollBar scrollbar)
|
||||
{
|
||||
control.Controls.Add(new ThemedVScrollIndicator(scrollbar));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ThemedVScrollIndicator(VScrollBar scrollBar)
|
||||
{
|
||||
_scrollbar = scrollBar;
|
||||
|
||||
Width = 8;
|
||||
SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
SetStyle(ControlStyles.UserPaint, true);
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
Left = scrollBar.Parent.Width - Width;
|
||||
Top = 0;
|
||||
Size = new Size(Width, scrollBar.Parent.Height);
|
||||
Anchor = AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
|
||||
Visible = scrollBar.Visible;
|
||||
|
||||
scrollBar.VisibleChanged += (s, e) => Visible = (s as ScrollBar).Visible;
|
||||
scrollBar.Scroll += (s, e) => Invalidate();
|
||||
scrollBar.ValueChanged += (s, e) => Invalidate();
|
||||
|
||||
scrollBar.Width = 0;
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
Graphics g = e.Graphics;
|
||||
|
||||
using (SolidBrush brush = new SolidBrush(Theme.Current.ScrollbarBackground))
|
||||
g.FillRectangle(brush, new Rectangle(0, 0, Bounds.Width, Bounds.Height));
|
||||
|
||||
int height = Bounds.Height;
|
||||
int range = _scrollbar.Maximum - _scrollbar.Minimum;
|
||||
|
||||
if (range > 0)
|
||||
{
|
||||
int start = height * (_scrollbar.Value - _scrollbar.Minimum) / range;
|
||||
int end = height * (_scrollbar.Value - _scrollbar.Minimum + _scrollbar.LargeChange) / range;
|
||||
using (SolidBrush brush = new SolidBrush(Theme.Current.ScrollbarTrack))
|
||||
g.FillRectangle(brush, new Rectangle(2, start, Bounds.Width - 4, end - start));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user