diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_FlagWork8b.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_FlagWork8b.cs index 755999f04..c127e2ab1 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_FlagWork8b.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_FlagWork8b.cs @@ -87,10 +87,9 @@ private void LoadFlags(EventLabelCollectionSystem editor) }; var panel = CreateBoolPanel($"TLP_F{group.Key}"); - tab.Controls.Add(panel); + var rows = new List<(string Search, CheckBox Check, Label Label)>(); TC_Flags.TabPages.Add(tab); - int i = 0; foreach (var (name, index, _) in group) { var lbl = new Label { Text = name, Margin = Padding.Empty, AutoSize = true }; @@ -108,12 +107,14 @@ private void LoadFlags(EventLabelCollectionSystem editor) if (NUD_Flag.Value == index) CHK_CustomFlag.Checked = chk.Checked; }; - panel.Controls.Add(chk, 0, i); - panel.Controls.Add(lbl, 1, i); - + rows.Add((name, chk, lbl)); FlagDict.Add(index, chk); - i++; } + + ApplyBoolFilter(panel, rows, string.Empty); + var search = CreateSearchBox(text => ApplyBoolFilter(panel, rows, text)); + var host = CreateSearchHost(search, panel); + tab.Controls.Add(host); } } @@ -131,10 +132,9 @@ private void LoadSystem(EventLabelCollectionSystem editor) }; var panel = CreateBoolPanel($"TLP_S{group.Key}"); - tab.Controls.Add(panel); + var rows = new List<(string Search, CheckBox Check, Label Label)>(); TC_System.TabPages.Add(tab); - int i = 0; foreach (var (name, index, _) in group) { var lbl = new Label { Text = name, Margin = Padding.Empty, AutoSize = true }; @@ -152,12 +152,14 @@ private void LoadSystem(EventLabelCollectionSystem editor) if (NUD_System.Value == index) CHK_CustomSystem.Checked = chk.Checked; }; - panel.Controls.Add(chk, 0, i); - panel.Controls.Add(lbl, 1, i); - + rows.Add((name, chk, lbl)); SystemDict.Add(index, chk); - i++; } + + ApplyBoolFilter(panel, rows, string.Empty); + var search = CreateSearchBox(text => ApplyBoolFilter(panel, rows, text)); + var host = CreateSearchHost(search, panel); + tab.Controls.Add(host); } } @@ -175,10 +177,9 @@ private void LoadWork(EventLabelCollectionSystem editor) }; var panel = CreateWorkPanel($"TLP_W{group.Key}"); - tab.Controls.Add(panel); + var rows = new List<(string Search, Label Label, ComboBox Combo, NumericUpDown Numeric)>(); TC_Work.TabPages.Add(tab); - int i = 0; foreach (var entry in group) { var lbl = new Label { Text = entry.Name, Margin = Padding.Empty, AutoSize = true }; @@ -235,16 +236,99 @@ void ChangeConstValue(object? sender, EventArgs e) if (mtb.Value == 0) ChangeConstValue(this, EventArgs.Empty); - panel.Controls.Add(lbl, 0, i); - panel.Controls.Add(cb, 1, i); - panel.Controls.Add(mtb, 2, i); - + rows.Add((entry.Name, lbl, cb, mtb)); WorkDict.Add(entry.Index, mtb); - i++; } + + ApplyWorkFilter(panel, rows, string.Empty); + var search = CreateSearchBox(text => ApplyWorkFilter(panel, rows, text)); + var host = CreateSearchHost(search, panel); + tab.Controls.Add(host); } } + private static void ApplyBoolFilter(TableLayoutPanel panel, IReadOnlyList<(string Search, CheckBox Check, Label Label)> rows, string text) + { + var query = text.Trim(); + var hasQuery = query.Length != 0; + + panel.SuspendLayout(); + panel.Controls.Clear(); + var rowIndex = 0; + for (var i = 0; i < rows.Count; i++) + { + var row = rows[i]; + if (hasQuery && !row.Search.Contains(query, StringComparison.CurrentCultureIgnoreCase)) + continue; + + panel.Controls.Add(row.Check, 0, rowIndex); + panel.Controls.Add(row.Label, 1, rowIndex); + rowIndex++; + } + panel.ResumeLayout(); + } + + private static void ApplyWorkFilter(TableLayoutPanel panel, IReadOnlyList<(string Search, Label Label, ComboBox Combo, NumericUpDown Numeric)> rows, string text) + { + var query = text.Trim(); + var hasQuery = query.Length != 0; + + panel.SuspendLayout(); + panel.Controls.Clear(); + var rowIndex = 0; + for (var i = 0; i < rows.Count; i++) + { + var row = rows[i]; + if (hasQuery && !row.Search.Contains(query, StringComparison.CurrentCultureIgnoreCase)) + continue; + + panel.Controls.Add(row.Label, 0, rowIndex); + panel.Controls.Add(row.Combo, 1, rowIndex); + panel.Controls.Add(row.Numeric, 2, rowIndex); + rowIndex++; + } + panel.ResumeLayout(); + } + + private TextBox CreateSearchBox(Action applyFilter) + { + var box = new TextBox + { + PlaceholderText = "Search...", + Dock = DockStyle.Top, + Margin = Padding.Empty, + }; + if (Application.IsDarkModeEnabled) + WinFormsTranslator.ReformatDark(box); + + var timer = new Timer { Interval = 150 }; + timer.Tick += (_, _) => + { + timer.Stop(); + applyFilter(box.Text); + }; + box.TextChanged += (_, _) => + { + timer.Stop(); + timer.Start(); + }; + box.Disposed += (_, _) => timer.Dispose(); + return box; + } + + private static Panel CreateSearchHost(TextBox search, Control content) + { + var host = new Panel + { + Dock = DockStyle.Fill, + Margin = Padding.Empty, + }; + content.Dock = DockStyle.Fill; + host.Controls.Add(content); + host.Controls.Add(search); + return host; + } + private static TableLayoutPanel CreateBoolPanel(string name) { var panel = new TableLayoutPanel diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags.cs index 3057954e6..d16a6dbe3 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags.cs @@ -97,10 +97,12 @@ private void AddFlagList(EventLabelCollection list, bool[] values) Name = $"Tab_F{group.Key}", Text = WinFormsTranslator.TranslateEnum(group.Key, Main.CurrentLanguage), }; - TC_Flags.TabPages.Add(tab); var grid = CreateFlagGrid(); - tab.Controls.Add(grid); + var search = CreateSearchBox(text => ApplyGridFilter(grid, text)); + var host = CreateSearchHost(search, grid); + tab.Controls.Add(host); + TC_Flags.TabPages.Add(tab); var cFlag = new DataGridViewCheckBoxColumn { @@ -137,6 +139,8 @@ private void AddFlagList(EventLabelCollection list, bool[] values) cells[1].Value = name; } + ApplyGridFilter(grid, string.Empty); + grid.CellValueChanged += (_, e) => { if (e.ColumnIndex != 0 || e.RowIndex == -1) @@ -172,6 +176,25 @@ private void AddFlagList(EventLabelCollection list, bool[] values) } } + private static void ApplyGridFilter(DataGridView grid, string text) + { + var query = text.Trim(); + var hasQuery = query.Length != 0; + foreach (DataGridViewRow row in grid.Rows) + { + if (row.Cells.Count < 2) + continue; + if (!hasQuery) + { + row.Visible = true; + continue; + } + + var value = row.Cells[1].Value?.ToString() ?? string.Empty; + row.Visible = value.Contains(query, StringComparison.CurrentCultureIgnoreCase); + } + } + private static DoubleBufferedDataGridView CreateFlagGrid() => new() { AllowUserToAddRows = false, @@ -214,10 +237,10 @@ private void AddConstList(EventLabelCollection list, ushort[] values) }; var panel = CreateConstPanel(); - tab.Controls.Add(panel); TC_Const.TabPages.Add(tab); var grouped = group.ToList(); + var rows = new List<(string Search, Label Label, ComboBox Combo, NumericUpDown Numeric)>(grouped.Count); for (var i = 0; i < grouped.Count; i++) { var entry = grouped[i]; @@ -276,15 +299,78 @@ void ChangeConstValue(object? sender, EventArgs e) if (mtb.Value == 0) ChangeConstValue(this, EventArgs.Empty); - panel.Controls.Add(lbl, 0, i); - panel.Controls.Add(cb, 1, i); - panel.Controls.Add(mtb, 2, i); - + rows.Add((entry.Name, lbl, cb, mtb)); WorkDict.Add(entry.Index, mtb); } + + ApplyConstFilter(panel, rows, string.Empty); + var search = CreateSearchBox(text => ApplyConstFilter(panel, rows, text)); + var host = CreateSearchHost(search, panel); + tab.Controls.Add(host); } } + private static void ApplyConstFilter(TableLayoutPanel panel, IReadOnlyList<(string Search, Label Label, ComboBox Combo, NumericUpDown Numeric)> rows, string text) + { + var query = text.Trim(); + var hasQuery = query.Length != 0; + + panel.SuspendLayout(); + panel.Controls.Clear(); + var rowIndex = 0; + for (var i = 0; i < rows.Count; i++) + { + var row = rows[i]; + if (hasQuery && !row.Search.Contains(query, StringComparison.CurrentCultureIgnoreCase)) + continue; + + panel.Controls.Add(row.Label, 0, rowIndex); + panel.Controls.Add(row.Combo, 1, rowIndex); + panel.Controls.Add(row.Numeric, 2, rowIndex); + rowIndex++; + } + panel.ResumeLayout(); + } + + private TextBox CreateSearchBox(Action applyFilter) + { + var box = new TextBox + { + PlaceholderText = "Search...", + Dock = DockStyle.Top, + Margin = Padding.Empty, + }; + if (Application.IsDarkModeEnabled) + WinFormsTranslator.ReformatDark(box); + + var timer = new Timer { Interval = 150 }; + timer.Tick += (_, _) => + { + timer.Stop(); + applyFilter(box.Text); + }; + box.TextChanged += (_, _) => + { + timer.Stop(); + timer.Start(); + }; + box.Disposed += (_, _) => timer.Dispose(); + return box; + } + + private static Panel CreateSearchHost(TextBox search, Control content) + { + var host = new Panel + { + Dock = DockStyle.Fill, + Margin = Padding.Empty, + }; + content.Dock = DockStyle.Fill; + host.Controls.Add(content); + host.Controls.Add(search); + return host; + } + private static TableLayoutPanel CreateConstPanel() { var panel = new TableLayoutPanel diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags2.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags2.cs index 442fc2738..e7dee4048 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags2.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags2.cs @@ -104,7 +104,9 @@ private void AddFlagList(EventLabelCollection list, bool[] values) }; var grid = CreateFlagGrid(); - tab.Controls.Add(grid); + var search = CreateSearchBox(text => ApplyGridFilter(grid, text)); + var host = CreateSearchHost(search, grid); + tab.Controls.Add(host); TC_Flags.TabPages.Add(tab); var cFlag = new DataGridViewCheckBoxColumn @@ -177,6 +179,25 @@ private void AddFlagList(EventLabelCollection list, bool[] values) } } + private static void ApplyGridFilter(DataGridView grid, string text) + { + var query = text.Trim(); + var hasQuery = query.Length != 0; + foreach (DataGridViewRow row in grid.Rows) + { + if (row.Cells.Count < 2) + continue; + if (!hasQuery) + { + row.Visible = true; + continue; + } + + var value = row.Cells[1].Value?.ToString() ?? string.Empty; + row.Visible = value.Contains(query, StringComparison.CurrentCultureIgnoreCase); + } + } + private static DoubleBufferedDataGridView CreateFlagGrid() => new() { AllowUserToAddRows = false, @@ -219,10 +240,10 @@ private void AddConstList(EventLabelCollection list, ReadOnlySpan values) }; var panel = CreateConstPanel(); - tab.Controls.Add(panel); TC_Const.TabPages.Add(tab); var grouped = group.ToList(); + var rows = new List<(string Search, Label Label, ComboBox Combo, NumericUpDown Numeric)>(grouped.Count); for (var i = 0; i < grouped.Count; i++) { var entry = grouped[i]; @@ -280,15 +301,78 @@ void ChangeConstValue(object? sender, EventArgs e) if (mtb.Value == 0) ChangeConstValue(this, EventArgs.Empty); - panel.Controls.Add(lbl, 0, i); - panel.Controls.Add(cb, 1, i); - panel.Controls.Add(mtb, 2, i); - + rows.Add((entry.Name, lbl, cb, mtb)); WorkDict.Add(entry.Index, mtb); } + + ApplyConstFilter(panel, rows, string.Empty); + var search = CreateSearchBox(text => ApplyConstFilter(panel, rows, text)); + var host = CreateSearchHost(search, panel); + tab.Controls.Add(host); } } + private static void ApplyConstFilter(TableLayoutPanel panel, IReadOnlyList<(string Search, Label Label, ComboBox Combo, NumericUpDown Numeric)> rows, string text) + { + var query = text.Trim(); + var hasQuery = query.Length != 0; + + panel.SuspendLayout(); + panel.Controls.Clear(); + var rowIndex = 0; + for (var i = 0; i < rows.Count; i++) + { + var row = rows[i]; + if (hasQuery && !row.Search.Contains(query, StringComparison.CurrentCultureIgnoreCase)) + continue; + + panel.Controls.Add(row.Label, 0, rowIndex); + panel.Controls.Add(row.Combo, 1, rowIndex); + panel.Controls.Add(row.Numeric, 2, rowIndex); + rowIndex++; + } + panel.ResumeLayout(); + } + + private TextBox CreateSearchBox(Action applyFilter) + { + var box = new TextBox + { + PlaceholderText = "Search...", + Dock = DockStyle.Top, + Margin = Padding.Empty, + }; + if (Application.IsDarkModeEnabled) + WinFormsTranslator.ReformatDark(box); + + var timer = new Timer { Interval = 150 }; + timer.Tick += (_, _) => + { + timer.Stop(); + applyFilter(box.Text); + }; + box.TextChanged += (_, _) => + { + timer.Stop(); + timer.Start(); + }; + box.Disposed += (_, _) => timer.Dispose(); + return box; + } + + private static Panel CreateSearchHost(TextBox search, Control content) + { + var host = new Panel + { + Dock = DockStyle.Fill, + Margin = Padding.Empty, + }; + content.Dock = DockStyle.Fill; + host.Controls.Add(content); + host.Controls.Add(search); + return host; + } + private static TableLayoutPanel CreateConstPanel() { var panel = new TableLayoutPanel diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs index b5063be57..4839f289f 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs @@ -78,7 +78,7 @@ private void LoadFlags(IEnumerable editorFlag) { var tlp = new TableLayoutPanel { Dock = DockStyle.Fill, Name = $"TLP_F{g.Type}", AutoScroll = true }; tlp.SuspendLayout(); - int i = 0; + var rows = new List<(string Search, CheckBox Check, Label Label)>(); foreach (var f in g.Vars.OfType()) { var lbl = new Label @@ -98,16 +98,17 @@ private void LoadFlags(IEnumerable editorFlag) }; lbl.Click += (_, _) => chk.Checked ^= true; chk.CheckedChanged += (_, _) => f.Flag = chk.Checked; - tlp.Controls.Add(chk, 0, i); - tlp.Controls.Add(lbl, 1, i); - i++; + rows.Add((f.Name, chk, lbl)); } + ApplyBoolFilter(tlp, rows, string.Empty); var tab = new TabPage { Name = $"Tab_F{g.Type}", Text = WinFormsTranslator.TranslateEnum(g.Type, Main.CurrentLanguage), }; - tab.Controls.Add(tlp); + var search = CreateSearchBox(text => ApplyBoolFilter(tlp, rows, text)); + var host = CreateSearchHost(search, tlp); + tab.Controls.Add(host); TC_Flag.Controls.Add(tab); tlp.ResumeLayout(); } @@ -119,7 +120,7 @@ private void LoadWork(IEnumerable editorWork) { var tlp = new TableLayoutPanel { Dock = DockStyle.Fill, Name = $"TLP_W{g.Type}", AutoScroll = true }; tlp.SuspendLayout(); - int i = 0; + var rows = new List<(string Search, Label Label, ComboBox Combo, NumericUpDown Numeric)>(); foreach (var f in g.Vars.OfType>()) { var lbl = new Label @@ -182,9 +183,6 @@ private void LoadWork(IEnumerable editorWork) NUD_Stat.Text = value.ToString(); editing = false; }; - tlp.Controls.Add(lbl, 0, i); - tlp.Controls.Add(cb, 1, i); - tlp.Controls.Add(nud, 2, i); { var match = f.Options.FirstOrDefault(z => z.Value == f.Value); if (match is not null) @@ -193,19 +191,104 @@ private void LoadWork(IEnumerable editorWork) nud.Enabled = false; } } - i++; + rows.Add((f.Name, lbl, cb, nud)); } + ApplyWorkFilter(tlp, rows, string.Empty); var tab = new TabPage { Name = $"Tab_W{g.Type}", Text = WinFormsTranslator.TranslateEnum(g.Type, Main.CurrentLanguage), }; - tab.Controls.Add(tlp); + var search = CreateSearchBox(text => ApplyWorkFilter(tlp, rows, text)); + var host = CreateSearchHost(search, tlp); + tab.Controls.Add(host); TC_Work.Controls.Add(tab); tlp.ResumeLayout(); } } + private static void ApplyBoolFilter(TableLayoutPanel panel, IReadOnlyList<(string Search, CheckBox Check, Label Label)> rows, string text) + { + var query = text.Trim(); + var hasQuery = query.Length != 0; + + panel.SuspendLayout(); + panel.Controls.Clear(); + var rowIndex = 0; + for (var i = 0; i < rows.Count; i++) + { + var row = rows[i]; + if (hasQuery && !row.Search.Contains(query, StringComparison.CurrentCultureIgnoreCase)) + continue; + + panel.Controls.Add(row.Check, 0, rowIndex); + panel.Controls.Add(row.Label, 1, rowIndex); + rowIndex++; + } + panel.ResumeLayout(); + } + + private static void ApplyWorkFilter(TableLayoutPanel panel, IReadOnlyList<(string Search, Label Label, ComboBox Combo, NumericUpDown Numeric)> rows, string text) + { + var query = text.Trim(); + var hasQuery = query.Length != 0; + + panel.SuspendLayout(); + panel.Controls.Clear(); + var rowIndex = 0; + for (var i = 0; i < rows.Count; i++) + { + var row = rows[i]; + if (hasQuery && !row.Search.Contains(query, StringComparison.CurrentCultureIgnoreCase)) + continue; + + panel.Controls.Add(row.Label, 0, rowIndex); + panel.Controls.Add(row.Combo, 1, rowIndex); + panel.Controls.Add(row.Numeric, 2, rowIndex); + rowIndex++; + } + panel.ResumeLayout(); + } + + private TextBox CreateSearchBox(Action applyFilter) + { + var box = new TextBox + { + PlaceholderText = "Search...", + Dock = DockStyle.Top, + Margin = Padding.Empty, + }; + if (Application.IsDarkModeEnabled) + WinFormsTranslator.ReformatDark(box); + + var timer = new Timer { Interval = 150 }; + timer.Tick += (_, _) => + { + timer.Stop(); + applyFilter(box.Text); + }; + box.TextChanged += (_, _) => + { + timer.Stop(); + timer.Start(); + }; + box.Disposed += (_, _) => timer.Dispose(); + return box; + } + + private static Panel CreateSearchHost(TextBox search, Control content) + { + var host = new Panel + { + Dock = DockStyle.Fill, + Margin = Padding.Empty, + }; + content.Dock = DockStyle.Fill; + host.Controls.Add(content); + host.Controls.Add(search); + return host; + } + private const string flagTag = "bool_"; private const string constTag = "const_"; private const string constCBTag = "cbconst_";