Add and use `Insert{Before,After}{,Last}` helpers

This commit is contained in:
YoshiRulz 2025-03-05 18:22:33 +10:00
parent 7d876dee2c
commit 957029fc30
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
8 changed files with 163 additions and 14 deletions

View File

@ -267,7 +267,7 @@ namespace BizHawk.Client.Common.FilterManager
if (currState.SurfaceDisposition == SurfaceDisposition.Texture)
{
var renderer = new Render();
Filters.Insert(Filters.Count, renderer);
Filters.Add(renderer);
Compile(channel, inSize, outsize, finalTarget);
return;
}

View File

@ -3,6 +3,7 @@ using System.IO;
using BizHawk.Common;
using BizHawk.Common.IOExtensions;
using BizHawk.Common.StringExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
@ -21,8 +22,7 @@ namespace BizHawk.Client.Common
return;
}
var backupName = Filename;
backupName = backupName.Insert(Filename.LastIndexOf('.'), $".{DateTime.Now:yyyy-MM-dd HH.mm.ss}");
var backupName = Filename.InsertBeforeLast('.', insert: $".{DateTime.Now:yyyy-MM-dd HH.mm.ss}", out _);
backupName = Path.Combine(Session.BackupDirectory, Path.GetFileName(backupName));
Write(backupName, isBackup: true);

View File

@ -1,5 +1,6 @@
#nullable enable
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
@ -12,6 +13,7 @@ using System.Windows.Forms;
using BizHawk.Client.Common;
using BizHawk.Common;
using BizHawk.Common.CollectionExtensions;
using BizHawk.Common.ReflectionExtensions;
using BizHawk.Emulation.Common;
@ -158,6 +160,20 @@ namespace BizHawk.Client.EmuHawk
return tabControl.TabPages.Cast<TabPage>();
}
#pragma warning disable CS0618 // WinForms doesn't use generics ofc
public static bool InsertAfter(this ToolStripItemCollection items, ToolStripItem needle, ToolStripItem insert)
=> ((IList) items).InsertAfter(needle, insert: insert);
public static bool InsertAfterLast(this ToolStripItemCollection items, ToolStripItem needle, ToolStripItem insert)
=> ((IList) items).InsertAfterLast(needle, insert: insert);
public static bool InsertBefore(this ToolStripItemCollection items, ToolStripItem needle, ToolStripItem insert)
=> ((IList) items).InsertBefore(needle, insert: insert);
public static bool InsertBeforeLast(this ToolStripItemCollection items, ToolStripItem needle, ToolStripItem insert)
=> ((IList) items).InsertBeforeLast(needle, insert: insert);
#pragma warning restore CS0618
public static void ReplaceDropDownItems(this ToolStripDropDownItem menu, params ToolStripItem[] items)
{
menu.DropDownItems.Clear();

View File

@ -79,9 +79,7 @@ namespace BizHawk.Client.EmuHawk
#if BIZHAWKBUILD_SUPERHAWK
ToolStripMenuItemEx superHawkThrottleMenuItem = new() { Text = "SUPER·HAWK" };
superHawkThrottleMenuItem.Click += (_, _) => Config.SuperHawkThrottle = !Config.SuperHawkThrottle;
SpeedSkipSubMenu.DropDownItems.Insert(
SpeedSkipSubMenu.DropDownItems.IndexOf(MinimizeSkippingMenuItem),
superHawkThrottleMenuItem);
_ = SpeedSkipSubMenu.DropDownItems.InsertBefore(MinimizeSkippingMenuItem, insert: superHawkThrottleMenuItem);
ConfigSubMenu.DropDownOpened += (_, _) => superHawkThrottleMenuItem.Checked = Config.SuperHawkThrottle;
#endif
@ -159,9 +157,9 @@ namespace BizHawk.Client.EmuHawk
submenu.Enabled = false;
}
}
ConfigSubMenu.DropDownItems.Insert(
ConfigSubMenu.DropDownItems.IndexOf(CoresSubMenu) + 1,
new ToolStripMenuItemEx
_ = ConfigSubMenu.DropDownItems.InsertAfter(
CoresSubMenu,
insert: new ToolStripMenuItemEx
{
DropDownItems =
{
@ -175,7 +173,7 @@ namespace BizHawk.Client.EmuHawk
Text = "Core Settings",
});
MainformMenu.Items.Insert(MainformMenu.Items.IndexOf(ToolsSubMenu) + 1, NullHawkVSysSubmenu);
_ = MainformMenu.Items.InsertAfter(ToolsSubMenu, insert: NullHawkVSysSubmenu);
// Hide Status bar icons and general StatusBar prep
MainStatusBar.Padding = new Padding(MainStatusBar.Padding.Left, MainStatusBar.Padding.Top, MainStatusBar.Padding.Left, MainStatusBar.Padding.Bottom); // Workaround to remove extra padding on right

View File

@ -135,9 +135,7 @@ namespace BizHawk.Client.EmuHawk
};
if (this.ShowDialogWithTempMute(dialog).IsOk()) GoToFrame(int.Parse(dialog.PromptText));
};
EditSubMenu.DropDownItems.Insert(
EditSubMenu.DropDownItems.IndexOf(ReselectClipboardMenuItem) + 1,
goToFrameMenuItem);
_ = EditSubMenu.DropDownItems.InsertAfter(ReselectClipboardMenuItem, insert: goToFrameMenuItem);
RecentSubMenu.Image = Resources.Recent;
recentMacrosToolStripMenuItem.Image = Resources.Recent;

View File

@ -123,7 +123,7 @@ namespace BizHawk.Client.EmuHawk
i++;
}
};
WatchesSubMenu.DropDownItems.Insert(11, deduperMenuItem);
_ = WatchesSubMenu.DropDownItems.InsertBefore(toolStripSeparator3, insert: deduperMenuItem);
Settings = new RamWatchSettings();

View File

@ -10,6 +10,10 @@ namespace BizHawk.Common.CollectionExtensions
public static class CollectionExtensions
#pragma warning restore MA0104
{
private const string ERR_MSG_IMMUTABLE_LIST = "immutable list passed to mutating method";
private const string WARN_NONGENERIC = "use generic overload";
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
@ -247,6 +251,111 @@ namespace BizHawk.Common.CollectionExtensions
return -1;
}
public static bool InsertAfter<T>(this IList<T> list, T needle, T insert)
{
Debug.Assert(!list.IsReadOnly, ERR_MSG_IMMUTABLE_LIST);
var insertPoint = list.IndexOf(needle);
if (insertPoint < 0) return false;
list.Insert(insertPoint + 1, insert);
return true;
}
[Obsolete(WARN_NONGENERIC)]
public static bool InsertAfter<T>(this IList list, T needle, T insert)
{
Debug.Assert(!list.IsReadOnly, ERR_MSG_IMMUTABLE_LIST);
var insertPoint = list.IndexOf(needle);
if (insertPoint < 0) return false;
list.Insert(insertPoint + 1, insert);
return true;
}
public static bool InsertAfterLast<T>(this IList<T> list, T needle, T insert)
{
Debug.Assert(!list.IsReadOnly, ERR_MSG_IMMUTABLE_LIST);
var insertPoint = list.LastIndexOf(needle);
if (insertPoint < 0) return false;
list.Insert(insertPoint + 1, insert);
return true;
}
[Obsolete(WARN_NONGENERIC)]
public static bool InsertAfterLast<T>(this IList list, T needle, T insert)
{
Debug.Assert(!list.IsReadOnly, ERR_MSG_IMMUTABLE_LIST);
var insertPoint = list.LastIndexOf(needle);
if (insertPoint < 0) return false;
list.Insert(insertPoint + 1, insert);
return true;
}
public static bool InsertBefore<T>(this IList<T> list, T needle, T insert)
{
Debug.Assert(!list.IsReadOnly, ERR_MSG_IMMUTABLE_LIST);
var insertPoint = list.IndexOf(needle);
if (insertPoint < 0) return false;
list.Insert(insertPoint, insert);
return true;
}
[Obsolete(WARN_NONGENERIC)]
public static bool InsertBefore<T>(this IList list, T needle, T insert)
{
Debug.Assert(!list.IsReadOnly, ERR_MSG_IMMUTABLE_LIST);
var insertPoint = list.IndexOf(needle);
if (insertPoint < 0) return false;
list.Insert(insertPoint, insert);
return true;
}
public static bool InsertBeforeLast<T>(this IList<T> list, T needle, T insert)
{
Debug.Assert(!list.IsReadOnly, ERR_MSG_IMMUTABLE_LIST);
var insertPoint = list.LastIndexOf(needle);
if (insertPoint < 0) return false;
list.Insert(insertPoint, insert);
return true;
}
[Obsolete(WARN_NONGENERIC)]
public static bool InsertBeforeLast<T>(this IList list, T needle, T insert)
{
Debug.Assert(!list.IsReadOnly, ERR_MSG_IMMUTABLE_LIST);
var insertPoint = list.LastIndexOf(needle);
if (insertPoint < 0) return false;
list.Insert(insertPoint, insert);
return true;
}
public static int LastIndexOf<T>(this IList<T> list, T item)
{
if (list is T[] arr) return Array.LastIndexOf(arr, item);
if (list is List<T> bclList) return bclList.LastIndexOf(item);
if (item is null)
{
for (var i = list.Count - 1; i >= 0; i--) if (list[i] is null) return i;
}
else
{
for (var i = list.Count - 1; i >= 0; i--) if (item.Equals(list[i])) return i;
}
return -1;
}
[Obsolete(WARN_NONGENERIC)]
public static int LastIndexOf(this IList list, object? item)
{
if (item is null)
{
for (var i = list.Count - 1; i >= 0; i--) if (list[i] is null) return i;
}
else
{
for (var i = list.Count - 1; i >= 0; i--) if (item.Equals(list[i])) return i;
}
return -1;
}
public static T? FirstOrNull<T>(this IEnumerable<T> list, Func<T, bool> predicate)
where T : struct
{

View File

@ -62,6 +62,34 @@ namespace BizHawk.Common.StringExtensions
public static bool In(this string str, params string[] options)
=> options.Any(str.EqualsIgnoreCase);
public static string InsertAfter(this string str, char needle, string insert, out bool found)
{
var insertPoint = str.IndexOf(needle);
found = insertPoint >= 0;
return found ? str.Insert(insertPoint + 1, insert) : str;
}
public static string InsertAfterLast(this string str, char needle, string insert, out bool found)
{
var insertPoint = str.LastIndexOf(needle);
found = insertPoint >= 0;
return found ? str.Insert(insertPoint + 1, insert) : str;
}
public static string InsertBefore(this string str, char needle, string insert, out bool found)
{
var insertPoint = str.IndexOf(needle);
found = insertPoint >= 0;
return found ? str.Insert(insertPoint, insert) : str;
}
public static string InsertBeforeLast(this string str, char needle, string insert, out bool found)
{
var insertPoint = str.LastIndexOf(needle);
found = insertPoint >= 0;
return found ? str.Insert(insertPoint, insert) : str;
}
/// <returns>a copy of <paramref name="raw"/> with all characters outside <c>[0-9A-Za-z]</c> removed</returns>
public static string OnlyAlphanumeric(this string raw)
=> string.Concat(raw.Where(static c => c is (>= '0' and <= '9') or (>= 'A' and <= 'Z') or (>= 'a' and <= 'z')));