From f3955b0ffcd75d8295ef49eff550d55e679a9a66 Mon Sep 17 00:00:00 2001 From: Ray Berezowski <6616212+rberezowski@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:17:29 -0400 Subject: [PATCH] Add open all menu action --- Services/LauncherController.cs | 76 +++++++++++++++++++++++++++++----- Views/LauncherPopup.xaml.cs | 34 ++++++++++++++- 2 files changed, 98 insertions(+), 12 deletions(-) diff --git a/Services/LauncherController.cs b/Services/LauncherController.cs index 1c5931a..4029094 100644 --- a/Services/LauncherController.cs +++ b/Services/LauncherController.cs @@ -62,7 +62,7 @@ public sealed class LauncherController : IDisposable return; } - popup = new LauncherPopup(Config, LaunchItem, ShowSettings); + popup = new LauncherPopup(Config, LaunchItem, OpenAllItems, ShowSettings); popup.Closed += (_, _) => popup = null; popup.ShowNearTaskbar(); } @@ -126,22 +126,78 @@ public sealed class LauncherController : IDisposable private void LaunchItem(LauncherItem item) { + if (TryLaunchItem(item, out string? error)) + { + popup?.Close(); + return; + } + + if (!string.IsNullOrWhiteSpace(error)) + { + System.Windows.MessageBox.Show(error, "Taskbar Launcher"); + } + } + + private void OpenAllItems(LauncherItem menuItem) + { + List failures = []; + int launchedCount = 0; + + foreach (LauncherItem child in menuItem.Children) + { + if (child.Type == LauncherItemType.Menu || string.IsNullOrWhiteSpace(child.Target)) + { + continue; + } + + if (TryLaunchItem(child, out string? error)) + { + launchedCount++; + } + else if (!string.IsNullOrWhiteSpace(error)) + { + failures.Add(error); + } + } + + popup?.Close(); + + if (failures.Count > 0) + { + string message = $"Opened {launchedCount} item(s), but {failures.Count} item(s) failed:\n\n" + + string.Join("\n\n", failures.Take(5)); + System.Windows.MessageBox.Show(message, "Taskbar Launcher"); + } + } + + private static bool TryLaunchItem(LauncherItem item, out string? error) + { + error = null; + if (item.Type == LauncherItemType.Menu || string.IsNullOrWhiteSpace(item.Target)) { - return; + return false; } string target = Environment.ExpandEnvironmentVariables(item.Target); - ProcessStartInfo startInfo = new() + try { - FileName = target, - Arguments = item.Arguments ?? "", - UseShellExecute = true, - WorkingDirectory = Directory.Exists(target) ? target : ConfigService.AppFolder - }; + ProcessStartInfo startInfo = new() + { + FileName = target, + Arguments = item.Arguments ?? "", + UseShellExecute = true, + WorkingDirectory = Directory.Exists(target) ? target : ConfigService.AppFolder + }; - Process.Start(startInfo); - popup?.Close(); + Process.Start(startInfo); + return true; + } + catch (Exception ex) + { + error = $"{item.Title}: {ex.Message}"; + return false; + } } } diff --git a/Views/LauncherPopup.xaml.cs b/Views/LauncherPopup.xaml.cs index 36a7bbe..f583f95 100644 --- a/Views/LauncherPopup.xaml.cs +++ b/Views/LauncherPopup.xaml.cs @@ -17,13 +17,15 @@ public partial class LauncherPopup : Window private readonly LauncherConfig config; private readonly Action launchItem; + private readonly Action openAllItems; private readonly Action showSettings; - public LauncherPopup(LauncherConfig config, Action launchItem, Action showSettings) + public LauncherPopup(LauncherConfig config, Action launchItem, Action openAllItems, Action showSettings) { InitializeComponent(); this.config = config; this.launchItem = launchItem; + this.openAllItems = openAllItems; this.showSettings = showSettings; BuildItems(); SizeChanged += (_, _) => QueueReposition(); @@ -102,7 +104,7 @@ public partial class LauncherPopup : Window { Expander expander = new() { - Header = item.Title, + Header = CreateMenuHeader(item), IsExpanded = expandMenusByDefault, Margin = new Thickness(depth * 12, 4, 0, 4) }; @@ -143,6 +145,34 @@ public partial class LauncherPopup : Window return button; } + private TextBlock CreateMenuHeader(LauncherItem item) + { + System.Windows.Controls.MenuItem openAllMenuItem = new() + { + Header = "Open All", + IsEnabled = item.Children.Any(IsLaunchable) + }; + openAllMenuItem.Click += (_, e) => + { + openAllItems(item); + e.Handled = true; + }; + + System.Windows.Controls.ContextMenu contextMenu = new(); + contextMenu.Items.Add(openAllMenuItem); + + return new TextBlock + { + Text = item.Title, + ContextMenu = contextMenu + }; + } + + private static bool IsLaunchable(LauncherItem item) + { + return item.Type != LauncherItemType.Menu && !string.IsNullOrWhiteSpace(item.Target); + } + private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) { string query = SearchBox.Text.Trim();