last bit of context menu shit
This commit is contained in:
parent
a1de3266ea
commit
4c0716e768
4 changed files with 130 additions and 147 deletions
110
CreamInstaller/Components/ContextMenuItem.cs
Normal file
110
CreamInstaller/Components/ContextMenuItem.cs
Normal file
|
@ -0,0 +1,110 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using CreamInstaller.Paradox;
|
||||
using CreamInstaller.Utility;
|
||||
|
||||
namespace CreamInstaller.Components;
|
||||
|
||||
internal class ContextMenuItem : ToolStripMenuItem
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, Image> images = new();
|
||||
|
||||
private static async Task TryImageIdentifier(ContextMenuItem item, string imageIdentifier) => await Task.Run(async () =>
|
||||
{
|
||||
if (images.TryGetValue(imageIdentifier, out Image image) && image is not null) item.Image = image;
|
||||
else
|
||||
{
|
||||
switch (imageIdentifier)
|
||||
{
|
||||
case "Paradox Launcher":
|
||||
if (Directory.Exists(ParadoxLauncher.InstallPath))
|
||||
foreach (string file in Directory.GetFiles(ParadoxLauncher.InstallPath, "*.exe"))
|
||||
{
|
||||
image = IconGrabber.GetFileIconImage(file);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "Notepad":
|
||||
image = IconGrabber.GetNotepadImage();
|
||||
break;
|
||||
case "Command Prompt":
|
||||
image = IconGrabber.GetCommandPromptImage();
|
||||
break;
|
||||
case "File Explorer":
|
||||
image = IconGrabber.GetFileExplorerImage();
|
||||
break;
|
||||
case "SteamDB":
|
||||
image = await HttpClientManager.GetImageFromUrl("https://steamdb.info/favicon.ico");
|
||||
break;
|
||||
case "Steam Store":
|
||||
image = await HttpClientManager.GetImageFromUrl("https://store.steampowered.com/favicon.ico");
|
||||
break;
|
||||
case "Steam Community":
|
||||
image = await HttpClientManager.GetImageFromUrl("https://steamcommunity.com/favicon.ico");
|
||||
break;
|
||||
case "ScreamDB":
|
||||
image = await HttpClientManager.GetImageFromUrl("https://scream-db.web.app/favicon.ico");
|
||||
break;
|
||||
case "Epic Games":
|
||||
image = await HttpClientManager.GetImageFromUrl("https://www.epicgames.com/favicon.ico");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (image is not null)
|
||||
{
|
||||
images[imageIdentifier] = image;
|
||||
item.Image = image;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
private static async Task TryImageIdentifierInfo(ContextMenuItem item, (string id, string iconUrl, bool sub) imageIdentifierInfo, Action onFail = null) => await Task.Run(async () =>
|
||||
{
|
||||
(string id, string iconUrl, bool sub) = imageIdentifierInfo;
|
||||
string imageIdentifier = sub ? "SubIcon_" + id : "Icon_" + id;
|
||||
if (images.TryGetValue(imageIdentifier, out Image image) && image is not null) item.Image = image;
|
||||
else
|
||||
{
|
||||
image = await HttpClientManager.GetImageFromUrl(iconUrl);
|
||||
if (image is not null)
|
||||
{
|
||||
images[imageIdentifier] = image;
|
||||
item.Image = image;
|
||||
}
|
||||
else if (onFail is not null)
|
||||
onFail();
|
||||
}
|
||||
});
|
||||
|
||||
private readonly EventHandler OnClickEvent;
|
||||
protected override void OnClick(EventArgs e)
|
||||
{
|
||||
base.OnClick(e);
|
||||
if (OnClickEvent is null) return;
|
||||
OnClickEvent.Invoke(this, e);
|
||||
}
|
||||
|
||||
internal ContextMenuItem(string text, EventHandler onClick = null)
|
||||
{
|
||||
Text = text;
|
||||
OnClickEvent = onClick;
|
||||
}
|
||||
|
||||
internal ContextMenuItem(string text, string imageIdentifier, EventHandler onClick = null)
|
||||
: this(text, onClick) => _ = TryImageIdentifier(this, imageIdentifier);
|
||||
|
||||
internal ContextMenuItem(string text, (string id, string iconUrl, bool sub) imageIdentifierInfo, EventHandler onClick = null)
|
||||
: this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo);
|
||||
|
||||
internal ContextMenuItem(string text, (string id, string iconUrl, bool sub) imageIdentifierInfo, string imageIdentifierFallback, EventHandler onClick = null)
|
||||
: this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo, async () => await TryImageIdentifier(this, imageIdentifierFallback));
|
||||
|
||||
internal ContextMenuItem(string text, (string id, string iconUrl, bool sub) imageIdentifierInfo, (string id, string iconUrl, bool sub) imageIdentifierInfoFallback, EventHandler onClick = null)
|
||||
: this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo, async () => await TryImageIdentifierInfo(this, imageIdentifierInfoFallback));
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<UseWindowsForms>True</UseWindowsForms>
|
||||
<ApplicationIcon>Resources\ini.ico</ApplicationIcon>
|
||||
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
|
||||
<Version>3.2.1.0</Version>
|
||||
<Version>3.2.1.1</Version>
|
||||
<PackageIcon>Resources\ini.ico</PackageIcon>
|
||||
<PackageIconUrl />
|
||||
<Description />
|
||||
|
|
7
CreamInstaller/SelectForm.Designer.cs
generated
7
CreamInstaller/SelectForm.Designer.cs
generated
|
@ -49,7 +49,6 @@ namespace CreamInstaller
|
|||
this.progressLabel = new System.Windows.Forms.Label();
|
||||
this.scanButton = new System.Windows.Forms.Button();
|
||||
this.uninstallButton = new System.Windows.Forms.Button();
|
||||
this.nodeContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.progressLabelGames = new System.Windows.Forms.Label();
|
||||
this.progressLabelDLCs = new System.Windows.Forms.Label();
|
||||
this.groupBox1.SuspendLayout();
|
||||
|
@ -261,11 +260,6 @@ namespace CreamInstaller
|
|||
this.uninstallButton.UseVisualStyleBackColor = true;
|
||||
this.uninstallButton.Click += new System.EventHandler(this.OnUninstall);
|
||||
//
|
||||
// nodeContextMenu
|
||||
//
|
||||
this.nodeContextMenu.Name = "nodeContextMenu";
|
||||
this.nodeContextMenu.Size = new System.Drawing.Size(61, 4);
|
||||
//
|
||||
// progressLabelGames
|
||||
//
|
||||
this.progressLabelGames.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||
|
@ -338,7 +332,6 @@ namespace CreamInstaller
|
|||
private FlowLayoutPanel flowLayoutPanel1;
|
||||
private FlowLayoutPanel flowLayoutPanel2;
|
||||
private Button uninstallButton;
|
||||
private ContextMenuStrip nodeContextMenu;
|
||||
private Label progressLabelGames;
|
||||
private Label progressLabelDLCs;
|
||||
}
|
||||
|
|
|
@ -536,133 +536,17 @@ internal partial class SelectForm : CustomForm
|
|||
+ progressBar.Size.Height);
|
||||
}
|
||||
|
||||
internal class ContextMenuItem : ToolStripMenuItem
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, Image> images = new();
|
||||
|
||||
private static async Task TryImageIdentifier(ContextMenuItem item, string imageIdentifier) => await Task.Run(async () =>
|
||||
{
|
||||
if (images.TryGetValue(imageIdentifier, out Image image) && image is not null) item.Image = image;
|
||||
else
|
||||
{
|
||||
switch (imageIdentifier)
|
||||
{
|
||||
case "Paradox Launcher":
|
||||
if (Directory.Exists(ParadoxLauncher.InstallPath))
|
||||
foreach (string file in Directory.GetFiles(ParadoxLauncher.InstallPath, "*.exe"))
|
||||
{
|
||||
image = IconGrabber.GetFileIconImage(file);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "Notepad":
|
||||
image = IconGrabber.GetNotepadImage();
|
||||
break;
|
||||
case "Command Prompt":
|
||||
image = IconGrabber.GetCommandPromptImage();
|
||||
break;
|
||||
case "File Explorer":
|
||||
image = IconGrabber.GetFileExplorerImage();
|
||||
break;
|
||||
case "SteamDB":
|
||||
image = await HttpClientManager.GetImageFromUrl("https://steamdb.info/favicon.ico");
|
||||
break;
|
||||
case "Steam Store":
|
||||
image = await HttpClientManager.GetImageFromUrl("https://store.steampowered.com/favicon.ico");
|
||||
break;
|
||||
case "Steam Community":
|
||||
image = await HttpClientManager.GetImageFromUrl("https://steamcommunity.com/favicon.ico");
|
||||
break;
|
||||
case "ScreamDB":
|
||||
image = await HttpClientManager.GetImageFromUrl("https://scream-db.web.app/favicon.ico");
|
||||
break;
|
||||
case "Epic Games":
|
||||
image = await HttpClientManager.GetImageFromUrl("https://www.epicgames.com/favicon.ico");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (image is not null)
|
||||
{
|
||||
images[imageIdentifier] = image;
|
||||
item.Image = image;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
private static async Task TryImageIdentifierInfo(ContextMenuItem item, (string id, string iconUrl, bool sub) imageIdentifierInfo, Action onFail = null) => await Task.Run(async () =>
|
||||
{
|
||||
(string id, string iconUrl, bool sub) = imageIdentifierInfo;
|
||||
string imageIdentifier = sub ? "SubIcon_" + id : "Icon_" + id;
|
||||
if (images.TryGetValue(imageIdentifier, out Image image) && image is not null) item.Image = image;
|
||||
else
|
||||
{
|
||||
image = await HttpClientManager.GetImageFromUrl(iconUrl);
|
||||
if (image is not null)
|
||||
{
|
||||
images[imageIdentifier] = image;
|
||||
item.Image = image;
|
||||
}
|
||||
else if (onFail is not null)
|
||||
onFail();
|
||||
}
|
||||
});
|
||||
|
||||
private readonly EventHandler OnClickEvent;
|
||||
protected override void OnClick(EventArgs e)
|
||||
{
|
||||
base.OnClick(e);
|
||||
if (OnClickEvent is null) return;
|
||||
OnClickEvent.Invoke(this, e);
|
||||
}
|
||||
|
||||
internal ContextMenuItem(string text, EventHandler onClick = null)
|
||||
{
|
||||
Text = text;
|
||||
OnClickEvent = onClick;
|
||||
}
|
||||
|
||||
internal ContextMenuItem(string text, string imageIdentifier, EventHandler onClick = null)
|
||||
: this(text, onClick) => _ = TryImageIdentifier(this, imageIdentifier);
|
||||
|
||||
internal ContextMenuItem(string text, (string id, string iconUrl, bool sub) imageIdentifierInfo, EventHandler onClick = null)
|
||||
: this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo);
|
||||
|
||||
internal ContextMenuItem(string text, (string id, string iconUrl, bool sub) imageIdentifierInfo, string imageIdentifierFallback, EventHandler onClick = null)
|
||||
: this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo, async () => await TryImageIdentifier(this, imageIdentifierFallback));
|
||||
|
||||
internal ContextMenuItem(string text, (string id, string iconUrl, bool sub) imageIdentifierInfo, (string id, string iconUrl, bool sub) imageIdentifierInfoFallback, EventHandler onClick = null)
|
||||
: this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo, async () => await TryImageIdentifierInfo(this, imageIdentifierInfoFallback));
|
||||
}
|
||||
|
||||
private void OnLoad(object sender, EventArgs _)
|
||||
{
|
||||
HideProgressBar();
|
||||
selectionTreeView.TreeViewNodeSorter = new TreeNodeSorter();
|
||||
selectionTreeView.AfterCheck += OnTreeViewNodeCheckedChanged;
|
||||
int contextMenuIndex = 0;
|
||||
void ClearContextMenu(int cmi)
|
||||
{
|
||||
if (cmi != contextMenuIndex || Program.Canceled) return;
|
||||
nodeContextMenu.Items.Clear();
|
||||
}
|
||||
void AddToContextMenu(int cmi, ToolStripItem item)
|
||||
{
|
||||
if (cmi != contextMenuIndex || Program.Canceled) return;
|
||||
nodeContextMenu.Items.Add(item);
|
||||
}
|
||||
selectionTreeView.NodeMouseClick += (sender, e) =>
|
||||
{
|
||||
int cmi = ++contextMenuIndex;
|
||||
TreeNode node = e.Node;
|
||||
if (node is null || e.Button != MouseButtons.Right)
|
||||
if (node is null || !node.Bounds.Contains(e.Location) || e.Button != MouseButtons.Right || e.Clicks != 1)
|
||||
return;
|
||||
try
|
||||
{
|
||||
if (!node.Bounds.Contains(e.Location))
|
||||
return;
|
||||
}
|
||||
catch { }
|
||||
ContextMenuStrip contextMenuStrip = new();
|
||||
selectionTreeView.SelectedNode = node;
|
||||
string id = node.Name;
|
||||
ProgramSelection selection = ProgramSelection.FromId(id);
|
||||
|
@ -672,23 +556,20 @@ internal partial class SelectForm : CustomForm
|
|||
if (dlc is not null) dlcParentSelection = ProgramSelection.FromId(dlc.Value.gameAppId);
|
||||
if (selection is null && dlcParentSelection is null)
|
||||
return;
|
||||
ClearContextMenu(cmi);
|
||||
ContextMenuItem header = null;
|
||||
if (id == "ParadoxLauncher")
|
||||
header = new(node.Text, "Paradox Launcher");
|
||||
else if (selection is not null)
|
||||
header = new(node.Text, (id, selection.IconUrl, false));
|
||||
else if (dlc is not null)
|
||||
{
|
||||
header = new(node.Text, (id, dlc.Value.app.icon, false), (id, dlcParentSelection.IconUrl, false));
|
||||
}
|
||||
AddToContextMenu(cmi, header ?? new ContextMenuItem(node.Text));
|
||||
contextMenuStrip.Items.Add(header ?? new ContextMenuItem(node.Text));
|
||||
string appInfoVDF = $@"{SteamCMD.AppInfoPath}\{id}.vdf";
|
||||
string appInfoJSON = $@"{SteamCMD.AppInfoPath}\{id}.json";
|
||||
if (Directory.Exists(Directory.GetDirectoryRoot(appInfoVDF)) && (File.Exists(appInfoVDF) || File.Exists(appInfoJSON)))
|
||||
{
|
||||
AddToContextMenu(cmi, new ToolStripSeparator());
|
||||
AddToContextMenu(cmi, new ContextMenuItem("Open AppInfo", "Notepad",
|
||||
contextMenuStrip.Items.Add(new ToolStripSeparator());
|
||||
contextMenuStrip.Items.Add(new ContextMenuItem("Open AppInfo", "Notepad",
|
||||
new EventHandler((sender, e) =>
|
||||
{
|
||||
if (File.Exists(appInfoVDF))
|
||||
|
@ -696,7 +577,7 @@ internal partial class SelectForm : CustomForm
|
|||
else if (File.Exists(appInfoJSON))
|
||||
Diagnostics.OpenFileInNotepad(appInfoJSON);
|
||||
})));
|
||||
AddToContextMenu(cmi, new ContextMenuItem("Refresh AppInfo", "Command Prompt",
|
||||
contextMenuStrip.Items.Add(new ContextMenuItem("Refresh AppInfo", "Command Prompt",
|
||||
new EventHandler((sender, e) =>
|
||||
{
|
||||
try
|
||||
|
@ -716,8 +597,8 @@ internal partial class SelectForm : CustomForm
|
|||
{
|
||||
if (id == "ParadoxLauncher")
|
||||
{
|
||||
AddToContextMenu(cmi, new ToolStripSeparator());
|
||||
AddToContextMenu(cmi, new ContextMenuItem("Repair", "Command Prompt",
|
||||
contextMenuStrip.Items.Add(new ToolStripSeparator());
|
||||
contextMenuStrip.Items.Add(new ContextMenuItem("Repair", "Command Prompt",
|
||||
new EventHandler(async (sender, e) =>
|
||||
{
|
||||
if (!Program.IsProgramRunningDialog(this, selection)) return;
|
||||
|
@ -796,13 +677,13 @@ internal partial class SelectForm : CustomForm
|
|||
+ "\nYou must reinstall Paradox Launcher to fix this issue.", "OK");
|
||||
})));
|
||||
}
|
||||
AddToContextMenu(cmi, new ToolStripSeparator());
|
||||
AddToContextMenu(cmi, new ContextMenuItem("Open Root Directory", "File Explorer",
|
||||
contextMenuStrip.Items.Add(new ToolStripSeparator());
|
||||
contextMenuStrip.Items.Add(new ContextMenuItem("Open Root Directory", "File Explorer",
|
||||
new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(selection.RootDirectory))));
|
||||
for (int i = 0; i < selection.DllDirectories.Count; i++)
|
||||
{
|
||||
string directory = selection.DllDirectories[i];
|
||||
AddToContextMenu(cmi, new ContextMenuItem($"Open {(selection.IsSteam ? "Steamworks" : "Epic Online Services")} SDK Directory ({i + 1})", "File Explorer",
|
||||
contextMenuStrip.Items.Add(new ContextMenuItem($"Open {(selection.IsSteam ? "Steamworks" : "Epic Online Services")} SDK Directory ({i + 1})", "File Explorer",
|
||||
new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory))));
|
||||
}
|
||||
}
|
||||
|
@ -810,31 +691,30 @@ internal partial class SelectForm : CustomForm
|
|||
{
|
||||
if (selection is not null && selection.IsSteam || dlcParentSelection is not null && dlcParentSelection.IsSteam)
|
||||
{
|
||||
AddToContextMenu(cmi, new ToolStripSeparator());
|
||||
AddToContextMenu(cmi, new ContextMenuItem("Open SteamDB", "SteamDB",
|
||||
contextMenuStrip.Items.Add(new ToolStripSeparator());
|
||||
contextMenuStrip.Items.Add(new ContextMenuItem("Open SteamDB", "SteamDB",
|
||||
new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamdb.info/app/" + id))));
|
||||
}
|
||||
if (selection is not null)
|
||||
{
|
||||
if (selection.IsSteam)
|
||||
{
|
||||
AddToContextMenu(cmi, new ContextMenuItem("Open Steam Store", "Steam Store",
|
||||
contextMenuStrip.Items.Add(new ContextMenuItem("Open Steam Store", "Steam Store",
|
||||
new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl))));
|
||||
AddToContextMenu(cmi, new ContextMenuItem("Open Steam Community", (id, selection.SubIconUrl, true), "Steam Community",
|
||||
contextMenuStrip.Items.Add(new ContextMenuItem("Open Steam Community", (id, selection.SubIconUrl, true), "Steam Community",
|
||||
new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamcommunity.com/app/" + id))));
|
||||
}
|
||||
else
|
||||
{
|
||||
AddToContextMenu(cmi, new ToolStripSeparator());
|
||||
AddToContextMenu(cmi, new ContextMenuItem("Open ScreamDB", "ScreamDB",
|
||||
contextMenuStrip.Items.Add(new ToolStripSeparator());
|
||||
contextMenuStrip.Items.Add(new ContextMenuItem("Open ScreamDB", "ScreamDB",
|
||||
new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://scream-db.web.app/offers/" + id))));
|
||||
AddToContextMenu(cmi, new ContextMenuItem("Open Epic Games Store", "Epic Games",
|
||||
contextMenuStrip.Items.Add(new ContextMenuItem("Open Epic Games Store", "Epic Games",
|
||||
new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl))));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cmi != contextMenuIndex) return;
|
||||
nodeContextMenu.Show(selectionTreeView, e.Location);
|
||||
contextMenuStrip.Show(selectionTreeView, e.Location);
|
||||
};
|
||||
OnLoad();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue