Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/code refactoring #443

Draft
wants to merge 8 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Source/IdleMasterExtended/IdleMasterExtended.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
Expand Down Expand Up @@ -192,6 +192,7 @@
<Compile Include="Settings.cs" />
<Compile Include="Statistics.cs" />
<Compile Include="SteamProfile.cs" />
<Compile Include="ThemeHandler.cs" />
<EmbeddedResource Include="frmAbout.resx">
<DependentUpon>frmAbout.cs</DependentUpon>
</EmbeddedResource>
Expand Down Expand Up @@ -300,7 +301,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="logo1.ico" />
<None Include="Resources\select2-spinner_inverted.gif" />
<None Include="Resources\select2-spinner_w.gif" />
<None Include="Resources\x-2x_w.png" />
<None Include="Resources\trash-2x_w.png" />
<None Include="Resources\power-standby-2x_w.png" />
Expand Down
6 changes: 3 additions & 3 deletions Source/IdleMasterExtended/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Source/IdleMasterExtended/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@
<data name="imgFalse_w" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\x-2x_w.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="imgSpinInv" type="System.Resources.ResXFileRef, System.Windows.Forms">
<data name="imgSpin_w" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\select2-spinner_inverted.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>
229 changes: 229 additions & 0 deletions Source/IdleMasterExtended/ThemeHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
using IdleMasterExtended.Properties;
using mshtml;
using System;
using System.Drawing;
using System.Reflection;
using System.Resources;
using System.Windows.Forms;
using static System.Windows.Forms.Control;

namespace IdleMasterExtended
{
internal class ThemeHandler
{
/// <summary>
/// This class is a static utility class to handle the applied theme coloring setting of all Windows forms.
///
/// When a theme change is applied through the settings each form will be responsible to change it's colors,
/// preferrably using this class as it automatically handles each embedded control of the form (e.g. labels, buttons, lists).
/// </summary>

static readonly Color DefaultBackColor = SystemColors.Control;
static readonly Color DefaultBoxColor = SystemColors.Window;
static readonly Color DefaultForeColor = SystemColors.ControlText;
static readonly Color DefaultGreenColor = Color.Green;
static readonly FlatStyle DefaultButtonStyle = FlatStyle.Standard;
static readonly Color DefaultLinkColor = Color.Blue;

static readonly Color DarkBackColor = Color.FromArgb(38, 38, 38);
static readonly Color DarkBoxColor = Color.FromArgb(58, 58, 58);
static readonly Color DarkForeColor = Color.FromArgb(196, 196, 196);
static readonly Color DarkGreenColor = Color.FromArgb(126, 166, 75);
static readonly FlatStyle DarkButtonStyle = FlatStyle.Flat;
static readonly Color DarkLinkColor = Color.GhostWhite;

const string PositiveStatusImage = "imgTrue";
const string NegativeStatusImage = "imgFalse";

/// <summary>
/// Sets the theme of the Windows `Form` (default or dark theme). Automatically handles all the `Controls` inside the `Form`.
/// <br/>
/// Example: `ThemeHandler.SetTheme(this, Properties.DarkTheme)`
/// </summary>
/// <param name="form">The Windows form to apply the theme to</param>
/// <param name="darkTheme">True if dark theme, else false</param>
public static void SetTheme(Form form, bool darkTheme)
{
SetThemeForm(form, darkTheme);
SetThemeControls(form.Controls, darkTheme);
}

/// <summary>
/// Toggle the picturebox image to represent a positive or negative status
/// </summary>
/// <param name="pictureBox">The picturebox to toggle</param>
/// <param name="isPositiveStatus">True if it's a positive status (e.g. Steam is running), else false/param>
/// <param name="darkTheme">True if dark theme, else false</param>
public static void ToggleStatusIcon(PictureBox pictureBox, bool isPositiveStatus, bool darkTheme)
{
if (isPositiveStatus && ResourceExists(PositiveStatusImage))
{
pictureBox.Image = GetImageFromResources(PositiveStatusImage, darkTheme);
}
else if (!isPositiveStatus && ResourceExists(NegativeStatusImage))
{
pictureBox.Image = GetImageFromResources(NegativeStatusImage, darkTheme);
}
}

/// <summary>
/// Toggle the label text to represent a positive or negative status
/// </summary>
/// <param name="label"></param>
/// <param name="isPositiveStatus"></param>
/// <param name="darkTheme"></param>
public static void ToggleStatusLabelColor(Label label, bool isPositiveStatus, bool darkTheme)
{
if (isPositiveStatus)
{
label.ForeColor = darkTheme ? DarkGreenColor : DefaultGreenColor;
}
else if (!isPositiveStatus)
{
label.ForeColor = darkTheme ? DarkForeColor : DefaultForeColor;
}
}

/// <summary>
/// Applies the theme colors on the `Form` (background and foreground)
/// </summary>
/// <param name="form">Windows form to apply the colors to</param>
/// <param name="darkTheme">True if dark theme, else false</param>
private static void SetThemeForm(Form form, bool darkTheme)
{
form.ForeColor = darkTheme ? DarkForeColor : DefaultForeColor;
form.BackColor = darkTheme ? DarkBackColor : DefaultBackColor;
}

/// <summary>
/// Applies the theme colors for each component in the collection of `Controls` (available in each `Form` via `Form.Controls`)
/// </summary>
/// <param name="collection">Collection of `Controls`</param>
/// <param name="darkTheme">True if dark theme, else false</param>
private static void SetThemeControls(ControlCollection collection, bool darkTheme)
{
foreach (Control control in collection)
{
if (control is Button button)
{
button.FlatStyle = darkTheme ? DarkButtonStyle : DefaultButtonStyle;
button.ForeColor = darkTheme ? DarkForeColor : DefaultForeColor;

if (button.Image != null && ResourceExists(button.Tag as string))
{
button.Image = GetImageFromResources(button.Tag as string, darkTheme);
}
}
else if (control is TextBox textBox)
{
textBox.BackColor = darkTheme ? DarkBoxColor : DefaultBoxColor;
textBox.ForeColor = darkTheme ? DarkForeColor : DefaultForeColor;
}
else if (control is ListBox listBox)
{
listBox.BackColor = darkTheme ? DarkBoxColor : DefaultBoxColor;
listBox.ForeColor = darkTheme ? DarkForeColor : DefaultForeColor;
}
else if (control is ListView listView)
{
listView.BackColor = darkTheme ? DarkBoxColor : DefaultBoxColor;
listView.ForeColor = darkTheme ? DarkForeColor : DefaultForeColor;
}
else if (control is LinkLabel linklabel)
{
linklabel.LinkColor = darkTheme ? DarkLinkColor : DefaultLinkColor;
}
else if (control is GroupBox groupBox)
{
groupBox.ForeColor = darkTheme ? DarkForeColor : DefaultForeColor;
SetThemeControls(groupBox.Controls, darkTheme);
}
else if (control is PictureBox pictureBox)
{
if (pictureBox.Image != null && ResourceExists(pictureBox.Tag as string))
{
pictureBox.Image = GetImageFromResources(pictureBox.Tag as string, darkTheme);
}
}
else if (control is MenuStrip menuStrip)
{
menuStrip.BackColor = darkTheme ? DarkBackColor : DefaultBackColor;
menuStrip.ForeColor = darkTheme ? DarkForeColor : DefaultForeColor;
SetThemeMenuStripItems(darkTheme, menuStrip);
}

else
{
control.BackColor = darkTheme ? DarkBackColor : DefaultBackColor;
control.ForeColor = darkTheme ? DarkForeColor : DefaultForeColor;
}
}
}

/// <summary>
/// Go through each menu strip item (dropdown) and apply the theme color and image.
/// </summary>
/// <param name="darkTheme"></param>
/// <param name="menuStrip"></param>
private static void SetThemeMenuStripItems(bool darkTheme, MenuStrip menuStrip)
{
foreach (ToolStripMenuItem menuStripItem in menuStrip.Items)
{
menuStripItem.BackColor = menuStripItem.DropDown.BackColor = menuStrip.BackColor;
menuStripItem.ForeColor = menuStripItem.DropDown.ForeColor = menuStrip.ForeColor;
SetImageDropDownItems(menuStripItem, darkTheme);
}
}

/// <summary>
/// Makes sure we only handle the necessary toolstrip sub-items, i.e. ToolStripMenuItems with a parent ToolStripMenuItem.
/// This avoids issues with for example `ToolStripSeparator` that cannot be cast to `ToolStripMenuItem`.
/// </summary>
/// <param name="menuItem">The parent ToolStripMenuItem</param>
/// <param name="darkTheme">True if a dark theme, otherwise False</param>
private static void SetImageDropDownItems(ToolStripMenuItem menuItem, bool darkTheme)
{
foreach (object dropDownItem in menuItem.DropDownItems)
{
if (dropDownItem is ToolStripMenuItem dropDownMenuItem)
{
string itemImageTag = dropDownMenuItem.Tag as string;

if (dropDownMenuItem.Image != null && ResourceExists(itemImageTag))
{
dropDownMenuItem.Image = GetImageFromResources(itemImageTag, darkTheme);
}
}
}
}

/// <summary>
/// Checks if a resource is available or not.
/// </summary>
/// <param name="resourceName">The filename of the resource</param>
/// <returns>True if the resource is available, else false</returns>
private static bool ResourceExists(string resourceName)
{
if (string.IsNullOrEmpty(resourceName))
{
return false;
}
else
{
return Resources.ResourceManager.GetObject(resourceName) != null;
}
}

/// <summary>
/// Gets the image from the resources. If dark mode: append "_w" to the default filename.
/// </summary>
/// <param name="defaultImageName">The default filename of the resource</param>
/// <param name="darkTheme">True if dark theme, else false</param>
/// <returns>Image</returns>
private static Image GetImageFromResources(string defaultImageName, bool darkTheme)
{
string imageResourceName = darkTheme ? $"{defaultImageName}_w" : defaultImageName;
return Resources.ResourceManager.GetObject(imageResourceName) as Image;
}
}
}
22 changes: 1 addition & 21 deletions Source/IdleMasterExtended/frmAbout.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using System.Deployment.Application;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

namespace IdleMasterExtended
Expand All @@ -21,33 +19,15 @@ private void btnOK_Click(object sender, EventArgs e)
private void frmAbout_Load(object sender, EventArgs e)
{
SetLocalization();
SetTheme();
SetVersion();
ThemeHandler.SetTheme(this, Properties.Settings.Default.customTheme);
}

private void SetLocalization()
{
btnOK.Text = localization.strings.ok;
}

private void SetTheme()
{
var settings = Properties.Settings.Default;
var customTheme = settings.customTheme;

if (customTheme)
{
this.BackColor = settings.colorBgd;
this.ForeColor = settings.colorTxt;

btnOK.FlatStyle = FlatStyle.Flat;
btnOK.BackColor = this.BackColor;
btnOK.ForeColor = this.ForeColor;

linkLabelVersion.LinkColor = this.ForeColor;
}
}

private void SetVersion()
{
var version = Assembly.GetExecutingAssembly().GetName().Version;
Expand Down
1 change: 1 addition & 0 deletions Source/IdleMasterExtended/frmBlacklist.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 3 additions & 37 deletions Source/IdleMasterExtended/frmBlacklist.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using IdleMasterExtended.Properties;
using System;
using System.Linq;
using System.Windows.Forms;
using IdleMasterExtended.Properties;

namespace IdleMasterExtended
{
Expand All @@ -26,43 +26,9 @@ private void frmBlacklist_Load(object sender, EventArgs e)
btnSave.Text = localization.strings.save;
this.Text = localization.strings.manage_blacklist;
grpAdd.Text = localization.strings.add_game_blacklist;

lstBlacklist.Items.AddRange(Settings.Default.blacklist.Cast<string>().ToArray());

if (Settings.Default.customTheme)
{
runtimeCustomThemeBlacklist(); // JN: Apply the dark theme
}
}

// Make everything dark to match the dark theme
private void runtimeCustomThemeBlacklist()
{
System.Drawing.Color colorBgd = Settings.Default.colorBgd; // Dark gray (from Steam)
System.Drawing.Color colorTxt = Settings.Default.colorTxt; // Light gray (from Steam)

// Form
this.BackColor = colorBgd;
this.ForeColor = colorTxt;

// Button
btnAdd.FlatStyle = btnSave.FlatStyle = btnRemove.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
btnAdd.BackColor = btnSave.BackColor = btnRemove.BackColor = colorBgd;
btnAdd.ForeColor = btnSave.ForeColor = btnRemove.ForeColor = colorTxt;

// List
lstBlacklist.BackColor = colorBgd;
lstBlacklist.ForeColor = colorTxt;

// Group
grpAdd.BackColor = colorBgd;
grpAdd.ForeColor = colorTxt;

// Textbox Appid
txtAppid.BackColor = colorBgd;
txtAppid.ForeColor = colorTxt;

btnRemove.Image = Settings.Default.whiteIcons ? Resources.imgTrash_w : Resources.imgTrash;
ThemeHandler.SetTheme(this, Settings.Default.customTheme);
}

private void btnSave_Click(object sender, EventArgs e)
Expand Down
Loading