diff --git a/CreamInstaller/Components/CustomTreeView.cs b/CreamInstaller/Components/CustomTreeView.cs index e048c15..28fcfcd 100644 --- a/CreamInstaller/Components/CustomTreeView.cs +++ b/CreamInstaller/Components/CustomTreeView.cs @@ -15,15 +15,6 @@ internal sealed class CustomTreeView : TreeView { private const string ProxyToggleString = "Proxy"; - private static readonly Color C1 = ColorTranslator.FromHtml("#FFFF99"); - private static readonly Color C2 = ColorTranslator.FromHtml("#696900"); - private static readonly Color C3 = ColorTranslator.FromHtml("#AAAA69"); - private static readonly Color C4 = ColorTranslator.FromHtml("#99FFFF"); - private static readonly Color C5 = ColorTranslator.FromHtml("#006969"); - private static readonly Color C6 = ColorTranslator.FromHtml("#69AAAA"); - private static readonly Color C7 = ColorTranslator.FromHtml("#006900"); - private static readonly Color C8 = ColorTranslator.FromHtml("#69AA69"); - private readonly Dictionary checkBoxBounds = []; private readonly Dictionary comboBoxBounds = []; @@ -105,10 +96,10 @@ internal sealed class CustomTreeView : TreeView return; Color color = highlighted - ? C1 + ? ThemeManager.CustomTreeViewHighlightPlatformColor : Enabled ? ThemeManager.CustomTreeViewPlatformColor - : C3; + : ThemeManager.CustomTreeViewDisabledPlatformColor; string text; if (dlcType is not DLCType.None) { @@ -127,10 +118,10 @@ internal sealed class CustomTreeView : TreeView if (platform is not Platform.Paradox) { color = highlighted - ? C4 + ? ThemeManager.CustomTreeViewHighlightIdColor : Enabled ? ThemeManager.CustomTreeViewIdColor - : C6; + : ThemeManager.CustomTreeViewDisabledIdColor; text = id; size = TextRenderer.MeasureText(graphics, text, font); const int left = -4; @@ -175,7 +166,9 @@ internal sealed class CustomTreeView : TreeView checkBoxBounds = new(checkBoxBounds.Location, checkBoxBounds.Size + bounds.Size with { Height = 0 }); graphics.FillRectangle(backBrush, bounds); point = new(bounds.Location.X - 1 + left, bounds.Location.Y + 1); - TextRenderer.DrawText(graphics, text, font, point, Enabled ? ThemeManager.CustomTreeViewProxyColor : C8, TextFormatFlags.Default); + TextRenderer.DrawText(graphics, text, font, point, + Enabled ? ThemeManager.CustomTreeViewProxyColor : ThemeManager.CustomTreeViewDisabledProxyColor, + TextFormatFlags.Default); this.checkBoxBounds[selection] = RectangleToClient(checkBoxBounds); @@ -183,8 +176,11 @@ internal sealed class CustomTreeView : TreeView { comboBoxFont ??= new(font.FontFamily, 6, font.Style, font.Unit, font.GdiCharSet, font.GdiVerticalFont); - ComboBoxState comboBoxState = Enabled ? ComboBoxState.Normal : ComboBoxState.Disabled; - ButtonState buttonState = Enabled ? ButtonState.Normal : ButtonState.Inactive; + + bool darkMode = Program.DarkModeEnabled; + Color comboBackColor = ThemeManager.CustomTreeViewComboBackColor; + Color comboBorderColor = ThemeManager.CustomTreeViewComboBorderColor; + Color comboTextColor = ThemeManager.CustomTreeViewComboTextColor; text = (selection.Proxy ?? Selection.DefaultProxy) + ".dll"; size = TextRenderer.MeasureText(graphics, text, comboBoxFont) + new Size(6, 0); @@ -193,17 +189,15 @@ internal sealed class CustomTreeView : TreeView selectionBounds = new(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 }); Rectangle comboBoxBounds = bounds; - graphics.FillRectangle(backBrush, bounds); - if (ComboBoxRenderer.IsSupported) - ComboBoxRenderer.DrawTextBox(graphics, bounds, text, comboBoxFont, comboBoxState); - else + + // Draw custom themed combobox + using (SolidBrush comboBrush = new(comboBackColor)) + using (Pen borderPen = new(comboBorderColor)) { - graphics.FillRectangle(SystemBrushes.ControlText, bounds); - ControlPaint.DrawButton(graphics, bounds, buttonState); - point = new(bounds.Location.X + 3 + bounds.Width / 2 - size.Width / 2, - bounds.Location.Y + bounds.Height / 2 - size.Height / 2); - TextRenderer.DrawText(graphics, text, comboBoxFont, point, - Enabled ? SystemColors.ControlText : SystemColors.GrayText, TextFormatFlags.Default); + graphics.FillRectangle(comboBrush, bounds); + graphics.DrawRectangle(borderPen, bounds); + point = new(bounds.Location.X + 3, bounds.Location.Y + bounds.Height / 2 - size.Height / 2); + TextRenderer.DrawText(graphics, text, comboBoxFont, point, comboTextColor, TextFormatFlags.Default); } size = new(14, 0); @@ -213,10 +207,28 @@ internal sealed class CustomTreeView : TreeView selectionBounds.Size + new Size(bounds.Size.Width + left, 0)); comboBoxBounds = new(comboBoxBounds.Location, comboBoxBounds.Size + new Size(bounds.Size.Width + left, 0)); - if (ComboBoxRenderer.IsSupported) - ComboBoxRenderer.DrawDropDownButton(graphics, bounds, comboBoxState); - else - ControlPaint.DrawComboButton(graphics, bounds, buttonState); + + // Draw custom themed dropdown button + using (SolidBrush comboBrush = new(comboBackColor)) + using (Pen borderPen = new(comboBorderColor)) + { + graphics.FillRectangle(comboBrush, bounds); + graphics.DrawRectangle(borderPen, bounds); + + // Draw arrow + int arrowSize = 3; + Point arrowTop = new(bounds.X + bounds.Width / 2, bounds.Y + bounds.Height / 2 - 1); + Point[] arrowPoints = new[] + { + arrowTop, + new Point(arrowTop.X - arrowSize, arrowTop.Y - arrowSize), + new Point(arrowTop.X + arrowSize, arrowTop.Y - arrowSize) + }; + using (SolidBrush arrowBrush = new(comboTextColor)) + { + graphics.FillPolygon(arrowBrush, arrowPoints); + } + } this.comboBoxBounds[selection] = RectangleToClient(comboBoxBounds); } @@ -258,6 +270,7 @@ internal sealed class CustomTreeView : TreeView comboBoxDropDown ??= new(); comboBoxDropDown.ShowItemToolTips = false; comboBoxDropDown.Items.Clear(); + foreach (string proxy in proxies) { bool canUse = true; @@ -273,13 +286,22 @@ internal sealed class CustomTreeView : TreeView } if (canUse) - _ = comboBoxDropDown.Items.Add(new ToolStripButton(proxy + ".dll", null, (_, _) => + { + ToolStripMenuItem menuItem = new(proxy + ".dll", null, (_, _) => { pair.Key.Proxy = proxy == Selection.DefaultProxy ? null : proxy; selectForm.OnProxyChanged(); - }) { Font = comboBoxFont }); + }) + { + Font = comboBoxFont + }; + _ = comboBoxDropDown.Items.Add(menuItem); + } } + // Apply theme using ThemeManager + ThemeManager.ApplyToolStripDropDown(comboBoxDropDown); + comboBoxDropDown.Show(this, PointToScreen(new(pair.Value.Left, pair.Value.Bottom - 1))); break; } diff --git a/CreamInstaller/Utility/ThemeManager.cs b/CreamInstaller/Utility/ThemeManager.cs index cd082d4..57f312f 100644 --- a/CreamInstaller/Utility/ThemeManager.cs +++ b/CreamInstaller/Utility/ThemeManager.cs @@ -32,6 +32,24 @@ internal static class ThemeManager ? ColorTranslator.FromHtml("#99FF99") // Light green for dark mode : ColorTranslator.FromHtml("#006900"); // Dark green for light mode + internal static Color CustomTreeViewHighlightPlatformColor => ColorTranslator.FromHtml("#FFFF99"); // C1 + internal static Color CustomTreeViewDisabledPlatformColor => ColorTranslator.FromHtml("#AAAA69"); // C3 + internal static Color CustomTreeViewHighlightIdColor => ColorTranslator.FromHtml("#99FFFF"); // C4 + internal static Color CustomTreeViewDisabledIdColor => ColorTranslator.FromHtml("#69AAAA"); // C6 + internal static Color CustomTreeViewDisabledProxyColor => ColorTranslator.FromHtml("#69AA69"); // C8 + + internal static Color CustomTreeViewComboBackColor => Program.DarkModeEnabled + ? DarkBackAlt // #252525 + : SystemColors.Control; + + internal static Color CustomTreeViewComboBorderColor => Program.DarkModeEnabled + ? DarkBorder // #3F3F46 + : SystemColors.ControlDark; + + internal static Color CustomTreeViewComboTextColor => Program.DarkModeEnabled + ? DarkFore // #D4D4D4 + : SystemColors.ControlText; + internal static void ToggleDarkMode(Form anyForm) { Program.DarkModeEnabled = !Program.DarkModeEnabled; @@ -229,16 +247,57 @@ internal static class ThemeManager ApplyContextMenuItem(subItem, dark); } + internal static void ApplyToolStripDropDown(ToolStripDropDown dropDown) + { + if (dropDown is null) return; + + bool dark = Program.DarkModeEnabled; + + dropDown.BackColor = dark ? DarkBackAlt : SystemColors.Menu; + dropDown.ForeColor = dark ? DarkFore : SystemColors.MenuText; + dropDown.Renderer = dark ? new DarkDropDownRenderer() : new ToolStripProfessionalRenderer(); + + foreach (ToolStripItem item in dropDown.Items) + ApplyToolStripItem(item, dark); + } + + private static void ApplyToolStripItem(ToolStripItem item, bool dark) + { + if (item is null) return; + + item.BackColor = dark ? DarkBackAlt : SystemColors.Menu; + item.ForeColor = dark ? DarkFore : SystemColors.MenuText; + } + private class DarkContextMenuRenderer : ToolStripProfessionalRenderer { public DarkContextMenuRenderer() : base(new DarkMenuColorTable()) { } + + protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) + { + if (e.Item.Selected) + e.TextColor = DarkFore; + base.OnRenderItemText(e); + } + } + + private class DarkDropDownRenderer : ToolStripProfessionalRenderer + { + public DarkDropDownRenderer() : base(new DarkMenuColorTable()) { } + + protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) + { + // Force text color to stay light even when selected + e.TextColor = DarkFore; + base.OnRenderItemText(e); + } } private class DarkMenuColorTable : ProfessionalColorTable { - public override Color MenuItemSelected => ColorTranslator.FromHtml("#3F3F46"); - public override Color MenuItemSelectedGradientBegin => ColorTranslator.FromHtml("#3F3F46"); - public override Color MenuItemSelectedGradientEnd => ColorTranslator.FromHtml("#3F3F46"); + public override Color MenuItemSelected => ColorTranslator.FromHtml("#2A2D2E"); + public override Color MenuItemSelectedGradientBegin => ColorTranslator.FromHtml("#2A2D2E"); + public override Color MenuItemSelectedGradientEnd => ColorTranslator.FromHtml("#2A2D2E"); public override Color MenuItemBorder => ColorTranslator.FromHtml("#3F3F46"); public override Color MenuBorder => ColorTranslator.FromHtml("#3F3F46"); public override Color MenuItemPressedGradientBegin => ColorTranslator.FromHtml("#252525");