mirror of
https://github.com/FroggMaster/CreamInstaller.git
synced 2026-06-12 11:01:23 -07:00
Added Game Search / Filter When Scanning Games Closes #15
- Added a "Game search:" label and text box above the game list in SelectDialogForm, allowing users to filter the program/game list by name in real-time (case-insensitive substring match). - Added TextBox theming support to ThemeManager for both dark and light modes, ensuring the new search field conforms to the active theme.
This commit is contained in:
+26
-2
@@ -33,6 +33,8 @@ namespace CreamInstaller.Forms
|
||||
saveButton = new Button();
|
||||
uninstallAllButton = new Button();
|
||||
selectionTreeView = new CustomTreeView();
|
||||
filterLabel = new System.Windows.Forms.Label();
|
||||
filterTextBox = new System.Windows.Forms.TextBox();
|
||||
groupBox.SuspendLayout();
|
||||
allCheckBoxFlowPanel.SuspendLayout();
|
||||
SuspendLayout();
|
||||
@@ -51,15 +53,33 @@ namespace CreamInstaller.Forms
|
||||
acceptButton.Text = "OK";
|
||||
acceptButton.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// filterLabel
|
||||
//
|
||||
filterLabel.AutoSize = true;
|
||||
filterLabel.Location = new System.Drawing.Point(12, 17);
|
||||
filterLabel.Name = "filterLabel";
|
||||
filterLabel.Size = new System.Drawing.Size(68, 15);
|
||||
filterLabel.TabIndex = 1008;
|
||||
filterLabel.Text = "Game search:";
|
||||
//
|
||||
// filterTextBox
|
||||
//
|
||||
filterTextBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
|
||||
filterTextBox.Location = new System.Drawing.Point(100, 14);
|
||||
filterTextBox.Name = "filterTextBox";
|
||||
filterTextBox.Size = new System.Drawing.Size(436, 23);
|
||||
filterTextBox.TabIndex = 0;
|
||||
filterTextBox.TextChanged += OnFilterTextChanged;
|
||||
//
|
||||
// groupBox
|
||||
//
|
||||
groupBox.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
groupBox.Controls.Add(selectionTreeView);
|
||||
groupBox.Controls.Add(allCheckBoxFlowPanel);
|
||||
groupBox.Location = new System.Drawing.Point(12, 12);
|
||||
groupBox.Location = new System.Drawing.Point(12, 43);
|
||||
groupBox.MinimumSize = new System.Drawing.Size(240, 40);
|
||||
groupBox.Name = "groupBox";
|
||||
groupBox.Size = new System.Drawing.Size(524, 225);
|
||||
groupBox.Size = new System.Drawing.Size(524, 194);
|
||||
groupBox.TabIndex = 3;
|
||||
groupBox.TabStop = false;
|
||||
groupBox.Text = "Choices";
|
||||
@@ -188,6 +208,8 @@ namespace CreamInstaller.Forms
|
||||
Controls.Add(cancelButton);
|
||||
Controls.Add(acceptButton);
|
||||
Controls.Add(groupBox);
|
||||
Controls.Add(filterTextBox);
|
||||
Controls.Add(filterLabel);
|
||||
FormBorderStyle = FormBorderStyle.FixedSingle;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
@@ -215,5 +237,7 @@ namespace CreamInstaller.Forms
|
||||
private Button saveButton;
|
||||
private CheckBox sortCheckBox;
|
||||
private Button uninstallAllButton;
|
||||
private System.Windows.Forms.Label filterLabel;
|
||||
private System.Windows.Forms.TextBox filterTextBox;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ namespace CreamInstaller.Forms;
|
||||
internal sealed partial class SelectDialogForm : CustomForm
|
||||
{
|
||||
private readonly List<(Platform platform, string id, string name)> selected = new();
|
||||
private readonly List<(Platform platform, string id, string name, bool alreadySelected)> allChoices = new();
|
||||
|
||||
internal SelectDialogForm(IWin32Window owner) : base(owner)
|
||||
{
|
||||
@@ -28,12 +29,12 @@ internal sealed partial class SelectDialogForm : CustomForm
|
||||
allCheckBox.Enabled = false;
|
||||
acceptButton.Enabled = false;
|
||||
selectionTreeView.AfterCheck += OnTreeNodeChecked;
|
||||
foreach ((Platform platform, string id, string name, bool alreadySelected) in potentialChoices)
|
||||
{
|
||||
TreeNode node = new() { Tag = platform, Name = id, Text = name, Checked = alreadySelected };
|
||||
OnTreeNodeChecked(node);
|
||||
_ = selectionTreeView.Nodes.Add(node);
|
||||
}
|
||||
allChoices.Clear();
|
||||
allChoices.AddRange(potentialChoices);
|
||||
foreach ((Platform platform, string id, string name, bool alreadySelected) in allChoices)
|
||||
if (alreadySelected)
|
||||
selected.Add((platform, id, name));
|
||||
ApplyFilter();
|
||||
|
||||
if (selected.Count < 1)
|
||||
OnLoad(null, null);
|
||||
@@ -70,6 +71,32 @@ internal sealed partial class SelectDialogForm : CustomForm
|
||||
allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
|
||||
}
|
||||
|
||||
private void OnFilterTextChanged(object sender, EventArgs e) => ApplyFilter();
|
||||
|
||||
private void ApplyFilter()
|
||||
{
|
||||
string filter = filterTextBox.Text.Trim();
|
||||
selectionTreeView.AfterCheck -= OnTreeNodeChecked;
|
||||
selectionTreeView.BeginUpdate();
|
||||
selectionTreeView.Nodes.Clear();
|
||||
bool hasSelections = selected.Count > 0;
|
||||
foreach ((Platform platform, string id, string name, bool alreadySelected) in allChoices)
|
||||
{
|
||||
if (filter.Length > 0 && name.IndexOf(filter, StringComparison.OrdinalIgnoreCase) < 0)
|
||||
continue;
|
||||
bool checkedState = hasSelections
|
||||
? selected.Any(s => s.platform == platform && s.id == id)
|
||||
: alreadySelected;
|
||||
TreeNode node = new() { Tag = platform, Name = id, Text = name, Checked = checkedState };
|
||||
_ = selectionTreeView.Nodes.Add(node);
|
||||
}
|
||||
selectionTreeView.EndUpdate();
|
||||
selectionTreeView.AfterCheck += OnTreeNodeChecked;
|
||||
allCheckBox.CheckedChanged -= OnAllCheckBoxChanged;
|
||||
allCheckBox.Checked = selectionTreeView.Nodes.Count > 0 && selectionTreeView.Nodes.Cast<TreeNode>().All(n => n.Checked);
|
||||
allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
|
||||
}
|
||||
|
||||
private void OnResize(object s, EventArgs e)
|
||||
=> Text = TextRenderer.MeasureText(Program.ApplicationName, Font).Width > Size.Width - 100
|
||||
? Program.ApplicationNameShort
|
||||
|
||||
@@ -206,6 +206,13 @@ internal static class ThemeManager
|
||||
rtb.ForeColor = DarkFore;
|
||||
break;
|
||||
|
||||
// TextBox follows alternate dark background
|
||||
case TextBox tb:
|
||||
tb.BackColor = DarkBackAlt;
|
||||
tb.ForeColor = DarkFore;
|
||||
tb.BorderStyle = BorderStyle.FixedSingle;
|
||||
break;
|
||||
|
||||
// Layout panels set a consistent background
|
||||
case TableLayoutPanel tlp:
|
||||
tlp.BackColor = DarkBack;
|
||||
@@ -258,6 +265,11 @@ internal static class ThemeManager
|
||||
rtb.BackColor = LightBack;
|
||||
rtb.ForeColor = LightFore;
|
||||
break;
|
||||
case TextBox tb:
|
||||
tb.BackColor = LightBackAlt;
|
||||
tb.ForeColor = LightFore;
|
||||
tb.BorderStyle = BorderStyle.Fixed3D;
|
||||
break;
|
||||
case TableLayoutPanel tlp:
|
||||
tlp.BackColor = LightBack;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user