using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Mesen.GUI { public static class ThemeHelper { public static MonoTheme Theme { get; private set; } = new MonoTheme(); private static Dictionary>> _excludedControls = new Dictionary>>(); public static void InitTheme(Color backColor) { if(backColor.R < 128 && backColor.G < 128 && backColor.B < 128) { Theme = new DarkMonoTheme(); } else { Theme = new MonoTheme(); } } public static bool IsDark { get { return Theme is DarkMonoTheme; } } public static void ExcludeFromTheme(Control ctrl) { if(Program.IsMono) { List> refList; if(!_excludedControls.TryGetValue(ctrl.Name, out refList)) { refList = new List>(); _excludedControls[ctrl.Name] = refList; } refList.Add(new WeakReference(ctrl)); } } public static bool IsExcludedFromTheme(Control ctrl) { if(Program.IsMono) { List> refList; if(_excludedControls.TryGetValue(ctrl.Name, out refList)) { foreach(WeakReference weakRef in refList) { object target; if(weakRef.TryGetTarget(out target)) { return target == ctrl; } } } } return false; } public static void FixMonoColors(Form form) { if(Program.IsMono) { form.BackColor = Theme.FormBgColor; FixMonoColors(form, Theme); } } public static void FixMonoColors(ContextMenuStrip menu) { if(Program.IsMono) { if(menu.Tag == null || (bool)menu.Tag != true) { //Only process this context menu a single time (uses its Tag to know if we've processed it or not) FixMonoColors(menu, Theme); menu.Tag = true; } } } private static void FixMonoColors(ToolStripItem item, MonoTheme theme) { item.ForeColor = item.Enabled ? theme.ToolStripItemForeColor : theme.ToolStripItemDisabledForeColor; item.BackColor = theme.ToolStripItemBgColor; item.Font = new Font("Microsoft Sans Serif", 8.25f); item.EnabledChanged += (object sender, EventArgs e) => { ((ToolStripItem)sender).ForeColor = ((ToolStripItem)sender).Enabled ? theme.ToolStripItemForeColor : theme.ToolStripItemDisabledForeColor; }; if(item is ToolStripDropDownItem) { ToolStripDropDownItem ddItem = item as ToolStripDropDownItem; ddItem.DropDownOpening += MonoToolStripHelper.DropdownOpening; ddItem.DropDownClosed += MonoToolStripHelper.DropdownClosed; ddItem.DropDownOpening += (s, e) => { ddItem.DropDown.BackColor = theme.ToolStripItemBgColor; foreach(ToolStripItem subItem in ddItem.DropDownItems) { FixMonoColors(subItem, theme); } }; foreach(ToolStripItem subItem in ddItem.DropDownItems) { FixMonoColors(subItem, theme); } } } private static void FixMonoColors(Control container, MonoTheme theme) { if(ThemeHelper.IsExcludedFromTheme(container)) { return; } if(container is TextBox) { TextBox txt = (TextBox)container; txt.BorderStyle = BorderStyle.FixedSingle; txt.BackColor = txt.ReadOnly ? theme.TextBoxDisabledBgColor : theme.TextBoxEnabledBgColor; txt.ForeColor = theme.TextBoxForeColor; txt.ReadOnlyChanged += (object sender, EventArgs e) => { ((TextBox)sender).BackColor = ((TextBox)sender).ReadOnly ? theme.TextBoxDisabledBgColor : theme.TextBoxEnabledBgColor; }; } else if(container is Label) { Label lbl = (Label)container; if(lbl.BackColor == Color.White) { //Trackbar labels lbl.BackColor = theme.TextBoxEnabledBgColor; lbl.ForeColor = theme.TextBoxForeColor; } else { if(lbl.ForeColor == SystemColors.GrayText) { //Headers lbl.ForeColor = theme.GrayTextColor; } else if(lbl.ForeColor == SystemColors.ControlDark) { //ctrlRiskyOption lbl.ForeColor = theme.DarkTextColor; } else { //Regular label lbl.ForeColor = lbl.Enabled ? theme.LabelForeColor : theme.LabelDisabledForeColor; lbl.EnabledChanged += (object sender, EventArgs e) => { ((Label)sender).ForeColor = ((Label)sender).Enabled ? theme.LabelForeColor : theme.LabelDisabledForeColor; }; } } } else if(container is CheckBox) { CheckBox chk = (CheckBox)container; chk.FlatStyle = FlatStyle.Flat; chk.ForeColor = chk.Enabled ? theme.LabelForeColor : theme.LabelDisabledForeColor; if(chk.BackColor == SystemColors.ControlLightLight) { //Enable equalizer checkbox chk.BackColor = theme.TabBgColor; } chk.EnabledChanged += (object sender, EventArgs e) => { ((CheckBox)sender).ForeColor = ((CheckBox)sender).Enabled ? theme.LabelForeColor : theme.LabelDisabledForeColor; }; } else if(container is RadioButton) { ((RadioButton)container).ForeColor = ((RadioButton)container).Enabled ? theme.LabelForeColor : theme.LabelDisabledForeColor; ((RadioButton)container).EnabledChanged += (object sender, EventArgs e) => { ((RadioButton)sender).ForeColor = ((RadioButton)sender).Enabled ? theme.LabelForeColor : theme.LabelDisabledForeColor; }; } else if(container is TrackBar) { ((TrackBar)container).BackColor = theme.TabBgColor; } else if(container is Button) { Button btn = (Button)container; btn.FlatStyle = FlatStyle.Flat; btn.BackColor = btn.Enabled ? theme.ButtonEnabledBgColor : theme.ButtonDisabledBgColor; btn.ForeColor = theme.ButtonForeColor; btn.EnabledChanged += (object sender, EventArgs e) => { ((Button)sender).BackColor = ((Button)sender).Enabled ? theme.ButtonEnabledBgColor : theme.ButtonDisabledBgColor; }; } else if(container is ComboBox) { ComboBox cbo = (ComboBox)container; cbo.FlatStyle = FlatStyle.Flat; cbo.BackColor = cbo.Enabled ? theme.ComboEnabledBgColor : theme.ComboDisabledBgColor; cbo.ForeColor = theme.TextBoxForeColor; cbo.EnabledChanged += (object sender, EventArgs e) => { ((ComboBox)sender).BackColor = ((ComboBox)sender).Enabled ? theme.ComboEnabledBgColor : theme.ComboDisabledBgColor; }; } else if(container is GroupBox) { ((GroupBox)container).ForeColor = theme.LabelForeColor; } else if(container is TabControl) { ((TabControl)container).BackColor = theme.TabBgColor; } else if(container is TabPage) { ((TabPage)container).BackColor = theme.TabBgColor; } else if(container is Panel && !(container is TableLayoutPanel) && !(container is FlowLayoutPanel)) { ((Panel)container).BackColor = theme.PanelBgColor; } else if(container is DataGridView) { DataGridView dgv = (DataGridView)container; dgv.BackgroundColor = theme.ListBgColor; dgv.ForeColor = theme.LabelForeColor; dgv.GridColor = theme.LabelForeColor; dgv.DefaultCellStyle.ForeColor = theme.LabelForeColor; dgv.DefaultCellStyle.BackColor = theme.ListBgColor; dgv.ColumnHeadersDefaultCellStyle.ForeColor = theme.LabelForeColor; dgv.ColumnHeadersDefaultCellStyle.BackColor = theme.TabBgColor; } else if(container is DataGridTextBox) { ((DataGridTextBox)container).BackColor = theme.TextBoxEnabledBgColor; ((DataGridTextBox)container).ForeColor = theme.TextBoxForeColor; } else if(container is ListView) { ((ListView)container).BackColor = theme.ListBgColor; ((ListView)container).ForeColor = theme.LabelForeColor; } else if(container is ToolStrip) { ((ToolStrip)container).BackColor = theme.FormBgColor; if(container is ContextMenuStrip) { ((ContextMenuStrip)container).Opening += MonoToolStripHelper.ContextMenuOpening; ((ContextMenuStrip)container).Closed += MonoToolStripHelper.ContextMenuClosed; } else { ((ToolStrip)container).RenderMode = ToolStripRenderMode.System; } foreach(ToolStripItem item in ((ToolStrip)container).Items) { FixMonoColors(item, theme); } } if(container.ContextMenuStrip != null) { container.ContextMenuStrip.Opening += MonoToolStripHelper.ContextMenuOpening; container.ContextMenuStrip.Closed += MonoToolStripHelper.ContextMenuClosed; foreach(ToolStripItem item in container.ContextMenuStrip.Items) { FixMonoColors(item, theme); } } foreach(Control ctrl in container.Controls) { FixMonoColors(ctrl, theme); } } public class MonoTheme { public virtual Color TextBoxDisabledBgColor { get; } = Color.FromArgb(240, 240, 240); public virtual Color TextBoxEnabledBgColor { get; } = Color.FromArgb(255, 255, 255); public virtual Color TextBoxForeColor { get; } = Color.FromArgb(0, 0, 0); public virtual Color ButtonDisabledBgColor { get; } = Color.FromArgb(180, 180, 180); public virtual Color ButtonEnabledBgColor { get; } = Color.FromArgb(230, 230, 230); public virtual Color ButtonForeColor { get; } = Color.FromArgb(0, 0, 0); public virtual Color LabelForeColor { get; } = Program.IsMono ? Color.Black : SystemColors.ControlText; public virtual Color LabelDisabledForeColor { get; } = Color.Gray; public virtual Color ErrorTextColor { get; } = Color.Red; public virtual Color GrayTextColor { get; } = Program.IsMono ? Color.Gray : SystemColors.GrayText; public virtual Color DarkTextColor { get; } = Program.IsMono ? Color.LightGray : SystemColors.ControlDark; public virtual Color LinkTextColor { get; } = Color.FromArgb(61, 125, 255); public virtual Color ComboEnabledBgColor { get; } = Color.FromArgb(230, 230, 230); public virtual Color ComboDisabledBgColor { get; } = Color.FromArgb(180, 180, 180); public virtual Color FormBgColor { get; } = Program.IsMono ? Color.FromArgb(239, 240, 241) : SystemColors.Control; public virtual Color TabBgColor { get; } = Program.IsMono ? Color.White : Color.Transparent; public virtual Color PanelBgColor { get; } = Program.IsMono ? Color.FromArgb(239, 240, 241) : SystemColors.Control; public virtual Color ListBgColor { get; } = Program.IsMono ? Color.White : SystemColors.ControlLightLight; public virtual Color ToolStripItemBgColor { get; } = Program.IsMono ? Color.FromArgb(239, 240, 241) : SystemColors.Control; public virtual Color ToolStripItemForeColor { get; } = Color.Black; public virtual Color ToolStripItemDisabledForeColor { get; } = Color.Gray; } class DarkMonoTheme : MonoTheme { private static readonly Color TextColor = Color.FromArgb(255, 255, 255); private static readonly Color MainBgColor = Color.FromArgb(49, 54, 69); private static readonly Color HighlightBgColor = Color.FromArgb(69, 73, 70); private static readonly Color HighlightDisabledBgColor = Color.FromArgb(47, 52, 57); public override Color TextBoxDisabledBgColor { get; } = DarkMonoTheme.HighlightDisabledBgColor; public override Color TextBoxEnabledBgColor { get; } = Color.FromArgb(69, 73, 78); public override Color TextBoxForeColor { get; } = DarkMonoTheme.TextColor; public override Color ButtonDisabledBgColor { get; } = DarkMonoTheme.HighlightDisabledBgColor; public override Color ButtonEnabledBgColor { get; } = DarkMonoTheme.HighlightBgColor; public override Color ButtonForeColor { get; } = DarkMonoTheme.TextColor; public override Color LabelForeColor { get; } = DarkMonoTheme.TextColor; public override Color LabelDisabledForeColor { get; } = Color.Gray; public override Color ErrorTextColor { get; } = Color.IndianRed; public override Color GrayTextColor { get; } = Color.LightGray; public override Color DarkTextColor { get; } = Color.LightGray; public override Color LinkTextColor { get; } = Color.FromArgb(61, 125, 255); public override Color ComboEnabledBgColor { get; } = Color.FromArgb(69, 73, 78); public override Color ComboDisabledBgColor { get; } = Color.FromArgb(47, 52, 47); public override Color FormBgColor { get; } = DarkMonoTheme.MainBgColor; public override Color TabBgColor { get; } = Color.FromArgb(45, 49, 54); public override Color PanelBgColor { get; } = DarkMonoTheme.MainBgColor; public override Color ListBgColor { get; } = Color.FromArgb(45, 49, 54); public override Color ToolStripItemBgColor { get; } = DarkMonoTheme.MainBgColor; public override Color ToolStripItemForeColor { get; } = DarkMonoTheme.TextColor; public override Color ToolStripItemDisabledForeColor { get; } = Color.Gray; } } }