diff --git a/CreamInstaller/Forms/SelectDialogForm.Designer.cs b/CreamInstaller/Forms/SelectDialogForm.Designer.cs index 1d8aa15..c627b86 100644 --- a/CreamInstaller/Forms/SelectDialogForm.Designer.cs +++ b/CreamInstaller/Forms/SelectDialogForm.Designer.cs @@ -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; } } \ No newline at end of file diff --git a/CreamInstaller/Forms/SelectDialogForm.cs b/CreamInstaller/Forms/SelectDialogForm.cs index 85e86f9..8d44097 100644 --- a/CreamInstaller/Forms/SelectDialogForm.cs +++ b/CreamInstaller/Forms/SelectDialogForm.cs @@ -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().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 diff --git a/CreamInstaller/Utility/ThemeManager.cs b/CreamInstaller/Utility/ThemeManager.cs index d0424d8..c588cce 100644 --- a/CreamInstaller/Utility/ThemeManager.cs +++ b/CreamInstaller/Utility/ThemeManager.cs @@ -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;