diff --git a/ReClass.NET/Forms/AboutForm.cs b/ReClass.NET/Forms/AboutForm.cs index b6e800a4..6d249c78 100644 --- a/ReClass.NET/Forms/AboutForm.cs +++ b/ReClass.NET/Forms/AboutForm.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Drawing; // Added for Color using System.Windows.Forms; using ReClassNET.UI; @@ -7,6 +8,8 @@ namespace ReClassNET.Forms { public partial class AboutForm : IconForm { + private bool isApplyingTheme = false; // To prevent re-entrancy + public AboutForm() { InitializeComponent(); @@ -19,6 +22,13 @@ public AboutForm() buildTimeValueLabel.Text = Properties.Resources.BuildDate; authorValueLabel.Text = Constants.Author; homepageValueLabel.Text = Constants.HomepageUrl; + + this.Activated += AboutForm_Activated; + } + + private void AboutForm_Activated(object sender, EventArgs e) + { + ApplyTheme(); } protected override void OnLoad(EventArgs e) @@ -26,6 +36,83 @@ protected override void OnLoad(EventArgs e) base.OnLoad(e); GlobalWindowManager.AddWindow(this); + + ApplyTheme(); + } + + private void ApplyTheme() + { + if (isApplyingTheme) return; + isApplyingTheme = true; + + try + { + var foreColor = Program.Settings.TextColor; + var backColor = Program.Settings.BackgroundColor; + var backColorSelected = Program.Settings.SelectedColor; // For input-like backgrounds + var linkColor = Program.Settings.OffsetColor; // Using OffsetColor for links as an example + + this.ForeColor = foreColor; + this.BackColor = backColor; + + // Apply to child controls recursively + UpdateControlTheme(this, foreColor, backColor, backColorSelected); + + // Specific controls + licenseTextBox.BackColor = backColorSelected; + licenseTextBox.ForeColor = foreColor; + + homepageValueLabel.LinkColor = linkColor; + // Make ActiveLinkColor slightly different, e.g., a bit lighter or darker than LinkColor + homepageValueLabel.ActiveLinkColor = ControlPaint.Light(linkColor); + homepageValueLabel.VisitedLinkColor = ControlPaint.Dark(linkColor); + + + // BannerBox theming will be handled more deeply in BannerBox.cs later. + // For now, set basic colors. + bannerBox.BackColor = backColor; // Or a specific banner background from settings if available + bannerBox.ForeColor = foreColor; // For title and text, if not custom painted + bannerBox.Invalidate(); // Ensure it redraws + } + finally + { + isApplyingTheme = false; + } + } + + private void UpdateControlTheme(Control parentControl, Color foreColor, Color backColor, Color backColorSelected) + { + foreach (Control control in parentControl.Controls) + { + // Skip BannerBox as it will have its own detailed theming. + if (control is BannerBox) continue; + + control.ForeColor = foreColor; + control.BackColor = backColor; + + if (control is TextBoxBase || control is ListBox || control is ComboBox) + { + control.BackColor = backColorSelected; + } + else if (control is GroupBox groupBox) + { + // GroupBox ForeColor sets the title color. + // Children are handled by recursion. + } + else if (control is LinkLabel linkLabel) + { + // Already handled homepageValueLabel specifically, but a general case: + linkLabel.LinkColor = Program.Settings.OffsetColor; + linkLabel.ActiveLinkColor = ControlPaint.Light(Program.Settings.OffsetColor); + linkLabel.VisitedLinkColor = ControlPaint.Dark(Program.Settings.OffsetColor); + } + + + if (control.HasChildren) + { + UpdateControlTheme(control, foreColor, backColor, backColorSelected); + } + } } protected override void OnFormClosed(FormClosedEventArgs e) diff --git a/ReClass.NET/Forms/ClassSelectionForm.cs b/ReClass.NET/Forms/ClassSelectionForm.cs index e8ed984d..7c52eacc 100644 --- a/ReClass.NET/Forms/ClassSelectionForm.cs +++ b/ReClass.NET/Forms/ClassSelectionForm.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.Contracts; +using System.Drawing; // Added for Color using System.Linq; using System.Windows.Forms; using ReClassNET.Nodes; @@ -11,6 +12,7 @@ namespace ReClassNET.Forms public partial class ClassSelectionForm : IconForm { private readonly List allClasses; + private bool isApplyingTheme = false; // To prevent re-entrancy public ClassNode SelectedClass => classesListBox.SelectedItem as ClassNode; @@ -23,6 +25,13 @@ public ClassSelectionForm(IEnumerable classes) InitializeComponent(); ShowFilteredClasses(); + + this.Activated += ClassSelectionForm_Activated; + } + + private void ClassSelectionForm_Activated(object sender, EventArgs e) + { + ApplyTheme(); } protected override void OnLoad(EventArgs e) @@ -30,8 +39,76 @@ protected override void OnLoad(EventArgs e) base.OnLoad(e); GlobalWindowManager.AddWindow(this); + + ApplyTheme(); } + private void ApplyTheme() + { + if (isApplyingTheme) return; + isApplyingTheme = true; + + try + { + var foreColor = Program.Settings.TextColor; + var backColor = Program.Settings.BackgroundColor; + var backColorSelected = Program.Settings.SelectedColor; + + this.ForeColor = foreColor; + this.BackColor = backColor; + + UpdateControlTheme(this, foreColor, backColor, backColorSelected); + + // Specific controls + classesListBox.BackColor = backColorSelected; + classesListBox.ForeColor = foreColor; + + filterNameTextBox.BackColor = backColorSelected; + filterNameTextBox.ForeColor = foreColor; + + // BannerBox theming will be handled more deeply in BannerBox.cs later. + bannerBox.BackColor = backColor; + bannerBox.ForeColor = foreColor; + bannerBox.Invalidate(); + } + finally + { + isApplyingTheme = false; + } + } + + private void UpdateControlTheme(Control parentControl, Color foreColor, Color backColor, Color backColorSelected) + { + foreach (Control control in parentControl.Controls) + { + if (control is BannerBox) continue; // Skip BannerBox + + control.ForeColor = foreColor; + control.BackColor = backColor; + + if (control is TextBoxBase || control is ListBox || control is ComboBox) + { + control.BackColor = backColorSelected; + } + else if (control is ButtonBase) + { + // Standard buttons often don't style well with BackColor. ForeColor is usually fine. + // If using FlatStyle.Flat or FlatStyle.Popup, BackColor can be set. + // For now, we'll assume default button styling is mostly acceptable or will be tweaked if issues arise. + } + else if (control is GroupBox) + { + // GroupBox ForeColor sets the title color. + } + + if (control.HasChildren) + { + UpdateControlTheme(control, foreColor, backColor, backColorSelected); + } + } + } + + protected override void OnFormClosed(FormClosedEventArgs e) { base.OnFormClosed(e); diff --git a/ReClass.NET/Forms/CodeForm.cs b/ReClass.NET/Forms/CodeForm.cs index f84d3f0e..d550b8af 100644 --- a/ReClass.NET/Forms/CodeForm.cs +++ b/ReClass.NET/Forms/CodeForm.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Windows.Forms; +using System.Drawing; // Added for Color using ColorCode; using ColorCode.Parsing; using ReClassNET.CodeGenerator; @@ -19,6 +20,8 @@ namespace ReClassNET.Forms { public partial class CodeForm : IconForm { + private bool isApplyingTheme = false; // To prevent re-entrancy + public CodeForm(ICodeGenerator generator, IReadOnlyList classes, IReadOnlyList enums, ILogger logger) { Contract.Requires(generator != null); @@ -44,6 +47,13 @@ public CodeForm(ICodeGenerator generator, IReadOnlyList classes, IRea } codeRichTextBox.Rtf = buffer.ToString(); + + this.Activated += CodeForm_Activated; + } + + private void CodeForm_Activated(object sender, EventArgs e) + { + ApplyTheme(); } protected override void OnLoad(EventArgs e) @@ -51,6 +61,64 @@ protected override void OnLoad(EventArgs e) base.OnLoad(e); GlobalWindowManager.AddWindow(this); + + ApplyTheme(); + } + + private void ApplyTheme() + { + if (isApplyingTheme) return; + isApplyingTheme = true; + + try + { + var foreColor = Program.Settings.TextColor; + var backColor = Program.Settings.BackgroundColor; + // For RichTextBox, the selected color might be too dark if it's used as a general input field background. + // Sticking to the main BackgroundColor for now, as RTF handles its own foreground colors. + var rtbBackColor = Program.Settings.BackgroundColor; + + this.ForeColor = foreColor; + this.BackColor = backColor; + + UpdateControlTheme(this, foreColor, backColor, rtbBackColor); // Pass rtbBackColor for specific use + + // Specific controls + codeRichTextBox.BackColor = rtbBackColor; + codeRichTextBox.ForeColor = foreColor; // Default text color if no RTF styling applies + + // BannerBox theming + bannerBox.BackColor = backColor; + bannerBox.ForeColor = foreColor; + bannerBox.Invalidate(); + } + finally + { + isApplyingTheme = false; + } + } + + private void UpdateControlTheme(Control parentControl, Color foreColor, Color backColor, Color specificBackColor) + { + foreach (Control control in parentControl.Controls) + { + if (control is BannerBox) continue; + + control.ForeColor = foreColor; + control.BackColor = backColor; + + if (control is RichTextBox) // Apply specificBackColor to RichTextBox + { + control.BackColor = specificBackColor; + } + // No other specific input controls like TextBox, ListBox on this form from designer. + // Buttons will take general ForeColor/BackColor. + + if (control.HasChildren) + { + UpdateControlTheme(control, foreColor, backColor, specificBackColor); + } + } } protected override void OnFormClosed(FormClosedEventArgs e) diff --git a/ReClass.NET/Forms/MainForm.cs b/ReClass.NET/Forms/MainForm.cs index e771a10d..9aad3bde 100644 --- a/ReClass.NET/Forms/MainForm.cs +++ b/ReClass.NET/Forms/MainForm.cs @@ -29,6 +29,7 @@ public partial class MainForm : IconForm { private readonly PluginManager pluginManager; private readonly IconProvider iconProvider = new IconProvider(); + private bool isApplyingTheme = false; // To prevent re-entrancy in ApplyTheme private ReClassNetProject currentProject; public ReClassNetProject CurrentProject => currentProject; @@ -95,6 +96,8 @@ public MainForm() }; pluginManager = new PluginManager(new DefaultPluginHost(this, Program.RemoteProcess, Program.Logger)); + + this.Activated += MainForm_Activated; // Subscribe to Activated event } protected override void OnLoad(EventArgs e) @@ -135,8 +138,131 @@ protected override void OnLoad(EventArgs e) { AttachToProcess(Program.CommandLineArgs[Constants.CommandLineOptions.AttachTo]); } + + ApplyTheme(); // Initial theme application + } + + private void MainForm_Activated(object sender, EventArgs e) + { + ApplyTheme(); // Re-apply theme when form is activated + } + + private void ApplyTheme() + { + if (isApplyingTheme) return; // Prevent re-entrancy + isApplyingTheme = true; + + try + { + var foreColor = Program.Settings.TextColor; + var backColor = Program.Settings.BackgroundColor; + var backColorSelected = Program.Settings.SelectedColor; // For input-like backgrounds + + this.ForeColor = foreColor; + this.BackColor = backColor; + + // Apply to specific top-level controls and containers first + mainMenuStrip.ForeColor = foreColor; // Text color for menu items + mainMenuStrip.BackColor = backColor; // Background of the menu bar itself + mainMenuStrip.Invalidate(); + + toolStrip.ForeColor = foreColor; // Text/icon color for toolstrip items + toolStrip.BackColor = backColor; // Background of the toolstrip bar + toolStrip.Invalidate(); + + statusStrip.ForeColor = foreColor; + statusStrip.BackColor = backColor; + foreach (ToolStripItem item in statusStrip.Items) + { + item.ForeColor = foreColor; + } + statusStrip.Invalidate(); + + splitContainer.BackColor = backColor; + splitContainer.Panel1.BackColor = backColor; + splitContainer.Panel2.BackColor = backColor; + + // Apply to child controls recursively + UpdateControlTheme(this, foreColor, backColor, backColorSelected); + + // Invalidate custom controls that depend on Program.Settings in their paint/draw logic + memoryViewControl.Invalidate(); + projectView.Invalidate(); // ProjectView might need more specific theming if Back/ForeColor isn't enough + } + finally + { + isApplyingTheme = false; + } + } + + private void UpdateControlTheme(Control parentControl, Color foreColor, Color backColor, Color backColorSelected) + { + foreach (Control control in parentControl.Controls) + { + control.ForeColor = foreColor; + control.BackColor = backColor; + + if (control is TextBoxBase || control is ListBox || control is ComboBox) + { + control.BackColor = backColorSelected; + } + else if (control is TreeView treeView) + { + treeView.BackColor = backColorSelected; // Typically tree backgrounds are different + treeView.LineColor = foreColor; // Color for the tree lines + } + else if (control is ListView listView) + { + listView.BackColor = backColorSelected; // Typically list backgrounds are different + } + else if (control is ButtonBase) + { + // Buttons are tricky with WinForms theming. ForeColor might work. + // BackColor often doesn't unless FlatStyle is changed, which can alter appearance significantly. + // For now, just ForeColor. + } + else if (control is SplitContainer childSplitContainer) + { + childSplitContainer.BackColor = backColor; + childSplitContainer.Panel1.BackColor = backColor; + childSplitContainer.Panel2.BackColor = backColor; + UpdateControlTheme(childSplitContainer.Panel1, foreColor, backColor, backColorSelected); + UpdateControlTheme(childSplitContainer.Panel2, foreColor, backColor, backColorSelected); + continue; // Skip default recursion for children as we handled its panels + } + else if (control is DataGridView dgv) + { + dgv.BackgroundColor = backColor; + dgv.GridColor = foreColor; // Color of the grid lines + + dgv.DefaultCellStyle.BackColor = backColorSelected; + dgv.DefaultCellStyle.ForeColor = foreColor; + dgv.DefaultCellStyle.SelectionBackColor = Program.Settings.HighlightChangedValues ? Program.Settings.AddressColor : backColor; // Example + dgv.DefaultCellStyle.SelectionForeColor = foreColor; + + dgv.ColumnHeadersDefaultCellStyle.BackColor = backColor; + dgv.ColumnHeadersDefaultCellStyle.ForeColor = foreColor; + dgv.EnableHeadersVisualStyles = false; // Important for custom header colors + + dgv.RowHeadersDefaultCellStyle.BackColor = backColor; + dgv.RowHeadersDefaultCellStyle.ForeColor = foreColor; + } + // Skip ToolStrip and MenuStrip as they are handled by CustomToolStripProfessionalRenderer + else if (control is ToolStrip || control is MenuStrip) + { + control.Invalidate(); // Ensure they redraw + continue; + } + + + if (control.HasChildren) + { + UpdateControlTheme(control, foreColor, backColor, backColorSelected); + } + } } + protected override void OnFormClosed(FormClosedEventArgs e) { pluginManager.UnloadAllPlugins(); @@ -1043,7 +1169,9 @@ private void memoryViewControl_DrawContextRequested(object sender, DrawContextRe } memoryViewBuffer.UpdateFrom(process, address); - args.Settings = Program.Settings; + // ApplyTheme might have already set general colors, but DrawContext is specific + // Ensure the settings object passed here is up-to-date. + args.Settings = Program.Settings; args.IconProvider = iconProvider; args.Process = process; args.Memory = memoryViewBuffer; diff --git a/ReClass.NET/Forms/SettingsForm.Designer.cs b/ReClass.NET/Forms/SettingsForm.Designer.cs index 82e4efd9..7e9a650d 100644 --- a/ReClass.NET/Forms/SettingsForm.Designer.cs +++ b/ReClass.NET/Forms/SettingsForm.Designer.cs @@ -128,6 +128,7 @@ private void InitializeComponent() this.int16TypeTextBox = new System.Windows.Forms.TextBox(); this.int8SettingsLabel = new System.Windows.Forms.Label(); this.int8TypeTextBox = new System.Windows.Forms.TextBox(); + this.darkModeCheckBox = new System.Windows.Forms.CheckBox(); // Added this.bannerBox = new ReClassNET.Controls.BannerBox(); this.utf32TextSettingsLabel = new System.Windows.Forms.Label(); this.utf32TextTypeTextBox = new System.Windows.Forms.TextBox(); @@ -155,6 +156,7 @@ private void InitializeComponent() // // generalSettingsTabPage // + this.generalSettingsTabPage.Controls.Add(this.darkModeCheckBox); // Added this.generalSettingsTabPage.Controls.Add(this.fileAssociationGroupBox); this.generalSettingsTabPage.Controls.Add(this.commentsGroupBox); this.generalSettingsTabPage.Controls.Add(this.displayGroupBox); @@ -172,10 +174,10 @@ private void InitializeComponent() this.fileAssociationGroupBox.Controls.Add(this.removeAssociationButton); this.fileAssociationGroupBox.Controls.Add(this.createAssociationButton); this.fileAssociationGroupBox.Controls.Add(this.associationInfoLabel); - this.fileAssociationGroupBox.Location = new System.Drawing.Point(6, 231); + this.fileAssociationGroupBox.Location = new System.Drawing.Point(6, 254); // Adjusted Y: 231 + 23 = 254 this.fileAssociationGroupBox.Name = "fileAssociationGroupBox"; this.fileAssociationGroupBox.Size = new System.Drawing.Size(542, 85); - this.fileAssociationGroupBox.TabIndex = 4; + this.fileAssociationGroupBox.TabIndex = 5; // Incremented this.fileAssociationGroupBox.TabStop = false; this.fileAssociationGroupBox.Text = "RCNET File Association"; // @@ -219,10 +221,10 @@ private void InitializeComponent() this.commentsGroupBox.Controls.Add(this.showPointerCheckBox); this.commentsGroupBox.Controls.Add(this.showIntegerCheckBox); this.commentsGroupBox.Controls.Add(this.showFloatCheckBox); - this.commentsGroupBox.Location = new System.Drawing.Point(6, 39); + this.commentsGroupBox.Location = new System.Drawing.Point(6, 62); // Adjusted Y: 39 + 23 = 62 this.commentsGroupBox.Name = "commentsGroupBox"; this.commentsGroupBox.Size = new System.Drawing.Size(265, 186); - this.commentsGroupBox.TabIndex = 3; + this.commentsGroupBox.TabIndex = 4; // Incremented this.commentsGroupBox.TabStop = false; this.commentsGroupBox.Text = "Node Comments"; // @@ -304,10 +306,10 @@ private void InitializeComponent() this.displayGroupBox.Controls.Add(this.showTextCheckBox); this.displayGroupBox.Controls.Add(this.showNodeOffsetCheckBox); this.displayGroupBox.Controls.Add(this.showNodeAddressCheckBox); - this.displayGroupBox.Location = new System.Drawing.Point(283, 39); + this.displayGroupBox.Location = new System.Drawing.Point(283, 62); // Adjusted Y: 39 + 23 = 62 this.displayGroupBox.Name = "displayGroupBox"; this.displayGroupBox.Size = new System.Drawing.Size(265, 160); - this.displayGroupBox.TabIndex = 2; + this.displayGroupBox.TabIndex = 3; // Incremented this.displayGroupBox.TabStop = false; this.displayGroupBox.Text = "Display"; // @@ -381,6 +383,16 @@ private void InitializeComponent() this.stayOnTopCheckBox.Text = "Force ReClass.NET to stay on top"; this.stayOnTopCheckBox.UseVisualStyleBackColor = true; // + // darkModeCheckBox + // + this.darkModeCheckBox.AutoSize = true; + this.darkModeCheckBox.Location = new System.Drawing.Point(6, 29); // Y = 6 (stayOnTop) + 17 (stayOnTop height) + 6 (spacing) = 29 + this.darkModeCheckBox.Name = "darkModeCheckBox"; + this.darkModeCheckBox.Size = new System.Drawing.Size(118, 17); + this.darkModeCheckBox.TabIndex = 2; // After stayOnTopCheckBox + this.darkModeCheckBox.Text = "Enable Dark Mode"; + this.darkModeCheckBox.UseVisualStyleBackColor = true; + // // colorsSettingTabPage // this.colorsSettingTabPage.Controls.Add(this.nodeColorGroupBox); @@ -1247,5 +1259,6 @@ private void InitializeComponent() private System.Windows.Forms.TextBox nintTypeTextBox; private System.Windows.Forms.Label utf32TextSettingsLabel; private System.Windows.Forms.TextBox utf32TextTypeTextBox; + private System.Windows.Forms.CheckBox darkModeCheckBox; } } \ No newline at end of file diff --git a/ReClass.NET/Forms/SettingsForm.cs b/ReClass.NET/Forms/SettingsForm.cs index fcc4121e..5cd366f2 100644 --- a/ReClass.NET/Forms/SettingsForm.cs +++ b/ReClass.NET/Forms/SettingsForm.cs @@ -7,6 +7,7 @@ using ReClassNET.Project; using ReClassNET.UI; using ReClassNET.Util; +using System.Drawing; // Required for Color namespace ReClassNET.Forms { @@ -41,6 +42,9 @@ public SettingsForm(Settings settings, CppTypeMapping typeMapping) SetColorBindings(); SetTypeDefinitionBindings(); + // Apply theme after bindings are set. + ApplyTheme(); + if (NativeMethods.IsUnix()) { fileAssociationGroupBox.Enabled = false; @@ -106,6 +110,97 @@ private void SetGeneralBindings() SetBinding(showPluginInfoCheckBox, nameof(CheckBox.Checked), settings, nameof(Settings.ShowCommentPluginInfo)); SetBinding(runAsAdminCheckBox, nameof(CheckBox.Checked), settings, nameof(Settings.RunAsAdmin)); SetBinding(randomizeWindowTitleCheckBox, nameof(CheckBox.Checked), settings, nameof(Settings.RandomizeWindowTitle)); + + // Dark Mode CheckBox Binding + SetBinding(darkModeCheckBox, nameof(CheckBox.Checked), settings, nameof(Settings.EnableDarkMode)); + darkModeCheckBox.CheckedChanged += (_, _2) => ApplyTheme(); + } + + private void ApplyTheme() + { + // Determine colors based on dark mode setting + var foreColor = settings.EnableDarkMode ? settings.DarkTextColor : SystemColors.ControlText; + var backColor = settings.EnableDarkMode ? settings.DarkBackgroundColor : SystemColors.Control; + + this.ForeColor = foreColor; + this.BackColor = backColor; + + // Recursively update all child controls + UpdateControlTheme(this); + + // Special handling for specific controls if needed + settingsTabControl.ForeColor = foreColor; + settingsTabControl.BackColor = backColor; // TabControl itself might not change much + + foreach (TabPage tabPage in settingsTabControl.TabPages) + { + tabPage.ForeColor = foreColor; + tabPage.BackColor = backColor; + UpdateControlTheme(tabPage); // Apply to controls within each tab page + } + + // BannerBox - Assuming it has public ForeColor/BackColor properties to set. + // If BannerBox internally uses specific colors, it might need its own dark mode logic. + bannerBox.ForeColor = foreColor; + bannerBox.BackColor = settings.EnableDarkMode ? settings.DarkSelectedColor : SystemColors.Control; // Example: using selected color for banner bg + } + + private void UpdateControlTheme(Control parentControl) + { + var foreColor = settings.EnableDarkMode ? settings.DarkTextColor : SystemColors.ControlText; + var backColor = settings.EnableDarkMode ? settings.DarkBackgroundColor : SystemColors.Control; + var contrastingBackColor = settings.EnableDarkMode ? settings.DarkSelectedColor : SystemColors.Window; // For TextBox, etc. + + foreach (Control control in parentControl.Controls) + { + control.ForeColor = foreColor; + control.BackColor = backColor; + + if (control is TextBox || control is ComboBox || control is ListBox) + { + control.BackColor = contrastingBackColor; // Use a contrasting background for input fields + } + else if (control is ButtonBase) // Buttons often use system styling + { + // Buttons might not fully support custom BackColor/ForeColor on all OS versions or themes. + // We can try, but it might not have the desired effect. + control.ForeColor = foreColor; + // control.BackColor = backColor; // Often ignored for buttons + } + else if (control is CheckBox) + { + // CheckBox text color is handled by ForeColor, background is usually transparent or uses parent's. + } + else if (control is GroupBox groupBox) + { + groupBox.ForeColor = foreColor; // GroupBox title color + UpdateControlTheme(groupBox); // Recursively update controls within the GroupBox + } + else if (control is Panel panel) + { + UpdateControlTheme(panel); // Recursively update controls within the Panel + } + else if (control is TabControl tabControl) + { + UpdateControlTheme(tabControl); // Apply to the TabControl itself + foreach (TabPage tabPage in tabControl.TabPages) + { + tabPage.ForeColor = foreColor; + tabPage.BackColor = backColor; + UpdateControlTheme(tabPage); // Apply to controls within each tab page + } + } + else if (control is ColorBox colorBox) // Assuming ColorBox is a custom control + { + // ColorBox might need specific properties if Fore/Back color don't cover its display + // For now, apply standard colors. It might have its own drawing logic. + colorBox.BackColor = backColor; + } + else if (control.HasChildren && !(control is TabPage || control is TextBoxBase)) // Avoid re-recursing on TabPage children here as it's handled above / TextBox + { + UpdateControlTheme(control); + } + } } private void SetColorBindings() diff --git a/ReClass.NET/Settings.cs b/ReClass.NET/Settings.cs index b5d9268b..a41f6977 100644 --- a/ReClass.NET/Settings.cs +++ b/ReClass.NET/Settings.cs @@ -16,6 +16,8 @@ public class Settings public bool RandomizeWindowTitle { get; set; } = false; + public bool EnableDarkMode { get; set; } = false; + // Node Drawing Settings public bool ShowNodeAddress { get; set; } = true; @@ -46,33 +48,61 @@ public class Settings // Colors - public Color BackgroundColor { get; set; } = Color.FromArgb(255, 255, 255); + private Color backgroundColor = Color.FromArgb(255, 255, 255); + public Color BackgroundColor { get => EnableDarkMode ? DarkBackgroundColor : backgroundColor; set => backgroundColor = value; } + public Color DarkBackgroundColor { get; set; } = ColorTranslator.FromHtml("#2D2D30"); - public Color SelectedColor { get; set; } = Color.FromArgb(240, 240, 240); + private Color selectedColor = Color.FromArgb(240, 240, 240); + public Color SelectedColor { get => EnableDarkMode ? DarkSelectedColor : selectedColor; set => selectedColor = value; } + public Color DarkSelectedColor { get; set; } = ColorTranslator.FromHtml("#3F3F46"); - public Color HiddenColor { get; set; } = Color.FromArgb(240, 240, 240); + private Color hiddenColor = Color.FromArgb(240, 240, 240); + public Color HiddenColor { get => EnableDarkMode ? DarkHiddenColor : hiddenColor; set => hiddenColor = value; } + public Color DarkHiddenColor { get; set; } = ColorTranslator.FromHtml("#434346"); - public Color OffsetColor { get; set; } = Color.FromArgb(255, 0, 0); + private Color offsetColor = Color.FromArgb(255, 0, 0); + public Color OffsetColor { get => EnableDarkMode ? DarkOffsetColor : offsetColor; set => offsetColor = value; } + public Color DarkOffsetColor { get; set; } = ColorTranslator.FromHtml("#569CD6"); - public Color AddressColor { get; set; } = Color.FromArgb(0, 200, 0); + private Color addressColor = Color.FromArgb(0, 200, 0); + public Color AddressColor { get => EnableDarkMode ? DarkAddressColor : addressColor; set => addressColor = value; } + public Color DarkAddressColor { get; set; } = ColorTranslator.FromHtml("#9CDCFE"); - public Color HexColor { get; set; } = Color.FromArgb(0, 0, 0); + private Color hexColor = Color.FromArgb(0, 0, 0); + public Color HexColor { get => EnableDarkMode ? DarkHexColor : hexColor; set => hexColor = value; } + public Color DarkHexColor { get; set; } = ColorTranslator.FromHtml("#D4D4D4"); - public Color TypeColor { get; set; } = Color.FromArgb(0, 0, 255); + private Color typeColor = Color.FromArgb(0, 0, 255); + public Color TypeColor { get => EnableDarkMode ? DarkTypeColor : typeColor; set => typeColor = value; } + public Color DarkTypeColor { get; set; } = ColorTranslator.FromHtml("#4EC9B0"); - public Color NameColor { get; set; } = Color.FromArgb(32, 32, 128); + private Color nameColor = Color.FromArgb(32, 32, 128); + public Color NameColor { get => EnableDarkMode ? DarkNameColor : nameColor; set => nameColor = value; } + public Color DarkNameColor { get; set; } = ColorTranslator.FromHtml("#C586C0"); - public Color ValueColor { get; set; } = Color.FromArgb(255, 128, 0); + private Color valueColor = Color.FromArgb(255, 128, 0); + public Color ValueColor { get => EnableDarkMode ? DarkValueColor : valueColor; set => valueColor = value; } + public Color DarkValueColor { get; set; } = ColorTranslator.FromHtml("#B5CEA8"); - public Color IndexColor { get; set; } = Color.FromArgb(32, 200, 200); + private Color indexColor = Color.FromArgb(32, 200, 200); + public Color IndexColor { get => EnableDarkMode ? DarkIndexColor : indexColor; set => indexColor = value; } + public Color DarkIndexColor { get; set; } = ColorTranslator.FromHtml("#499CD6"); - public Color CommentColor { get; set; } = Color.FromArgb(0, 200, 0); + private Color commentColor = Color.FromArgb(0, 200, 0); + public Color CommentColor { get => EnableDarkMode ? DarkCommentColor : commentColor; set => commentColor = value; } + public Color DarkCommentColor { get; set; } = ColorTranslator.FromHtml("#608B4E"); - public Color TextColor { get; set; } = Color.FromArgb(0, 0, 255); + private Color textColor = Color.FromArgb(0, 0, 255); + public Color TextColor { get => EnableDarkMode ? DarkTextColor : textColor; set => textColor = value; } + public Color DarkTextColor { get; set; } = ColorTranslator.FromHtml("#D4D4D4"); - public Color VTableColor { get; set; } = Color.FromArgb(0, 255, 0); + private Color vTableColor = Color.FromArgb(0, 255, 0); + public Color VTableColor { get => EnableDarkMode ? DarkVTableColor : vTableColor; set => vTableColor = value; } + public Color DarkVTableColor { get; set; } = ColorTranslator.FromHtml("#C586C0"); - public Color PluginColor { get; set; } = Color.FromArgb(255, 0, 255); + private Color pluginColor = Color.FromArgb(255, 0, 255); + public Color PluginColor { get => EnableDarkMode ? DarkPluginColor : pluginColor; set => pluginColor = value; } + public Color DarkPluginColor { get; set; } = ColorTranslator.FromHtml("#DCDCAA"); public CustomDataMap CustomData { get; } = new CustomDataMap(); diff --git a/ReClass.NET/UI/CustomToolStripProfessionalRenderer.cs b/ReClass.NET/UI/CustomToolStripProfessionalRenderer.cs index 64ac3e44..40089de1 100644 --- a/ReClass.NET/UI/CustomToolStripProfessionalRenderer.cs +++ b/ReClass.NET/UI/CustomToolStripProfessionalRenderer.cs @@ -1,5 +1,6 @@ using System.Drawing; using System.Windows.Forms; +using ReClassNET; // Added for Program.Settings namespace ReClassNET.UI { @@ -39,14 +40,36 @@ protected override void OnRenderToolStripPanelBackground(ToolStripPanelRenderEve internal class CustomProfessionalColorTable : ProfessionalColorTable { - public override Color MenuStripGradientBegin => SystemColors.Control; + private static readonly Color DarkModeBackgroundColor = Color.FromArgb(45, 45, 48); - public override Color MenuStripGradientEnd => SystemColors.Control; + public override Color MenuStripGradientBegin => Program.Settings.EnableDarkMode ? DarkModeBackgroundColor : SystemColors.Control; - public override Color ToolStripGradientBegin => SystemColors.Control; + public override Color MenuStripGradientEnd => Program.Settings.EnableDarkMode ? DarkModeBackgroundColor : SystemColors.Control; - public override Color ToolStripGradientMiddle => SystemColors.Control; + public override Color ToolStripGradientBegin => Program.Settings.EnableDarkMode ? DarkModeBackgroundColor : SystemColors.Control; - public override Color ToolStripGradientEnd => SystemColors.Control; + public override Color ToolStripGradientMiddle => Program.Settings.EnableDarkMode ? DarkModeBackgroundColor : SystemColors.Control; + + public override Color ToolStripGradientEnd => Program.Settings.EnableDarkMode ? DarkModeBackgroundColor : SystemColors.Control; + + // It's important to override other colors for a complete dark mode experience. + // For example, item selection, borders, text, etc. + // Adding a few more overrides as examples: + + public override Color MenuItemSelected => Program.Settings.EnableDarkMode ? Color.FromArgb(70, 70, 70) : SystemColors.Highlight; + public override Color MenuItemBorder => Program.Settings.EnableDarkMode ? Color.FromArgb(80, 80, 80) : SystemColors.MenuBar; // Or another appropriate color + public override Color ToolStripDropDownBackground => Program.Settings.EnableDarkMode ? DarkModeBackgroundColor : SystemColors.Control; + public override Color ImageMarginGradientBegin => Program.Settings.EnableDarkMode ? DarkModeBackgroundColor : SystemColors.ControlLight; + public override Color ImageMarginGradientMiddle => Program.Settings.EnableDarkMode ? DarkModeBackgroundColor : SystemColors.ControlLight; + public override Color ImageMarginGradientEnd => Program.Settings.EnableDarkMode ? DarkModeBackgroundColor : SystemColors.ControlLight; + public override Color SeparatorDark => Program.Settings.EnableDarkMode ? Color.FromArgb(80, 80, 80) : SystemColors.ControlDark; + public override Color SeparatorLight => Program.Settings.EnableDarkMode ? Color.FromArgb(100, 100, 100) : SystemColors.ControlLightLight; + public override Color StatusStripGradientBegin => Program.Settings.EnableDarkMode ? DarkModeBackgroundColor : SystemColors.Control; + public override Color StatusStripGradientEnd => Program.Settings.EnableDarkMode ? DarkModeBackgroundColor : SystemColors.Control; + + // For text, you would typically rely on the control's ForeColor, + // but if the renderer specifically uses a color table item for text, it should be overridden. + // Example (if there was a TextColor property): + // public override Color TextColor => Program.Settings.EnableDarkMode ? Color.White : SystemColors.ControlText; } }