From f77d01d4f8af5393da283c801dfd9438bed04343 Mon Sep 17 00:00:00 2001 From: pointfeev Date: Thu, 25 Aug 2022 22:04:45 -0400 Subject: [PATCH] koaloader proxy choices --- CreamInstaller/Components/CustomTreeView.cs | 79 +++++++++++++++++---- CreamInstaller/Forms/SelectForm.Designer.cs | 12 ---- CreamInstaller/Forms/SelectForm.cs | 5 ++ CreamInstaller/Forms/SelectForm.resx | 3 - CreamInstaller/ProgramSelection.cs | 2 +- CreamInstaller/Resources/Koaloader.cs | 21 +++++- CreamInstaller/Utility/ProgramData.cs | 50 +++++++++++++ 7 files changed, 139 insertions(+), 33 deletions(-) diff --git a/CreamInstaller/Components/CustomTreeView.cs b/CreamInstaller/Components/CustomTreeView.cs index 0d26381..8180c5b 100644 --- a/CreamInstaller/Components/CustomTreeView.cs +++ b/CreamInstaller/Components/CustomTreeView.cs @@ -1,6 +1,10 @@ -using System; +using CreamInstaller.Resources; +using CreamInstaller.Utility; + +using System; using System.Collections.Generic; using System.Drawing; +using System.Linq; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; @@ -10,12 +14,14 @@ namespace CreamInstaller.Components; internal class CustomTreeView : TreeView { + private Form form; protected override void WndProc(ref Message m) { if (m.Msg == 0x203) m.Result = IntPtr.Zero; else base.WndProc(ref m); + form = FindForm(); } internal CustomTreeView() : base() @@ -27,6 +33,7 @@ internal class CustomTreeView : TreeView private readonly Dictionary selectionBounds = new(); private readonly Dictionary checkBoxBounds = new(); + private readonly Dictionary comboBoxBounds = new(); private const string koaloaderToggleString = "Koaloader"; private SolidBrush backBrush; @@ -118,8 +125,8 @@ internal class CustomTreeView : TreeView size = TextRenderer.MeasureText(graphics, text, font); int left = 1; bounds = new(bounds.X + bounds.Width, bounds.Y, size.Width + left, bounds.Height); - selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width + left, 0)); - checkBoxBounds = new(checkBoxBounds.Location, checkBoxBounds.Size + new Size(bounds.Size.Width + left, 0)); + selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width, 0)); + checkBoxBounds = new(checkBoxBounds.Location, checkBoxBounds.Size + new Size(bounds.Size.Width, 0)); graphics.FillRectangle(backBrush, bounds); point = new(bounds.Location.X - 1 + left, bounds.Location.Y + 1); TextRenderer.DrawText(graphics, text, font, point, @@ -127,6 +134,29 @@ internal class CustomTreeView : TreeView TextFormatFlags.Default); this.checkBoxBounds[selection] = RectangleToClient(checkBoxBounds); + + if (selection.Koaloader && selection.KoaloaderProxy is not null) + { + ComboBoxState comboBoxState = Enabled ? ComboBoxState.Normal : ComboBoxState.Disabled; + + text = selection.KoaloaderProxy.GetKoaloaderProxyDisplay(); + size = TextRenderer.MeasureText(graphics, text, font) + new Size(6, 0); + bounds = new(bounds.X + bounds.Width, bounds.Y, size.Width, bounds.Height); + selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width, 0)); + Rectangle comboBoxBounds = bounds; + graphics.FillRectangle(backBrush, bounds); + ComboBoxRenderer.DrawTextBox(graphics, bounds, text, font, comboBoxState); + + size = new(16, 0); + left = -1; + bounds = new(bounds.X + bounds.Width + left, bounds.Y, size.Width, bounds.Height); + selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width + left, 0)); + comboBoxBounds = new(comboBoxBounds.Location, comboBoxBounds.Size + new Size(bounds.Size.Width + left, 0)); + ComboBoxRenderer.DrawDropDownButton(graphics, bounds, comboBoxState); + + this.comboBoxBounds[selection] = RectangleToClient(comboBoxBounds); + } + else _ = comboBoxBounds.Remove(selection); } } @@ -138,28 +168,48 @@ internal class CustomTreeView : TreeView base.OnMouseDown(e); Refresh(); Point clickPoint = PointToClient(e.Location); + SelectForm selectForm = (form ??= FindForm()) as SelectForm; foreach (KeyValuePair pair in selectionBounds) if (pair.Key.IsVisible && pair.Value.Contains(clickPoint)) { SelectedNode = pair.Key; - if (e.Button is MouseButtons.Right && FindForm() is SelectForm selectForm) + if (e.Button is MouseButtons.Right && selectForm is not null) selectForm.OnNodeRightClick(pair.Key, e.Location); break; } if (e.Button is MouseButtons.Left) { bool invalidate = false; - foreach (KeyValuePair pair in checkBoxBounds) - if (pair.Value.Contains(clickPoint)) - { - pair.Key.Koaloader = !pair.Key.Koaloader; - invalidate = true; - break; - } - if (invalidate) + if (comboBoxBounds.Any() && selectForm is not null) + foreach (KeyValuePair pair in comboBoxBounds) + if (pair.Value.Contains(clickPoint)) + { + ContextMenuStrip contextMenuStrip = selectForm.ContextMenuStrip; + contextMenuStrip.Items.Clear(); + foreach (string proxy in Resources.Resources.EmbeddedResources.FindAll(r => r.StartsWith("Koaloader"))) + { + _ = contextMenuStrip.Items.Add(new ContextMenuItem(proxy.GetKoaloaderProxyDisplay(), + new EventHandler((sender, e) => + { + pair.Key.KoaloaderProxy = proxy; + ProgramData.UpdateKoaloaderProxyChoices(); + Invalidate(); + }))); + } + contextMenuStrip.Show(this, PointToScreen(new(pair.Value.Left, pair.Value.Bottom))); + invalidate = true; + break; + } + if (!invalidate) { - Invalidate(); - if (FindForm() is SelectForm selectForm) + foreach (KeyValuePair pair in checkBoxBounds) + if (pair.Value.Contains(clickPoint)) + { + pair.Key.Koaloader = !pair.Key.Koaloader; + invalidate = true; + break; + } + if (invalidate && selectForm is not null) { CheckBox koaloaderAllCheckBox = selectForm.KoaloaderAllCheckBox(); koaloaderAllCheckBox.CheckedChanged -= selectForm.OnKoaloaderAllCheckBoxChanged; @@ -167,6 +217,7 @@ internal class CustomTreeView : TreeView koaloaderAllCheckBox.CheckedChanged += selectForm.OnKoaloaderAllCheckBoxChanged; } } + if (invalidate) Invalidate(); } } } \ No newline at end of file diff --git a/CreamInstaller/Forms/SelectForm.Designer.cs b/CreamInstaller/Forms/SelectForm.Designer.cs index 7b667fa..27392e7 100644 --- a/CreamInstaller/Forms/SelectForm.Designer.cs +++ b/CreamInstaller/Forms/SelectForm.Designer.cs @@ -31,7 +31,6 @@ namespace CreamInstaller /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); this.installButton = new System.Windows.Forms.Button(); this.cancelButton = new System.Windows.Forms.Button(); this.label1 = new System.Windows.Forms.Label(); @@ -53,7 +52,6 @@ namespace CreamInstaller this.progressLabelGames = new System.Windows.Forms.Label(); this.progressLabelDLCs = new System.Windows.Forms.Label(); this.sortCheckBox = new System.Windows.Forms.CheckBox(); - this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.groupBox1.SuspendLayout(); this.flowLayoutPanel4.SuspendLayout(); this.flowLayoutPanel1.SuspendLayout(); @@ -340,15 +338,6 @@ namespace CreamInstaller this.sortCheckBox.Text = "Sort By Name"; this.sortCheckBox.CheckedChanged += new System.EventHandler(this.OnSortCheckBoxChanged); // - // contextMenuStrip - // - this.contextMenuStrip.AllowMerge = false; - this.contextMenuStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow; - this.contextMenuStrip.Name = "contextMenuStrip"; - this.contextMenuStrip.ShowItemToolTips = false; - this.contextMenuStrip.Size = new System.Drawing.Size(61, 4); - this.contextMenuStrip.TabStop = true; - // // SelectForm // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); @@ -406,7 +395,6 @@ namespace CreamInstaller private Label progressLabelDLCs; private CheckBox sortCheckBox; private FlowLayoutPanel flowLayoutPanel3; - private ContextMenuStrip contextMenuStrip; private FlowLayoutPanel flowLayoutPanel4; private CheckBox koaloaderAllCheckBox; } diff --git a/CreamInstaller/Forms/SelectForm.cs b/CreamInstaller/Forms/SelectForm.cs index 53a441e..e1c8265 100644 --- a/CreamInstaller/Forms/SelectForm.cs +++ b/CreamInstaller/Forms/SelectForm.cs @@ -31,6 +31,8 @@ internal partial class SelectForm : CustomForm Text = Program.ApplicationName; } + public override ContextMenuStrip ContextMenuStrip => base.ContextMenuStrip ??= new(); + private static void UpdateRemaining(Label label, SynchronizedCollection list, string descriptor) => label.Text = list.Any() ? $"Remaining {descriptor} ({list.Count}): " + string.Join(", ", list).Replace("&", "&&") : ""; @@ -558,6 +560,8 @@ internal partial class SelectForm : CustomForm await SteamCMD.Cleanup(); } + ProgramData.UpdateKoaloaderProxyChoices(); + HideProgressBar(); selectionTreeView.Enabled = ProgramSelection.All.Any(); allCheckBox.Enabled = selectionTreeView.Enabled; @@ -668,6 +672,7 @@ internal partial class SelectForm : CustomForm internal void OnNodeRightClick(TreeNode node, Point location) { + ContextMenuStrip contextMenuStrip = ContextMenuStrip; contextMenuStrip.Items.Clear(); string id = node.Name; Platform platform = (Platform)node.Tag; diff --git a/CreamInstaller/Forms/SelectForm.resx b/CreamInstaller/Forms/SelectForm.resx index 39d5bcf..f298a7b 100644 --- a/CreamInstaller/Forms/SelectForm.resx +++ b/CreamInstaller/Forms/SelectForm.resx @@ -57,7 +57,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 17, 17 - \ No newline at end of file diff --git a/CreamInstaller/ProgramSelection.cs b/CreamInstaller/ProgramSelection.cs index 3ebde3e..f2669f4 100644 --- a/CreamInstaller/ProgramSelection.cs +++ b/CreamInstaller/ProgramSelection.cs @@ -28,7 +28,7 @@ internal class ProgramSelection { internal bool Enabled; internal bool Koaloader; - internal string KoaloaderProxy = "Koaloader.version_64.version.dll"; + internal string KoaloaderProxy; internal Platform Platform; internal string Id = "0"; diff --git a/CreamInstaller/Resources/Koaloader.cs b/CreamInstaller/Resources/Koaloader.cs index 3ba428c..d37e188 100644 --- a/CreamInstaller/Resources/Koaloader.cs +++ b/CreamInstaller/Resources/Koaloader.cs @@ -26,6 +26,15 @@ internal static class Koaloader config = directory + @"\Koaloader.json"; } + internal static string GetKoaloaderProxyDisplay(this string proxy) + { + string proxyDisplay = proxy[(proxy.IndexOf('.') + 1)..]; + proxyDisplay = proxyDisplay[..proxyDisplay.IndexOf('.')]; + string name = proxyDisplay[..proxyDisplay.LastIndexOf('_')]; + string bitness = proxyDisplay[(proxyDisplay.LastIndexOf('_') + 1)..]; + return $"{name}.dll ({bitness}-bit)"; + } + internal static readonly List<(string unlocker, string dll)> AutoLoadDlls = new() { ("SmokeAPI", "SmokeAPI32.dll"), ("SmokeAPI", "SmokeAPI64.dll"), @@ -102,11 +111,11 @@ internal static class Koaloader internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) => await Task.Run(async () => { directory.GetKoaloaderComponents(out List proxies, out string config); - foreach (string proxy in proxies.Where(proxy => File.Exists(proxy) && proxy.IsResourceFile(Resources.ResourceIdentifier.Koaloader))) + foreach (string proxyPath in proxies.Where(proxyPath => File.Exists(proxyPath) && proxyPath.IsResourceFile(Resources.ResourceIdentifier.Koaloader))) { - File.Delete(proxy); + File.Delete(proxyPath); if (installForm is not null) - installForm.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxy)}", InstallationLog.Action, info: false); + installForm.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", InstallationLog.Action, info: false); } foreach ((string unlocker, string path) in AutoLoadDlls .Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll)) @@ -135,6 +144,12 @@ internal static class Koaloader proxy = proxy[(proxy.IndexOf('.') + 1)..]; proxy = proxy[(proxy.IndexOf('.') + 1)..]; string path = directory + @"\" + proxy; + foreach (string proxyPath in proxies.Where(proxyPath => proxyPath != path && File.Exists(proxyPath) && proxyPath.IsResourceFile(Resources.ResourceIdentifier.Koaloader))) + { + File.Delete(proxyPath); + if (installForm is not null) + installForm.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", InstallationLog.Action, info: false); + } selection.KoaloaderProxy.Write(path); if (installForm is not null) installForm.UpdateUser($"Wrote Koaloader: {Path.GetFileName(path)}", InstallationLog.Action, info: false); diff --git a/CreamInstaller/Utility/ProgramData.cs b/CreamInstaller/Utility/ProgramData.cs index e161866..ad51c7e 100644 --- a/CreamInstaller/Utility/ProgramData.cs +++ b/CreamInstaller/Utility/ProgramData.cs @@ -3,10 +3,13 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; +using Windows.Foundation.Metadata; + namespace CreamInstaller.Utility; internal static class ProgramData @@ -24,6 +27,8 @@ internal static class ProgramData internal static readonly string OldChoicesPath = DirectoryPath + @"\choices.txt"; internal static readonly string ChoicesPath = DirectoryPath + @"\choices.json"; + internal static readonly string KoaloaderProxyChoicesPath = DirectoryPath + @"\proxies.json"; + internal static async Task Setup() => await Task.Run(() => { if (Directory.Exists(DirectoryPathOld)) @@ -103,4 +108,49 @@ internal static class ProgramData } catch { } } + + internal static List<(Platform platform, string id, string proxy)> ReadKoaloaderProxyChoices() + { + if (!File.Exists(KoaloaderProxyChoicesPath)) return null; + try + { + return JsonConvert.DeserializeObject(File.ReadAllText(KoaloaderProxyChoicesPath), + typeof(List<(Platform platform, string id, string proxy)>)) as List<(Platform platform, string id, string proxy)>; + } + catch + { + return new(); + } + } + + internal static void WriteKoaloaderProxyChoices(List<(Platform platform, string id, string proxy)> choices) + { + try + { + File.WriteAllText(KoaloaderProxyChoicesPath, JsonConvert.SerializeObject(choices)); + } + catch { } + } + + internal static void UpdateKoaloaderProxyChoices() + { + string defaultProxy = Resources.Resources.EmbeddedResources.Find(r => r.Contains("version_64")); + List<(Platform platform, string id, string proxy)> choices = ReadKoaloaderProxyChoices() ?? new(); + foreach ((Platform platform, string id, string proxy) choice in choices.ToList()) + if (ProgramSelection.FromPlatformId(choice.platform, choice.id) is ProgramSelection selection) + { + if (selection.KoaloaderProxy is null) + selection.KoaloaderProxy = choice.proxy; + else if (selection.KoaloaderProxy != choice.proxy && choices.Remove(choice)) + choices.Add((selection.Platform, selection.Id, selection.KoaloaderProxy)); + } + foreach (ProgramSelection selection in ProgramSelection.AllSafe) + if (selection.KoaloaderProxy is null) + { + selection.KoaloaderProxy = defaultProxy; + choices.Add((selection.Platform, selection.Id, selection.KoaloaderProxy)); + } + if (choices.Any()) + WriteKoaloaderProxyChoices(choices); + } }