Files
HawkeyeVision/framework/MaterialSkin.Core/MaterialSkinManager.cs
2025-07-14 12:03:59 +02:00

350 lines
15 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using MaterialSkin.Controls;
using MaterialSkin.Core.Resources;
namespace MaterialSkin
{
public class MaterialSkinManager
{
public static void ConfigureForInspectron()
{
Instance.ColorScheme = new ColorScheme(Primary.Red800, Primary.Red800, Primary.Red400, Accent.Red200, TextShade.BLACK);
}
//Singleton instance
private static MaterialSkinManager _instance;
//Forms to control
private readonly List<MaterialForm> _formsToManage = new List<MaterialForm>();
//Theme
private Themes _theme;
public Themes Theme
{
get { return _theme; }
set
{
_theme = value;
UpdateBackgrounds();
}
}
private ColorScheme _colorScheme;
public ColorScheme ColorScheme
{
get { return _colorScheme; }
set
{
_colorScheme = value;
UpdateBackgrounds();
}
}
public enum Themes : byte
{
LIGHT,
DARK
}
//Constant color values
private static readonly Color PRIMARY_TEXT_BLACK = Color.FromArgb(222, 0, 0, 0);
private static readonly Brush PRIMARY_TEXT_BLACK_BRUSH = new SolidBrush(PRIMARY_TEXT_BLACK);
public static Color SECONDARY_TEXT_BLACK = Color.FromArgb(138, 0, 0, 0);
public static Brush SECONDARY_TEXT_BLACK_BRUSH = new SolidBrush(SECONDARY_TEXT_BLACK);
private static readonly Color DISABLED_OR_HINT_TEXT_BLACK = Color.FromArgb(66, 0, 0, 0);
private static readonly Brush DISABLED_OR_HINT_TEXT_BLACK_BRUSH = new SolidBrush(DISABLED_OR_HINT_TEXT_BLACK);
private static readonly Color DIVIDERS_BLACK = Color.FromArgb(31, 0, 0, 0);
private static readonly Brush DIVIDERS_BLACK_BRUSH = new SolidBrush(DIVIDERS_BLACK);
private static readonly Color PRIMARY_TEXT_WHITE = Color.FromArgb(255, 255, 255, 255);
private static readonly Brush PRIMARY_TEXT_WHITE_BRUSH = new SolidBrush(PRIMARY_TEXT_WHITE);
public static Color SECONDARY_TEXT_WHITE = Color.FromArgb(179, 255, 255, 255);
public static Brush SECONDARY_TEXT_WHITE_BRUSH = new SolidBrush(SECONDARY_TEXT_WHITE);
private static readonly Color DISABLED_OR_HINT_TEXT_WHITE = Color.FromArgb(77, 255, 255, 255);
private static readonly Brush DISABLED_OR_HINT_TEXT_WHITE_BRUSH = new SolidBrush(DISABLED_OR_HINT_TEXT_WHITE);
private static readonly Color DIVIDERS_WHITE = Color.FromArgb(31, 255, 255, 255);
private static readonly Brush DIVIDERS_WHITE_BRUSH = new SolidBrush(DIVIDERS_WHITE);
// Checkbox colors
private static readonly Color CHECKBOX_OFF_LIGHT = Color.FromArgb(138, 0, 0, 0);
private static readonly Brush CHECKBOX_OFF_LIGHT_BRUSH = new SolidBrush(CHECKBOX_OFF_LIGHT);
private static readonly Color CHECKBOX_OFF_DISABLED_LIGHT = Color.FromArgb(66, 0, 0, 0);
private static readonly Brush CHECKBOX_OFF_DISABLED_LIGHT_BRUSH = new SolidBrush(CHECKBOX_OFF_DISABLED_LIGHT);
private static readonly Color CHECKBOX_OFF_DARK = Color.FromArgb(179, 255, 255, 255);
private static readonly Brush CHECKBOX_OFF_DARK_BRUSH = new SolidBrush(CHECKBOX_OFF_DARK);
private static readonly Color CHECKBOX_OFF_DISABLED_DARK = Color.FromArgb(77, 255, 255, 255);
private static readonly Brush CHECKBOX_OFF_DISABLED_DARK_BRUSH = new SolidBrush(CHECKBOX_OFF_DISABLED_DARK);
//Raised button
private static readonly Color RAISED_BUTTON_BACKGROUND = Color.FromArgb(255, 255, 255, 255);
private static readonly Brush RAISED_BUTTON_BACKGROUND_BRUSH = new SolidBrush(RAISED_BUTTON_BACKGROUND);
private static readonly Color RAISED_BUTTON_TEXT_LIGHT = PRIMARY_TEXT_WHITE;
private static readonly Brush RAISED_BUTTON_TEXT_LIGHT_BRUSH = new SolidBrush(RAISED_BUTTON_TEXT_LIGHT);
private static readonly Color RAISED_BUTTON_TEXT_DARK = PRIMARY_TEXT_BLACK;
private static readonly Brush RAISED_BUTTON_TEXT_DARK_BRUSH = new SolidBrush(RAISED_BUTTON_TEXT_DARK);
//Flat button
private static readonly Color FLAT_BUTTON_BACKGROUND_HOVER_LIGHT = Color.FromArgb(20.PercentageToColorComponent(), 0x999999.ToColor());
private static readonly Brush FLAT_BUTTON_BACKGROUND_HOVER_LIGHT_BRUSH = new SolidBrush(FLAT_BUTTON_BACKGROUND_HOVER_LIGHT);
private static readonly Color FLAT_BUTTON_BACKGROUND_PRESSED_LIGHT = Color.FromArgb(40.PercentageToColorComponent(), 0x999999.ToColor());
private static readonly Brush FLAT_BUTTON_BACKGROUND_PRESSED_LIGHT_BRUSH = new SolidBrush(FLAT_BUTTON_BACKGROUND_PRESSED_LIGHT);
private static readonly Color FLAT_BUTTON_DISABLEDTEXT_LIGHT = Color.FromArgb(26.PercentageToColorComponent(), 0x000000.ToColor());
private static readonly Brush FLAT_BUTTON_DISABLEDTEXT_LIGHT_BRUSH = new SolidBrush(FLAT_BUTTON_DISABLEDTEXT_LIGHT);
private static readonly Color FLAT_BUTTON_BACKGROUND_HOVER_DARK = Color.FromArgb(15.PercentageToColorComponent(), 0xCCCCCC.ToColor());
private static readonly Brush FLAT_BUTTON_BACKGROUND_HOVER_DARK_BRUSH = new SolidBrush(FLAT_BUTTON_BACKGROUND_HOVER_DARK);
private static readonly Color FLAT_BUTTON_BACKGROUND_PRESSED_DARK = Color.FromArgb(25.PercentageToColorComponent(), 0xCCCCCC.ToColor());
private static readonly Brush FLAT_BUTTON_BACKGROUND_PRESSED_DARK_BRUSH = new SolidBrush(FLAT_BUTTON_BACKGROUND_PRESSED_DARK);
private static readonly Color FLAT_BUTTON_DISABLEDTEXT_DARK = Color.FromArgb(30.PercentageToColorComponent(), 0xFFFFFF.ToColor());
private static readonly Brush FLAT_BUTTON_DISABLEDTEXT_DARK_BRUSH = new SolidBrush(FLAT_BUTTON_DISABLEDTEXT_DARK);
//ContextMenuStrip
private static readonly Color CMS_BACKGROUND_LIGHT_HOVER = Color.FromArgb(255, 238, 238, 238);
private static readonly Brush CMS_BACKGROUND_HOVER_LIGHT_BRUSH = new SolidBrush(CMS_BACKGROUND_LIGHT_HOVER);
private static readonly Color CMS_BACKGROUND_DARK_HOVER = Color.FromArgb(38, 204, 204, 204);
private static readonly Brush CMS_BACKGROUND_HOVER_DARK_BRUSH = new SolidBrush(CMS_BACKGROUND_DARK_HOVER);
//Application background
private static readonly Color BACKGROUND_LIGHT = Color.FromArgb(255, 255, 255, 255);
private static Brush BACKGROUND_LIGHT_BRUSH = new SolidBrush(BACKGROUND_LIGHT);
private static readonly Color BACKGROUND_DARK = Color.FromArgb(255, 51, 51, 51);
private static Brush BACKGROUND_DARK_BRUSH = new SolidBrush(BACKGROUND_DARK);
//Application action bar
public readonly Color ACTION_BAR_TEXT = Color.FromArgb(255, 255, 255, 255);
public readonly Brush ACTION_BAR_TEXT_BRUSH = new SolidBrush(Color.FromArgb(255, 255, 255, 255));
public readonly Color ACTION_BAR_TEXT_SECONDARY = Color.FromArgb(153, 255, 255, 255);
public readonly Brush ACTION_BAR_TEXT_SECONDARY_BRUSH = new SolidBrush(Color.FromArgb(153, 255, 255, 255));
public Color GetPrimaryTextColor()
{
return Theme == Themes.LIGHT ? PRIMARY_TEXT_BLACK : PRIMARY_TEXT_WHITE;
}
public Brush GetPrimaryTextBrush()
{
return Theme == Themes.LIGHT ? PRIMARY_TEXT_BLACK_BRUSH : PRIMARY_TEXT_WHITE_BRUSH;
}
public Color GetSecondaryTextColor()
{
return Theme == Themes.LIGHT ? SECONDARY_TEXT_BLACK : SECONDARY_TEXT_WHITE;
}
public Brush GetSecondaryTextBrush()
{
return Theme == Themes.LIGHT ? SECONDARY_TEXT_BLACK_BRUSH : SECONDARY_TEXT_WHITE_BRUSH;
}
public Color GetDisabledOrHintColor()
{
return Theme == Themes.LIGHT ? DISABLED_OR_HINT_TEXT_BLACK : DISABLED_OR_HINT_TEXT_WHITE;
}
public Brush GetDisabledOrHintBrush()
{
return Theme == Themes.LIGHT ? DISABLED_OR_HINT_TEXT_BLACK_BRUSH : DISABLED_OR_HINT_TEXT_WHITE_BRUSH;
}
public Color GetDividersColor()
{
return Theme == Themes.LIGHT ? DIVIDERS_BLACK : DIVIDERS_WHITE;
}
public Brush GetDividersBrush()
{
return Theme == Themes.LIGHT ? DIVIDERS_BLACK_BRUSH : DIVIDERS_WHITE_BRUSH;
}
public Color GetCheckboxOffColor()
{
return Theme == Themes.LIGHT ? CHECKBOX_OFF_LIGHT : CHECKBOX_OFF_DARK;
}
public Brush GetCheckboxOffBrush()
{
return Theme == Themes.LIGHT ? CHECKBOX_OFF_LIGHT_BRUSH : CHECKBOX_OFF_DARK_BRUSH;
}
public Color GetCheckBoxOffDisabledColor()
{
return Theme == Themes.LIGHT ? CHECKBOX_OFF_DISABLED_LIGHT : CHECKBOX_OFF_DISABLED_DARK;
}
public Brush GetCheckBoxOffDisabledBrush()
{
return Theme == Themes.LIGHT ? CHECKBOX_OFF_DISABLED_LIGHT_BRUSH : CHECKBOX_OFF_DISABLED_DARK_BRUSH;
}
public Brush GetRaisedButtonBackgroundBrush()
{
return RAISED_BUTTON_BACKGROUND_BRUSH;
}
public Brush GetRaisedButtonTextBrush(bool primary)
{
return primary ? RAISED_BUTTON_TEXT_LIGHT_BRUSH : RAISED_BUTTON_TEXT_DARK_BRUSH;
}
public Color GetFlatButtonHoverBackgroundColor()
{
return Theme == Themes.LIGHT ? FLAT_BUTTON_BACKGROUND_HOVER_LIGHT : FLAT_BUTTON_BACKGROUND_HOVER_DARK;
}
public Brush GetFlatButtonHoverBackgroundBrush()
{
return Theme == Themes.LIGHT ? FLAT_BUTTON_BACKGROUND_HOVER_LIGHT_BRUSH : FLAT_BUTTON_BACKGROUND_HOVER_DARK_BRUSH;
}
public Color GetFlatButtonPressedBackgroundColor()
{
return Theme == Themes.LIGHT ? FLAT_BUTTON_BACKGROUND_PRESSED_LIGHT : FLAT_BUTTON_BACKGROUND_PRESSED_DARK;
}
public Brush GetFlatButtonPressedBackgroundBrush()
{
return Theme == Themes.LIGHT ? FLAT_BUTTON_BACKGROUND_PRESSED_LIGHT_BRUSH : FLAT_BUTTON_BACKGROUND_PRESSED_DARK_BRUSH;
}
public Brush GetFlatButtonDisabledTextBrush()
{
return Theme == Themes.LIGHT ? FLAT_BUTTON_DISABLEDTEXT_LIGHT_BRUSH : FLAT_BUTTON_DISABLEDTEXT_DARK_BRUSH;
}
public Brush GetCmsSelectedItemBrush()
{
return Theme == Themes.LIGHT ? CMS_BACKGROUND_HOVER_LIGHT_BRUSH : CMS_BACKGROUND_HOVER_DARK_BRUSH;
}
public Color GetApplicationBackgroundColor()
{
return Theme == Themes.LIGHT ? BACKGROUND_LIGHT : BACKGROUND_DARK;
}
//Roboto font
public Font ROBOTO_MEDIUM_12;
public Font ROBOTO_REGULAR_11;
public Font ROBOTO_MEDIUM_11;
public Font ROBOTO_MEDIUM_10;
//Other constants
public int FORM_PADDING = 14;
[DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pvd, [In] ref uint pcFonts);
private MaterialSkinManager()
{
ROBOTO_MEDIUM_12 = new Font(LoadFont(Resource1.Roboto_Medium), 12f);
ROBOTO_MEDIUM_10 = new Font(LoadFont(Resource1.Roboto_Medium), 10f);
ROBOTO_REGULAR_11 = new Font(LoadFont(Resource1.Roboto_Regular), 11f);
ROBOTO_MEDIUM_11 = new Font(LoadFont(Resource1.Roboto_Medium), 11f);
Theme = Themes.LIGHT;
ColorScheme = new ColorScheme(Primary.BlueGrey800, Primary.BlueGrey900, Primary.BlueGrey500, Accent.LightBlue200, TextShade.WHITE);
}
public static MaterialSkinManager Instance => _instance ?? (_instance = new MaterialSkinManager());
public void AddFormToManage(MaterialForm materialForm)
{
_formsToManage.Add(materialForm);
UpdateBackgrounds();
}
public void RemoveFormToManage(MaterialForm materialForm)
{
_formsToManage.Remove(materialForm);
}
private readonly PrivateFontCollection privateFontCollection = new PrivateFontCollection();
private FontFamily LoadFont(byte[] fontResource)
{
int dataLength = fontResource.Length;
IntPtr fontPtr = Marshal.AllocCoTaskMem(dataLength);
Marshal.Copy(fontResource, 0, fontPtr, dataLength);
uint cFonts = 0;
AddFontMemResourceEx(fontPtr, (uint)fontResource.Length, IntPtr.Zero, ref cFonts);
privateFontCollection.AddMemoryFont(fontPtr, dataLength);
return privateFontCollection.Families.Last();
}
private void UpdateBackgrounds()
{
var newBackColor = GetApplicationBackgroundColor();
foreach (var materialForm in _formsToManage)
{
materialForm.BackColor = newBackColor;
UpdateControl(materialForm, newBackColor);
}
}
private void UpdateToolStrip(ToolStrip toolStrip, Color newBackColor)
{
if (toolStrip == null) return;
toolStrip.BackColor = newBackColor;
foreach (ToolStripItem control in toolStrip.Items)
{
control.BackColor = newBackColor;
if (control is MaterialToolStripMenuItem && (control as MaterialToolStripMenuItem).HasDropDown)
{
//recursive call
UpdateToolStrip((control as MaterialToolStripMenuItem).DropDown, newBackColor);
}
}
}
private void UpdateControl(Control controlToUpdate, Color newBackColor)
{
if (controlToUpdate == null) return;
if (controlToUpdate.ContextMenuStrip != null)
{
UpdateToolStrip(controlToUpdate.ContextMenuStrip, newBackColor);
}
var tabControl = controlToUpdate as MaterialTabControl;
if (tabControl != null)
{
foreach (TabPage tabPage in tabControl.TabPages)
{
tabPage.BackColor = newBackColor;
}
}
if (controlToUpdate is MaterialDivider)
{
controlToUpdate.BackColor = GetDividersColor();
}
if (controlToUpdate is MaterialListView)
{
controlToUpdate.BackColor = newBackColor;
}
//recursive call
foreach (Control control in controlToUpdate.Controls)
{
UpdateControl(control, newBackColor);
}
controlToUpdate.Invalidate();
}
}
}