From 73100a3179811772d475f5e94035d0c3262fc58e Mon Sep 17 00:00:00 2001 From: Mertsch Date: Sun, 1 Jan 2023 19:11:00 +0100 Subject: [PATCH 01/18] Target .NET 7 --- CHANGELOG.md | 4 + Source/Launchbar/App.xaml.cs | 415 +++++++------- Source/Launchbar/Area.cs | 35 +- Source/Launchbar/ElementCreator.cs | 61 +- Source/Launchbar/IconType.cs | 13 +- Source/Launchbar/Launchbar.csproj | 8 +- Source/Launchbar/Menu.cs | 109 ++-- Source/Launchbar/MenuEntry.cs | 176 +++--- Source/Launchbar/MenuEntryAdvanced.cs | 296 +++++----- Source/Launchbar/MenuEntryCollection.cs | 79 ++- Source/Launchbar/MenuEntryExit.cs | 35 +- Source/Launchbar/MenuEntrySettings.cs | 35 +- Source/Launchbar/MenuItemExtensions.cs | 26 +- Source/Launchbar/MenuItemStyleSelector.cs | 52 +- Source/Launchbar/MetaData.cs | 17 +- Source/Launchbar/NotifyBase.cs | 34 +- Source/Launchbar/Program.cs | 263 +++++---- Source/Launchbar/Properties/AssemblyInfo.cs | 3 +- .../Properties/Resources.Designer.cs | 13 +- .../Launchbar/Properties/Settings.Designer.cs | 2 +- Source/Launchbar/Separator.cs | 13 +- .../Launchbar/Shapes/ShapeApplication.xaml.cs | 30 +- Source/Launchbar/Shapes/ShapeClose.xaml.cs | 52 +- Source/Launchbar/Shapes/ShapeDelete.xaml.cs | 32 +- Source/Launchbar/Shapes/ShapeFolder.xaml.cs | 54 +- .../Launchbar/Shapes/ShapeFolderGoTo.xaml.cs | 30 +- Source/Launchbar/Shapes/ShapeMonitor.xaml.cs | 30 +- Source/Launchbar/Shapes/ShapeNext.xaml.cs | 30 +- Source/Launchbar/Shapes/ShapePlus.xaml.cs | 20 +- Source/Launchbar/Shapes/ShapeWarning.xaml.cs | 30 +- Source/Launchbar/Submenu.cs | 104 ++-- .../Launchbar/Win32/ExtendedWindowStyles.cs | 67 ++- Source/Launchbar/Win32/GWL.cs | 23 +- Source/Launchbar/Win32/SafeNativeMethods.cs | 459 ++++++++------- Source/Launchbar/Win32/WinHelper.cs | 225 ++++---- Source/Launchbar/WindowBar.xaml.cs | 321 ++++++----- Source/Launchbar/WindowSettings.xaml.cs | 525 +++++++++--------- 37 files changed, 1836 insertions(+), 1885 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de0976c..04b8cb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [5.1.0] - 2023-01-01 +### Changed +- Upgrade to .NET 7.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/7.0/runtime) to run + ## [5.0.0] - 2021-12-15 ### Changed - Upgrade to .NET 6.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/6.0/runtime) to run diff --git a/Source/Launchbar/App.xaml.cs b/Source/Launchbar/App.xaml.cs index 4a84d4c..0a86f27 100644 --- a/Source/Launchbar/App.xaml.cs +++ b/Source/Launchbar/App.xaml.cs @@ -10,284 +10,283 @@ using Microsoft.Win32; using WpfScreenHelper; -namespace Launchbar +namespace Launchbar; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application { - /// - /// Interaction logic for App.xaml - /// - public partial class App : Application - { #if DEBUG - private const string MutexName = @"Global\LaunchbarSingleInstanceMutex(Debug)"; + private const string MutexName = @"Global\LaunchbarSingleInstanceMutex(Debug)"; #else private const string MutexName = @"Global\LaunchbarSingleInstanceMutex"; #endif - #region Fields + #region Fields - private static SplashScreen splashScreen; + private static SplashScreen splashScreen; - // ReSharper disable NotAccessedField.Local + // ReSharper disable NotAccessedField.Local #pragma warning disable IDE0052 // Remove unread private members - We need to keep the mutex alive during the lifetime of the app. - private static Mutex instanceMutex; + private static Mutex instanceMutex; #pragma warning restore IDE0052 // Remove unread private members - // ReSharper restore NotAccessedField.Local - - private WindowBar barLeft; - - private WindowBar barTop; + // ReSharper restore NotAccessedField.Local - private WindowBar barRight; + private WindowBar barLeft; - private WindowBar barBottom; + private WindowBar barTop; - private WindowBar barLeftSecondary; + private WindowBar barRight; - private WindowBar barTopSecondary; + private WindowBar barBottom; - private WindowBar barRightSecondary; + private WindowBar barLeftSecondary; - private WindowBar barBottomSecondary; + private WindowBar barTopSecondary; - private readonly Area primaryArea = new Area(); + private WindowBar barRightSecondary; - private readonly Area secondaryArea = new Area(); + private WindowBar barBottomSecondary; - private int currentDisplayCount; - - private readonly ContextMenu contextMenu; - - #endregion - - static App() - { - splashScreen = new SplashScreen(@"Resources/SplashScreen.png"); - splashScreen.Show(false); - } + private readonly Area primaryArea = new Area(); - /// - /// Create a new instance of this class and upgrade application settings if possible. - /// - public App() - { - this.InitializeComponent(); + private readonly Area secondaryArea = new Area(); - #region Make sure that only one instance of the application is running at any given time. + private int currentDisplayCount; - instanceMutex = new Mutex(false, MutexName, out bool instantiated); - if (!instantiated) - { - MessageBox.Show(Launchbar.Properties.Resources.SingleInstanceWarning, - Launchbar.Properties.Resources.ApplicationName, MessageBoxButton.OK, - MessageBoxImage.Information); - try - { - splashScreen.Close(TimeSpan.Zero); - } - catch (Win32Exception) { } - this.Shutdown(); - return; - } + private readonly ContextMenu contextMenu; - #endregion + #endregion - Settings setting = Settings.Default; - if (setting.Menu is null) - { - setting.Upgrade(); + static App() + { + splashScreen = new SplashScreen(@"Resources/SplashScreen.png"); + splashScreen.Show(false); + } - setting.Menu ??= Menu.CreateDefault(); - } + /// + /// Create a new instance of this class and upgrade application settings if possible. + /// + public App() + { + this.InitializeComponent(); - setting.Menu.FillIconCacheAsync(this.Dispatcher); + #region Make sure that only one instance of the application is running at any given time. + instanceMutex = new Mutex(false, MutexName, out bool instantiated); + if (!instantiated) + { + MessageBox.Show(Launchbar.Properties.Resources.SingleInstanceWarning, + Launchbar.Properties.Resources.ApplicationName, MessageBoxButton.OK, + MessageBoxImage.Information); try { - SystemEvents.DisplaySettingsChanged += this.displaySettingsChanged; + splashScreen.Close(TimeSpan.Zero); } - catch (SecurityException) { } - this.displaySettingsChanged(null, null); // Do primary initialization. + catch (Win32Exception) { } + this.Shutdown(); + return; + } - setting.PropertyChanged += this.settingsPropertyChanged; + #endregion - // ReSharper disable PossibleNullReferenceException - this.contextMenu = (ContextMenu)this.FindResource("contextMenuTemplate"); - // ReSharper restore PossibleNullReferenceException - this.forceContextMenuLayout(); + Settings setting = Settings.Default; + if (setting.Menu is null) + { + setting.Upgrade(); - try - { - splashScreen.Close(new TimeSpan(TimeSpan.TicksPerSecond)); - } - catch (Win32Exception) - { - splashScreen.Close(TimeSpan.Zero); - } - finally - { - splashScreen = null; - } + setting.Menu ??= Menu.CreateDefault(); } - #region Force context menu layout on load + setting.Menu.FillIconCacheAsync(this.Dispatcher); - private void forceContextMenuLayout() + try { - this.contextMenu.Visibility = Visibility.Hidden; - this.contextMenu.Opened += this.contextMenuOpened; - this.contextMenu.IsOpen = true; + SystemEvents.DisplaySettingsChanged += this.displaySettingsChanged; } + catch (SecurityException) { } + this.displaySettingsChanged(null, null); // Do primary initialization. + + setting.PropertyChanged += this.settingsPropertyChanged; + + // ReSharper disable PossibleNullReferenceException + this.contextMenu = (ContextMenu)this.FindResource("contextMenuTemplate"); + // ReSharper restore PossibleNullReferenceException + this.forceContextMenuLayout(); - private void contextMenuOpened(object sender, RoutedEventArgs e) + try { - this.contextMenu.Opened -= this.contextMenuOpened; - this.contextMenu.Closed += this.contextMenuClosed; - this.contextMenu.IsOpen = false; + splashScreen.Close(new TimeSpan(TimeSpan.TicksPerSecond)); } - - private void contextMenuClosed(object sender, RoutedEventArgs e) + catch (Win32Exception) + { + splashScreen.Close(TimeSpan.Zero); + } + finally { - this.contextMenu.Closed -= this.contextMenuClosed; - this.contextMenu.Visibility = Visibility.Visible; + splashScreen = null; } + } - #endregion + #region Force context menu layout on load + + private void forceContextMenuLayout() + { + this.contextMenu.Visibility = Visibility.Hidden; + this.contextMenu.Opened += this.contextMenuOpened; + this.contextMenu.IsOpen = true; + } - private void settingsPropertyChanged(object sender, PropertyChangedEventArgs e) + private void contextMenuOpened(object sender, RoutedEventArgs e) + { + this.contextMenu.Opened -= this.contextMenuOpened; + this.contextMenu.Closed += this.contextMenuClosed; + this.contextMenu.IsOpen = false; + } + + private void contextMenuClosed(object sender, RoutedEventArgs e) + { + this.contextMenu.Closed -= this.contextMenuClosed; + this.contextMenu.Visibility = Visibility.Visible; + } + + #endregion + + private void settingsPropertyChanged(object sender, PropertyChangedEventArgs e) + { + switch (e.PropertyName) { - switch (e.PropertyName) - { - case "BarLeft": - openOrCloseBar(Dock.Left, Settings.Default.BarLeft, this.primaryArea, ref this.barLeft); - break; - case "BarTop": - openOrCloseBar(Dock.Top, Settings.Default.BarTop, this.primaryArea, ref this.barTop); - break; - case "BarRight": - openOrCloseBar(Dock.Right, Settings.Default.BarRight, this.primaryArea, ref this.barRight); - break; - case "BarBottom": - openOrCloseBar(Dock.Bottom, Settings.Default.BarBottom, this.primaryArea, ref this.barBottom); - break; - case "BarLeftSecondary": - openOrCloseBar(Dock.Left, Settings.Default.BarLeftSecondary, this.secondaryArea, - ref this.barLeftSecondary); - break; - case "BarTopSecondary": - openOrCloseBar(Dock.Top, Settings.Default.BarTopSecondary, this.secondaryArea, - ref this.barTopSecondary); - break; - case "BarRightSecondary": - openOrCloseBar(Dock.Right, Settings.Default.BarRightSecondary, this.secondaryArea, - ref this.barRightSecondary); - break; - case "BarBottomSecondary": - openOrCloseBar(Dock.Bottom, Settings.Default.BarBottomSecondary, this.secondaryArea, - ref this.barBottomSecondary); - break; - } + case "BarLeft": + openOrCloseBar(Dock.Left, Settings.Default.BarLeft, this.primaryArea, ref this.barLeft); + break; + case "BarTop": + openOrCloseBar(Dock.Top, Settings.Default.BarTop, this.primaryArea, ref this.barTop); + break; + case "BarRight": + openOrCloseBar(Dock.Right, Settings.Default.BarRight, this.primaryArea, ref this.barRight); + break; + case "BarBottom": + openOrCloseBar(Dock.Bottom, Settings.Default.BarBottom, this.primaryArea, ref this.barBottom); + break; + case "BarLeftSecondary": + openOrCloseBar(Dock.Left, Settings.Default.BarLeftSecondary, this.secondaryArea, + ref this.barLeftSecondary); + break; + case "BarTopSecondary": + openOrCloseBar(Dock.Top, Settings.Default.BarTopSecondary, this.secondaryArea, + ref this.barTopSecondary); + break; + case "BarRightSecondary": + openOrCloseBar(Dock.Right, Settings.Default.BarRightSecondary, this.secondaryArea, + ref this.barRightSecondary); + break; + case "BarBottomSecondary": + openOrCloseBar(Dock.Bottom, Settings.Default.BarBottomSecondary, this.secondaryArea, + ref this.barBottomSecondary); + break; } + } - private void displaySettingsChanged(object sender, EventArgs e) - { - ImmutableArray screens = Screen.AllScreens.ToImmutableArray(); - int count = screens.Length; + private void displaySettingsChanged(object sender, EventArgs e) + { + ImmutableArray screens = Screen.AllScreens.ToImmutableArray(); + int count = screens.Length; - if (count > 0) - { - Rect area = screens[0].WorkingArea; - this.primaryArea.Update(area.X, area.Y, area.Width, area.Height); + if (count > 0) + { + Rect area = screens[0].WorkingArea; + this.primaryArea.Update(area.X, area.Y, area.Width, area.Height); - if (this.currentDisplayCount < 1) - { - openOrCloseBar(Dock.Left, Settings.Default.BarLeft, this.primaryArea, ref this.barLeft); - openOrCloseBar(Dock.Top, Settings.Default.BarTop, this.primaryArea, ref this.barTop); - openOrCloseBar(Dock.Right, Settings.Default.BarRight, this.primaryArea, ref this.barRight); - openOrCloseBar(Dock.Bottom, Settings.Default.BarBottom, this.primaryArea, ref this.barBottom); - this.currentDisplayCount = 1; - } - } - else + if (this.currentDisplayCount < 1) { - openOrCloseBar(Dock.Left, false, null, ref this.barLeft); - openOrCloseBar(Dock.Top, false, null, ref this.barTop); - openOrCloseBar(Dock.Right, false, null, ref this.barRight); - openOrCloseBar(Dock.Bottom, false, null, ref this.barBottom); + openOrCloseBar(Dock.Left, Settings.Default.BarLeft, this.primaryArea, ref this.barLeft); + openOrCloseBar(Dock.Top, Settings.Default.BarTop, this.primaryArea, ref this.barTop); + openOrCloseBar(Dock.Right, Settings.Default.BarRight, this.primaryArea, ref this.barRight); + openOrCloseBar(Dock.Bottom, Settings.Default.BarBottom, this.primaryArea, ref this.barBottom); + this.currentDisplayCount = 1; } + } + else + { + openOrCloseBar(Dock.Left, false, null, ref this.barLeft); + openOrCloseBar(Dock.Top, false, null, ref this.barTop); + openOrCloseBar(Dock.Right, false, null, ref this.barRight); + openOrCloseBar(Dock.Bottom, false, null, ref this.barBottom); + } - if (count > 1) - { - Rect area = screens[1].WorkingArea; - this.secondaryArea.Update(area.X, area.Y, area.Width, area.Height); + if (count > 1) + { + Rect area = screens[1].WorkingArea; + this.secondaryArea.Update(area.X, area.Y, area.Width, area.Height); - if (this.currentDisplayCount < 2) - { - openOrCloseBar(Dock.Left, Settings.Default.BarLeftSecondary, this.secondaryArea, - ref this.barLeftSecondary); - openOrCloseBar(Dock.Top, Settings.Default.BarTopSecondary, this.secondaryArea, - ref this.barTopSecondary); - openOrCloseBar(Dock.Right, Settings.Default.BarRightSecondary, this.secondaryArea, - ref this.barRightSecondary); - openOrCloseBar(Dock.Bottom, Settings.Default.BarBottomSecondary, this.secondaryArea, - ref this.barBottomSecondary); - this.currentDisplayCount = 2; - } - } - else + if (this.currentDisplayCount < 2) { - openOrCloseBar(Dock.Left, false, null, ref this.barLeftSecondary); - openOrCloseBar(Dock.Top, false, null, ref this.barTopSecondary); - openOrCloseBar(Dock.Right, false, null, ref this.barRightSecondary); - openOrCloseBar(Dock.Bottom, false, null, ref this.barBottomSecondary); + openOrCloseBar(Dock.Left, Settings.Default.BarLeftSecondary, this.secondaryArea, + ref this.barLeftSecondary); + openOrCloseBar(Dock.Top, Settings.Default.BarTopSecondary, this.secondaryArea, + ref this.barTopSecondary); + openOrCloseBar(Dock.Right, Settings.Default.BarRightSecondary, this.secondaryArea, + ref this.barRightSecondary); + openOrCloseBar(Dock.Bottom, Settings.Default.BarBottomSecondary, this.secondaryArea, + ref this.barBottomSecondary); + this.currentDisplayCount = 2; } } + else + { + openOrCloseBar(Dock.Left, false, null, ref this.barLeftSecondary); + openOrCloseBar(Dock.Top, false, null, ref this.barTopSecondary); + openOrCloseBar(Dock.Right, false, null, ref this.barRightSecondary); + openOrCloseBar(Dock.Bottom, false, null, ref this.barBottomSecondary); + } + } - private static void openOrCloseBar(Dock dock, bool open, Area area, ref WindowBar windowBar) + private static void openOrCloseBar(Dock dock, bool open, Area area, ref WindowBar windowBar) + { + if (windowBar == null && open && area != null && area.IsActive) { - if (windowBar == null && open && area != null && area.IsActive) - { - windowBar = new WindowBar(dock, area); - windowBar.Show(); - } - else if (windowBar != null && !open) - { - windowBar.Close(); - windowBar = null; - } + windowBar = new WindowBar(dock, area); + windowBar.Show(); } + else if (windowBar != null && !open) + { + windowBar.Close(); + windowBar = null; + } + } - public static void OpenOrActivateSettings() + public static void OpenOrActivateSettings() + { + WindowCollection wc = Current.Windows; + lock (wc.SyncRoot!) { - WindowCollection wc = Current.Windows; - lock (wc.SyncRoot!) + foreach (Window w in wc) { - foreach (Window w in wc) + if (w is WindowSettings) { - if (w is WindowSettings) - { - w.Activate(); - return; - } + w.Activate(); + return; } } - new WindowSettings().Show(); } + new WindowSettings().Show(); + } - private void contextMenuKeyDown(object sender, KeyEventArgs e) + private void contextMenuKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.S && (e.KeyboardDevice.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) { - if (e.Key == Key.S && (e.KeyboardDevice.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) - { - OpenOrActivateSettings(); - } + OpenOrActivateSettings(); } + } - public static ContextMenu RequestContextMenu() - { - App app = (App)Current; - // Detach from the current parent. - ((FrameworkElement)app.contextMenu.Parent).ContextMenu = null; - // Attach to this object. - return app.contextMenu; - } + public static ContextMenu RequestContextMenu() + { + App app = (App)Current; + // Detach from the current parent. + ((FrameworkElement)app.contextMenu.Parent).ContextMenu = null; + // Attach to this object. + return app.contextMenu; } } \ No newline at end of file diff --git a/Source/Launchbar/Area.cs b/Source/Launchbar/Area.cs index 51d62e8..4ae1fc3 100644 --- a/Source/Launchbar/Area.cs +++ b/Source/Launchbar/Area.cs @@ -1,31 +1,30 @@ using System; -namespace Launchbar +namespace Launchbar; + +public sealed class Area { - public sealed class Area - { - public double Left { get; private set; } + public double Left { get; private set; } - public double Top { get; private set; } + public double Top { get; private set; } - public double Width { get; private set; } + public double Width { get; private set; } - public double Height { get; private set; } + public double Height { get; private set; } - public bool IsActive { get; private set; } + public bool IsActive { get; private set; } - public event EventHandler Updated = delegate { }; + public event EventHandler Updated = delegate { }; - public void Update(double left, double top, double width, double height) - { - this.Left = left; - this.Top = top; - this.Width = width; - this.Height = height; + public void Update(double left, double top, double width, double height) + { + this.Left = left; + this.Top = top; + this.Width = width; + this.Height = height; - this.IsActive = Math.Abs(width) > 0.1 && Math.Abs(height) > 0.1; // ~0 + this.IsActive = Math.Abs(width) > 0.1 && Math.Abs(height) > 0.1; // ~0 - this.Updated(this, EventArgs.Empty); - } + this.Updated(this, EventArgs.Empty); } } \ No newline at end of file diff --git a/Source/Launchbar/ElementCreator.cs b/Source/Launchbar/ElementCreator.cs index 5abbb70..a9d79f6 100644 --- a/Source/Launchbar/ElementCreator.cs +++ b/Source/Launchbar/ElementCreator.cs @@ -4,41 +4,40 @@ using System.Windows.Data; using JetBrains.Annotations; -namespace Launchbar +namespace Launchbar; + +/// +/// Creates objects from a given template. +/// +public sealed class ElementCreator : IValueConverter { /// - /// Creates objects from a given template. + /// Creates the the objects described by a template. /// - public sealed class ElementCreator : IValueConverter + /// + /// + /// A . + /// + /// Objects described by the template. + public object Convert([CanBeNull] object value, Type targetType, object parameter, CultureInfo culture) { - /// - /// Creates the the objects described by a template. - /// - /// - /// - /// A . - /// - /// Objects described by the template. - public object Convert([CanBeNull] object value, Type targetType, object parameter, CultureInfo culture) - { - return parameter switch - { - ControlTemplate ct => new Control { Template = ct }, - _ => throw new ArgumentException("You must specify a ControlTemplate.", nameof(parameter)) - }; - } + return parameter switch + { + ControlTemplate ct => new Control { Template = ct }, + _ => throw new ArgumentException("You must specify a ControlTemplate.", nameof(parameter)) + }; + } - /// - /// Not implemented. - /// - /// - /// - /// - /// - /// - public object ConvertBack([CanBeNull] object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotSupportedException(); - } + /// + /// Not implemented. + /// + /// + /// + /// + /// + /// + public object ConvertBack([CanBeNull] object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotSupportedException(); } } \ No newline at end of file diff --git a/Source/Launchbar/IconType.cs b/Source/Launchbar/IconType.cs index c6afb07..ac0780b 100644 --- a/Source/Launchbar/IconType.cs +++ b/Source/Launchbar/IconType.cs @@ -1,11 +1,8 @@ -using System; +namespace Launchbar; -namespace Launchbar +public enum IconType { - public enum IconType - { - Warning, - Default, - Custom, - } + Warning, + Default, + Custom, } \ No newline at end of file diff --git a/Source/Launchbar/Launchbar.csproj b/Source/Launchbar/Launchbar.csproj index 525e8ef..866ccf7 100644 --- a/Source/Launchbar/Launchbar.csproj +++ b/Source/Launchbar/Launchbar.csproj @@ -1,7 +1,7 @@  - net6.0-windows + net7.0-windows true WinExe false @@ -14,10 +14,10 @@ - - + + - + diff --git a/Source/Launchbar/Menu.cs b/Source/Launchbar/Menu.cs index e7b9941..8888685 100644 --- a/Source/Launchbar/Menu.cs +++ b/Source/Launchbar/Menu.cs @@ -5,78 +5,77 @@ using System.Windows.Threading; using JetBrains.Annotations; -namespace Launchbar +namespace Launchbar; + +/// +/// Dummy class. +/// This class contains the menu entries and will be saved with the application settings. +/// +public class Menu : NotifyBase { - /// - /// Dummy class. - /// This class contains the menu entries and will be saved with the application settings. - /// - public class Menu : NotifyBase - { - #region Fields + #region Fields - private MenuEntryCollection entries; + private MenuEntryCollection entries; - #endregion + #endregion - /// - /// Gets or sets a list of menu entries. - /// - public MenuEntryCollection Entries + /// + /// Gets or sets a list of menu entries. + /// + public MenuEntryCollection Entries + { + get { return this.entries; } + set { - get { return this.entries; } - set + if (this.entries == value) { - if (this.entries == value) - { - return; - } - this.entries = value; - this.OnPropertyChanged(nameof(this.Entries)); + return; } + this.entries = value; + this.OnPropertyChanged(nameof(this.Entries)); } + } + + public static Menu CreateDefault() + { + return new Menu + { + entries = new MenuEntryCollection + { + new MenuEntrySettings(), + new MenuEntryExit(), + } + }; + } - public static Menu CreateDefault() + public void FillIconCacheAsync([NotNull] Dispatcher dispatcher) + { + if (dispatcher == null) { - return new Menu - { - entries = new MenuEntryCollection - { - new MenuEntrySettings(), - new MenuEntryExit(), - } - }; + throw new ArgumentNullException(nameof(dispatcher)); } - public void FillIconCacheAsync([NotNull] Dispatcher dispatcher) - { - if (dispatcher == null) - { - throw new ArgumentNullException(nameof(dispatcher)); - } + Task.Run(() => getIcons(this.Entries, dispatcher)); + } - Task.Run(() => getIcons(this.Entries, dispatcher)); + private static async Task getIcons([CanBeNull, ItemNotNull] ObservableCollection entries, [NotNull] Dispatcher dispatcher) + { + if (entries == null) + { + return; // Nothing to do } - - private static async Task getIcons([CanBeNull, ItemNotNull] ObservableCollection entries, [NotNull] Dispatcher dispatcher) + MenuEntry[] entriesa = entries.ToArray(); + for (int i = 0; i < entriesa.Length; i++) { - if (entries == null) - { - return; // Nothing to do - } - MenuEntry[] entriesa = entries.ToArray(); - for (int i = 0; i < entriesa.Length; i++) + if (entriesa[i] is MenuEntryAdvanced mea) { - if (entriesa[i] is MenuEntryAdvanced mea) - { - // We are not interested in the actual value, but getting it will fill the cache. - await dispatcher.InvokeAsync(mea.UpdateIcon, DispatcherPriority.ApplicationIdle); + // We are not interested in the actual value, but getting it will fill the cache. + await dispatcher.InvokeAsync(mea.UpdateIcon, DispatcherPriority.ApplicationIdle); - // Also Refresh sub entries. - if (mea is Submenu submenu) - { - await getIcons(submenu.MenuEntries, dispatcher); - } + // Also Refresh sub entries. + if (mea is Submenu submenu) + { + await getIcons(submenu.MenuEntries, dispatcher); } } } diff --git a/Source/Launchbar/MenuEntry.cs b/Source/Launchbar/MenuEntry.cs index 33de4b4..8a05744 100644 --- a/Source/Launchbar/MenuEntry.cs +++ b/Source/Launchbar/MenuEntry.cs @@ -1,124 +1,122 @@ -using System; using System.Xml.Serialization; -namespace Launchbar +namespace Launchbar; + +/// +/// The base for all different menu entries. +/// +[XmlInclude(typeof(MenuEntryAdvanced))] +[XmlInclude(typeof(Separator))] +[XmlInclude(typeof(MenuEntrySettings))] +[XmlInclude(typeof(MenuEntryExit))] +public class MenuEntry : NotifyBase { + public const string IsSelectedProperty = "IsSelected"; + + private bool isSelected; + /// - /// The base for all different menu entries. + /// Gets or sets whether this object is selected. /// - [XmlInclude(typeof(MenuEntryAdvanced))] - [XmlInclude(typeof(Separator))] - [XmlInclude(typeof(MenuEntrySettings))] - [XmlInclude(typeof(MenuEntryExit))] - public class MenuEntry : NotifyBase + [XmlIgnore] + public bool IsSelected { - public const string IsSelectedProperty = "IsSelected"; - - private bool isSelected; - - /// - /// Gets or sets whether this object is selected. - /// - [XmlIgnore] - public bool IsSelected + get { return this.isSelected; } + set { - get { return this.isSelected; } - set + if (this.isSelected == value) { - if (this.isSelected == value) - { - return; - } - this.isSelected = value; - this.OnPropertyChanged(IsSelectedProperty); + return; } + this.isSelected = value; + this.OnPropertyChanged(IsSelectedProperty); } + } + + /// + /// Gets or sets the parent of this object. + /// + [XmlIgnore] + public MenuEntryCollection Parent { get; set; } + + /// + /// Move this item upwards in the parent collection. + /// + public void MoveUp() + { + this.move(true); + } - /// - /// Gets or sets the parent of this object. - /// - [XmlIgnore] - public MenuEntryCollection Parent { get; set; } + /// + /// Move this item downwards in the parent collection. + /// + public void MoveDown() + { + this.move(false); + } - /// - /// Move this item upwards in the parent collection. - /// - public void MoveUp() + private void move(bool up) + { + MenuEntryCollection parent = this.Parent; + if (parent == null) { - this.move(true); + return; // Unable to do anything } - /// - /// Move this item downwards in the parent collection. - /// - public void MoveDown() + int index = parent.IndexOf(this); + // The item is at the beginning of the collection + if ((index == 0 && up) || (index == parent.Count - 1 && !up)) { - this.move(false); + if (parent.Parent == null) + { + return; // We can't move the element any further. + } + MenuEntryCollection parentParent = parent.Parent.Parent; + if (parentParent == null) + { + return; // There is nothing we can do. + } + int parentIndex = parentParent.IndexOf(parent.Parent); + this.IsSelected = false; + parent.Remove(this); + if (up) + { + parentParent.Insert(parentIndex, this); + } + else + { + parentParent.Insert(parentIndex + 1, this); + } + this.IsSelected = true; } - - private void move(bool up) + else // The element is somewhere in the parent collection and can be moved. { - MenuEntryCollection parent = this.Parent; - if (parent == null) + int delta = 1; // Increase the index by one. + if (up) { - return; // Unable to do anything + delta = -1; // Decrease the index by one. } - int index = parent.IndexOf(this); - // The item is at the beginning of the collection - if ((index == 0 && up) || (index == parent.Count - 1 && !up)) + Submenu moveInto = parent[index + delta] as Submenu; + if (moveInto == null) + { + parent.Move(index, index + delta); + } + else { - if (parent.Parent == null) - { - return; // We can't move the element any further. - } - MenuEntryCollection parentParent = parent.Parent.Parent; - if (parentParent == null) - { - return; // There is nothing we can do. - } - int parentIndex = parentParent.IndexOf(parent.Parent); this.IsSelected = false; parent.Remove(this); + moveInto.IsExpanded = true; if (up) { - parentParent.Insert(parentIndex, this); + moveInto.MenuEntries.Add(this); } else { - parentParent.Insert(parentIndex + 1, this); + moveInto.MenuEntries.Insert(0, this); } this.IsSelected = true; } - else // The element is somewhere in the parent collection and can be moved. - { - int delta = 1; // Increase the index by one. - if (up) - { - delta = -1; // Decrease the index by one. - } - - Submenu moveInto = parent[index + delta] as Submenu; - if (moveInto == null) - { - parent.Move(index, index + delta); - } - else - { - this.IsSelected = false; - parent.Remove(this); - moveInto.IsExpanded = true; - if (up) - { - moveInto.MenuEntries.Add(this); - } - else - { - moveInto.MenuEntries.Insert(0, this); - } - this.IsSelected = true; - } - } } } } \ No newline at end of file diff --git a/Source/Launchbar/MenuEntryAdvanced.cs b/Source/Launchbar/MenuEntryAdvanced.cs index b4c15ec..0f1416a 100644 --- a/Source/Launchbar/MenuEntryAdvanced.cs +++ b/Source/Launchbar/MenuEntryAdvanced.cs @@ -1,211 +1,209 @@ -using System; using System.Text; using System.Windows.Media; using System.Xml.Serialization; using Launchbar.Win32; -namespace Launchbar +namespace Launchbar; + +/// +/// An extended menu entry. It has all the properties every active element has (name, icon). +/// +[XmlInclude(typeof(Submenu))] +[XmlInclude(typeof(Program))] +public class MenuEntryAdvanced : MenuEntry { - /// - /// An extended menu entry. It has all the properties every active element has (name, icon). - /// - [XmlInclude(typeof(Submenu))] - [XmlInclude(typeof(Program))] - public class MenuEntryAdvanced : MenuEntry - { - #region Fields + #region Fields - private string text; + private string text; - private string iconPath; + private string iconPath; - private int iconIndex; + private int iconIndex; - private ImageSource icon; + private ImageSource icon; - private IconType iconType = IconType.Default; + private IconType iconType = IconType.Default; - #endregion + #endregion - #region Properties + #region Properties - /// - /// Get or set the text to be shown for this entry. - /// - public string Text + /// + /// Get or set the text to be shown for this entry. + /// + public string Text + { + get { return this.text; } + set { - get { return this.text; } - set + if (this.text == value) { - if (this.text == value) - { - return; - } - this.text = value; - this.OnPropertyChanged(nameof(this.Text)); + return; } + this.text = value; + this.OnPropertyChanged(nameof(this.Text)); } + } - /// - /// Path to a file that contains an icon at the specified icon index - /// - public string IconPath + /// + /// Path to a file that contains an icon at the specified icon index + /// + public string IconPath + { + get { return this.iconPath; } + set { - get { return this.iconPath; } - set + if (value == string.Empty) { - if (value == string.Empty) - { - value = null; - } - if (this.iconPath == value) - { - return; - } - this.iconPath = value; - this.OnPropertyChanged(nameof(this.IconPath)); - this.UpdateIcon(); + value = null; } + if (this.iconPath == value) + { + return; + } + this.iconPath = value; + this.OnPropertyChanged(nameof(this.IconPath)); + this.UpdateIcon(); } + } - /// - /// Index of the icon inside the specified file - /// - public int IconIndex + /// + /// Index of the icon inside the specified file + /// + public int IconIndex + { + get { return this.iconIndex; } + set { - get { return this.iconIndex; } - set + if (this.iconIndex == value) { - if (this.iconIndex == value) - { - return; - } - this.iconIndex = value; - this.OnPropertyChanged(nameof(this.IconIndex)); - this.UpdateIcon(); + return; } + this.iconIndex = value; + this.OnPropertyChanged(nameof(this.IconIndex)); + this.UpdateIcon(); } + } - /// - /// Gets the type of icon to display. - /// - [XmlIgnore] - public IconType IconType + /// + /// Gets the type of icon to display. + /// + [XmlIgnore] + public IconType IconType + { + get { return this.iconType; } + private set { - get { return this.iconType; } - private set + if (this.iconType == value) { - if (this.iconType == value) - { - return; - } - this.iconType = value; - this.OnPropertyChanged(nameof(this.IconType)); + return; } + this.iconType = value; + this.OnPropertyChanged(nameof(this.IconType)); } + } - /// - /// Gets the icon to display when is set to . - /// - [XmlIgnore] - public ImageSource Icon + /// + /// Gets the icon to display when is set to . + /// + [XmlIgnore] + public ImageSource Icon + { + get { return this.icon; } + private set { - get { return this.icon; } - private set + if (this.icon == value) { - if (this.icon == value) - { - return; - } - this.icon = value; - this.OnPropertyChanged(nameof(this.Icon)); + return; } + this.icon = value; + this.OnPropertyChanged(nameof(this.Icon)); } + } - #endregion + #endregion - /// - /// Extract the icon based on the current data. - /// - public void UpdateIcon() - { - ImageSource newIcon = null; - IconType newType = IconType.Warning; + /// + /// Extract the icon based on the current data. + /// + public void UpdateIcon() + { + ImageSource newIcon = null; + IconType newType = IconType.Warning; - if (!string.IsNullOrEmpty(this.iconPath)) - { - newIcon = WinHelper.ExtractIcon(this.iconPath, this.iconIndex); - if (newIcon != null) - { - newType = IconType.Custom; - } - } - else + if (!string.IsNullOrEmpty(this.iconPath)) + { + newIcon = WinHelper.ExtractIcon(this.iconPath, this.iconIndex); + if (newIcon != null) { - Program p = this as Program; - if (p == null) // Not a program - use the default icon. - { - newType = IconType.Default; - } - else - { - if (p.IsValidFile) // Valid file? - { - newIcon = WinHelper.ExtractAssociatedIcon(p.PathAbsolute); - newType = IconType.Custom; - } - else if (p.IsValidPath) // Valid dictionary? - { - newType = IconType.Default; - } - } + newType = IconType.Custom; } - - this.Icon = newIcon; - this.IconType = newType; } - - /// - /// Displays the pick icon dialog with path based on the object data and sets the new icon. - /// - public void ChooseIcon() + else { - string path = @"%SystemRoot%\system32\shell32.dll"; // Default icon path - int index = 0; - if (!string.IsNullOrEmpty(this.iconPath)) // Did the user already choose an icon? + Program p = this as Program; + if (p == null) // Not a program - use the default icon. { - // Preset path and index to the previous values. - path = this.iconPath; - index = this.iconIndex; + newType = IconType.Default; } else { - if (this is Program p && p.IsValidFile) // When the program path is valid, use that path as default. + if (p.IsValidFile) // Valid file? { - path = p.Path; + newIcon = WinHelper.ExtractAssociatedIcon(p.PathAbsolute); + newType = IconType.Custom; + } + else if (p.IsValidPath) // Valid dictionary? + { + newType = IconType.Default; } } + } - // We need to have a string that is long enough to handle a more complex path than - // the default one (more characters in length). - StringBuilder sb = new StringBuilder(path, 4096); // 4095 + null-char should be enough + this.Icon = newIcon; + this.IconType = newType; + } - // Methods returns one when pressing OK in the dialog. - if (SafeNativeMethods.PickIconDlg(IntPtr.Zero, sb, (uint)sb.Capacity, ref index) == 1) + /// + /// Displays the pick icon dialog with path based on the object data and sets the new icon. + /// + public void ChooseIcon() + { + string path = @"%SystemRoot%\system32\shell32.dll"; // Default icon path + int index = 0; + if (!string.IsNullOrEmpty(this.iconPath)) // Did the user already choose an icon? + { + // Preset path and index to the previous values. + path = this.iconPath; + index = this.iconIndex; + } + else + { + if (this is Program p && p.IsValidFile) // When the program path is valid, use that path as default. { - this.IconPath = sb.ToString(); //save the information - this.IconIndex = index; + path = p.Path; } - this.UpdateIcon(); } - /// - /// Remove any user-set icon. - /// - public void ClearIcon() + // We need to have a string that is long enough to handle a more complex path than + // the default one (more characters in length). + StringBuilder sb = new StringBuilder(path, 4096); // 4095 + null-char should be enough + + // Methods returns one when pressing OK in the dialog. + if (SafeNativeMethods.PickIconDlg(nint.Zero, sb, (uint)sb.Capacity, ref index) == 1) { - this.IconPath = null; - this.IconIndex = 0; + this.IconPath = sb.ToString(); //save the information + this.IconIndex = index; } + this.UpdateIcon(); + } + + /// + /// Remove any user-set icon. + /// + public void ClearIcon() + { + this.IconPath = null; + this.IconIndex = 0; } } \ No newline at end of file diff --git a/Source/Launchbar/MenuEntryCollection.cs b/Source/Launchbar/MenuEntryCollection.cs index d0726f9..f27f2e0 100644 --- a/Source/Launchbar/MenuEntryCollection.cs +++ b/Source/Launchbar/MenuEntryCollection.cs @@ -2,57 +2,56 @@ using System.Collections.ObjectModel; using JetBrains.Annotations; -namespace Launchbar +namespace Launchbar; + +public class MenuEntryCollection : ObservableCollection { - public class MenuEntryCollection : ObservableCollection - { - public Submenu Parent { get; set; } + public Submenu Parent { get; set; } - // ReSharper disable once AnnotationConflictInHierarchy - protected override void InsertItem(int index, [NotNull] MenuEntry item) + // ReSharper disable once AnnotationConflictInHierarchy + protected override void InsertItem(int index, [NotNull] MenuEntry item) + { + if (item is null) { - if (item is null) - { - throw new ArgumentNullException(nameof(item)); - } - item.Parent = this; - base.InsertItem(index, item); - item.IsSelected = true; + throw new ArgumentNullException(nameof(item)); } + item.Parent = this; + base.InsertItem(index, item); + item.IsSelected = true; + } - protected override void RemoveItem(int index) + protected override void RemoveItem(int index) + { + this[index].IsSelected = false; + this[index].Parent = null; + base.RemoveItem(index); + if (index == 0) { - this[index].IsSelected = false; - this[index].Parent = null; - base.RemoveItem(index); - if (index == 0) + if (this.Parent == null) { - if (this.Parent == null) - { - return; - } - this.Parent.IsSelected = true; - } - else if (index >= this.Count) - { - this[^1].IsSelected = true; - } - else - { - this[index].IsSelected = true; + return; } + this.Parent.IsSelected = true; + } + else if (index >= this.Count) + { + this[^1].IsSelected = true; + } + else + { + this[index].IsSelected = true; } + } - // ReSharper disable once AnnotationConflictInHierarchy - protected override void SetItem(int index, [NotNull] MenuEntry item) + // ReSharper disable once AnnotationConflictInHierarchy + protected override void SetItem(int index, [NotNull] MenuEntry item) + { + if (item is null) { - if (item is null) - { - throw new ArgumentNullException(nameof(item)); - } - this[index].Parent = null; - item.Parent = this; - base.SetItem(index, item); + throw new ArgumentNullException(nameof(item)); } + this[index].Parent = null; + item.Parent = this; + base.SetItem(index, item); } } \ No newline at end of file diff --git a/Source/Launchbar/MenuEntryExit.cs b/Source/Launchbar/MenuEntryExit.cs index d60381d..a7681f7 100644 --- a/Source/Launchbar/MenuEntryExit.cs +++ b/Source/Launchbar/MenuEntryExit.cs @@ -2,27 +2,26 @@ using System.Windows; using System.Windows.Input; -namespace Launchbar +namespace Launchbar; + +/// +/// This class represents an exit entry. +/// +public sealed class MenuEntryExit : MenuEntry, ICommand { - /// - /// This class represents an exit entry. - /// - public sealed class MenuEntryExit : MenuEntry, ICommand + public event EventHandler CanExecuteChanged { - public event EventHandler CanExecuteChanged - { - add { } - remove { } - } + add { } + remove { } + } - public bool CanExecute(object parameter) - { - return true; - } + public bool CanExecute(object parameter) + { + return true; + } - public void Execute(object parameter) - { - Application.Current.Shutdown(); // Quit - } + public void Execute(object parameter) + { + Application.Current.Shutdown(); // Quit } } \ No newline at end of file diff --git a/Source/Launchbar/MenuEntrySettings.cs b/Source/Launchbar/MenuEntrySettings.cs index 1e60d07..66377e3 100644 --- a/Source/Launchbar/MenuEntrySettings.cs +++ b/Source/Launchbar/MenuEntrySettings.cs @@ -1,27 +1,26 @@ using System; using System.Windows.Input; -namespace Launchbar +namespace Launchbar; + +/// +/// This class represents a settings entry. +/// +public class MenuEntrySettings : MenuEntry, ICommand { - /// - /// This class represents a settings entry. - /// - public class MenuEntrySettings : MenuEntry, ICommand + public event EventHandler CanExecuteChanged { - public event EventHandler CanExecuteChanged - { - add { } - remove { } - } + add { } + remove { } + } - public bool CanExecute(object parameter) - { - return true; - } + public bool CanExecute(object parameter) + { + return true; + } - public void Execute(object parameter) - { - App.OpenOrActivateSettings(); // Quit - } + public void Execute(object parameter) + { + App.OpenOrActivateSettings(); // Quit } } \ No newline at end of file diff --git a/Source/Launchbar/MenuItemExtensions.cs b/Source/Launchbar/MenuItemExtensions.cs index 85cf8b6..88945b7 100644 --- a/Source/Launchbar/MenuItemExtensions.cs +++ b/Source/Launchbar/MenuItemExtensions.cs @@ -1,21 +1,19 @@ -using System; using System.Windows; -namespace Launchbar +namespace Launchbar; + +public static class MenuItemExtensions { - public static class MenuItemExtensions + public static void SetIconTemplate(DependencyObject d, DataTemplate value) { - public static void SetIconTemplate(DependencyObject d, DataTemplate value) - { - d.SetValue(IconTemplateProperty, value); - } - - public static DataTemplate GetIconTemplate(DependencyObject d) - { - return (DataTemplate)d.GetValue(IconTemplateProperty); - } + d.SetValue(IconTemplateProperty, value); + } - public static readonly DependencyProperty IconTemplateProperty = DependencyProperty.RegisterAttached( - "IconTemplate", typeof(DataTemplate), typeof(MenuItemExtensions), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); + public static DataTemplate GetIconTemplate(DependencyObject d) + { + return (DataTemplate)d.GetValue(IconTemplateProperty); } + + public static readonly DependencyProperty IconTemplateProperty = DependencyProperty.RegisterAttached( + "IconTemplate", typeof(DataTemplate), typeof(MenuItemExtensions), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); } \ No newline at end of file diff --git a/Source/Launchbar/MenuItemStyleSelector.cs b/Source/Launchbar/MenuItemStyleSelector.cs index af28504..0f4d926 100644 --- a/Source/Launchbar/MenuItemStyleSelector.cs +++ b/Source/Launchbar/MenuItemStyleSelector.cs @@ -1,39 +1,37 @@ -using System; using System.Windows; using System.Windows.Controls; using JetBrains.Annotations; -namespace Launchbar +namespace Launchbar; + +public sealed class MenuItemStyleSelector : StyleSelector { - public sealed class MenuItemStyleSelector : StyleSelector - { - [CanBeNull] - public Style ProgramStyle { get; set; } + [CanBeNull] + public Style ProgramStyle { get; set; } - [CanBeNull] - public Style SubmenuStyle { get; set; } + [CanBeNull] + public Style SubmenuStyle { get; set; } - [CanBeNull] - public Style SeparatorStyle { get; set; } + [CanBeNull] + public Style SeparatorStyle { get; set; } - [CanBeNull] - public Style SettingsStyle { get; set; } + [CanBeNull] + public Style SettingsStyle { get; set; } - [CanBeNull] - public Style ExitStyle { get; set; } + [CanBeNull] + public Style ExitStyle { get; set; } - [CanBeNull, MustUseReturnValue] - public override Style SelectStyle([CanBeNull] object item, [CanBeNull] DependencyObject container) - { - return item switch - { - Program => this.ProgramStyle, - Submenu => this.SubmenuStyle, - Separator => this.SeparatorStyle, - MenuEntrySettings => this.SettingsStyle, - MenuEntryExit => this.ExitStyle, - _ => null - }; - } + [CanBeNull, MustUseReturnValue] + public override Style SelectStyle([CanBeNull] object item, [CanBeNull] DependencyObject container) + { + return item switch + { + Program => this.ProgramStyle, + Submenu => this.SubmenuStyle, + Separator => this.SeparatorStyle, + MenuEntrySettings => this.SettingsStyle, + MenuEntryExit => this.ExitStyle, + _ => null + }; } } \ No newline at end of file diff --git a/Source/Launchbar/MetaData.cs b/Source/Launchbar/MetaData.cs index 2dc6d56..88bbeb1 100644 --- a/Source/Launchbar/MetaData.cs +++ b/Source/Launchbar/MetaData.cs @@ -2,15 +2,14 @@ using System.Reflection; using JetBrains.Annotations; -namespace Launchbar +namespace Launchbar; + +public static class MetaData { - public static class MetaData - { - [NotNull] - private static readonly Lazy version = new Lazy(() => - Assembly.GetExecutingAssembly().GetCustomAttribute()?.InformationalVersion ?? "Unknown"); + [NotNull] + private static readonly Lazy version = new Lazy(() => + Assembly.GetExecutingAssembly().GetCustomAttribute()?.InformationalVersion ?? "Unknown"); - [NotNull] - public static string Version => version.Value; - } + [NotNull] + public static string Version => version.Value; } \ No newline at end of file diff --git a/Source/Launchbar/NotifyBase.cs b/Source/Launchbar/NotifyBase.cs index a8c357e..532a707 100644 --- a/Source/Launchbar/NotifyBase.cs +++ b/Source/Launchbar/NotifyBase.cs @@ -1,24 +1,22 @@ -using System; -using System.ComponentModel; +using System.ComponentModel; using JetBrains.Annotations; -namespace Launchbar +namespace Launchbar; + +public class NotifyBase : INotifyPropertyChanged { - public class NotifyBase : INotifyPropertyChanged - { - /// - /// Indicates the change of a property. - /// - public event PropertyChangedEventHandler PropertyChanged = delegate { }; + /// + /// Indicates the change of a property. + /// + public event PropertyChangedEventHandler PropertyChanged = delegate { }; - /// - /// Raises the event. - /// - /// Name of the property which changed. - [NotifyPropertyChangedInvocator] - protected void OnPropertyChanged([NotNull] string propertyName) - { - this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); - } + /// + /// Raises the event. + /// + /// Name of the property which changed. + [NotifyPropertyChangedInvocator] + protected void OnPropertyChanged([NotNull] string propertyName) + { + this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } \ No newline at end of file diff --git a/Source/Launchbar/Program.cs b/Source/Launchbar/Program.cs index fc268f4..5b0b3a8 100644 --- a/Source/Launchbar/Program.cs +++ b/Source/Launchbar/Program.cs @@ -5,179 +5,178 @@ using System.Windows.Input; using JetBrains.Annotations; -namespace Launchbar +namespace Launchbar; + +/// +/// Contains all informations to start an application +/// +public sealed class Program : MenuEntryAdvanced, ICommand { - /// - /// Contains all informations to start an application - /// - public sealed class Program : MenuEntryAdvanced, ICommand - { - #region Fields + #region Fields - private string path; + private string path; - private string pathAbsolute; + private string pathAbsolute; - private string arguments; + private string arguments; - private ProcessPriorityClass priority = ProcessPriorityClass.Normal; + private ProcessPriorityClass priority = ProcessPriorityClass.Normal; - #endregion + #endregion - #region Properties + #region Properties - /// - /// Path to the file to start. - /// - public string Path + /// + /// Path to the file to start. + /// + public string Path + { + get { return this.path; } + set { - get { return this.path; } - set + if (value == string.Empty) + { + value = null; + } + if (this.path == value) + { + return; + } + this.path = value; + if (value == null) + { + this.pathAbsolute = null; + } + else { - if (value == string.Empty) - { - value = null; - } - if (this.path == value) - { - return; - } - this.path = value; - if (value == null) - { - this.pathAbsolute = null; - } - else - { - this.pathAbsolute = Environment.ExpandEnvironmentVariables(value); - } - - this.OnPropertyChanged(nameof(this.Path)); - this.OnPropertyChanged(nameof(this.IsValidFile)); - this.OnPropertyChanged(nameof(this.IsValidPath)); - this.UpdateIcon(); + this.pathAbsolute = Environment.ExpandEnvironmentVariables(value); } + + this.OnPropertyChanged(nameof(this.Path)); + this.OnPropertyChanged(nameof(this.IsValidFile)); + this.OnPropertyChanged(nameof(this.IsValidPath)); + this.UpdateIcon(); } + } - /// - /// Absolute path to the file to start (resolves environment variables). - /// - public string PathAbsolute => this.pathAbsolute; + /// + /// Absolute path to the file to start (resolves environment variables). + /// + public string PathAbsolute => this.pathAbsolute; - /// - /// Arguments to pass when starting the file. - /// - public string Arguments + /// + /// Arguments to pass when starting the file. + /// + public string Arguments + { + get { return this.arguments; } + set { - get { return this.arguments; } - set + if (value == string.Empty) { - if (value == string.Empty) - { - value = null; - } - if (this.arguments == value) - { - return; - } - this.arguments = value; - this.OnPropertyChanged(nameof(this.Arguments)); + value = null; } + if (this.arguments == value) + { + return; + } + this.arguments = value; + this.OnPropertyChanged(nameof(this.Arguments)); } + } - /// - /// Priority to start the program with. - /// - public ProcessPriorityClass Priority + /// + /// Priority to start the program with. + /// + public ProcessPriorityClass Priority + { + get { return this.priority; } + set { - get { return this.priority; } - set + if (this.priority == value) { - if (this.priority == value) - { - return; - } - this.priority = value; - this.OnPropertyChanged(nameof(this.Priority)); + return; } + this.priority = value; + this.OnPropertyChanged(nameof(this.Priority)); } + } - /// - /// Does the specified path point to an existing file? - /// - public bool IsValidFile => File.Exists(this.pathAbsolute); + /// + /// Does the specified path point to an existing file? + /// + public bool IsValidFile => File.Exists(this.pathAbsolute); - /// - /// Does the specified path point to an existing directory? - /// - public bool IsValidPath => Directory.Exists(this.pathAbsolute); + /// + /// Does the specified path point to an existing directory? + /// + public bool IsValidPath => Directory.Exists(this.pathAbsolute); - #endregion + #endregion - /// - /// Create a new instance of this class. - /// - public Program() - { - this.Text = "Program"; - } + /// + /// Create a new instance of this class. + /// + public Program() + { + this.Text = "Program"; + } - /// - /// Run the specified application with its arguments, working directory and priority - /// - public void Run() - { - ProcessStartInfo startInfo = new ProcessStartInfo - { - UseShellExecute = true, - FileName = this.pathAbsolute, - Arguments = this.arguments - }; - - string workingDir = System.IO.Path.GetDirectoryName(this.pathAbsolute); - if (workingDir != null) + /// + /// Run the specified application with its arguments, working directory and priority + /// + public void Run() + { + ProcessStartInfo startInfo = new ProcessStartInfo { - startInfo.WorkingDirectory = workingDir; - } + UseShellExecute = true, + FileName = this.pathAbsolute, + Arguments = this.arguments + }; - if (Process.Start(startInfo) is Process process) // Start the process and set the priority (if a new process has been created). - { - if (this.Priority != ProcessPriorityClass.Normal) // Only set priority if not default (as setting priority may cause an exception). - { - process.PriorityClass = this.Priority; - } - } + string workingDir = System.IO.Path.GetDirectoryName(this.pathAbsolute); + if (workingDir != null) + { + startInfo.WorkingDirectory = workingDir; } - /// - /// Calls and display if there is a failure. - /// - public void TryRun() + if (Process.Start(startInfo) is Process process) // Start the process and set the priority (if a new process has been created). { - try - { - this.Run(); - } - catch (Exception ex) + if (this.Priority != ProcessPriorityClass.Normal) // Only set priority if not default (as setting priority may cause an exception). { - MessageBox.Show($"An error occured while trying to start the application:\n\n{ex}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + process.PriorityClass = this.Priority; } } + } - public event EventHandler CanExecuteChanged + /// + /// Calls and display if there is a failure. + /// + public void TryRun() + { + try { - add { } - remove { } + this.Run(); } - - public bool CanExecute([CanBeNull] object parameter) + catch (Exception ex) { - return true; + MessageBox.Show($"An error occured while trying to start the application:\n\n{ex}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } + } - public void Execute([CanBeNull] object parameter) - { - this.TryRun(); - } + public event EventHandler CanExecuteChanged + { + add { } + remove { } + } + + public bool CanExecute([CanBeNull] object parameter) + { + return true; + } + + public void Execute([CanBeNull] object parameter) + { + this.TryRun(); } } \ No newline at end of file diff --git a/Source/Launchbar/Properties/AssemblyInfo.cs b/Source/Launchbar/Properties/AssemblyInfo.cs index 75d3a41..c7fe67b 100644 --- a/Source/Launchbar/Properties/AssemblyInfo.cs +++ b/Source/Launchbar/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Media; [assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] diff --git a/Source/Launchbar/Properties/Resources.Designer.cs b/Source/Launchbar/Properties/Resources.Designer.cs index a2ef864..5423542 100644 --- a/Source/Launchbar/Properties/Resources.Designer.cs +++ b/Source/Launchbar/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace Launchbar.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { @@ -87,15 +87,14 @@ public static string ApplicationName { ///The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ///and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). /// - ///## [Unreleased] + ///## [5.0.0] - 2021-12-15 ///### Changed - ///- Upgrade to .NET Core 3.1, built with Visual Studio 2019 + ///- Upgrade to .NET 6.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/6.0/runtime) to run ///- Changelog is now rendered with Markdown + ///### Removed + ///- Assembly Strong Name /// - ///## [4.6.0] - 2019-08-28 - ///### Changed - ///- Upgrade to .NET 4.8, built with Visual Studio 2019 - ///- Disable DPI awareness, as [rest of string was truncated]";. + ///## [4.6.0 [rest of string was truncated]";. /// public static string Changelog { get { diff --git a/Source/Launchbar/Properties/Settings.Designer.cs b/Source/Launchbar/Properties/Settings.Designer.cs index 58ca486..0d13941 100644 --- a/Source/Launchbar/Properties/Settings.Designer.cs +++ b/Source/Launchbar/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace Launchbar.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/Source/Launchbar/Separator.cs b/Source/Launchbar/Separator.cs index d9250c3..913be73 100644 --- a/Source/Launchbar/Separator.cs +++ b/Source/Launchbar/Separator.cs @@ -1,9 +1,6 @@ -using System; +namespace Launchbar; -namespace Launchbar -{ - /// - /// This class represents a separator. - /// - public sealed class Separator : MenuEntry { } -} \ No newline at end of file +/// +/// This class represents a separator. +/// +public sealed class Separator : MenuEntry { } \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapeApplication.xaml.cs b/Source/Launchbar/Shapes/ShapeApplication.xaml.cs index 1233457..c479eef 100644 --- a/Source/Launchbar/Shapes/ShapeApplication.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeApplication.xaml.cs @@ -1,23 +1,21 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Controls; -namespace Launchbar.Shapes +namespace Launchbar.Shapes; + +/// +/// Interaction logic for ShapeApplications.xaml +/// +public sealed partial class ShapeApplication : UserControl { - /// - /// Interaction logic for ShapeApplications.xaml - /// - public sealed partial class ShapeApplication : UserControl + public ShapeApplication() { - public ShapeApplication() - { - this.InitializeComponent(); - } + this.InitializeComponent(); + } - private void sizeChanged(object sender, SizeChangedEventArgs e) - { - this.scaler.ScaleX = this.ActualWidth / this.shape.Width; - this.scaler.ScaleY = this.ActualHeight / this.shape.Height; - } + private void sizeChanged(object sender, SizeChangedEventArgs e) + { + this.scaler.ScaleX = this.ActualWidth / this.shape.Width; + this.scaler.ScaleY = this.ActualHeight / this.shape.Height; } } \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapeClose.xaml.cs b/Source/Launchbar/Shapes/ShapeClose.xaml.cs index b267a92..71288a9 100644 --- a/Source/Launchbar/Shapes/ShapeClose.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeClose.xaml.cs @@ -1,38 +1,36 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Controls; -namespace Launchbar.Shapes +namespace Launchbar.Shapes; + +/// +/// Interaction logic for ShapeClose.xaml +/// +public sealed partial class ShapeClose : UserControl { /// - /// Interaction logic for ShapeClose.xaml + /// Gets or sets whether this shape is hovered. /// - public sealed partial class ShapeClose : UserControl + public bool IsHover { - /// - /// Gets or sets whether this shape is hovered. - /// - public bool IsHover - { - get { return (bool)this.GetValue(IsHoverProperty); } - set { this.SetValue(IsHoverProperty, value); } - } + get { return (bool)this.GetValue(IsHoverProperty); } + set { this.SetValue(IsHoverProperty, value); } + } - /// - /// Identifies the property. - /// - public static readonly DependencyProperty IsHoverProperty = - DependencyProperty.Register("IsHover", typeof(bool), typeof(ShapeClose)); + /// + /// Identifies the property. + /// + public static readonly DependencyProperty IsHoverProperty = + DependencyProperty.Register("IsHover", typeof(bool), typeof(ShapeClose)); - public ShapeClose() - { - this.InitializeComponent(); - } + public ShapeClose() + { + this.InitializeComponent(); + } - private void sizeChanged(object sender, SizeChangedEventArgs e) - { - this.scaler.ScaleX = this.ActualWidth / this.shape.Width; - this.scaler.ScaleY = this.ActualHeight / this.shape.Height; - } + private void sizeChanged(object sender, SizeChangedEventArgs e) + { + this.scaler.ScaleX = this.ActualWidth / this.shape.Width; + this.scaler.ScaleY = this.ActualHeight / this.shape.Height; } } \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapeDelete.xaml.cs b/Source/Launchbar/Shapes/ShapeDelete.xaml.cs index 1a09600..3c3fe03 100644 --- a/Source/Launchbar/Shapes/ShapeDelete.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeDelete.xaml.cs @@ -1,26 +1,24 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Controls; -namespace Launchbar.Shapes +namespace Launchbar.Shapes; + +/// +/// Interaction logic for ShapeDelete.xaml +/// +public sealed partial class ShapeDelete : UserControl { /// - /// Interaction logic for ShapeDelete.xaml + /// Create a new instance of this class. /// - public sealed partial class ShapeDelete : UserControl + public ShapeDelete() { - /// - /// Create a new instance of this class. - /// - public ShapeDelete() - { - this.InitializeComponent(); - } + this.InitializeComponent(); + } - private void sizeChanged(object sender, SizeChangedEventArgs e) - { - this.scaler.ScaleX = this.ActualWidth / this.shape.Width; - this.scaler.ScaleY = this.ActualHeight / this.shape.Height; - } + private void sizeChanged(object sender, SizeChangedEventArgs e) + { + this.scaler.ScaleX = this.ActualWidth / this.shape.Width; + this.scaler.ScaleY = this.ActualHeight / this.shape.Height; } } \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapeFolder.xaml.cs b/Source/Launchbar/Shapes/ShapeFolder.xaml.cs index 1b2f964..f417dab 100644 --- a/Source/Launchbar/Shapes/ShapeFolder.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeFolder.xaml.cs @@ -1,39 +1,37 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Controls; -namespace Launchbar.Shapes +namespace Launchbar.Shapes; + +/// +/// Interaction logic for ShapeFolder.xaml +/// +public sealed partial class ShapeFolder : UserControl { /// - /// Interaction logic for ShapeFolder.xaml + /// Gets or sets whether the folder is open. /// - public sealed partial class ShapeFolder : UserControl + public bool IsOpen { - /// - /// Gets or sets whether the folder is open. - /// - public bool IsOpen - { - get { return (bool)this.GetValue(IsOpenProperty); } - set { this.SetValue(IsOpenProperty, value); } - } + get { return (bool)this.GetValue(IsOpenProperty); } + set { this.SetValue(IsOpenProperty, value); } + } - /// - /// Identifies the property. - /// - public static readonly DependencyProperty IsOpenProperty = - DependencyProperty.Register("IsOpen", typeof(bool), typeof(ShapeFolder)); + /// + /// Identifies the property. + /// + public static readonly DependencyProperty IsOpenProperty = + DependencyProperty.Register("IsOpen", typeof(bool), typeof(ShapeFolder)); - public ShapeFolder() - { - this.InitializeComponent(); - this.shape.DataContext = this; - } + public ShapeFolder() + { + this.InitializeComponent(); + this.shape.DataContext = this; + } - private void sizeChanged(object sender, SizeChangedEventArgs e) - { - this.scaler.ScaleX = this.ActualWidth / this.shape.Width; - this.scaler.ScaleY = this.ActualHeight / this.shape.Height; - } + private void sizeChanged(object sender, SizeChangedEventArgs e) + { + this.scaler.ScaleX = this.ActualWidth / this.shape.Width; + this.scaler.ScaleY = this.ActualHeight / this.shape.Height; } } \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapeFolderGoTo.xaml.cs b/Source/Launchbar/Shapes/ShapeFolderGoTo.xaml.cs index 5cfd441..88c1a3b 100644 --- a/Source/Launchbar/Shapes/ShapeFolderGoTo.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeFolderGoTo.xaml.cs @@ -1,23 +1,21 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Controls; -namespace Launchbar.Shapes +namespace Launchbar.Shapes; + +/// +/// Interaction logic for ShapeFolderGoTo.xaml +/// +public sealed partial class ShapeFolderGoTo : UserControl { - /// - /// Interaction logic for ShapeFolderGoTo.xaml - /// - public sealed partial class ShapeFolderGoTo : UserControl + public ShapeFolderGoTo() { - public ShapeFolderGoTo() - { - this.InitializeComponent(); - } + this.InitializeComponent(); + } - private void sizeChanged(object sender, SizeChangedEventArgs e) - { - this.scaler.ScaleX = this.ActualWidth / this.shape.Width; - this.scaler.ScaleY = this.ActualHeight / this.shape.Height; - } + private void sizeChanged(object sender, SizeChangedEventArgs e) + { + this.scaler.ScaleX = this.ActualWidth / this.shape.Width; + this.scaler.ScaleY = this.ActualHeight / this.shape.Height; } } \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapeMonitor.xaml.cs b/Source/Launchbar/Shapes/ShapeMonitor.xaml.cs index de1fc4e..e94ef4c 100644 --- a/Source/Launchbar/Shapes/ShapeMonitor.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeMonitor.xaml.cs @@ -1,23 +1,21 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Controls; -namespace Launchbar.Shapes +namespace Launchbar.Shapes; + +/// +/// Interaction logic for ShapeMonitor.xaml +/// +public sealed partial class ShapeMonitor : UserControl { - /// - /// Interaction logic for ShapeMonitor.xaml - /// - public sealed partial class ShapeMonitor : UserControl + public ShapeMonitor() { - public ShapeMonitor() - { - this.InitializeComponent(); - } + this.InitializeComponent(); + } - private void sizeChanged(object sender, SizeChangedEventArgs e) - { - this.scaler.ScaleX = this.ActualWidth / this.shape.Width; - this.scaler.ScaleY = this.ActualHeight / this.shape.Height; - } + private void sizeChanged(object sender, SizeChangedEventArgs e) + { + this.scaler.ScaleX = this.ActualWidth / this.shape.Width; + this.scaler.ScaleY = this.ActualHeight / this.shape.Height; } } \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapeNext.xaml.cs b/Source/Launchbar/Shapes/ShapeNext.xaml.cs index c642127..f7ea69b 100644 --- a/Source/Launchbar/Shapes/ShapeNext.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeNext.xaml.cs @@ -1,23 +1,21 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Controls; -namespace Launchbar.Shapes +namespace Launchbar.Shapes; + +/// +/// Interaction logic for ShapeNext.xaml +/// +public sealed partial class ShapeNext : UserControl { - /// - /// Interaction logic for ShapeNext.xaml - /// - public sealed partial class ShapeNext : UserControl + public ShapeNext() { - public ShapeNext() - { - this.InitializeComponent(); - } + this.InitializeComponent(); + } - private void sizeChanged(object sender, SizeChangedEventArgs e) - { - this.scaler.ScaleX = this.ActualWidth / this.shape.Width; - this.scaler.ScaleY = this.ActualHeight / this.shape.Height; - } + private void sizeChanged(object sender, SizeChangedEventArgs e) + { + this.scaler.ScaleX = this.ActualWidth / this.shape.Width; + this.scaler.ScaleY = this.ActualHeight / this.shape.Height; } } \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapePlus.xaml.cs b/Source/Launchbar/Shapes/ShapePlus.xaml.cs index f350fd7..ba5947d 100644 --- a/Source/Launchbar/Shapes/ShapePlus.xaml.cs +++ b/Source/Launchbar/Shapes/ShapePlus.xaml.cs @@ -1,16 +1,14 @@ -using System; -using System.Windows.Controls; +using System.Windows.Controls; -namespace Launchbar.Shapes +namespace Launchbar.Shapes; + +/// +/// Interaction logic for ShapePlus.xaml +/// +public sealed partial class ShapePlus : UserControl { - /// - /// Interaction logic for ShapePlus.xaml - /// - public sealed partial class ShapePlus : UserControl + public ShapePlus() { - public ShapePlus() - { - this.InitializeComponent(); - } + this.InitializeComponent(); } } \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapeWarning.xaml.cs b/Source/Launchbar/Shapes/ShapeWarning.xaml.cs index fe0f03a..91dafcf 100644 --- a/Source/Launchbar/Shapes/ShapeWarning.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeWarning.xaml.cs @@ -1,23 +1,21 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Controls; -namespace Launchbar.Shapes +namespace Launchbar.Shapes; + +/// +/// Interaction logic for ShapeWarning.xaml +/// +public sealed partial class ShapeWarning : UserControl { - /// - /// Interaction logic for ShapeWarning.xaml - /// - public sealed partial class ShapeWarning : UserControl + public ShapeWarning() { - public ShapeWarning() - { - this.InitializeComponent(); - } + this.InitializeComponent(); + } - private void sizeChanged(object sender, SizeChangedEventArgs e) - { - this.scaler.ScaleX = this.ActualWidth / this.shape.Width; - this.scaler.ScaleY = this.ActualHeight / this.shape.Height; - } + private void sizeChanged(object sender, SizeChangedEventArgs e) + { + this.scaler.ScaleX = this.ActualWidth / this.shape.Width; + this.scaler.ScaleY = this.ActualHeight / this.shape.Height; } } \ No newline at end of file diff --git a/Source/Launchbar/Submenu.cs b/Source/Launchbar/Submenu.cs index cc712ef..8834f47 100644 --- a/Source/Launchbar/Submenu.cs +++ b/Source/Launchbar/Submenu.cs @@ -1,72 +1,70 @@ -using System; using System.Xml.Serialization; -namespace Launchbar +namespace Launchbar; + +/// +/// This class introduces lower level entries. +/// +public sealed class Submenu : MenuEntryAdvanced { - /// - /// This class introduces lower level entries. - /// - public sealed class Submenu : MenuEntryAdvanced - { - #region Fields + #region Fields - private MenuEntryCollection entries; + private MenuEntryCollection entries; - private bool isExpanded; + private bool isExpanded; - #endregion + #endregion - /// - /// Gets or sets whether this submenu is expanded. - /// - [XmlIgnore] - public bool IsExpanded + /// + /// Gets or sets whether this submenu is expanded. + /// + [XmlIgnore] + public bool IsExpanded + { + get { return this.isExpanded; } + set { - get { return this.isExpanded; } - set + if (this.isExpanded == value) { - if (this.isExpanded == value) - { - return; - } - this.isExpanded = value; - this.OnPropertyChanged(nameof(this.IsExpanded)); + return; } + this.isExpanded = value; + this.OnPropertyChanged(nameof(this.IsExpanded)); } + } - /// - /// List of entries inside this sub menu. - /// - public MenuEntryCollection MenuEntries + /// + /// List of entries inside this sub menu. + /// + public MenuEntryCollection MenuEntries + { + get { return this.entries; } + set { - get { return this.entries; } - set + if (this.entries == value) { - if (this.entries == value) - { - return; - } - if (this.entries != null) - { - this.entries.Parent = null; - } - this.entries = value; - if (this.entries != null) - { - this.entries.Parent = this; - } - - this.OnPropertyChanged(nameof(this.MenuEntries)); + return; + } + if (this.entries != null) + { + this.entries.Parent = null; + } + this.entries = value; + if (this.entries != null) + { + this.entries.Parent = this; } - } - /// - /// Create a new instance of this class. - /// - public Submenu() - { - this.entries = new MenuEntryCollection { Parent = this }; - this.Text = "Submenu"; + this.OnPropertyChanged(nameof(this.MenuEntries)); } } + + /// + /// Create a new instance of this class. + /// + public Submenu() + { + this.entries = new MenuEntryCollection { Parent = this }; + this.Text = "Submenu"; + } } \ No newline at end of file diff --git a/Source/Launchbar/Win32/ExtendedWindowStyles.cs b/Source/Launchbar/Win32/ExtendedWindowStyles.cs index f462844..56c6d22 100644 --- a/Source/Launchbar/Win32/ExtendedWindowStyles.cs +++ b/Source/Launchbar/Win32/ExtendedWindowStyles.cs @@ -1,41 +1,40 @@ -using System; + // ReSharper disable InconsistentNaming // ReSharper disable UnusedMember.Global #pragma warning disable 169 -namespace Launchbar.Win32 +namespace Launchbar.Win32; + +internal static class ExtendedWindowStyles { - internal static class ExtendedWindowStyles - { - public static readonly long WS_EX_ACCEPTFILES = 0x00000010L; - public static readonly long WS_EX_APPWINDOW = 0x00040000L; - public static readonly long WS_EX_CLIENTEDGE = 0x00000200L; - public static readonly long WS_EX_COMPOSITED = 0x02000000L; - public static readonly long WS_EX_CONTEXTHELP = 0x00000400L; - public static readonly long WS_EX_CONTROLPARENT = 0x00010000L; - public static readonly long WS_EX_DLGMODALFRAME = 0x00000001L; - public static readonly long WS_EX_LAYERED = 0x00080000L; - public static readonly long WS_EX_LAYOUTRTL = 0x00400000L; - public static readonly long WS_EX_LEFT = 0x00000000L; - public static readonly long WS_EX_LEFTSCROLLBAR = 0x00004000L; - public static readonly long WS_EX_LTRREADING = 0x00000000L; - public static readonly long WS_EX_MDICHILD = 0x00000040L; - public static readonly long WS_EX_NOACTIVATE = 0x08000000L; - public static readonly long WS_EX_NOINHERITLAYOUT = 0x00100000L; - public static readonly long WS_EX_NOPARENTNOTIFY = 0x00000004L; - public static readonly long WS_EX_RIGHT = 0x00001000L; - public static readonly long WS_EX_RIGHTSCROLLBAR = 0x00000000L; - public static readonly long WS_EX_RTLREADING = 0x00002000L; - public static readonly long WS_EX_STATICEDGE = 0x00020000L; - /// - /// The window is intended to be used as a floating toolbar. A tool window has a title bar that is shorter than a normal title bar, and the window title is drawn using a smaller font. A tool window does not appear in the taskbar or in the dialog that appears when the user presses ALT+TAB. If a tool window has a system menu, its icon is not displayed on the title bar. However, you can display the system menu by right-clicking or by typing ALT+SPACE. - /// - public static readonly long WS_EX_TOOLWINDOW = 0x00000080L; - public static readonly long WS_EX_TOPMOST = 0x00000008L; - public static readonly long WS_EX_TRANSPARENT = 0x00000020L; - public static readonly long WS_EX_WINDOWEDGE = 0x00000100L; - public static readonly long WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE; - public static readonly long WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST; - } + public static readonly long WS_EX_ACCEPTFILES = 0x00000010L; + public static readonly long WS_EX_APPWINDOW = 0x00040000L; + public static readonly long WS_EX_CLIENTEDGE = 0x00000200L; + public static readonly long WS_EX_COMPOSITED = 0x02000000L; + public static readonly long WS_EX_CONTEXTHELP = 0x00000400L; + public static readonly long WS_EX_CONTROLPARENT = 0x00010000L; + public static readonly long WS_EX_DLGMODALFRAME = 0x00000001L; + public static readonly long WS_EX_LAYERED = 0x00080000L; + public static readonly long WS_EX_LAYOUTRTL = 0x00400000L; + public static readonly long WS_EX_LEFT = 0x00000000L; + public static readonly long WS_EX_LEFTSCROLLBAR = 0x00004000L; + public static readonly long WS_EX_LTRREADING = 0x00000000L; + public static readonly long WS_EX_MDICHILD = 0x00000040L; + public static readonly long WS_EX_NOACTIVATE = 0x08000000L; + public static readonly long WS_EX_NOINHERITLAYOUT = 0x00100000L; + public static readonly long WS_EX_NOPARENTNOTIFY = 0x00000004L; + public static readonly long WS_EX_RIGHT = 0x00001000L; + public static readonly long WS_EX_RIGHTSCROLLBAR = 0x00000000L; + public static readonly long WS_EX_RTLREADING = 0x00002000L; + public static readonly long WS_EX_STATICEDGE = 0x00020000L; + /// + /// The window is intended to be used as a floating toolbar. A tool window has a title bar that is shorter than a normal title bar, and the window title is drawn using a smaller font. A tool window does not appear in the taskbar or in the dialog that appears when the user presses ALT+TAB. If a tool window has a system menu, its icon is not displayed on the title bar. However, you can display the system menu by right-clicking or by typing ALT+SPACE. + /// + public static readonly long WS_EX_TOOLWINDOW = 0x00000080L; + public static readonly long WS_EX_TOPMOST = 0x00000008L; + public static readonly long WS_EX_TRANSPARENT = 0x00000020L; + public static readonly long WS_EX_WINDOWEDGE = 0x00000100L; + public static readonly long WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE; + public static readonly long WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST; } \ No newline at end of file diff --git a/Source/Launchbar/Win32/GWL.cs b/Source/Launchbar/Win32/GWL.cs index 51e7679..b0ad858 100644 --- a/Source/Launchbar/Win32/GWL.cs +++ b/Source/Launchbar/Win32/GWL.cs @@ -1,19 +1,18 @@ -using System; + // ReSharper disable InconsistentNaming // ReSharper disable UnusedMember.Global #pragma warning disable 169 -namespace Launchbar.Win32 +namespace Launchbar.Win32; + +internal static class GWL { - internal static class GWL - { - public static readonly int GWL_WNDPROC = -4; - public static readonly int GWL_HINSTANCE = -6; - public static readonly int GWL_HWNDPARENT = -8; - public static readonly int GWL_STYLE = -16; - public static readonly int GWL_EXSTYLE = -20; - public static readonly int GWL_USERDATA = -21; - public static readonly int GWL_ID = -12; - } + public static readonly int GWL_WNDPROC = -4; + public static readonly int GWL_HINSTANCE = -6; + public static readonly int GWL_HWNDPARENT = -8; + public static readonly int GWL_STYLE = -16; + public static readonly int GWL_EXSTYLE = -20; + public static readonly int GWL_USERDATA = -21; + public static readonly int GWL_ID = -12; } \ No newline at end of file diff --git a/Source/Launchbar/Win32/SafeNativeMethods.cs b/Source/Launchbar/Win32/SafeNativeMethods.cs index 6cfb63a..81f1d81 100644 --- a/Source/Launchbar/Win32/SafeNativeMethods.cs +++ b/Source/Launchbar/Win32/SafeNativeMethods.cs @@ -8,238 +8,237 @@ // ReSharper disable FieldCanBeMadeReadOnly.Global // ReSharper disable UnusedMethodReturnValue.Global -namespace Launchbar.Win32 +namespace Launchbar.Win32; + +[SuppressUnmanagedCodeSecurity] +internal static class SafeNativeMethods { - [SuppressUnmanagedCodeSecurity] - internal static class SafeNativeMethods + internal const string User32 = @"user32.dll"; + + internal const string Shell32 = @"shell32.dll"; + + #region SetWindowLongPtr + + [DllImport(User32, EntryPoint = "GetWindowLong")] + private static extern int GetWindowLongPtr32(nint hWnd, int nIndex); + + [DllImport(User32, EntryPoint = "GetWindowLongPtr")] + private static extern nint GetWindowLongPtr64(nint hWnd, int nIndex); + + /// + /// The GetWindowLongPtr function retrieves information about the specified window. + /// The function also retrieves the value at a specified offset into the extra window memory. + /// + /// Handle to the window and, indirectly, the class to which the window belongs. + /// Specifies the zero-based offset to the value to be retrieved. + /// Valid values are in the range zero through the number of bytes of extra window memory, + /// minus the size of an integer. + /// If the function succeeds, the return value is the requested value. + /// If the function fails, the return value is zero. To get extended error information, call GetLastError. + /// If SetWindowLong or SetWindowLongPtr has not been called previously, GetWindowLongPtr returns zero + /// for values in the extra window or class memory. + public static nint GetWindowLongPtr(nint hWnd, int nIndex) + { + return nint.Size == 8 ? GetWindowLongPtr64(hWnd, nIndex) : new nint(GetWindowLongPtr32(hWnd, nIndex)); + } + + #endregion + + #region SetWindowLongPtr + + [DllImport(User32, EntryPoint = "SetWindowLong")] + private static extern int SetWindowLong32(nint hWnd, int nIndex, int dwNewLong); + + [DllImport(User32, EntryPoint = "SetWindowLongPtr")] + private static extern nint SetWindowLongPtr64(nint hWnd, int nIndex, nint dwNewLong); + + /// + /// The SetWindowLongPtr function changes an attribute of the specified window. + /// The function also sets a value at the specified offset in the extra window memory. + /// + /// Handle to the window and, indirectly, the class to which the window belongs. + /// The SetWindowLongPtr function fails if the process that owns the window specified by the + /// hWnd parameter is at a higher process privilege in the User Interface Privilege Isolation (UIPI) + /// hierarchy than the process the calling thread resides in. Microsoft Windows XP and earlier: + /// The SetWindowLongPtr function fails if the window specified by the hWnd parameter does not belong + /// to the same process as the calling thread. + /// Specifies the zero-based offset to the value to be set. + /// Valid values are in the range zero through the number of bytes of extra window memory, + /// minus the size of an integer. + /// Specifies the replacement value. + /// If the function succeeds, the return value is the previous value of the specified offset. + /// If the function fails, the return value is zero. To get extended error information, call GetLastError. + /// If the previous value is zero and the function succeeds, the return value is zero, but the function + /// does not clear the last error information. To determine success or failure, clear the last + /// error information by calling SetLastError(0), then call SetWindowLongPtr. + /// Function failure will be indicated by a return value of zero and a GetLastError result that is nonzero. + public static nint SetWindowLongPtr(nint hWnd, int nIndex, nint dwNewLong) + { + return nint.Size == 8 + ? SetWindowLongPtr64(hWnd, nIndex, dwNewLong) + : new nint(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32())); + } + + #endregion + + /// + /// Displays a dialog box that enables a user to select an icon from a module. + /// + /// [in] The handle of the parent window. + /// [in, out] A null-terminated string that contains the fully-qualified path + /// of the default DLL that contains the icons. If the user chooses a different DLL, this buffer + /// contains the path of that DLL when the function returns. This buffer should be at least MAX_PATH + /// characters in length, or the returned path may be truncated. You should verify that the path is + /// valid before using it. + /// [in] The number of characters in , + /// including the terminating NULL character. + /// [in, out] A pointer to an integer that, on entry, specified the index of + /// the initial selection. On exit, the integer specifies the index of the icon that was selected. + /// Returns 1 if successful; otherwise, 0. + [DllImport(Shell32, EntryPoint = "PickIconDlg", CharSet = CharSet.Unicode)] + public static extern int PickIconDlg(nint hwnd, StringBuilder pszIconPath, uint cchIconPath, ref int piIconIndex); + + /// + /// Destroys an icon and frees any memory the icon occupied. + /// + /// [in] Handle to the icon to be destroyed. The icon must not be in use. + /// If the function succeeds, the return value is nonzero. If the function fails, + /// the return value is zero. To get extended error information, call GetLastError. + [DllImport(User32, EntryPoint = "DestroyIcon", CharSet = CharSet.Auto, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool DestroyIcon(nint hIcon); + + /// + /// The ExtractIcon function retrieves a handle to an icon from the specified executable file, DLL, or icon file. + /// + /// [in] Handle to the instance of the application calling the function. + /// [in] Pointer to a null-terminated string specifying the name of an + /// executable file, DLL, or icon file. + /// [in] Specifies the zero-based index of the icon to retrieve. + /// For example, if this value is 0, the function returns a handle to the first icon in the specified file. + /// If this value is -1, the function returns the total number of icons in the specified file. + /// If the file is an executable file or DLL, the return value is the number of RT_GROUP_ICON resources. + /// If the file is an .ICO file, the return value is 1. + /// The return value is a handle to an icon. If the file specified was not an executable file, DLL, or icon file, the return is 1. + /// If no icons were found in the file, the return value is NULL. + [DllImport(Shell32, EntryPoint = "ExtractIcon", CharSet = CharSet.Unicode)] + internal static extern nint ExtractIcon(nint hInst, string lpszExeFileName, uint nIconIndex); + + /// + /// The ExtractAssociatedIcon function returns a handle to an indexed icon found in a file or an icon found in an associated executable file. + /// + /// [in] Specifies the instance of the application calling the function. + /// [in] Pointer to a string that specifies the full path and file name of the + /// file that contains the icon. The function extracts the icon handle from that file, or from an + /// executable file associated with that file. If the icon handle is obtained from an executable file, + /// the function stores the full path and file name of that executable in the string pointed to by + /// . + /// [in, out] Pointer to a WORD that specifies the index of the icon whose handle + /// is to be obtained. If the icon handle is obtained from an executable file, the function stores the + /// icon's identifier in the WORD pointed to by . + /// If the function succeeds, the return value is an icon handle. If the icon is extracted + /// from an associated executable file, the function stores the full path and file name of the + /// executable file in the string pointed to by , and stores the icon's + /// identifier in the WORD pointed to by . If the function fails, the + /// return value is NULL. + [DllImport(Shell32, EntryPoint = "ExtractAssociatedIcon", CharSet = CharSet.Unicode)] + internal static extern nint ExtractAssociatedIcon(nint hInst, string lpIconPath, ref int lpiIcon); + + #region SendInput + + [StructLayout(LayoutKind.Sequential)] + internal struct MOUSEINPUT + { + public int dx; + + public int dy; + + public MOUSEINPUTDATA mouseData; + + public MOUSEINPUTFLAGS dwFlags; + + public uint time; + + public nint dwExtraInfo; + } + + internal enum MOUSEINPUTDATA : uint { - internal const string User32 = @"user32.dll"; - - internal const string Shell32 = @"shell32.dll"; - - #region SetWindowLongPtr - - [DllImport(User32, EntryPoint = "GetWindowLong")] - private static extern int GetWindowLongPtr32(IntPtr hWnd, int nIndex); - - [DllImport(User32, EntryPoint = "GetWindowLongPtr")] - private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex); - - /// - /// The GetWindowLongPtr function retrieves information about the specified window. - /// The function also retrieves the value at a specified offset into the extra window memory. - /// - /// Handle to the window and, indirectly, the class to which the window belongs. - /// Specifies the zero-based offset to the value to be retrieved. - /// Valid values are in the range zero through the number of bytes of extra window memory, - /// minus the size of an integer. - /// If the function succeeds, the return value is the requested value. - /// If the function fails, the return value is zero. To get extended error information, call GetLastError. - /// If SetWindowLong or SetWindowLongPtr has not been called previously, GetWindowLongPtr returns zero - /// for values in the extra window or class memory. - public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex) - { - return IntPtr.Size == 8 ? GetWindowLongPtr64(hWnd, nIndex) : new IntPtr(GetWindowLongPtr32(hWnd, nIndex)); - } - - #endregion - - #region SetWindowLongPtr - - [DllImport(User32, EntryPoint = "SetWindowLong")] - private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong); - - [DllImport(User32, EntryPoint = "SetWindowLongPtr")] - private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong); - - /// - /// The SetWindowLongPtr function changes an attribute of the specified window. - /// The function also sets a value at the specified offset in the extra window memory. - /// - /// Handle to the window and, indirectly, the class to which the window belongs. - /// The SetWindowLongPtr function fails if the process that owns the window specified by the - /// hWnd parameter is at a higher process privilege in the User Interface Privilege Isolation (UIPI) - /// hierarchy than the process the calling thread resides in. Microsoft Windows XP and earlier: - /// The SetWindowLongPtr function fails if the window specified by the hWnd parameter does not belong - /// to the same process as the calling thread. - /// Specifies the zero-based offset to the value to be set. - /// Valid values are in the range zero through the number of bytes of extra window memory, - /// minus the size of an integer. - /// Specifies the replacement value. - /// If the function succeeds, the return value is the previous value of the specified offset. - /// If the function fails, the return value is zero. To get extended error information, call GetLastError. - /// If the previous value is zero and the function succeeds, the return value is zero, but the function - /// does not clear the last error information. To determine success or failure, clear the last - /// error information by calling SetLastError(0), then call SetWindowLongPtr. - /// Function failure will be indicated by a return value of zero and a GetLastError result that is nonzero. - public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong) - { - return IntPtr.Size == 8 - ? SetWindowLongPtr64(hWnd, nIndex, dwNewLong) - : new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32())); - } - - #endregion - - /// - /// Displays a dialog box that enables a user to select an icon from a module. - /// - /// [in] The handle of the parent window. - /// [in, out] A null-terminated string that contains the fully-qualified path - /// of the default DLL that contains the icons. If the user chooses a different DLL, this buffer - /// contains the path of that DLL when the function returns. This buffer should be at least MAX_PATH - /// characters in length, or the returned path may be truncated. You should verify that the path is - /// valid before using it. - /// [in] The number of characters in , - /// including the terminating NULL character. - /// [in, out] A pointer to an integer that, on entry, specified the index of - /// the initial selection. On exit, the integer specifies the index of the icon that was selected. - /// Returns 1 if successful; otherwise, 0. - [DllImport(Shell32, EntryPoint = "PickIconDlg", CharSet = CharSet.Unicode)] - public static extern int PickIconDlg(IntPtr hwnd, StringBuilder pszIconPath, uint cchIconPath, ref int piIconIndex); - - /// - /// Destroys an icon and frees any memory the icon occupied. - /// - /// [in] Handle to the icon to be destroyed. The icon must not be in use. - /// If the function succeeds, the return value is nonzero. If the function fails, - /// the return value is zero. To get extended error information, call GetLastError. - [DllImport(User32, EntryPoint = "DestroyIcon", CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DestroyIcon(IntPtr hIcon); - - /// - /// The ExtractIcon function retrieves a handle to an icon from the specified executable file, DLL, or icon file. - /// - /// [in] Handle to the instance of the application calling the function. - /// [in] Pointer to a null-terminated string specifying the name of an - /// executable file, DLL, or icon file. - /// [in] Specifies the zero-based index of the icon to retrieve. - /// For example, if this value is 0, the function returns a handle to the first icon in the specified file. - /// If this value is -1, the function returns the total number of icons in the specified file. - /// If the file is an executable file or DLL, the return value is the number of RT_GROUP_ICON resources. - /// If the file is an .ICO file, the return value is 1. - /// The return value is a handle to an icon. If the file specified was not an executable file, DLL, or icon file, the return is 1. - /// If no icons were found in the file, the return value is NULL. - [DllImport(Shell32, EntryPoint = "ExtractIcon", CharSet = CharSet.Unicode)] - internal static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, uint nIconIndex); - - /// - /// The ExtractAssociatedIcon function returns a handle to an indexed icon found in a file or an icon found in an associated executable file. - /// - /// [in] Specifies the instance of the application calling the function. - /// [in] Pointer to a string that specifies the full path and file name of the - /// file that contains the icon. The function extracts the icon handle from that file, or from an - /// executable file associated with that file. If the icon handle is obtained from an executable file, - /// the function stores the full path and file name of that executable in the string pointed to by - /// . - /// [in, out] Pointer to a WORD that specifies the index of the icon whose handle - /// is to be obtained. If the icon handle is obtained from an executable file, the function stores the - /// icon's identifier in the WORD pointed to by . - /// If the function succeeds, the return value is an icon handle. If the icon is extracted - /// from an associated executable file, the function stores the full path and file name of the - /// executable file in the string pointed to by , and stores the icon's - /// identifier in the WORD pointed to by . If the function fails, the - /// return value is NULL. - [DllImport(Shell32, EntryPoint = "ExtractAssociatedIcon", CharSet = CharSet.Unicode)] - internal static extern IntPtr ExtractAssociatedIcon(IntPtr hInst, string lpIconPath, ref int lpiIcon); - - #region SendInput - - [StructLayout(LayoutKind.Sequential)] - internal struct MOUSEINPUT - { - public int dx; - - public int dy; - - public MOUSEINPUTDATA mouseData; - - public MOUSEINPUTFLAGS dwFlags; - - public uint time; - - public IntPtr dwExtraInfo; - } - - internal enum MOUSEINPUTDATA : uint - { - XBUTTON1 = 0x0001, - XBUTTON2 = 0x0002, - } - - [Flags] - internal enum MOUSEINPUTFLAGS : uint - { - MOUSEEVENTF_MOVE = 0x0001, - MOUSEEVENTF_LEFTDOWN = 0x0002, - MOUSEEVENTF_LEFTUP = 0x0004, - MOUSEEVENTF_RIGHTDOWN = 0x0008, - MOUSEEVENTF_RIGHTUP = 0x0010, - MOUSEEVENTF_MIDDLEDOWN = 0x0020, - MOUSEEVENTF_MIDDLEUP = 0x0040, - MOUSEEVENTF_XDOWN = 0x0080, - MOUSEEVENTF_XUP = 0x0100, - MOUSEEVENTF_WHEEL = 0x0800, - MOUSEEVENTF_VIRTUALDESK = 0x4000, - MOUSEEVENTF_ABSOLUTE = 0x8000, - } - - [StructLayout(LayoutKind.Sequential)] - internal struct KEYBDINPUT - { - public ushort wVk; - - public ushort wScan; - - public uint dwFlags; - - public uint time; - - public IntPtr dwExtraInfo; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HARDWAREINPUT - { - public int uMsg; - - public short wParamL; - - public short wParamH; - } - - [StructLayout(LayoutKind.Explicit)] - internal struct MOUSEKEYBDHARDWAREINPUT - { - [FieldOffset(0)] - public MOUSEINPUT mi; - - [FieldOffset(0)] - public KEYBDINPUT ki; - - [FieldOffset(0)] - public HARDWAREINPUT hi; - } - - internal enum INPUT_TYPE - { - MOUSE = 0, - KEYBOARD = 1, - HARDWARE = 2, - } - - [StructLayout(LayoutKind.Sequential)] - internal struct INPUT - { - public INPUT_TYPE type; - - public MOUSEKEYBDHARDWAREINPUT mkhi; - } - - [DllImport(User32, SetLastError = true)] - internal static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize); + XBUTTON1 = 0x0001, + XBUTTON2 = 0x0002, + } - #endregion + [Flags] + internal enum MOUSEINPUTFLAGS : uint + { + MOUSEEVENTF_MOVE = 0x0001, + MOUSEEVENTF_LEFTDOWN = 0x0002, + MOUSEEVENTF_LEFTUP = 0x0004, + MOUSEEVENTF_RIGHTDOWN = 0x0008, + MOUSEEVENTF_RIGHTUP = 0x0010, + MOUSEEVENTF_MIDDLEDOWN = 0x0020, + MOUSEEVENTF_MIDDLEUP = 0x0040, + MOUSEEVENTF_XDOWN = 0x0080, + MOUSEEVENTF_XUP = 0x0100, + MOUSEEVENTF_WHEEL = 0x0800, + MOUSEEVENTF_VIRTUALDESK = 0x4000, + MOUSEEVENTF_ABSOLUTE = 0x8000, } + + [StructLayout(LayoutKind.Sequential)] + internal struct KEYBDINPUT + { + public ushort wVk; + + public ushort wScan; + + public uint dwFlags; + + public uint time; + + public nint dwExtraInfo; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HARDWAREINPUT + { + public int uMsg; + + public short wParamL; + + public short wParamH; + } + + [StructLayout(LayoutKind.Explicit)] + internal struct MOUSEKEYBDHARDWAREINPUT + { + [FieldOffset(0)] + public MOUSEINPUT mi; + + [FieldOffset(0)] + public KEYBDINPUT ki; + + [FieldOffset(0)] + public HARDWAREINPUT hi; + } + + internal enum INPUT_TYPE + { + MOUSE = 0, + KEYBOARD = 1, + HARDWARE = 2, + } + + [StructLayout(LayoutKind.Sequential)] + internal struct INPUT + { + public INPUT_TYPE type; + + public MOUSEKEYBDHARDWAREINPUT mkhi; + } + + [DllImport(User32, SetLastError = true)] + internal static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize); + + #endregion } \ No newline at end of file diff --git a/Source/Launchbar/Win32/WinHelper.cs b/Source/Launchbar/Win32/WinHelper.cs index f8d44a4..02b063f 100644 --- a/Source/Launchbar/Win32/WinHelper.cs +++ b/Source/Launchbar/Win32/WinHelper.cs @@ -6,140 +6,139 @@ using System.Windows.Media.Imaging; using JetBrains.Annotations; -namespace Launchbar.Win32 +namespace Launchbar.Win32; + +/// +/// Contains various methods to work with the windows operating system. +/// +internal static class WinHelper { /// - /// Contains various methods to work with the windows operating system. + /// Extract the associated icon from a file or directory. /// - internal static class WinHelper + /// Path to the file or directory to extract the icon from. + /// Does NOT support environment variables. + /// The extracted icon as . + public static BitmapSource ExtractAssociatedIcon([NotNull] string path) { - /// - /// Extract the associated icon from a file or directory. - /// - /// Path to the file or directory to extract the icon from. - /// Does NOT support environment variables. - /// The extracted icon as . - public static BitmapSource ExtractAssociatedIcon([NotNull] string path) + int i = 0; + nint hIcon = SafeNativeMethods.ExtractAssociatedIcon(nint.Zero, path, ref i); + if (hIcon != nint.Zero) { - int i = 0; - IntPtr hIcon = SafeNativeMethods.ExtractAssociatedIcon(IntPtr.Zero, path, ref i); - if (hIcon != IntPtr.Zero) - { - BitmapSource bms = Imaging.CreateBitmapSourceFromHIcon(hIcon, Int32Rect.Empty, null); - SafeNativeMethods.DestroyIcon(hIcon); - return bms; - } - return null; + BitmapSource bms = Imaging.CreateBitmapSourceFromHIcon(hIcon, Int32Rect.Empty, null); + SafeNativeMethods.DestroyIcon(hIcon); + return bms; } + return null; + } - /// - /// Extract an icon from a file or directory. - /// - /// Path to the file or directory to extract the icon from. - /// Supports environment variables. - /// A zero-based index of the icon. - /// The extracted icon as . - public static BitmapSource ExtractIcon([NotNull] string path, int index) + /// + /// Extract an icon from a file or directory. + /// + /// Path to the file or directory to extract the icon from. + /// Supports environment variables. + /// A zero-based index of the icon. + /// The extracted icon as . + public static BitmapSource ExtractIcon([NotNull] string path, int index) + { + nint hIcon = SafeNativeMethods.ExtractIcon(nint.Zero, path, (uint)index); + if (hIcon != nint.Zero) { - IntPtr hIcon = SafeNativeMethods.ExtractIcon(IntPtr.Zero, path, (uint)index); - if (hIcon != IntPtr.Zero) - { - BitmapSource bms = Imaging.CreateBitmapSourceFromHIcon(hIcon, Int32Rect.Empty, null); - SafeNativeMethods.DestroyIcon(hIcon); - return bms; - } - return null; + BitmapSource bms = Imaging.CreateBitmapSourceFromHIcon(hIcon, Int32Rect.Empty, null); + SafeNativeMethods.DestroyIcon(hIcon); + return bms; } + return null; + } - /// - /// Send a mouse button down signal. - /// Errors will not be handled. - /// - public static void SendMouseButtonDown(MouseButton button) - { - SafeNativeMethods.MOUSEINPUT mi = new SafeNativeMethods.MOUSEINPUT(); + /// + /// Send a mouse button down signal. + /// Errors will not be handled. + /// + public static void SendMouseButtonDown(MouseButton button) + { + SafeNativeMethods.MOUSEINPUT mi = new SafeNativeMethods.MOUSEINPUT(); - switch (button) - { - case MouseButton.Left: - mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_LEFTDOWN; - break; - case MouseButton.Right: - mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_RIGHTDOWN; - break; - default: - throw new NotSupportedException(); - } - SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT mkhInput = new SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT { mi = mi }; - - SafeNativeMethods.INPUT input = new SafeNativeMethods.INPUT { type = SafeNativeMethods.INPUT_TYPE.MOUSE, mkhi = mkhInput }; - - SafeNativeMethods.SendInput(1, ref input, Marshal.SizeOf(input)); + switch (button) + { + case MouseButton.Left: + mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_LEFTDOWN; + break; + case MouseButton.Right: + mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_RIGHTDOWN; + break; + default: + throw new NotSupportedException(); } + SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT mkhInput = new SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT { mi = mi }; + + SafeNativeMethods.INPUT input = new SafeNativeMethods.INPUT { type = SafeNativeMethods.INPUT_TYPE.MOUSE, mkhi = mkhInput }; + + SafeNativeMethods.SendInput(1, ref input, Marshal.SizeOf(input)); + } + + /// + /// Send a mouse button up signal. + /// Errors will not be handled. + /// + public static void SendMouseButtonUp(MouseButton button) + { + SafeNativeMethods.MOUSEINPUT mi = new SafeNativeMethods.MOUSEINPUT(); - /// - /// Send a mouse button up signal. - /// Errors will not be handled. - /// - public static void SendMouseButtonUp(MouseButton button) + switch (button) { - SafeNativeMethods.MOUSEINPUT mi = new SafeNativeMethods.MOUSEINPUT(); + case MouseButton.Left: + mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_LEFTUP; + break; + case MouseButton.Right: + mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_RIGHTUP; + break; + default: + throw new NotSupportedException(); + } - switch (button) - { - case MouseButton.Left: - mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_LEFTUP; - break; - case MouseButton.Right: - mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_RIGHTUP; - break; - default: - throw new NotSupportedException(); - } + SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT mkhInput = new SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT { mi = mi }; - SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT mkhInput = new SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT { mi = mi }; + SafeNativeMethods.INPUT input = new SafeNativeMethods.INPUT { type = SafeNativeMethods.INPUT_TYPE.MOUSE, mkhi = mkhInput }; - SafeNativeMethods.INPUT input = new SafeNativeMethods.INPUT { type = SafeNativeMethods.INPUT_TYPE.MOUSE, mkhi = mkhInput }; + SafeNativeMethods.SendInput(1, ref input, Marshal.SizeOf(input)); + } - SafeNativeMethods.SendInput(1, ref input, Marshal.SizeOf(input)); - } + /// + /// Send a mouse move signal. + /// Errors will not be handled. + /// + public static void SendMouseMoveRelative(int x, int y) + { + SafeNativeMethods.MOUSEINPUT mi = new SafeNativeMethods.MOUSEINPUT + { + dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_MOVE, + dx = x, + dy = y + }; - /// - /// Send a mouse move signal. - /// Errors will not be handled. - /// - public static void SendMouseMoveRelative(int x, int y) - { - SafeNativeMethods.MOUSEINPUT mi = new SafeNativeMethods.MOUSEINPUT - { - dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_MOVE, - dx = x, - dy = y - }; - - SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT mkhInput = new SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT - { - mi = mi - }; - - SafeNativeMethods.INPUT input = new SafeNativeMethods.INPUT - { - type = SafeNativeMethods.INPUT_TYPE.MOUSE, - mkhi = mkhInput - }; - - SafeNativeMethods.SendInput(1, ref input, Marshal.SizeOf(input)); - } + SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT mkhInput = new SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT + { + mi = mi + }; - public static void SetAsToolWindow([NotNull] this Window window) - { - IntPtr handle = new WindowInteropHelper(window).EnsureHandle(); - IntPtr oldFlags = SafeNativeMethods.GetWindowLongPtr(handle, GWL.GWL_EXSTYLE); - if (oldFlags != IntPtr.Zero) + SafeNativeMethods.INPUT input = new SafeNativeMethods.INPUT { - IntPtr newFlags = new IntPtr(oldFlags.ToInt64() | ExtendedWindowStyles.WS_EX_TOOLWINDOW); - SafeNativeMethods.SetWindowLongPtr(handle, GWL.GWL_EXSTYLE, newFlags); - } + type = SafeNativeMethods.INPUT_TYPE.MOUSE, + mkhi = mkhInput + }; + + SafeNativeMethods.SendInput(1, ref input, Marshal.SizeOf(input)); + } + + public static void SetAsToolWindow([NotNull] this Window window) + { + nint handle = new WindowInteropHelper(window).EnsureHandle(); + nint oldFlags = SafeNativeMethods.GetWindowLongPtr(handle, GWL.GWL_EXSTYLE); + if (oldFlags != nint.Zero) + { + nint newFlags = new nint(oldFlags.ToInt64() | ExtendedWindowStyles.WS_EX_TOOLWINDOW); + SafeNativeMethods.SetWindowLongPtr(handle, GWL.GWL_EXSTYLE, newFlags); } } } \ No newline at end of file diff --git a/Source/Launchbar/WindowBar.xaml.cs b/Source/Launchbar/WindowBar.xaml.cs index 011bd8e..ac19fb0 100644 --- a/Source/Launchbar/WindowBar.xaml.cs +++ b/Source/Launchbar/WindowBar.xaml.cs @@ -7,201 +7,200 @@ using Launchbar.Properties; using Launchbar.Win32; -namespace Launchbar +namespace Launchbar; + +public sealed partial class WindowBar : Window { - public sealed partial class WindowBar : Window - { - #region Fields + #region Fields - private static bool isContextMenuOpen; + private static bool isContextMenuOpen; - private bool canClose; + private bool canClose; - #endregion + #endregion - #region Properties + #region Properties - /// - /// Gets the side of the screen this window docks to. - /// - public Dock Dock - { - get { return this.GetValue(DockProperty); } - private init { this.SetValue(DockProperty, value); } - } + /// + /// Gets the side of the screen this window docks to. + /// + public Dock Dock + { + get { return this.GetValue(DockProperty); } + private init { this.SetValue(DockProperty, value); } + } - public static readonly DependencyProperty DockProperty = DependencyProperty.Register( - nameof(Dock), typeof(Dock), typeof(WindowBar)); + public static readonly DependencyProperty DockProperty = DependencyProperty.Register( + nameof(Dock), typeof(Dock), typeof(WindowBar)); - /// - /// Gets the working area (desktop without task bar). - /// - public Area WorkArea - { - get { return this.GetValue(WorkAreaProperty); } - private init { this.SetValue(WorkAreaProperty, value); } - } - - public static readonly DependencyProperty WorkAreaProperty = DependencyProperty.Register( - nameof(WorkArea), typeof(Area), typeof(WindowBar)); + /// + /// Gets the working area (desktop without task bar). + /// + public Area WorkArea + { + get { return this.GetValue(WorkAreaProperty); } + private init { this.SetValue(WorkAreaProperty, value); } + } - #endregion + public static readonly DependencyProperty WorkAreaProperty = DependencyProperty.Register( + nameof(WorkArea), typeof(Area), typeof(WindowBar)); - /// - /// This constructor is reserved for the WPF designer. - /// - public WindowBar() - { - this.InitializeComponent(); + #endregion - this.SetAsToolWindow(); - } + /// + /// This constructor is reserved for the WPF designer. + /// + public WindowBar() + { + this.InitializeComponent(); - /// - /// Create a new instance of this class. - /// - /// Side of the work area to dock to. - /// Area of the screen. - public WindowBar(Dock dock, Area area) : this() - { - this.Dock = dock; - this.WorkArea = area; - area.Updated += this.areaUpdated; - this.areaUpdated(null, null); - } + this.SetAsToolWindow(); + } - private void areaUpdated(object sender, EventArgs e) - { - Area area = this.WorkArea; + /// + /// Create a new instance of this class. + /// + /// Side of the work area to dock to. + /// Area of the screen. + public WindowBar(Dock dock, Area area) : this() + { + this.Dock = dock; + this.WorkArea = area; + area.Updated += this.areaUpdated; + this.areaUpdated(null, null); + } - switch (this.Dock) - { - case Dock.Left: - this.Left = area.Left - 1; - this.Top = area.Top + 1; - this.Width = 2; - this.Height = area.Height - 2; - break; - case Dock.Top: - this.Left = area.Left + 1; - this.Top = area.Top - 1; - this.Width = area.Width - 2; - this.Height = 2; - break; - case Dock.Right: - this.Left = area.Left + area.Width - 1; - this.Top = area.Top + 1; - this.Width = 2; - this.Height = area.Height - 2; - break; - case Dock.Bottom: - this.Left = area.Left + 1; - this.Top = area.Top + area.Height - 1; - this.Width = area.Width - 1; - this.Height = 2; - break; - } - } + private void areaUpdated(object sender, EventArgs e) + { + Area area = this.WorkArea; - /// - /// Save context menu state as the property is reset before . - /// - /// - protected override void OnContextMenuOpening(ContextMenuEventArgs e) + switch (this.Dock) { - isContextMenuOpen = true; - base.OnContextMenuOpening(e); + case Dock.Left: + this.Left = area.Left - 1; + this.Top = area.Top + 1; + this.Width = 2; + this.Height = area.Height - 2; + break; + case Dock.Top: + this.Left = area.Left + 1; + this.Top = area.Top - 1; + this.Width = area.Width - 2; + this.Height = 2; + break; + case Dock.Right: + this.Left = area.Left + area.Width - 1; + this.Top = area.Top + 1; + this.Width = 2; + this.Height = area.Height - 2; + break; + case Dock.Bottom: + this.Left = area.Left + 1; + this.Top = area.Top + area.Height - 1; + this.Width = area.Width - 1; + this.Height = 2; + break; } + } - /// - /// Reset context menu state. - /// - /// - protected override void OnContextMenuClosing(ContextMenuEventArgs e) - { - isContextMenuOpen = false; - base.OnContextMenuClosing(e); - } + /// + /// Save context menu state as the property is reset before . + /// + /// + protected override void OnContextMenuOpening(ContextMenuEventArgs e) + { + isContextMenuOpen = true; + base.OnContextMenuOpening(e); + } - /// - /// Handle mouse clicks when the context menu is open. - /// - /// - protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) + /// + /// Reset context menu state. + /// + /// + protected override void OnContextMenuClosing(ContextMenuEventArgs e) + { + isContextMenuOpen = false; + base.OnContextMenuClosing(e); + } + + /// + /// Handle mouse clicks when the context menu is open. + /// + /// + protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) + { + if (isContextMenuOpen) { - if (isContextMenuOpen) - { - e.Handled = true; + e.Handled = true; - if (Settings.Default.QuickLaunch) + if (Settings.Default.QuickLaunch) + { + Menu menu = Settings.Default.Menu; + if (menu?.Entries is { Count: > 0 } menuEntries) { - Menu menu = Settings.Default.Menu; - if (menu?.Entries is { Count: > 0 } menuEntries) + if (menuEntries[0] is Program p) { - if (menuEntries[0] is Program p) - { - p.TryRun(); - } + p.TryRun(); } } } } + } - /// - /// Catch left mouse button and send it to the underlying window. - /// - /// - protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) + /// + /// Catch left mouse button and send it to the underlying window. + /// + /// + protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) + { + WinHelper.SendMouseButtonUp(MouseButton.Left); + switch (this.Dock) { - WinHelper.SendMouseButtonUp(MouseButton.Left); - switch (this.Dock) - { - case Dock.Left: - WinHelper.SendMouseMoveRelative(1, 0); - break; - case Dock.Top: - WinHelper.SendMouseMoveRelative(0, 1); - break; - case Dock.Right: - WinHelper.SendMouseMoveRelative(-1, 0); - break; - case Dock.Bottom: - WinHelper.SendMouseMoveRelative(0, -1); - break; - } - WinHelper.SendMouseButtonDown(MouseButton.Left); + case Dock.Left: + WinHelper.SendMouseMoveRelative(1, 0); + break; + case Dock.Top: + WinHelper.SendMouseMoveRelative(0, 1); + break; + case Dock.Right: + WinHelper.SendMouseMoveRelative(-1, 0); + break; + case Dock.Bottom: + WinHelper.SendMouseMoveRelative(0, -1); + break; } + WinHelper.SendMouseButtonDown(MouseButton.Left); + } - /// - /// Takes over the ownership of the context menu. - /// - /// - protected override void OnMouseRightButtonDown(MouseButtonEventArgs e) - { - this.ContextMenu ??= App.RequestContextMenu(); - base.OnMouseRightButtonDown(e); - } + /// + /// Takes over the ownership of the context menu. + /// + /// + protected override void OnMouseRightButtonDown(MouseButtonEventArgs e) + { + this.ContextMenu ??= App.RequestContextMenu(); + base.OnMouseRightButtonDown(e); + } - /// - /// Prevent this object from closing unless the method has been called. - /// - /// - protected override void OnClosing(CancelEventArgs e) + /// + /// Prevent this object from closing unless the method has been called. + /// + /// + protected override void OnClosing(CancelEventArgs e) + { + if (!this.canClose) { - if (!this.canClose) - { - e.Cancel = true; - } - base.OnClosing(e); + e.Cancel = true; } + base.OnClosing(e); + } - /// - /// Close this window. - /// - public new void Close() - { - this.canClose = true; - base.Close(); - } + /// + /// Close this window. + /// + public new void Close() + { + this.canClose = true; + base.Close(); } } \ No newline at end of file diff --git a/Source/Launchbar/WindowSettings.xaml.cs b/Source/Launchbar/WindowSettings.xaml.cs index 7627d34..5ba1bcd 100644 --- a/Source/Launchbar/WindowSettings.xaml.cs +++ b/Source/Launchbar/WindowSettings.xaml.cs @@ -10,343 +10,342 @@ using Launchbar.Properties; using Microsoft.Win32; -namespace Launchbar +namespace Launchbar; + +internal sealed partial class WindowSettings : Window { - internal sealed partial class WindowSettings : Window + #region Properties + + /// + /// Gets the currently selected . + /// + public MenuEntry SelectedMenuEntry { - #region Properties + get { return this.GetValue(SelectedMenuEntryProperty); } + set { this.SetValue(SelectedMenuEntryProperty, value); } + } - /// - /// Gets the currently selected . - /// - public MenuEntry SelectedMenuEntry - { - get { return this.GetValue(SelectedMenuEntryProperty); } - set { this.SetValue(SelectedMenuEntryProperty, value); } - } + /// + /// Identifies the property. + /// + public static readonly DependencyProperty SelectedMenuEntryProperty = DependencyProperty.Register( + nameof(SelectedMenuEntry), typeof(MenuEntry), typeof(WindowSettings)); - /// - /// Identifies the property. - /// - public static readonly DependencyProperty SelectedMenuEntryProperty = DependencyProperty.Register( - nameof(SelectedMenuEntry), typeof(MenuEntry), typeof(WindowSettings)); + /// + /// Gets whether the currently selected item is of type . + /// + public bool IsProgram + { + get { return this.GetValue(IsProgramProperty); } + private set { this.SetValueBox(IsProgramProperty, value); } + } - /// - /// Gets whether the currently selected item is of type . - /// - public bool IsProgram - { - get { return this.GetValue(IsProgramProperty); } - private set { this.SetValueBox(IsProgramProperty, value); } - } + /// + /// Identifies the property. + /// + public static readonly DependencyProperty IsProgramProperty = DependencyProperty.Register( + nameof(IsProgram), typeof(bool), typeof(WindowSettings)); - /// - /// Identifies the property. - /// - public static readonly DependencyProperty IsProgramProperty = DependencyProperty.Register( - nameof(IsProgram), typeof(bool), typeof(WindowSettings)); + /// + /// Gets the currently selected object. + /// + public Program SelectedProgram + { + get { return this.GetValue(SelectedProgramProperty); } + private set { this.SetValue(SelectedProgramProperty, value); } + } - /// - /// Gets the currently selected object. - /// - public Program SelectedProgram - { - get { return this.GetValue(SelectedProgramProperty); } - private set { this.SetValue(SelectedProgramProperty, value); } - } + /// + /// Identifies the property. + /// + public static readonly DependencyProperty SelectedProgramProperty = DependencyProperty.Register( + nameof(SelectedProgram), typeof(Program), typeof(WindowSettings)); - /// - /// Identifies the property. - /// - public static readonly DependencyProperty SelectedProgramProperty = DependencyProperty.Register( - nameof(SelectedProgram), typeof(Program), typeof(WindowSettings)); + /// + /// Gets whether the currently selected item is of type . + /// + public bool IsMenuEntryAdvanced + { + get { return this.GetValue(IsMenuEntryAdvancedProperty); } + private set { this.SetValueBox(IsMenuEntryAdvancedProperty, value); } + } - /// - /// Gets whether the currently selected item is of type . - /// - public bool IsMenuEntryAdvanced - { - get { return this.GetValue(IsMenuEntryAdvancedProperty); } - private set { this.SetValueBox(IsMenuEntryAdvancedProperty, value); } - } + /// + /// Identifies the property. + /// + public static readonly DependencyProperty IsMenuEntryAdvancedProperty = DependencyProperty.Register( + nameof(IsMenuEntryAdvanced), typeof(bool), typeof(WindowSettings)); - /// - /// Identifies the property. - /// - public static readonly DependencyProperty IsMenuEntryAdvancedProperty = DependencyProperty.Register( - nameof(IsMenuEntryAdvanced), typeof(bool), typeof(WindowSettings)); + /// + /// Gets the currently selected object. + /// + public MenuEntryAdvanced SelectedMenuEntryAdvanced + { + get { return this.GetValue(SelectedMenuEntryAdvancedProperty); } + private set { this.SetValue(SelectedMenuEntryAdvancedProperty, value); } + } - /// - /// Gets the currently selected object. - /// - public MenuEntryAdvanced SelectedMenuEntryAdvanced - { - get { return this.GetValue(SelectedMenuEntryAdvancedProperty); } - private set { this.SetValue(SelectedMenuEntryAdvancedProperty, value); } - } + /// + /// Identifies the property. + /// + public static readonly DependencyProperty SelectedMenuEntryAdvancedProperty = DependencyProperty.Register( + nameof(SelectedMenuEntryAdvanced), typeof(MenuEntryAdvanced), typeof(WindowSettings)); - /// - /// Identifies the property. - /// - public static readonly DependencyProperty SelectedMenuEntryAdvancedProperty = DependencyProperty.Register( - nameof(SelectedMenuEntryAdvanced), typeof(MenuEntryAdvanced), typeof(WindowSettings)); + #endregion - #endregion + public WindowSettings() + { + this.InitializeComponent(); + } - public WindowSettings() - { - this.InitializeComponent(); - } + private void treeViewEntriesSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) + { + object newValue = e.NewValue; - private void treeViewEntriesSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) - { - object newValue = e.NewValue; + this.SelectedMenuEntry = newValue as MenuEntry; - this.SelectedMenuEntry = newValue as MenuEntry; + MenuEntryAdvanced mea = newValue as MenuEntryAdvanced; + Program program = newValue as Program; - MenuEntryAdvanced mea = newValue as MenuEntryAdvanced; - Program program = newValue as Program; + this.SelectedMenuEntryAdvanced = mea; + this.IsMenuEntryAdvanced = mea != null; + this.SelectedProgram = program; + this.IsProgram = program != null; + } - this.SelectedMenuEntryAdvanced = mea; - this.IsMenuEntryAdvanced = mea != null; - this.SelectedProgram = program; - this.IsProgram = program != null; - } + private void requestNavigateHyperlink([CanBeNull] object sender, [NotNull] RequestNavigateEventArgs e) + { + requestNavigate(e); + } - private void requestNavigateHyperlink([CanBeNull] object sender, [NotNull] RequestNavigateEventArgs e) - { - requestNavigate(e); - } + private void requestNavigateCommand([CanBeNull] object sender, [NotNull] ExecutedRoutedEventArgs e) + { + requestNavigate(e); + } - private void requestNavigateCommand([CanBeNull] object sender, [NotNull] ExecutedRoutedEventArgs e) + private static void requestNavigate([NotNull] RoutedEventArgs e) + { + string uri = null; + switch (e) { - requestNavigate(e); + case RequestNavigateEventArgs en: + uri = en.Uri.ToString(); + break; + case ExecutedRoutedEventArgs er: + switch (er.Parameter) + { + case Uri u: + uri = u.ToString(); + break; + case string s: + uri = s; + break; + } + break; + default: + if (e.OriginalSource is Hyperlink hyperlink && + hyperlink.NavigateUri is Uri navUri) + { + uri = navUri.ToString(); + } + break; } - - private static void requestNavigate([NotNull] RoutedEventArgs e) + if (string.IsNullOrEmpty(uri)) { - string uri = null; - switch (e) - { - case RequestNavigateEventArgs en: - uri = en.Uri.ToString(); - break; - case ExecutedRoutedEventArgs er: - switch (er.Parameter) - { - case Uri u: - uri = u.ToString(); - break; - case string s: - uri = s; - break; - } - break; - default: - if (e.OriginalSource is Hyperlink hyperlink && - hyperlink.NavigateUri is Uri navUri) - { - uri = navUri.ToString(); - } - break; - } - if (string.IsNullOrEmpty(uri)) - { - return; - } - try - { - Process.Start(new ProcessStartInfo(uri) { UseShellExecute = true }); - e.Handled = true; - } - catch - { - // We do not care if this crashes - } + return; } - - #region Buttons - - private void buttonOkClick(object sender, RoutedEventArgs e) + try { - this.buttonApplyClick(null, null); - this.Close(); + Process.Start(new ProcessStartInfo(uri) { UseShellExecute = true }); + e.Handled = true; } - - private void buttonCancelClick(object sender, RoutedEventArgs e) + catch { - Settings.Default.Reload(); - this.Close(); + // We do not care if this crashes } + } - private void buttonApplyClick(object sender, RoutedEventArgs e) - { - // Read the Menu property to force a settings file update on save. - if (Settings.Default.Menu == null) { } + #region Buttons - Settings.Default.Save(); - } + private void buttonOkClick(object sender, RoutedEventArgs e) + { + this.buttonApplyClick(null, null); + this.Close(); + } - private void buttonShutdownClick(object sender, RoutedEventArgs e) - { - Application.Current.Shutdown(); - } + private void buttonCancelClick(object sender, RoutedEventArgs e) + { + Settings.Default.Reload(); + this.Close(); + } - #endregion + private void buttonApplyClick(object sender, RoutedEventArgs e) + { + // Read the Menu property to force a settings file update on save. + if (Settings.Default.Menu == null) { } - #region Menu modification methods + Settings.Default.Save(); + } - private void buttonMoveUpClick(object sender, RoutedEventArgs e) - { - this.SelectedMenuEntry.MoveUp(); - } + private void buttonShutdownClick(object sender, RoutedEventArgs e) + { + Application.Current.Shutdown(); + } - private void buttonMoveDownClick(object sender, RoutedEventArgs e) - { - this.SelectedMenuEntry.MoveDown(); - } + #endregion - private void buttonAddProgramClick(object sender, RoutedEventArgs e) - { - this.addMenuEntry(new Program()); - this.selectTextTextBox(); - } + #region Menu modification methods - private void buttonAddSubmenuClick(object sender, RoutedEventArgs e) - { - this.addMenuEntry(new Submenu()); - this.selectTextTextBox(); - } + private void buttonMoveUpClick(object sender, RoutedEventArgs e) + { + this.SelectedMenuEntry.MoveUp(); + } - private void buttonAddSeparatorClick(object sender, RoutedEventArgs e) - { - this.addMenuEntry(new Separator()); - } + private void buttonMoveDownClick(object sender, RoutedEventArgs e) + { + this.SelectedMenuEntry.MoveDown(); + } - private void buttonAddSettingsClick(object sender, RoutedEventArgs e) - { - this.addMenuEntry(new MenuEntrySettings()); - } + private void buttonAddProgramClick(object sender, RoutedEventArgs e) + { + this.addMenuEntry(new Program()); + this.selectTextTextBox(); + } - private void buttonAddExitClick(object sender, RoutedEventArgs e) - { - this.addMenuEntry(new MenuEntryExit()); - } + private void buttonAddSubmenuClick(object sender, RoutedEventArgs e) + { + this.addMenuEntry(new Submenu()); + this.selectTextTextBox(); + } + + private void buttonAddSeparatorClick(object sender, RoutedEventArgs e) + { + this.addMenuEntry(new Separator()); + } - private void addMenuEntry(MenuEntry newEntry) + private void buttonAddSettingsClick(object sender, RoutedEventArgs e) + { + this.addMenuEntry(new MenuEntrySettings()); + } + + private void buttonAddExitClick(object sender, RoutedEventArgs e) + { + this.addMenuEntry(new MenuEntryExit()); + } + + private void addMenuEntry(MenuEntry newEntry) + { + MenuEntry selected = this.SelectedMenuEntry; + if (selected != null) { - MenuEntry selected = this.SelectedMenuEntry; - if (selected != null) + if (selected is Submenu submenu) { - if (selected is Submenu submenu) - { - if (submenu.MenuEntries == null) - { - submenu.MenuEntries = new MenuEntryCollection(); - } - submenu.MenuEntries.Add(newEntry); - } - else + if (submenu.MenuEntries == null) { - selected.Parent.Insert(selected.Parent.IndexOf(selected) + 1, newEntry); + submenu.MenuEntries = new MenuEntryCollection(); } + submenu.MenuEntries.Add(newEntry); } else { - Settings.Default.Menu.Entries.Add(newEntry); + selected.Parent.Insert(selected.Parent.IndexOf(selected) + 1, newEntry); } } - - private void buttonDeleteClick(object sender, RoutedEventArgs e) + else { - if (this.SelectedMenuEntry != null) - { - this.SelectedMenuEntry.Parent.Remove(this.SelectedMenuEntry); - } + Settings.Default.Menu.Entries.Add(newEntry); } + } - private void selectTextTextBox() + private void buttonDeleteClick(object sender, RoutedEventArgs e) + { + if (this.SelectedMenuEntry != null) { - this.textBoxName.SelectAll(); - this.textBoxName.Focus(); + this.SelectedMenuEntry.Parent.Remove(this.SelectedMenuEntry); } + } - #endregion + private void selectTextTextBox() + { + this.textBoxName.SelectAll(); + this.textBoxName.Focus(); + } - #region Menu entry modification methods + #endregion - private void buttonChooseIconClick(object sender, RoutedEventArgs e) + #region Menu entry modification methods + + private void buttonChooseIconClick(object sender, RoutedEventArgs e) + { + this.SelectedMenuEntryAdvanced.ChooseIcon(); + } + + private void buttonClearIconClick(object sender, RoutedEventArgs e) + { + this.SelectedMenuEntryAdvanced.ClearIcon(); + } + + #endregion + + private void buttonBrowseClick(object sender, RoutedEventArgs e) + { + if (this.SelectedProgram == null) { - this.SelectedMenuEntryAdvanced.ChooseIcon(); + return; // Not possible. } - private void buttonClearIconClick(object sender, RoutedEventArgs e) + OpenFileDialog ofd = new OpenFileDialog + { + Filter = @"Executables (*.exe)|*.exe|All files (*.*)|*.*", + FilterIndex = 1, + // Text to be displayed in the file textbox. + FileName = "Use this directory.", + // Do not check for valid filename because we also want to accept directories. + CheckFileExists = false + }; + + if (ofd.ShowDialog() != true) { - this.SelectedMenuEntryAdvanced.ClearIcon(); + return; // Do nothing because the user canceled the dialog. } - #endregion - - private void buttonBrowseClick(object sender, RoutedEventArgs e) - { - if (this.SelectedProgram == null) - { - return; // Not possible. - } + this.SelectedProgram.Path = ofd.FileName; + } - OpenFileDialog ofd = new OpenFileDialog - { - Filter = @"Executables (*.exe)|*.exe|All files (*.*)|*.*", - FilterIndex = 1, - // Text to be displayed in the file textbox. - FileName = "Use this directory.", - // Do not check for valid filename because we also want to accept directories. - CheckFileExists = false - }; - - if (ofd.ShowDialog() != true) - { - return; // Do nothing because the user canceled the dialog. - } + private void treeViewDrop(object sender, DragEventArgs e) + { + string[] files = e.Data.GetData(DataFormats.FileDrop) as string[]; - this.SelectedProgram.Path = ofd.FileName; + if (files == null || files.Length == 0) + { + return; // Nothing to add; } - private void treeViewDrop(object sender, DragEventArgs e) + MenuEntry selected = this.SelectedMenuEntry; + MenuEntryCollection parent; + if (selected == null) { - string[] files = e.Data.GetData(DataFormats.FileDrop) as string[]; - - if (files == null || files.Length == 0) - { - return; // Nothing to add; - } - - MenuEntry selected = this.SelectedMenuEntry; - MenuEntryCollection parent; - if (selected == null) + parent = Settings.Default.Menu.Entries; + } + else + { + Submenu submenu = selected as Submenu; + if (submenu == null) { - parent = Settings.Default.Menu.Entries; + parent = selected.Parent; } else { - Submenu submenu = selected as Submenu; - if (submenu == null) - { - parent = selected.Parent; - } - else - { - parent = submenu.MenuEntries; - } - } - foreach (string file in files) - { - parent.Add(new Program - { - Text = Path.GetFileNameWithoutExtension(file), - Path = file - }); + parent = submenu.MenuEntries; } } + foreach (string file in files) + { + parent.Add(new Program + { + Text = Path.GetFileNameWithoutExtension(file), + Path = file + }); + } } } \ No newline at end of file From b7124fd965497f8e153c9da58982d7a0834590ca Mon Sep 17 00:00:00 2001 From: Mertsch Date: Sun, 1 Jan 2023 19:24:46 +0100 Subject: [PATCH 02/18] Build on branches and update pipeline --- .github/workflows/dotnet.yml | 15 ++++++++------- Source/Launchbar.sln | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index ff6496c..945d349 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -2,21 +2,22 @@ name: Build Launchbar on: push: - branches: [ main ] + branches: + - '*' pull_request: - branches: [ main ] + branches: + - '*' jobs: build: - runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: - dotnet-version: 6.x + dotnet-version: 7.x - name: Restore dependencies run: dotnet restore Source/Launchbar.sln - name: Build @@ -26,7 +27,7 @@ jobs: - name: Publish run: dotnet publish Source/Launchbar.sln --no-build --configuration Release - name: Upload - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: Launchbar path: Source/Launchbar/bin/Release/publish/** diff --git a/Source/Launchbar.sln b/Source/Launchbar.sln index a75d6c1..6321d5a 100644 --- a/Source/Launchbar.sln +++ b/Source/Launchbar.sln @@ -8,6 +8,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2EDD5948-9BFA-47F7-AC71-5E19EF7522D0}" ProjectSection(SolutionItems) = preProject ..\CHANGELOG.md = ..\CHANGELOG.md + ..\.github\workflows\dotnet.yml = ..\.github\workflows\dotnet.yml EndProjectSection EndProject Global From c2c7a8a644b0a60d5158b7c74f32e54dc282e7e2 Mon Sep 17 00:00:00 2001 From: Mertsch Date: Sun, 1 Jan 2023 19:34:49 +0100 Subject: [PATCH 03/18] Update version number --- Source/Launchbar/Launchbar.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Launchbar/Launchbar.csproj b/Source/Launchbar/Launchbar.csproj index 866ccf7..63c84f5 100644 --- a/Source/Launchbar/Launchbar.csproj +++ b/Source/Launchbar/Launchbar.csproj @@ -7,7 +7,7 @@ false Resources\Next.ico - 5.1.0-preview.1 + 5.1.0 Launchbar RunIT to the next level. Copyright © Mertsch $([System.DateTime]::UtcNow.Year) From 90ff637651d33d8b639d3bc8d54def1802f63b70 Mon Sep 17 00:00:00 2001 From: Mertsch Date: Tue, 13 Feb 2024 22:52:00 +0100 Subject: [PATCH 04/18] .NET 8 Upgrade --- .editorconfig | 130 ++++++++++++++++++ CHANGELOG.md | 5 +- Source/Common.props | 31 +++++ Source/Directory.Build.props | 25 ++++ Source/Launchbar.sln | 3 + Source/Launchbar/App.xaml | 6 +- Source/Launchbar/App.xaml.cs | 52 ++++--- Source/Launchbar/Area.cs | 2 - Source/Launchbar/Design.cs | 11 ++ Source/Launchbar/ElementCreator.cs | 10 +- Source/Launchbar/Launchbar.csproj | 16 ++- Source/Launchbar/Menu.cs | 24 ++-- Source/Launchbar/MenuEntry.cs | 8 +- Source/Launchbar/MenuEntryAdvanced.cs | 18 +-- Source/Launchbar/MenuEntryCollection.cs | 24 ++-- Source/Launchbar/MenuEntryExit.cs | 7 +- Source/Launchbar/MenuEntrySettings.cs | 9 +- Source/Launchbar/MenuItemExtensions.cs | 5 +- Source/Launchbar/MenuItemStyleSelector.cs | 22 ++- Source/Launchbar/MetaData.cs | 6 +- Source/Launchbar/NotifyBase.cs | 7 +- Source/Launchbar/Program.cs | 28 ++-- Source/Launchbar/Resources/Aero.Extended.xaml | 9 +- Source/Launchbar/Resources/Images.xaml | 128 +++++++++-------- Source/Launchbar/Shapes/ShapeClose.xaml.cs | 15 +- Source/Launchbar/Shapes/ShapeFolder.xaml.cs | 15 +- Source/Launchbar/Submenu.cs | 12 +- .../Launchbar/Win32/ExtendedWindowStyles.cs | 8 +- Source/Launchbar/Win32/GWL.cs | 6 +- Source/Launchbar/Win32/SafeNativeMethods.cs | 41 +++--- Source/Launchbar/Win32/WinHelper.cs | 57 ++++---- Source/Launchbar/WindowBar.xaml.cs | 11 +- Source/Launchbar/WindowSettings.xaml | 31 +++-- Source/Launchbar/WindowSettings.xaml.cs | 117 +++++++--------- 34 files changed, 519 insertions(+), 380 deletions(-) create mode 100644 .editorconfig create mode 100644 Source/Common.props create mode 100644 Source/Directory.Build.props create mode 100644 Source/Launchbar/Design.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..79c5cd1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,130 @@ +[*.cs] +# IDE0028: Simplify collection initialization +dotnet_diagnostic.IDE0028.severity = silent +# IDE0037: Use inferred member name +dotnet_diagnostic.IDE0037.severity = none +# IDE0063: Use simple 'using' statement +csharp_prefer_simple_using_statement = true:none +# IDE0090: Use 'new(...)' +dotnet_diagnostic.IDE0090.severity = silent + +# CA1024: Use properties where appropriate +dotnet_diagnostic.CA1024.severity = none +# CA1062: Validate arguments of public methods +dotnet_diagnostic.CA1062.severity = silent +# CA1304: Specify CultureInfo +dotnet_diagnostic.CA1304.severity = none +# CA1305: Specify IFormatProvider +dotnet_diagnostic.CA1305.severity = none +# CA1309: Use ordinal string comparison +dotnet_diagnostic.CA1309.severity = none +# CA1507: Use nameof to express symbol names +dotnet_diagnostic.CA1507.severity = suggestion +# CA1716: Identifiers should not match keywords +dotnet_diagnostic.CA1716.severity = none +# CA1720: Identifier contains type name +dotnet_diagnostic.CA1720.severity = none +# CA1725: Parameter names should match base declaration +dotnet_diagnostic.CA1725.severity = silent +# CA1806: Do not ignore method results +dotnet_diagnostic.CA1806.severity = silent +# CA1815: Override equals and operator equals on value types +dotnet_diagnostic.CA1815.severity = silent +# CA1819: Properties should not return arrays +dotnet_diagnostic.CA1819.severity = none +# CA1822: Mark members as static +dotnet_diagnostic.CA1822.severity = silent +# CA1847: Use char literal for a single character lookup +dotnet_diagnostic.CA1847.severity = warning +# CA1848: Use the LoggerMessage delegates +dotnet_diagnostic.CA1848.severity = silent +# CA2007: Consider calling ConfigureAwait on the awaited task +dotnet_diagnostic.CA2007.severity = none +# CA2201: Do not raise reserved exception types +dotnet_diagnostic.CA2201.severity = error +# CA2234: Pass system uri objects instead of strings +dotnet_diagnostic.CA2234.severity = none + +# CS8602: Dereference of a possibly null reference. +dotnet_diagnostic.CS8602.severity = error + +[*.{cs,vb}] +dotnet_style_qualification_for_field=true:silent +dotnet_style_qualification_for_property=true:silent +dotnet_style_qualification_for_method=true:silent +dotnet_style_qualification_for_event=true:silent + +# ■■■ Naming rules ■■■ + +# Dependency Property backend field - public static readonly DependencyProperty MyProperty = DependencyProperty.Register(...) +dotnet_naming_rule.PublicStaticReadonlyField.severity = warning +dotnet_naming_rule.PublicStaticReadonlyField.symbols = public_static_readonly_field +dotnet_naming_rule.PublicStaticReadonlyField.style = PascalCaseProperty +# Public static readonly field (Default) - public static readonly TypeOfField MyFieldName = ... +dotnet_naming_rule.PublicStaticReadonlyField.severity = warning +dotnet_naming_rule.PublicStaticReadonlyField.symbols = public_static_readonly_field +dotnet_naming_rule.PublicStaticReadonlyField.style = PascalCase + +# Dependency Property backend field - private static readonly DependencyPropertyKey MyPropertyKey = DependencyProperty.RegisterReadOnly(...) +dotnet_naming_rule.PrivateStaticReadonlyField.severity = warning # Should be warning +dotnet_naming_rule.PrivateStaticReadonlyField.symbols = private_static_readonly_field +dotnet_naming_rule.PrivateStaticReadonlyField.style = PascalCasePropertyKey +# Private static readonly field (Default) - private static readonly TypeOfField myFieldName = ... +dotnet_naming_rule.PrivateStaticReadonlyField.severity = information # Should be warning +dotnet_naming_rule.PrivateStaticReadonlyField.symbols = private_static_readonly_field +dotnet_naming_rule.PrivateStaticReadonlyField.style = CamelCase + +dotnet_naming_rule.InstanceField.severity = suggestion +dotnet_naming_rule.InstanceField.symbols = instance_fields +dotnet_naming_rule.InstanceField.style = CamelCase + +dotnet_naming_rule.ConstantField.severity = suggestion +dotnet_naming_rule.ConstantField.symbols = const_fields +dotnet_naming_rule.ConstantField.style = PascalCase + +# ■■■ Symbol specifications ■■■ + +dotnet_naming_symbols.instance_fields.applicable_kinds = field + +dotnet_naming_symbols.const_fields.applicable_kinds = field +dotnet_naming_symbols.const_fields.required_modifiers = const + +dotnet_naming_symbols.public_field.applicable_kinds = field +dotnet_naming_symbols.public_field.applicable_accessibilities = public + +dotnet_naming_symbols.private_static_readonly_field.applicable_kinds = field +dotnet_naming_symbols.private_static_readonly_field.applicable_accessibilities = private +dotnet_naming_symbols.private_static_readonly_field.required_modifiers = readonly, static + +dotnet_naming_symbols.public_static_readonly_field.applicable_kinds = field +dotnet_naming_symbols.public_static_readonly_field.applicable_accessibilities = public +dotnet_naming_symbols.public_static_readonly_field.required_modifiers = readonly, static + +# ■■■ Naming styles ■■■ + +dotnet_naming_style.PascalCase.required_prefix = +dotnet_naming_style.PascalCase.required_suffix = +dotnet_naming_style.PascalCase.word_separator = +dotnet_naming_style.PascalCase.capitalization = pascal_case + +dotnet_naming_style.CamelCase.required_prefix = +dotnet_naming_style.CamelCase.required_suffix = +dotnet_naming_style.CamelCase.word_separator = +dotnet_naming_style.CamelCase.capitalization = camel_case + +dotnet_naming_style.IPascalCase.required_prefix = I +dotnet_naming_style.IPascalCase.required_suffix = +dotnet_naming_style.IPascalCase.word_separator = +dotnet_naming_style.IPascalCase.capitalization = pascal_case + +dotnet_naming_style.PascalCaseProperty.required_suffix = Property +dotnet_naming_style.PascalCaseProperty.capitalization = pascal_case + +dotnet_naming_style.PascalCasePropertyKey.required_suffix = PropertyKey +dotnet_naming_style.PascalCasePropertyKey.capitalization = pascal_case + +[*.resx] +resx_formatter_sort_entries=true +resx_formatter_remove_xsd_schema=false +resx_formatter_remove_documentation_comment=true +resx_formatter_sort_comparer=OrdinalIgnoreCase \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 04b8cb3..11225e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,12 @@ # Changelog All notable changes to this project will be documented in this file. - The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [5.2.0] - 2022-02-13 +### Changed +- Upgrade to .NET 8.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/8.0/runtime) to run + ## [5.1.0] - 2023-01-01 ### Changed - Upgrade to .NET 7.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/7.0/runtime) to run diff --git a/Source/Common.props b/Source/Common.props new file mode 100644 index 0000000..f7e1e90 --- /dev/null +++ b/Source/Common.props @@ -0,0 +1,31 @@ + + + + + false + false + + + + + + + + + + + + + embedded + + + + + true + + + + + + + \ No newline at end of file diff --git a/Source/Directory.Build.props b/Source/Directory.Build.props new file mode 100644 index 0000000..9aad919 --- /dev/null +++ b/Source/Directory.Build.props @@ -0,0 +1,25 @@ + + + + 12.0 + + latest-recommended + + enable + + en + + true + true + + + + + true + true + + + + $(DefaultItemExcludes);**\*.DotSettings + + \ No newline at end of file diff --git a/Source/Launchbar.sln b/Source/Launchbar.sln index 6321d5a..2f5b708 100644 --- a/Source/Launchbar.sln +++ b/Source/Launchbar.sln @@ -7,7 +7,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Launchbar", "Launchbar\Laun EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2EDD5948-9BFA-47F7-AC71-5E19EF7522D0}" ProjectSection(SolutionItems) = preProject + ..\.editorconfig = ..\.editorconfig ..\CHANGELOG.md = ..\CHANGELOG.md + Common.props = Common.props + Directory.Build.props = Directory.Build.props ..\.github\workflows\dotnet.yml = ..\.github\workflows\dotnet.yml EndProjectSection EndProject diff --git a/Source/Launchbar/App.xaml b/Source/Launchbar/App.xaml index 1b29a87..e453ec0 100644 --- a/Source/Launchbar/App.xaml +++ b/Source/Launchbar/App.xaml @@ -38,16 +38,16 @@ - + diff --git a/Source/Launchbar/App.xaml.cs b/Source/Launchbar/App.xaml.cs index 0a86f27..ecc7c94 100644 --- a/Source/Launchbar/App.xaml.cs +++ b/Source/Launchbar/App.xaml.cs @@ -1,13 +1,11 @@ -using System; +using Launchbar.Properties; +using Microsoft.Win32; using System.Collections.Immutable; using System.ComponentModel; using System.Security; -using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Input; -using Launchbar.Properties; -using Microsoft.Win32; using WpfScreenHelper; namespace Launchbar; @@ -15,7 +13,7 @@ namespace Launchbar; /// /// Interaction logic for App.xaml /// -public partial class App : Application +public sealed partial class App : Application { #if DEBUG private const string MutexName = @"Global\LaunchbarSingleInstanceMutex(Debug)"; @@ -25,29 +23,29 @@ public partial class App : Application #region Fields - private static SplashScreen splashScreen; + private static SplashScreen? splashScreen; // ReSharper disable NotAccessedField.Local #pragma warning disable IDE0052 // Remove unread private members - We need to keep the mutex alive during the lifetime of the app. - private static Mutex instanceMutex; + private readonly Mutex instanceMutex; #pragma warning restore IDE0052 // Remove unread private members // ReSharper restore NotAccessedField.Local - private WindowBar barLeft; + private WindowBar? barLeft; - private WindowBar barTop; + private WindowBar? barTop; - private WindowBar barRight; + private WindowBar? barRight; - private WindowBar barBottom; + private WindowBar? barBottom; - private WindowBar barLeftSecondary; + private WindowBar? barLeftSecondary; - private WindowBar barTopSecondary; + private WindowBar? barTopSecondary; - private WindowBar barRightSecondary; + private WindowBar? barRightSecondary; - private WindowBar barBottomSecondary; + private WindowBar? barBottomSecondary; private readonly Area primaryArea = new Area(); @@ -74,7 +72,7 @@ public App() #region Make sure that only one instance of the application is running at any given time. - instanceMutex = new Mutex(false, MutexName, out bool instantiated); + this.instanceMutex = new Mutex(false, MutexName, out bool instantiated); if (!instantiated) { MessageBox.Show(Launchbar.Properties.Resources.SingleInstanceWarning, @@ -82,7 +80,7 @@ public App() MessageBoxImage.Information); try { - splashScreen.Close(TimeSpan.Zero); + splashScreen?.Close(TimeSpan.Zero); } catch (Win32Exception) { } this.Shutdown(); @@ -106,22 +104,20 @@ public App() SystemEvents.DisplaySettingsChanged += this.displaySettingsChanged; } catch (SecurityException) { } - this.displaySettingsChanged(null, null); // Do primary initialization. + this.displaySettingsChanged(null, EventArgs.Empty); // Do primary initialization. setting.PropertyChanged += this.settingsPropertyChanged; - // ReSharper disable PossibleNullReferenceException - this.contextMenu = (ContextMenu)this.FindResource("contextMenuTemplate"); - // ReSharper restore PossibleNullReferenceException + this.contextMenu = this.FindResource("contextMenuTemplate") as ContextMenu ?? throw new InvalidOperationException("Missing 'contextMenuTemplate'."); this.forceContextMenuLayout(); try { - splashScreen.Close(new TimeSpan(TimeSpan.TicksPerSecond)); + splashScreen?.Close(new TimeSpan(TimeSpan.TicksPerSecond)); } catch (Win32Exception) { - splashScreen.Close(TimeSpan.Zero); + splashScreen?.Close(TimeSpan.Zero); } finally { @@ -153,7 +149,7 @@ private void contextMenuClosed(object sender, RoutedEventArgs e) #endregion - private void settingsPropertyChanged(object sender, PropertyChangedEventArgs e) + private void settingsPropertyChanged(object? sender, PropertyChangedEventArgs e) { switch (e.PropertyName) { @@ -188,7 +184,7 @@ private void settingsPropertyChanged(object sender, PropertyChangedEventArgs e) } } - private void displaySettingsChanged(object sender, EventArgs e) + private void displaySettingsChanged(object? sender, EventArgs e) { ImmutableArray screens = Screen.AllScreens.ToImmutableArray(); int count = screens.Length; @@ -242,14 +238,14 @@ private void displaySettingsChanged(object sender, EventArgs e) } } - private static void openOrCloseBar(Dock dock, bool open, Area area, ref WindowBar windowBar) + private static void openOrCloseBar(Dock dock, bool open, Area? area, ref WindowBar? windowBar) { - if (windowBar == null && open && area != null && area.IsActive) + if (windowBar is null && open && area is { IsActive: true }) { windowBar = new WindowBar(dock, area); windowBar.Show(); } - else if (windowBar != null && !open) + else if (windowBar is { } && !open) { windowBar.Close(); windowBar = null; diff --git a/Source/Launchbar/Area.cs b/Source/Launchbar/Area.cs index 4ae1fc3..b8b881d 100644 --- a/Source/Launchbar/Area.cs +++ b/Source/Launchbar/Area.cs @@ -1,5 +1,3 @@ -using System; - namespace Launchbar; public sealed class Area diff --git a/Source/Launchbar/Design.cs b/Source/Launchbar/Design.cs new file mode 100644 index 0000000..82b7871 --- /dev/null +++ b/Source/Launchbar/Design.cs @@ -0,0 +1,11 @@ +namespace Launchbar; + +public static class Design +{ + public static Program Program => new Program() { Text = "DesignProgram" }; + public static Separator Separator => new Separator(); + public static MenuEntry MenuEntry => new Submenu(); + public static Submenu Submenu => new Submenu(); + public static MenuEntrySettings Settings => new MenuEntrySettings(); + public static MenuEntryExit Exit => new MenuEntryExit(); +} \ No newline at end of file diff --git a/Source/Launchbar/ElementCreator.cs b/Source/Launchbar/ElementCreator.cs index a9d79f6..cacc305 100644 --- a/Source/Launchbar/ElementCreator.cs +++ b/Source/Launchbar/ElementCreator.cs @@ -1,8 +1,6 @@ -using System; -using System.Globalization; +using System.Globalization; using System.Windows.Controls; using System.Windows.Data; -using JetBrains.Annotations; namespace Launchbar; @@ -19,12 +17,12 @@ public sealed class ElementCreator : IValueConverter /// A . /// /// Objects described by the template. - public object Convert([CanBeNull] object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type targetType, object? parameter, CultureInfo? culture) { return parameter switch { ControlTemplate ct => new Control { Template = ct }, - _ => throw new ArgumentException("You must specify a ControlTemplate.", nameof(parameter)) + _ => throw new ArgumentException(@"You must specify a ControlTemplate.", nameof(parameter)), }; } @@ -36,7 +34,7 @@ public object Convert([CanBeNull] object value, Type targetType, object paramete /// /// /// - public object ConvertBack([CanBeNull] object value, Type targetType, object parameter, CultureInfo culture) + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { throw new NotSupportedException(); } diff --git a/Source/Launchbar/Launchbar.csproj b/Source/Launchbar/Launchbar.csproj index 63c84f5..1239d06 100644 --- a/Source/Launchbar/Launchbar.csproj +++ b/Source/Launchbar/Launchbar.csproj @@ -1,21 +1,27 @@  + + - net7.0-windows + net8.0-windows true WinExe - false Resources\Next.ico - 5.1.0 + 5.2.0-preview.1 Launchbar RunIT to the next level. Copyright © Mertsch $([System.DateTime]::UtcNow.Year) + true + + true + + false - - + + diff --git a/Source/Launchbar/Menu.cs b/Source/Launchbar/Menu.cs index 8888685..6435620 100644 --- a/Source/Launchbar/Menu.cs +++ b/Source/Launchbar/Menu.cs @@ -1,9 +1,5 @@ -using System; using System.Collections.ObjectModel; -using System.Linq; -using System.Threading.Tasks; using System.Windows.Threading; -using JetBrains.Annotations; namespace Launchbar; @@ -11,7 +7,7 @@ namespace Launchbar; /// Dummy class. /// This class contains the menu entries and will be saved with the application settings. /// -public class Menu : NotifyBase +public sealed class Menu : NotifyBase { #region Fields @@ -36,31 +32,29 @@ public MenuEntryCollection Entries } } + [MustUseReturnValue] public static Menu CreateDefault() { return new Menu { - entries = new MenuEntryCollection - { + entries = + [ new MenuEntrySettings(), new MenuEntryExit(), - } + ], }; } - public void FillIconCacheAsync([NotNull] Dispatcher dispatcher) + public void FillIconCacheAsync(Dispatcher dispatcher) { - if (dispatcher == null) - { - throw new ArgumentNullException(nameof(dispatcher)); - } + ArgumentNullException.ThrowIfNull(dispatcher); Task.Run(() => getIcons(this.Entries, dispatcher)); } - private static async Task getIcons([CanBeNull, ItemNotNull] ObservableCollection entries, [NotNull] Dispatcher dispatcher) + private static async Task getIcons(ObservableCollection? entries, Dispatcher dispatcher) { - if (entries == null) + if (entries is null) { return; // Nothing to do } diff --git a/Source/Launchbar/MenuEntry.cs b/Source/Launchbar/MenuEntry.cs index 8a05744..274f8a7 100644 --- a/Source/Launchbar/MenuEntry.cs +++ b/Source/Launchbar/MenuEntry.cs @@ -37,7 +37,7 @@ public bool IsSelected /// Gets or sets the parent of this object. /// [XmlIgnore] - public MenuEntryCollection Parent { get; set; } + public MenuEntryCollection? Parent { get; set; } /// /// Move this item upwards in the parent collection. @@ -57,7 +57,7 @@ public void MoveDown() private void move(bool up) { - MenuEntryCollection parent = this.Parent; + MenuEntryCollection? parent = this.Parent; if (parent == null) { return; // Unable to do anything @@ -71,7 +71,7 @@ private void move(bool up) { return; // We can't move the element any further. } - MenuEntryCollection parentParent = parent.Parent.Parent; + MenuEntryCollection? parentParent = parent.Parent.Parent; if (parentParent == null) { return; // There is nothing we can do. @@ -97,7 +97,7 @@ private void move(bool up) delta = -1; // Decrease the index by one. } - Submenu moveInto = parent[index + delta] as Submenu; + Submenu? moveInto = parent[index + delta] as Submenu; if (moveInto == null) { parent.Move(index, index + delta); diff --git a/Source/Launchbar/MenuEntryAdvanced.cs b/Source/Launchbar/MenuEntryAdvanced.cs index 0f1416a..1135827 100644 --- a/Source/Launchbar/MenuEntryAdvanced.cs +++ b/Source/Launchbar/MenuEntryAdvanced.cs @@ -14,13 +14,13 @@ public class MenuEntryAdvanced : MenuEntry { #region Fields - private string text; + private string? text; - private string iconPath; + private string? iconPath; private int iconIndex; - private ImageSource icon; + private ImageSource? icon; private IconType iconType = IconType.Default; @@ -31,7 +31,7 @@ public class MenuEntryAdvanced : MenuEntry /// /// Get or set the text to be shown for this entry. /// - public string Text + public string? Text { get { return this.text; } set @@ -48,7 +48,7 @@ public string Text /// /// Path to a file that contains an icon at the specified icon index /// - public string IconPath + public string? IconPath { get { return this.iconPath; } set @@ -107,7 +107,7 @@ private set /// Gets the icon to display when is set to . /// [XmlIgnore] - public ImageSource Icon + public ImageSource? Icon { get { return this.icon; } private set @@ -128,7 +128,7 @@ private set /// public void UpdateIcon() { - ImageSource newIcon = null; + ImageSource? newIcon = null; IconType newType = IconType.Warning; if (!string.IsNullOrEmpty(this.iconPath)) @@ -141,7 +141,7 @@ public void UpdateIcon() } else { - Program p = this as Program; + Program? p = this as Program; if (p == null) // Not a program - use the default icon. { newType = IconType.Default; @@ -179,7 +179,7 @@ public void ChooseIcon() } else { - if (this is Program p && p.IsValidFile) // When the program path is valid, use that path as default. + if (this is Program { IsValidFile: true } p) // When the program path is valid, use that path as default. { path = p.Path; } diff --git a/Source/Launchbar/MenuEntryCollection.cs b/Source/Launchbar/MenuEntryCollection.cs index f27f2e0..90c4634 100644 --- a/Source/Launchbar/MenuEntryCollection.cs +++ b/Source/Launchbar/MenuEntryCollection.cs @@ -1,20 +1,16 @@ -using System; using System.Collections.ObjectModel; -using JetBrains.Annotations; namespace Launchbar; -public class MenuEntryCollection : ObservableCollection +public sealed class MenuEntryCollection : ObservableCollection { - public Submenu Parent { get; set; } + public Submenu? Parent { get; set; } // ReSharper disable once AnnotationConflictInHierarchy - protected override void InsertItem(int index, [NotNull] MenuEntry item) + protected override void InsertItem(int index, MenuEntry item) { - if (item is null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); + item.Parent = this; base.InsertItem(index, item); item.IsSelected = true; @@ -25,7 +21,7 @@ protected override void RemoveItem(int index) this[index].IsSelected = false; this[index].Parent = null; base.RemoveItem(index); - if (index == 0) + if (index <= 0) { if (this.Parent == null) { @@ -44,12 +40,10 @@ protected override void RemoveItem(int index) } // ReSharper disable once AnnotationConflictInHierarchy - protected override void SetItem(int index, [NotNull] MenuEntry item) + protected override void SetItem(int index, MenuEntry item) { - if (item is null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); + this[index].Parent = null; item.Parent = this; base.SetItem(index, item); diff --git a/Source/Launchbar/MenuEntryExit.cs b/Source/Launchbar/MenuEntryExit.cs index a7681f7..e4344a4 100644 --- a/Source/Launchbar/MenuEntryExit.cs +++ b/Source/Launchbar/MenuEntryExit.cs @@ -1,4 +1,3 @@ -using System; using System.Windows; using System.Windows.Input; @@ -9,18 +8,18 @@ namespace Launchbar; /// public sealed class MenuEntryExit : MenuEntry, ICommand { - public event EventHandler CanExecuteChanged + public event EventHandler? CanExecuteChanged { add { } remove { } } - public bool CanExecute(object parameter) + public bool CanExecute(object? parameter) { return true; } - public void Execute(object parameter) + public void Execute(object? parameter) { Application.Current.Shutdown(); // Quit } diff --git a/Source/Launchbar/MenuEntrySettings.cs b/Source/Launchbar/MenuEntrySettings.cs index 66377e3..9fed092 100644 --- a/Source/Launchbar/MenuEntrySettings.cs +++ b/Source/Launchbar/MenuEntrySettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Input; namespace Launchbar; @@ -6,20 +5,20 @@ namespace Launchbar; /// /// This class represents a settings entry. /// -public class MenuEntrySettings : MenuEntry, ICommand +public sealed class MenuEntrySettings : MenuEntry, ICommand { - public event EventHandler CanExecuteChanged + public event EventHandler? CanExecuteChanged { add { } remove { } } - public bool CanExecute(object parameter) + public bool CanExecute(object? parameter) { return true; } - public void Execute(object parameter) + public void Execute(object? parameter) { App.OpenOrActivateSettings(); // Quit } diff --git a/Source/Launchbar/MenuItemExtensions.cs b/Source/Launchbar/MenuItemExtensions.cs index 88945b7..ef35a80 100644 --- a/Source/Launchbar/MenuItemExtensions.cs +++ b/Source/Launchbar/MenuItemExtensions.cs @@ -4,12 +4,13 @@ namespace Launchbar; public static class MenuItemExtensions { - public static void SetIconTemplate(DependencyObject d, DataTemplate value) + public static void SetIconTemplate(DependencyObject d, DataTemplate? value) { d.SetValue(IconTemplateProperty, value); } - public static DataTemplate GetIconTemplate(DependencyObject d) + [MustUseReturnValue] + public static DataTemplate? GetIconTemplate(DependencyObject d) { return (DataTemplate)d.GetValue(IconTemplateProperty); } diff --git a/Source/Launchbar/MenuItemStyleSelector.cs b/Source/Launchbar/MenuItemStyleSelector.cs index 0f4d926..145f160 100644 --- a/Source/Launchbar/MenuItemStyleSelector.cs +++ b/Source/Launchbar/MenuItemStyleSelector.cs @@ -1,28 +1,22 @@ using System.Windows; using System.Windows.Controls; -using JetBrains.Annotations; namespace Launchbar; public sealed class MenuItemStyleSelector : StyleSelector { - [CanBeNull] - public Style ProgramStyle { get; set; } + public Style? ProgramStyle { get; set; } - [CanBeNull] - public Style SubmenuStyle { get; set; } + public Style? SubmenuStyle { get; set; } - [CanBeNull] - public Style SeparatorStyle { get; set; } + public Style? SeparatorStyle { get; set; } - [CanBeNull] - public Style SettingsStyle { get; set; } + public Style? SettingsStyle { get; set; } - [CanBeNull] - public Style ExitStyle { get; set; } + public Style? ExitStyle { get; set; } - [CanBeNull, MustUseReturnValue] - public override Style SelectStyle([CanBeNull] object item, [CanBeNull] DependencyObject container) + [MustUseReturnValue] + public override Style? SelectStyle(object? item, DependencyObject? container) { return item switch { @@ -31,7 +25,7 @@ public override Style SelectStyle([CanBeNull] object item, [CanBeNull] Dependenc Separator => this.SeparatorStyle, MenuEntrySettings => this.SettingsStyle, MenuEntryExit => this.ExitStyle, - _ => null + _ => null, }; } } \ No newline at end of file diff --git a/Source/Launchbar/MetaData.cs b/Source/Launchbar/MetaData.cs index 88bbeb1..bbfd385 100644 --- a/Source/Launchbar/MetaData.cs +++ b/Source/Launchbar/MetaData.cs @@ -1,15 +1,11 @@ -using System; -using System.Reflection; -using JetBrains.Annotations; +using System.Reflection; namespace Launchbar; public static class MetaData { - [NotNull] private static readonly Lazy version = new Lazy(() => Assembly.GetExecutingAssembly().GetCustomAttribute()?.InformationalVersion ?? "Unknown"); - [NotNull] public static string Version => version.Value; } \ No newline at end of file diff --git a/Source/Launchbar/NotifyBase.cs b/Source/Launchbar/NotifyBase.cs index 532a707..48a3596 100644 --- a/Source/Launchbar/NotifyBase.cs +++ b/Source/Launchbar/NotifyBase.cs @@ -1,5 +1,4 @@ using System.ComponentModel; -using JetBrains.Annotations; namespace Launchbar; @@ -8,15 +7,15 @@ public class NotifyBase : INotifyPropertyChanged /// /// Indicates the change of a property. /// - public event PropertyChangedEventHandler PropertyChanged = delegate { }; + public event PropertyChangedEventHandler? PropertyChanged = delegate { }; /// /// Raises the event. /// /// Name of the property which changed. [NotifyPropertyChangedInvocator] - protected void OnPropertyChanged([NotNull] string propertyName) + protected void OnPropertyChanged(string propertyName) { - this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + this.PropertyChanged!.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } \ No newline at end of file diff --git a/Source/Launchbar/Program.cs b/Source/Launchbar/Program.cs index 5b0b3a8..07e060d 100644 --- a/Source/Launchbar/Program.cs +++ b/Source/Launchbar/Program.cs @@ -1,9 +1,7 @@ -using System; using System.Diagnostics; using System.IO; using System.Windows; using System.Windows.Input; -using JetBrains.Annotations; namespace Launchbar; @@ -14,11 +12,11 @@ public sealed class Program : MenuEntryAdvanced, ICommand { #region Fields - private string path; + private string? path; - private string pathAbsolute; + private string? pathAbsolute; - private string arguments; + private string? arguments; private ProcessPriorityClass priority = ProcessPriorityClass.Normal; @@ -29,7 +27,7 @@ public sealed class Program : MenuEntryAdvanced, ICommand /// /// Path to the file to start. /// - public string Path + public string? Path { get { return this.path; } set @@ -62,12 +60,12 @@ public string Path /// /// Absolute path to the file to start (resolves environment variables). /// - public string PathAbsolute => this.pathAbsolute; + public string? PathAbsolute => this.pathAbsolute; /// /// Arguments to pass when starting the file. /// - public string Arguments + public string? Arguments { get { return this.arguments; } set @@ -134,15 +132,15 @@ public void Run() Arguments = this.arguments }; - string workingDir = System.IO.Path.GetDirectoryName(this.pathAbsolute); - if (workingDir != null) + string? workingDir = System.IO.Path.GetDirectoryName(this.pathAbsolute); + if (workingDir is { }) { startInfo.WorkingDirectory = workingDir; } - if (Process.Start(startInfo) is Process process) // Start the process and set the priority (if a new process has been created). + if (Process.Start(startInfo) is { } process) // Start the process and set the priority (if a new process has been created). { - if (this.Priority != ProcessPriorityClass.Normal) // Only set priority if not default (as setting priority may cause an exception). + if (this.Priority is not ProcessPriorityClass.Normal) // Only set priority if not default (as setting priority may cause an exception). { process.PriorityClass = this.Priority; } @@ -164,18 +162,18 @@ public void TryRun() } } - public event EventHandler CanExecuteChanged + public event EventHandler? CanExecuteChanged { add { } remove { } } - public bool CanExecute([CanBeNull] object parameter) + public bool CanExecute(object? parameter) { return true; } - public void Execute([CanBeNull] object parameter) + public void Execute(object? parameter) { this.TryRun(); } diff --git a/Source/Launchbar/Resources/Aero.Extended.xaml b/Source/Launchbar/Resources/Aero.Extended.xaml index 40241cd..1997360 100644 --- a/Source/Launchbar/Resources/Aero.Extended.xaml +++ b/Source/Launchbar/Resources/Aero.Extended.xaml @@ -30,7 +30,7 @@ Offset="1"/> - + @@ -290,7 +290,7 @@ CornerRadius="3" Margin="1" Visibility="Hidden" - Width="22" + Width="22" Height="22"> - + - \ No newline at end of file diff --git a/Source/Launchbar/Resources/Images.xaml b/Source/Launchbar/Resources/Images.xaml index e26b230..e0fb9fc 100644 --- a/Source/Launchbar/Resources/Images.xaml +++ b/Source/Launchbar/Resources/Images.xaml @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - + @@ -12,8 +12,8 @@ - - + + @@ -22,91 +22,95 @@ - - + + - + - - + + - + - + - + - - + + - + - - + + - + - + - + - - + + - + - - + + @@ -115,23 +119,24 @@ - - + + - + - - + + @@ -140,15 +145,16 @@ - - + + - + @@ -158,9 +164,9 @@ - + - + @@ -170,54 +176,54 @@ - - + + - + - - + + - + - - + + - + - + - + - + @@ -225,9 +231,9 @@ - + - + @@ -237,59 +243,59 @@ - - + + - + - - + + - + - - + + - + - + - + - + - + \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapeClose.xaml.cs b/Source/Launchbar/Shapes/ShapeClose.xaml.cs index 71288a9..2f24f86 100644 --- a/Source/Launchbar/Shapes/ShapeClose.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeClose.xaml.cs @@ -1,4 +1,6 @@ -using System.Windows; +using fm; +using fm.Extensions; +using System.Windows; using System.Windows.Controls; namespace Launchbar.Shapes; @@ -13,15 +15,12 @@ public sealed partial class ShapeClose : UserControl /// public bool IsHover { - get { return (bool)this.GetValue(IsHoverProperty); } - set { this.SetValue(IsHoverProperty, value); } + get { return this.GetValue(IsHoverProperty); } + set { this.SetValueBox(IsHoverProperty, value); } } - /// - /// Identifies the property. - /// - public static readonly DependencyProperty IsHoverProperty = - DependencyProperty.Register("IsHover", typeof(bool), typeof(ShapeClose)); + public static readonly DependencyProperty IsHoverProperty = DependencyProperty.Register( + nameof(IsHover), typeof(bool), typeof(ShapeClose), new PropertyMetadata(Boxes.False)); public ShapeClose() { diff --git a/Source/Launchbar/Shapes/ShapeFolder.xaml.cs b/Source/Launchbar/Shapes/ShapeFolder.xaml.cs index f417dab..a4507a1 100644 --- a/Source/Launchbar/Shapes/ShapeFolder.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeFolder.xaml.cs @@ -1,4 +1,6 @@ -using System.Windows; +using fm; +using fm.Extensions; +using System.Windows; using System.Windows.Controls; namespace Launchbar.Shapes; @@ -13,15 +15,12 @@ public sealed partial class ShapeFolder : UserControl /// public bool IsOpen { - get { return (bool)this.GetValue(IsOpenProperty); } - set { this.SetValue(IsOpenProperty, value); } + get { return this.GetValue(IsOpenProperty); } + set { this.SetValueBox(IsOpenProperty, value); } } - /// - /// Identifies the property. - /// - public static readonly DependencyProperty IsOpenProperty = - DependencyProperty.Register("IsOpen", typeof(bool), typeof(ShapeFolder)); + public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register( + nameof(IsOpen), typeof(bool), typeof(ShapeFolder), new PropertyMetadata(Boxes.False)); public ShapeFolder() { diff --git a/Source/Launchbar/Submenu.cs b/Source/Launchbar/Submenu.cs index 8834f47..1f541e6 100644 --- a/Source/Launchbar/Submenu.cs +++ b/Source/Launchbar/Submenu.cs @@ -41,19 +41,13 @@ public MenuEntryCollection MenuEntries get { return this.entries; } set { - if (this.entries == value) + if (ReferenceEquals(this.entries, value)) { return; } - if (this.entries != null) - { - this.entries.Parent = null; - } + this.entries.Parent = null; this.entries = value; - if (this.entries != null) - { - this.entries.Parent = this; - } + this.entries.Parent = this; this.OnPropertyChanged(nameof(this.MenuEntries)); } diff --git a/Source/Launchbar/Win32/ExtendedWindowStyles.cs b/Source/Launchbar/Win32/ExtendedWindowStyles.cs index 56c6d22..a568dca 100644 --- a/Source/Launchbar/Win32/ExtendedWindowStyles.cs +++ b/Source/Launchbar/Win32/ExtendedWindowStyles.cs @@ -1,8 +1,8 @@ - - -// ReSharper disable InconsistentNaming +// ReSharper disable InconsistentNaming // ReSharper disable UnusedMember.Global -#pragma warning disable 169 + +#pragma warning disable CA1805 // Do not initialize unnecessarily +#pragma warning disable CS0414 // Field is assigned but its value is never used namespace Launchbar.Win32; diff --git a/Source/Launchbar/Win32/GWL.cs b/Source/Launchbar/Win32/GWL.cs index b0ad858..646309d 100644 --- a/Source/Launchbar/Win32/GWL.cs +++ b/Source/Launchbar/Win32/GWL.cs @@ -1,9 +1,7 @@ - - -// ReSharper disable InconsistentNaming +// ReSharper disable InconsistentNaming // ReSharper disable UnusedMember.Global -#pragma warning disable 169 +#pragma warning disable CS0414 // Field is assigned but its value is never used namespace Launchbar.Win32; internal static class GWL diff --git a/Source/Launchbar/Win32/SafeNativeMethods.cs b/Source/Launchbar/Win32/SafeNativeMethods.cs index 81f1d81..b751e5f 100644 --- a/Source/Launchbar/Win32/SafeNativeMethods.cs +++ b/Source/Launchbar/Win32/SafeNativeMethods.cs @@ -1,5 +1,4 @@ -using System; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using System.Security; using System.Text; @@ -11,7 +10,7 @@ namespace Launchbar.Win32; [SuppressUnmanagedCodeSecurity] -internal static class SafeNativeMethods +internal static partial class SafeNativeMethods { internal const string User32 = @"user32.dll"; @@ -19,11 +18,11 @@ internal static class SafeNativeMethods #region SetWindowLongPtr - [DllImport(User32, EntryPoint = "GetWindowLong")] - private static extern int GetWindowLongPtr32(nint hWnd, int nIndex); + [LibraryImport(User32, EntryPoint = "GetWindowLongW")] + private static partial int GetWindowLongPtr32(nint hWnd, int nIndex); - [DllImport(User32, EntryPoint = "GetWindowLongPtr")] - private static extern nint GetWindowLongPtr64(nint hWnd, int nIndex); + [LibraryImport(User32, EntryPoint = "GetWindowLongPtrW")] + private static partial nint GetWindowLongPtr64(nint hWnd, int nIndex); /// /// The GetWindowLongPtr function retrieves information about the specified window. @@ -39,18 +38,18 @@ internal static class SafeNativeMethods /// for values in the extra window or class memory. public static nint GetWindowLongPtr(nint hWnd, int nIndex) { - return nint.Size == 8 ? GetWindowLongPtr64(hWnd, nIndex) : new nint(GetWindowLongPtr32(hWnd, nIndex)); + return nint.Size is 8 ? GetWindowLongPtr64(hWnd, nIndex) : new nint(GetWindowLongPtr32(hWnd, nIndex)); } #endregion #region SetWindowLongPtr - [DllImport(User32, EntryPoint = "SetWindowLong")] - private static extern int SetWindowLong32(nint hWnd, int nIndex, int dwNewLong); + [LibraryImport(User32, EntryPoint = "SetWindowLongW")] + private static partial int SetWindowLong32(nint hWnd, int nIndex, int dwNewLong); - [DllImport(User32, EntryPoint = "SetWindowLongPtr")] - private static extern nint SetWindowLongPtr64(nint hWnd, int nIndex, nint dwNewLong); + [LibraryImport(User32, EntryPoint = "SetWindowLongPtrW")] + private static partial nint SetWindowLongPtr64(nint hWnd, int nIndex, nint dwNewLong); /// /// The SetWindowLongPtr function changes an attribute of the specified window. @@ -74,7 +73,7 @@ public static nint GetWindowLongPtr(nint hWnd, int nIndex) /// Function failure will be indicated by a return value of zero and a GetLastError result that is nonzero. public static nint SetWindowLongPtr(nint hWnd, int nIndex, nint dwNewLong) { - return nint.Size == 8 + return nint.Size is 8 ? SetWindowLongPtr64(hWnd, nIndex, dwNewLong) : new nint(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32())); } @@ -104,9 +103,9 @@ public static nint SetWindowLongPtr(nint hWnd, int nIndex, nint dwNewLong) /// [in] Handle to the icon to be destroyed. The icon must not be in use. /// If the function succeeds, the return value is nonzero. If the function fails, /// the return value is zero. To get extended error information, call GetLastError. - [DllImport(User32, EntryPoint = "DestroyIcon", CharSet = CharSet.Auto, SetLastError = true)] + [LibraryImport(User32, EntryPoint = "DestroyIcon", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DestroyIcon(nint hIcon); + public static partial bool DestroyIcon(nint hIcon); /// /// The ExtractIcon function retrieves a handle to an icon from the specified executable file, DLL, or icon file. @@ -121,8 +120,8 @@ public static nint SetWindowLongPtr(nint hWnd, int nIndex, nint dwNewLong) /// If the file is an .ICO file, the return value is 1. /// The return value is a handle to an icon. If the file specified was not an executable file, DLL, or icon file, the return is 1. /// If no icons were found in the file, the return value is NULL. - [DllImport(Shell32, EntryPoint = "ExtractIcon", CharSet = CharSet.Unicode)] - internal static extern nint ExtractIcon(nint hInst, string lpszExeFileName, uint nIconIndex); + [LibraryImport(Shell32, EntryPoint = "ExtractIconW", StringMarshalling = StringMarshalling.Utf16)] + internal static partial nint ExtractIcon(nint hInst, string lpszExeFileName, uint nIconIndex); /// /// The ExtractAssociatedIcon function returns a handle to an indexed icon found in a file or an icon found in an associated executable file. @@ -141,8 +140,8 @@ public static nint SetWindowLongPtr(nint hWnd, int nIndex, nint dwNewLong) /// executable file in the string pointed to by , and stores the icon's /// identifier in the WORD pointed to by . If the function fails, the /// return value is NULL. - [DllImport(Shell32, EntryPoint = "ExtractAssociatedIcon", CharSet = CharSet.Unicode)] - internal static extern nint ExtractAssociatedIcon(nint hInst, string lpIconPath, ref int lpiIcon); + [LibraryImport(Shell32, EntryPoint = "ExtractAssociatedIconW", StringMarshalling = StringMarshalling.Utf16)] + internal static partial nint ExtractAssociatedIcon(nint hInst, string lpIconPath, ref int lpiIcon); #region SendInput @@ -237,8 +236,8 @@ internal struct INPUT public MOUSEKEYBDHARDWAREINPUT mkhi; } - [DllImport(User32, SetLastError = true)] - internal static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize); + [LibraryImport(User32, SetLastError = true)] + internal static partial uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize); #endregion } \ No newline at end of file diff --git a/Source/Launchbar/Win32/WinHelper.cs b/Source/Launchbar/Win32/WinHelper.cs index 02b063f..a411516 100644 --- a/Source/Launchbar/Win32/WinHelper.cs +++ b/Source/Launchbar/Win32/WinHelper.cs @@ -1,10 +1,8 @@ -using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media.Imaging; -using JetBrains.Annotations; namespace Launchbar.Win32; @@ -19,7 +17,7 @@ internal static class WinHelper /// Path to the file or directory to extract the icon from. /// Does NOT support environment variables. /// The extracted icon as . - public static BitmapSource ExtractAssociatedIcon([NotNull] string path) + public static BitmapSource? ExtractAssociatedIcon(string path) { int i = 0; nint hIcon = SafeNativeMethods.ExtractAssociatedIcon(nint.Zero, path, ref i); @@ -39,7 +37,7 @@ public static BitmapSource ExtractAssociatedIcon([NotNull] string path) /// Supports environment variables. /// A zero-based index of the icon. /// The extracted icon as . - public static BitmapSource ExtractIcon([NotNull] string path, int index) + public static BitmapSource? ExtractIcon(string path, int index) { nint hIcon = SafeNativeMethods.ExtractIcon(nint.Zero, path, (uint)index); if (hIcon != nint.Zero) @@ -57,19 +55,16 @@ public static BitmapSource ExtractIcon([NotNull] string path, int index) /// public static void SendMouseButtonDown(MouseButton button) { - SafeNativeMethods.MOUSEINPUT mi = new SafeNativeMethods.MOUSEINPUT(); + SafeNativeMethods.MOUSEINPUT mi = new SafeNativeMethods.MOUSEINPUT + { + dwFlags = button switch + { + MouseButton.Left => SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_LEFTDOWN, + MouseButton.Right => SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_RIGHTDOWN, + _ => throw new NotSupportedException(), + }, + }; - switch (button) - { - case MouseButton.Left: - mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_LEFTDOWN; - break; - case MouseButton.Right: - mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_RIGHTDOWN; - break; - default: - throw new NotSupportedException(); - } SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT mkhInput = new SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT { mi = mi }; SafeNativeMethods.INPUT input = new SafeNativeMethods.INPUT { type = SafeNativeMethods.INPUT_TYPE.MOUSE, mkhi = mkhInput }; @@ -83,19 +78,15 @@ public static void SendMouseButtonDown(MouseButton button) /// public static void SendMouseButtonUp(MouseButton button) { - SafeNativeMethods.MOUSEINPUT mi = new SafeNativeMethods.MOUSEINPUT(); - - switch (button) - { - case MouseButton.Left: - mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_LEFTUP; - break; - case MouseButton.Right: - mi.dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_RIGHTUP; - break; - default: - throw new NotSupportedException(); - } + SafeNativeMethods.MOUSEINPUT mi = new SafeNativeMethods.MOUSEINPUT + { + dwFlags = button switch + { + MouseButton.Left => SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_LEFTUP, + MouseButton.Right => SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_RIGHTUP, + _ => throw new NotSupportedException(), + }, + }; SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT mkhInput = new SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT { mi = mi }; @@ -114,24 +105,24 @@ public static void SendMouseMoveRelative(int x, int y) { dwFlags = SafeNativeMethods.MOUSEINPUTFLAGS.MOUSEEVENTF_MOVE, dx = x, - dy = y + dy = y, }; SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT mkhInput = new SafeNativeMethods.MOUSEKEYBDHARDWAREINPUT { - mi = mi + mi = mi, }; SafeNativeMethods.INPUT input = new SafeNativeMethods.INPUT { type = SafeNativeMethods.INPUT_TYPE.MOUSE, - mkhi = mkhInput + mkhi = mkhInput, }; SafeNativeMethods.SendInput(1, ref input, Marshal.SizeOf(input)); } - public static void SetAsToolWindow([NotNull] this Window window) + public static void SetAsToolWindow(this Window window) { nint handle = new WindowInteropHelper(window).EnsureHandle(); nint oldFlags = SafeNativeMethods.GetWindowLongPtr(handle, GWL.GWL_EXSTYLE); diff --git a/Source/Launchbar/WindowBar.xaml.cs b/Source/Launchbar/WindowBar.xaml.cs index ac19fb0..59bc3c9 100644 --- a/Source/Launchbar/WindowBar.xaml.cs +++ b/Source/Launchbar/WindowBar.xaml.cs @@ -1,11 +1,10 @@ -using System; +using fm.Extensions; +using Launchbar.Properties; +using Launchbar.Win32; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; -using fm.Extensions; -using Launchbar.Properties; -using Launchbar.Win32; namespace Launchbar; @@ -67,10 +66,10 @@ public WindowBar(Dock dock, Area area) : this() this.Dock = dock; this.WorkArea = area; area.Updated += this.areaUpdated; - this.areaUpdated(null, null); + this.areaUpdated(null, EventArgs.Empty); } - private void areaUpdated(object sender, EventArgs e) + private void areaUpdated(object? sender, EventArgs e) { Area area = this.WorkArea; diff --git a/Source/Launchbar/WindowSettings.xaml b/Source/Launchbar/WindowSettings.xaml index 7fcf50c..1680ca2 100644 --- a/Source/Launchbar/WindowSettings.xaml +++ b/Source/Launchbar/WindowSettings.xaml @@ -1,6 +1,7 @@  - + @@ -348,23 +349,23 @@ Margin="3,0,0,0" VerticalAlignment="Center"/> - + - + - + - + - + @@ -374,17 +375,19 @@ - - - + - + - + - + - + - + - - - - - + ProgramStyle="{StaticResource StyleProgram}" + SubmenuStyle="{StaticResource StyleSubmenu}" + SeparatorStyle="{StaticResource StyleSeparator}" + SettingsStyle="{StaticResource StyleSettings}" + ExitStyle="{StaticResource StyleExit}"/> - diff --git a/Source/Launchbar/App.xaml.cs b/Source/Launchbar/App.xaml.cs index ecc7c94..82b5c49 100644 --- a/Source/Launchbar/App.xaml.cs +++ b/Source/Launchbar/App.xaml.cs @@ -84,6 +84,7 @@ public App() } catch (Win32Exception) { } this.Shutdown(); + this.contextMenu = default!; return; } diff --git a/Source/Launchbar/Design.cs b/Source/Launchbar/Design.cs index 82b7871..bc42c8a 100644 --- a/Source/Launchbar/Design.cs +++ b/Source/Launchbar/Design.cs @@ -2,7 +2,7 @@ public static class Design { - public static Program Program => new Program() { Text = "DesignProgram" }; + public static Program Program => new Program { Text = "DesignProgram" }; public static Separator Separator => new Separator(); public static MenuEntry MenuEntry => new Submenu(); public static Submenu Submenu => new Submenu(); diff --git a/Source/Launchbar/Launchbar.csproj b/Source/Launchbar/Launchbar.csproj index 1239d06..e5ea1ba 100644 --- a/Source/Launchbar/Launchbar.csproj +++ b/Source/Launchbar/Launchbar.csproj @@ -20,8 +20,8 @@ - - + + diff --git a/Source/Launchbar/Program.cs b/Source/Launchbar/Program.cs index 07e060d..fdc4ec2 100644 --- a/Source/Launchbar/Program.cs +++ b/Source/Launchbar/Program.cs @@ -41,14 +41,7 @@ public string? Path return; } this.path = value; - if (value == null) - { - this.pathAbsolute = null; - } - else - { - this.pathAbsolute = Environment.ExpandEnvironmentVariables(value); - } + this.pathAbsolute = value == null ? null : Environment.ExpandEnvironmentVariables(value); this.OnPropertyChanged(nameof(this.Path)); this.OnPropertyChanged(nameof(this.IsValidFile)); diff --git a/Source/Launchbar/Shapes/ShapePlus.xaml b/Source/Launchbar/Shapes/ShapePlus.xaml index 833581f..011ec34 100644 --- a/Source/Launchbar/Shapes/ShapePlus.xaml +++ b/Source/Launchbar/Shapes/ShapePlus.xaml @@ -3,7 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - + @@ -11,7 +11,7 @@ - + @@ -22,6 +22,6 @@ - + \ No newline at end of file diff --git a/Source/Launchbar/WindowSettings.xaml b/Source/Launchbar/WindowSettings.xaml index 1680ca2..2f122aa 100644 --- a/Source/Launchbar/WindowSettings.xaml +++ b/Source/Launchbar/WindowSettings.xaml @@ -341,7 +341,7 @@ Margin="0,3,3,0"> - + @@ -349,89 +349,89 @@ Margin="3,0,0,0" VerticalAlignment="Center"/> - + - + - + - + - + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From ebaf9ad5384a63d6e452e9accc6e44dededfeafe Mon Sep 17 00:00:00 2001 From: Mertsch Date: Wed, 18 Jun 2025 12:16:48 +0200 Subject: [PATCH 11/18] Use .NET 9 in pipeline --- .github/workflows/dotnet.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index d01fdf5..a6219a0 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -1,4 +1,4 @@ -name: Build Launchbar +name: Build Launchbar on: push: @@ -17,7 +17,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.x + dotnet-version: 9.x - name: Restore dependencies run: dotnet restore Source/Launchbar.sln - name: Build From 5a283ab9091b2bfa2e8c028522aa324e4241dc2f Mon Sep 17 00:00:00 2001 From: Mertsch Date: Wed, 18 Jun 2025 12:38:29 +0200 Subject: [PATCH 12/18] Update build --- ReSharper.Global.DotSettings | 1634 +++++++++++++++++++++++++ Source/Common.props | 31 - Source/Directory.Build.props | 97 +- Source/Launchbar.sln | 2 +- Source/Launchbar.sln.DotSettings | 6 + Source/Launchbar/Launchbar.csproj | 15 +- Source/Launchbar/Menu.cs | 4 +- Source/Launchbar/MenuEntry.cs | 10 +- Source/Launchbar/MenuEntryAdvanced.cs | 32 +- Source/Launchbar/Program.cs | 20 +- Source/Launchbar/Submenu.cs | 10 +- Source/Product.props | 11 + 12 files changed, 1781 insertions(+), 91 deletions(-) create mode 100644 ReSharper.Global.DotSettings delete mode 100644 Source/Common.props create mode 100644 Source/Launchbar.sln.DotSettings create mode 100644 Source/Product.props diff --git a/ReSharper.Global.DotSettings b/ReSharper.Global.DotSettings new file mode 100644 index 0000000..dd83859 --- /dev/null +++ b/ReSharper.Global.DotSettings @@ -0,0 +1,1634 @@ + + None + True + True + False + Advanced + All + True + 1000 + True + $Value$ + True + True + True + Directory.Packages.props + *.Generated.html + *.Generated.json + *ModelSnapshot.cs + SOLUTION + True + True + True + ERROR + ERROR + HINT + HINT + DO_NOT_SHOW + DO_NOT_SHOW + HINT + HINT + HINT + HINT + HINT + HINT + HINT + HINT + SUGGESTION + WARNING + WARNING + HINT + HINT + WARNING + WARNING + ERROR + WARNING + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + HINT + SUGGESTION + WARNING + ERROR + ERROR + ERROR + ERROR + ERROR + HINT + HINT + HINT + SUGGESTION + HINT + WARNING + DO_NOT_SHOW + DO_NOT_SHOW + HINT + DO_NOT_SHOW + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + HINT + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + WARNING + ERROR + ERROR + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + SUGGESTION + ERROR + ERROR + ERROR + ERROR + HINT + ERROR + ERROR + ERROR + ERROR + ERROR + DO_NOT_SHOW + ERROR + ERROR + ERROR + ERROR + DO_NOT_SHOW + HINT + ERROR + HINT + WARNING + DO_NOT_SHOW + HINT + HINT + HINT + ERROR + HINT + WARNING + HINT + SUGGESTION + WARNING + WARNING + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + SUGGESTION + HINT + ERROR + ERROR + ERROR + ERROR + HINT + ERROR + DO_NOT_SHOW + HINT + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + ERROR + ERROR + ERROR + ERROR + ERROR + HINT + SUGGESTION + ERROR + HINT + HINT + HINT + HINT + HINT + ERROR + HINT + ERROR + ERROR + HINT + ERROR + ERROR + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + ERROR + WARNING + SUGGESTION + WARNING + HINT + HINT + ERROR + HINT + DO_NOT_SHOW + HINT + ERROR + ERROR + ERROR + HINT + ERROR + DO_NOT_SHOW + HINT + HINT + SUGGESTION + HINT + ERROR + SUGGESTION + HINT + ERROR + WARNING + WARNING + ERROR + ERROR + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + ERROR + ERROR + ERROR + SUGGESTION + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + ERROR + DO_NOT_SHOW + WARNING + SUGGESTION + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + SUGGESTION + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + WARNING + ERROR + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + WARNING + ERROR + ERROR + WARNING + ERROR + WARNING + ERROR + ERROR + ERROR + ERROR + HINT + ERROR + WARNING + ERROR + ERROR + WARNING + ERROR + HINT + WARNING + ERROR + ERROR + ERROR + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + HINT + HINT + WARNING + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + ERROR + WARNING + ERROR + WARNING + WARNING + ERROR + ERROR + WARNING + ERROR + WARNING + ERROR + DO_NOT_SHOW + ERROR + ERROR + ERROR + ERROR + ERROR + WARNING + ERROR + ERROR + True + ShowAndRun + OPTIMISTIC + MergeVsActionsIntoResharperMenu + Experimental + <?xml version="1.0" encoding="utf-16"?><Profile name="fm"><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSRemoveCodeRedundancies>True</CSRemoveCodeRedundancies><XMLReformatCode>True</XMLReformatCode><CSArrangeQualifiers>True</CSArrangeQualifiers><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings><JsReformatCode>True</JsReformatCode><HtmlReformatCode>True</HtmlReformatCode><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="False" AddMissingParentheses="False" ArrangeBraces="True" ArrangeAttributes="False" ArrangeArgumentsStyle="False" ArrangeCodeBodyStyle="False" ArrangeVarStyle="True" /><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor></Profile> + <?xml version="1.0" encoding="utf-16"?><Profile name="fm Full Reformat"><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSRemoveCodeRedundancies>True</CSRemoveCodeRedundancies><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSReorderTypeMembers>True</CSReorderTypeMembers><XMLReformatCode>True</XMLReformatCode><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings><CSArrangeQualifiers>True</CSArrangeQualifiers><HtmlReformatCode>True</HtmlReformatCode><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><JsReformatCode>True</JsReformatCode><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="False" AddMissingParentheses="False" ArrangeBraces="True" ArrangeAttributes="False" ArrangeArgumentsStyle="False" ArrangeCodeBodyStyle="False" ArrangeVarStyle="True" ArrangeTrailingCommas="False" /><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences></Profile> + <?xml version="1.0" encoding="utf-16"?><Profile name="fm Solution Wide Cleanup"><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="False" AddMissingParentheses="False" ArrangeBraces="True" ArrangeAttributes="True" ArrangeArgumentsStyle="False" ArrangeCodeBodyStyle="False" ArrangeVarStyle="True" ArrangeTrailingCommas="False" /><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings><CSArrangeQualifiers>True</CSArrangeQualifiers><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences></Profile> + fm + True + Required + Required + Required + Required + Join + public private protected internal file static extern new virtual abstract sealed override readonly unsafe required volatile async + EmptyRecursivePattern + ExplicitlyTyped + ExplicitlyTyped + All + True + False + 0 + 0 + 0 + 0 + TOGETHER_SAME_LINE + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + INDENT + NEXT_LINE_SHIFTED_2 + 1 + 1 + NEVER + False + NEVER + False + ALWAYS_USE + False + False + True + False + False + True + 230 + True + True + ALIGN_ALL + NEXT_LINE + TOGETHER_SAME_LINE + ALWAYS_ADD + NEXT_LINE + NEXT_LINE + True + 1 + 1 + 1 + True + True + True + LINE_BREAK + False + False + WRAP_IF_LONG + WRAP_IF_LONG + 260 + WRAP_IF_LONG + False + 1 + ByFirstAttr + False + 230 + 230 + False + DoNotTouch + False + False + 1 + False + False + 250 + 250 + <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> + <TypePattern DisplayName="Non-reorderable types"> + <TypePattern.Match> + <Or> + <And> + <Kind Is="Interface" /> + <Or> + <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> + <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> + </Or> + </And> + <Kind Is="Struct" /> + <HasAttribute Name="JetBrains.Annotations.NoReorderAttribute" /> + <HasAttribute Name="JetBrains.Annotations.NoReorder" /> + </Or> + </TypePattern.Match> + </TypePattern> + + <TypePattern DisplayName="xUnit.net Test Classes" RemoveRegions="All"> + <TypePattern.Match> + <And> + <Kind Is="Class" /> + <HasMember> + <And> + <Kind Is="Method"></Kind> + <HasAttribute Name="Xunit.FactAttribute" Inherited="True" /> + </And> + </HasMember> + </And> + </TypePattern.Match> + + <Region Name="Setup/Teardown"> + <Entry DisplayName="Setup/Teardown Methods"> + <Entry.Match> + <Or> + <Kind Is="Constructor" /> + <And> + <Kind Is="Method"></Kind> + <ImplementsInterface Name="System.IDisposable"></ImplementsInterface> + </And> + </Or> + </Entry.Match> + + <Entry.SortBy> + <Kind> + <Kind.Order> + <DeclarationKind>Constructor</DeclarationKind> + </Kind.Order> + </Kind> + </Entry.SortBy> + </Entry> + </Region> + + <Entry DisplayName="All other members" /> + + <Entry DisplayName="Test Methods" Priority="100"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <HasAttribute Name="Xunit.FactAttribute" Inherited="false" /> + </And> + </Entry.Match> + + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </TypePattern> + + <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> + <TypePattern.Match> + <And> + <Kind Is="Class" /> + <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="true" /> + </And> + </TypePattern.Match> + + <Region Name="Setup/Teardown"> + <Entry DisplayName="Setup/Teardown Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <Or> + <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="true" /> + <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="true" /> + <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="true" /> + <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="true" /> + </Or> + </And> + </Entry.Match> + </Entry> + </Region> + + <Entry DisplayName="All other members" /> + + <Entry DisplayName="Test Methods" Priority="100"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <HasAttribute Name="NUnit.Framework.TestAttribute" Inherited="false" /> + </And> + </Entry.Match> + + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </TypePattern> + + <TypePattern DisplayName="Default Pattern"> + <Region Name="Delegates"> + <Entry DisplayName="Public Delegates" Priority="100"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Delegate" /> + </And> + </Entry.Match> + + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </Region> + + <Region Name="${0} enum" Priority="100"> + <Region.GroupBy> + <Name /> + </Region.GroupBy> + + <Entry DisplayName="Public Enums"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Enum" /> + </And> + </Entry.Match> + + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </Region> + + <Entry DisplayName="Static Fields and Constants"> + <Entry.Match> + <Or> + <Kind Is="Constant" /> + <And> + <Kind Is="Field" /> + <Static /> + </And> + </Or> + </Entry.Match> + + <Entry.SortBy> + <Kind> + <Kind.Order> + <DeclarationKind>Constant</DeclarationKind> + <DeclarationKind>Field</DeclarationKind> + </Kind.Order> + </Kind> + </Entry.SortBy> + </Entry> + + <Entry DisplayName="Fields"> + <Entry.Match> + <And> + <Kind Is="Field" /> + <Not> + <Static /> + </Not> + </And> + </Entry.Match> + + <Entry.SortBy> + <Readonly /> + <Name /> + </Entry.SortBy> + </Entry> + + <Entry DisplayName="Constructors"> + <Entry.Match> + <Kind Is="Constructor" /> + </Entry.Match> + + <Entry.SortBy> + <Static/> + </Entry.SortBy> + </Entry> + + <Entry DisplayName="Properties, Indexers"> + <Entry.Match> + <Or> + <Kind Is="Property" /> + <Kind Is="Indexer" /> + </Or> + </Entry.Match> + </Entry> + + <Region Name="${0} Members" Priority="100"> + <Region.GroupBy> + <ImplementsInterface Immediate="true" /> + </Region.GroupBy> + + <Entry DisplayName="Interface Members"> + <Entry.Match> + <And> + <Kind Is="Member" /> + <ImplementsInterface /> + </And> + </Entry.Match> + + <Entry.SortBy> + <ImplementsInterface Immediate="true" /> + </Entry.SortBy> + </Entry> + </Region> + + <Entry DisplayName="All Other Members" /> + + <Region Name="Nested type: ${0}"> + <Region.GroupBy> + <Name /> + </Region.GroupBy> + + <Entry DisplayName="Nested Types"> + <Entry.Match> + <Kind Is="Type" /> + </Entry.Match> + </Entry> + </Region> + </TypePattern> +</Patterns> + + + UsingRegions + False + UseExplicitType + UseExplicitType + UseExplicitType + AD + DB + FS + UI + False + $object$$event$ + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Type parameters"><ElementKinds><Kind Name="TYPE_PARAMETER" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Field (private, static, read-only)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="PropertyKey" Style="AaBb" /></Policy></Policy> + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Instance fields (not private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local variables"><ElementKinds><Kind Name="LOCAL_VARIABLE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static fields (not private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Parameters"><ElementKinds><Kind Name="PARAMETER" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Enum members"><ElementKinds><Kind Name="ENUM_MEMBER" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"><ElementKinds><Kind Name="NAMESPACE" /><Kind Name="CLASS" /><Kind Name="STRUCT" /><Kind Name="ENUM" /><Kind Name="DELEGATE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local constants"><ElementKinds><Kind Name="LOCAL_CONSTANT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Interfaces"><ElementKinds><Kind Name="INTERFACE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Methods, properties, events (private)"><ElementKinds><Kind Name="METHOD" /><Kind Name="PROPERTY" /><Kind Name="EVENT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="Methods, properties, events"><ElementKinds><Kind Name="METHOD" /><Kind Name="PROPERTY" /><Kind Name="EVENT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Main method (private)"><ElementKinds><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="Main" Style="AaBb" /></Policy></Policy> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True + True + DisabledOnSelection + BOTH_SIDES + OUTLINE + Narrow + False + True + False + True + PushToShowHints + PushToShowHints + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + False + True + True + MergeVsActionsIntoResharperMenu + True + True + MSTest + TestMethod + True + testMethod + True + [$TestMethodAttribute$] +public void Test() +{ + $END$ +} + True + fixedTypeName("Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute") + -1 + 0 + True + 2.0 + InCSharpTypeMember + True + True + XAML + True + propdpBool + True + #region $PropertyName$ + +public $Type$ $PropertyName$ +{ + get { return this.GetValue<$Type$>($PropertyName$Property); } + set { this.SetValueBox($PropertyName$Property, value); } +} + +public static readonly $DependencyProperty$ $PropertyName$Property = $DependencyProperty$.Register( + nameof($PropertyName$), typeof($Type$), typeof($containingType$), new $PropertyMetadata$($Boxes$.$False$)); + +#endregion + True + fixedTypeName("fm.Boxes") + -1 + 5 + True + typeName() + -1 + 2 + True + fixedTypeName("System.Windows.DependencyProperty") + -1 + 3 + True + constant("False") + 6 + True + fixedTypeName("System.Windows.PropertyMetadata") + -1 + 4 + True + 1 + 1 + True + parameterOfType("System.Boolean") + -1 + 0 + True + 3.0 + InCSharpTypeMember + True + True + True + nn + True + [NotNull] + True + 2.0 + InCSharpFile + True + True + XAML + Overrides the default style key with with current class. + True + defaultStyleKeyOverride + True + DefaultStyleKeyProperty.OverrideMetadata(typeof($containingType$), new FrameworkPropertyMetadata(typeof($containingType$))); + True + typeName() + -1 + 0 + True + 3.0 + InCSharpFile + XAML + True + True + Dependency property + True + typeName() + -1 + 0 + True + 3 + True + 4 + True + 1 + True + 2 + True + True + 3.0 + InCSharpTypeMember + propdp + True + #region $PropertyName$ + +public $Type$ $PropertyName$ +{ + get { return ($Type$)this.GetValue($PropertyName$Property); } + set { this.SetValue($PropertyName$Property, value); } +} + +public static readonly $DependencyProperty$ $PropertyName$Property = $DependencyProperty$.Register( + nameof($PropertyName$), typeof($Type$), typeof($containingType$), new $PropertyMetadata$(default($Type$))); + +#endregion + True + True + inserts typeof(<ContainingType>) + True + typeofThis + True + typeof($ContainingType$) + True + typeName() + -1 + 0 + True + 2.0 + InCSharpFile + True + True + MSTest + Inset a ClassInitialize method + True + testClassInitialize + True + [$ClassInitializeAttribute$] +public static void ClassInitialize($TestContext$ testContext) +{ + $END$ +} + True + fixedTypeName("Microsoft.VisualStudio.TestTools.UnitTesting.ClassInitializeAttribute") + -1 + 0 + True + fixedTypeName("Microsoft.VisualStudio.TestTools.UnitTesting.TestContext") + -1 + 1 + True + 2.0 + InCSharpFile + True + True + XAML + True + propdpChangedCallback + True + private static void on$PropertyName$Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) +{ + (($ContainingType$)d).on$PropertyName$Changed(); +} + +private void on$PropertyName$Changed() +{ + $END$ +} + True + typeName() + -1 + 1 + True + 0 + True + 3.0 + InCSharpTypeMember + True + True + cs + Tests + True + &UnitTest + True + True + $HEADER$namespace $NAMESPACE$ +{ + [Microsoft.VisualStudio.TestTools.UnitTesting.TestClass] + public sealed class $CLASS$ + { + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod] + public void Test() + { + $END$ + } + } +} + True + getFileNameWithoutExtension() + -1 + 2 + True + fileheader() + -1 + 0 + True + fileDefaultNamespace() + -1 + 1 + True + InCSharpProjectFile + True + True + MSTest + Inset a TestInitialize method + True + testInitialize + True + [$TestInitializeAttribute$] +public void TestInitialize() +{ + $END$ +} + True + fixedTypeName("Microsoft.VisualStudio.TestTools.UnitTesting.TestInitializeAttribute") + -1 + 0 + True + 2.0 + InCSharpFile + True + True + XAML + True + propdpReadOnly + True + #region $PropertyName$ + +public $Type$ $PropertyName$ +{ + get { return ($Type$)this.GetValue($PropertyName$Property); } + private set { this.SetValue($PropertyName$PropertyKey, value); } +} + +private static readonly $DependencyPropertyKey$ $PropertyName$PropertyKey = $DependencyProperty$.RegisterReadOnly( + nameof($PropertyName$), typeof($Type$), typeof($containingType$), new $PropertyMetadata$(default($Type$))); + +public static readonly $DependencyProperty$ $PropertyName$Property = $PropertyName$PropertyKey.DependencyProperty; + +#endregion + True + typeName() + -1 + 2 + True + fixedTypeName("System.Windows.DependencyProperty") + -1 + 4 + True + fixedTypeName("System.Windows.DependencyPropertyKey") + -1 + 3 + True + fixedTypeName("System.Windows.PropertyMetadata") + -1 + 5 + True + 1 + 1 + True + parameterOfType("System.Boolean") + 0 + True + 3.0 + InCSharpTypeMember + True + True + MSTest + True + testCleanup + True + [$TestCleanupAttribute$] +public void TestCleanup() +{ + $END$ +} + True + fixedTypeName("Microsoft.VisualStudio.TestTools.UnitTesting.TestCleanupAttribute") + -1 + 0 + True + 2.0 + InCSharpFile + True + True + Adds the basic implementation of IComparable methods + True + compareMethods + True + #region IComparable Member + +[Pure] +public int CompareTo([CanBeNull] object obj) +{ + return this.CompareTo(obj as $ContainingType$); +} + +[Pure] +public int CompareTo([CanBeNull] $ContainingType$ other) +{ + if (other == null) + { + return 1; + } + return $END$; +} + +#endregion + True + typeName() + -1 + 0 + True + 2.0 + InCSharpFile + True + True + MSTest + True + testClassCleanup + True + [$ClassCleanupAttribute$] +public static void ClassInitialize() +{ + $END$ +} + True + fixedTypeName("Microsoft.VisualStudio.TestTools.UnitTesting.ClassCleanupAttribute") + -1 + 0 + True + 2.0 + InCSharpFile + True + True + XAML + True + routedEvent + True + #region $Name$ + +public event $RoutedEventHandler$ $Name$ +{ + add { this.AddHandler($Name$Event, value); } + remove { this.RemoveHandler($Name$Event, value); } +} + +public static readonly $RoutedEvent$ $Name$Event = $EventManager$.RegisterRoutedEvent( + nameof($Name$), $RoutingStrategy$.Bubble, typeof($RoutedEventHandler$), typeof($containingType$)); + +#endregion + True + typeName() + -1 + 1 + True + fixedTypeName("System.Windows.EventManager") + -1 + 5 + True + 1 + 0 + True + fixedTypeName("System.Windows.RoutedEvent") + -1 + 4 + True + fixedTypeName("System.Windows.RoutedEventHandler") + -1 + 3 + True + fixedTypeName("System.Windows.RoutingStrategy") + -1 + 2 + True + 3.0 + InCSharpTypeMember + True + True + True + cbn + True + [CanBeNull] + True + 2.0 + InCSharpFile + True + Convert .ShouldBeFalse() to Assert.IsFalse() + True + CSHARP + Convert to Assert.IsFalse($exp$) + Microsoft.VisualStudio.TestTools.UnitTesting.Assert.IsFalse($exp$) + $exp$.ShouldBeFalse() + True + True + System.Boolean + ExpressionPlaceholder + True + Redundant 'ICollection.Count()' call + True + CSHARP + Use 'Count' instead + $collection$.Count + $collection$.Count() + ERROR + True + False + System.Collections.ICollection + ExpressionPlaceholder + True + Convert Assert.IsTrue() + True + CSHARP + Convert to $exp$.ShouldBeTrue() + $exp$.ShouldBeTrue() + $Assert$.IsTrue($exp$) + HINT + True + False + Microsoft.VisualStudio.TestTools.UnitTesting.Assert + TypePlaceholder + True + False + System.Object + ExpressionPlaceholder + True + Comparing 'null' with variable + False + False + False + True + CSHARP + False + False + Compare variable with 'null' + if($expr$ == null) $stmt$ + if(null == $expr$) $stmt$ + SUGGESTION + False + False + Never + False + True + False + + ExpressionPlaceholder + True + -1 + -1 + StatementPlaceholder + True + Negation of ICollection.HasItems() + True + CSHARP + False + Replace !$collection$.HasItems() with $collection$.IsNullOrEmpty() + $collection$.IsNullOrEmpty() + !$collection$.HasItems() + SUGGESTION + True + False + System.Collections.ICollection + ExpressionPlaceholder + True + Negation of ICollection.IsNullOrEmpty() + True + CSHARP + False + Replace !$collection$.IsNullOrEmpty() with $collection$.HasItems() + $collection$.HasItems() + !$collection$.IsNullOrEmpty() + SUGGESTION + True + False + System.Collections.ICollection + ExpressionPlaceholder + True + Convert .ShouldBeTrue() to Assert.IsTrue() + True + CSHARP + Convert to Assert.IsTrue($exp$) + Microsoft.VisualStudio.TestTools.UnitTesting.Assert.IsTrue($exp$) + $exp$.ShouldBeTrue() + True + True + System.Boolean + ExpressionPlaceholder + True + Possible misuse of overloaded constructor + True + CSHARP + Use new $PropertyMetadata$((object)null) + new $PropertyMetadata$((object)null) + new $PropertyMetadata$(null) + WARNING + True + True + System.Object + TypePlaceholder + True + False + System.Windows.PropertyMetadata + TypePlaceholder + True + Possible unintended use of local time + True + CSHARP + Use $dateTime$.UtcNow.Date instead (and convert to local time if needed) + $dateTime$.UtcNow.Date + $dateTime$.Today + ERROR + True + True + System.DateTime + ExpressionPlaceholder + True + Convert Assert.AreEqual() to .ShouldBe() with Comment + True + CSHARP + Convert to $expActual$.ShouldBe($expExpected$, $comment$) + $expActual$.ShouldBe($expExpected$, $comment$) + $Assert$.AreEqual($expExpected$, $expActual$, $comment$) + HINT + True + False + Microsoft.VisualStudio.TestTools.UnitTesting.Assert + Microsoft.VisualStudio.TestTools.UnitTesting.Assert + ExpressionPlaceholder + True + False + System.String + 1 + 1 + ArgumentPlaceholder + True + False + System.Object + ExpressionPlaceholder + True + 1 + 1 + ArgumentPlaceholder + True + 1 + 1 + ArgumentPlaceholder + True + Convert '(T)GetValue(DP)' to 'GetValue<T>(DP)' + True + False + System.Windows.DependencyProperty + ExpressionPlaceholder + True + False + + TypePlaceholder + True + CSHARP + False + Replace with 'GetValue<$type$>($DependencyProperty$)' + this.GetValue<$type$>($DependencyProperty$) + ($type$)this.GetValue($DependencyProperty$) + SUGGESTION + True + Redundant 'Array.Any()' call + True + CSHARP + Use 'Array.Length > 0' instead + $array$.Length > 0 + $array$.Any() + ERROR + True + False + System.Array + ExpressionPlaceholder + True + Redundant 'Array.Count()' call + True + CSHARP + Use 'Length' instead + $array$.Length + $array$.Count() + ERROR + True + False + System.Array + ExpressionPlaceholder + True + Return type should be Task for async TestMethod + True + CSHARP + Replace return type with Task + [$TestMethod$] +public async System.Threading.Tasks.Task $TestMethodName$() +{ + $TestMethodBody$ +} + [$TestMethod$] +public async void $TestMethodName$() +{ + $TestMethodBody$ +} + ERROR + True + False + + TypePlaceholder + True + -1 + -1 + StatementPlaceholder + True + True + False + + IdentifierPlaceholder + True + False + + TypePlaceholder + True + This may throw TaskCanceledException, $action$ should return a $task$ instead of void + CSHARP + $task$.Run($action$, $ct$) + ERROR + True + False + System.Action + ExpressionPlaceholder + True + False + System.Threading.CancellationToken + ExpressionPlaceholder + True + False + System.Threading.Tasks.Task + TypePlaceholder + True + Convert Assert.AreEqual() to .ShouldBe() + True + CSHARP + Convert to $expActual$.ShouldBe($expExpected$) + $expActual$.ShouldBe($expExpected$) + $Assert$.AreEqual($expExpected$, $expActual$) + HINT + True + False + Microsoft.VisualStudio.TestTools.UnitTesting.Assert + ExpressionPlaceholder + True + 1 + 1 + ArgumentPlaceholder + True + 1 + 1 + ArgumentPlaceholder + True + Convert 'SetValue(DP, bool)' to 'SetValueBox(DP, bool)' + True + True + System.Windows.DependencyProperty + ExpressionPlaceholder + True + True + System.Boolean + ExpressionPlaceholder + True + CSHARP + False + Replace with 'SetValueBox($DependencyProperty$, $value$)' + this.SetValueBox($DependencyProperty$, $value$) + this.SetValue($DependencyProperty$, $value$) + SUGGESTION + True + Convert 'SetValue(DPK, bool)' to 'SetValueBox(DPK, bool)' + True + True + System.Windows.DependencyPropertyKey + ExpressionPlaceholder + True + True + System.Boolean + ExpressionPlaceholder + True + CSHARP + False + Replace with 'SetValueBox($DependencyProperty$, $value$)' + this.SetValueBox($DependencyProperty$, $value$) + this.SetValue($DependencyProperty$, $value$) + SUGGESTION + True + Convert Assert.IsFalse() to .ShouldBeFalse() + True + CSHARP + Convert to $exp$.ShouldBeFalse() + $exp$.ShouldBeFalse() + $Assert$.IsFalse($exp$) + HINT + True + False + Microsoft.VisualStudio.TestTools.UnitTesting.Assert + TypePlaceholder + True + False + System.Object + ExpressionPlaceholder + True + ExpectedException is deprecated + False + True + CSHARP + Use Exception.Expect + $ExpectedException$ + ERROR + False + True + False + System.Exception + TypePlaceholder + True + False + Microsoft.VisualStudio.TestTools.UnitTesting.ExpectedExceptionBaseAttribute + TypePlaceholder + True + Redundant Boolean conversion + True + CSHARP + $input$ + $Convert$.ToBoolean($input$) + ERROR + True + True + System.Convert + TypePlaceholder + True + True + System.Boolean + ExpressionPlaceholder + True + Possible unintended use of local time + True + CSHARP + Use DateTime.UtcNow instead (and convert to local time if needed) + $dateTime$.UtcNow + $dateTime$.Now + ERROR + True + True + System.DateTime + ExpressionPlaceholder + True + Redundant KeyCollection iteration + True + CSHARP + Replace with ContainsKey + $dic$.ContainsKey($exp$) + $dic$.Keys.Contains($exp$) + ERROR + True + False + System.Collections.IDictionary + ExpressionPlaceholder + True + True + + ExpressionPlaceholder + SUGGESTION + True + Negation of string.HasContent() + True + CSHARP + False + Replace !$string$.HasContent() with $string$.IsNullOrEmpty() + $string$.IsNullOrEmpty() + !$string$.HasContent() + SUGGESTION + True + False + System.String + ExpressionPlaceholder + True + Redundant 'Array.ToArray()' call + True + CSHARP + Remove redundant 'ToArray' + $array$ + $array$.ToArray() + ERROR + True + False + System.Array + ExpressionPlaceholder + True + Negation of string.IsNullOrEmpty() + True + CSHARP + False + Replace !$string$.IsNullOrEmpty() with $string$.HasContent() + $string$.HasContent() + !$string$.IsNullOrEmpty() + SUGGESTION + True + False + System.String + ExpressionPlaceholder + False + diff --git a/Source/Common.props b/Source/Common.props deleted file mode 100644 index f7e1e90..0000000 --- a/Source/Common.props +++ /dev/null @@ -1,31 +0,0 @@ - - - - - false - false - - - - - - - - - - - - - embedded - - - - - true - - - - - - - \ No newline at end of file diff --git a/Source/Directory.Build.props b/Source/Directory.Build.props index 9aad919..2544469 100644 --- a/Source/Directory.Build.props +++ b/Source/Directory.Build.props @@ -1,25 +1,108 @@ - + - 12.0 + preview latest-recommended + + true enable + + enable en true true + $(DefaultItemExcludes);**\*.DotSettings + + false + true + false + true + true + false + + + + + + + + + true + + $(NoWarn);CS1591 + - - true true - - $(DefaultItemExcludes);**\*.DotSettings - + + + + + net9.0 + + false + false + + + embedded + + + + + + + + + + + + + + + + + + net9.0 + + false + false + + $(MSBuildThisFileDirectory)\Default.runsettings + + + + + + + + + + + true + + + true + + + + + + + + + net9.0 + + false + false + + + + \ No newline at end of file diff --git a/Source/Launchbar.sln b/Source/Launchbar.sln index 434fd2d..6f7ae62 100644 --- a/Source/Launchbar.sln +++ b/Source/Launchbar.sln @@ -9,10 +9,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject ..\.editorconfig = ..\.editorconfig ..\CHANGELOG.md = ..\CHANGELOG.md - Common.props = Common.props Directory.Build.props = Directory.Build.props Directory.Packages.props = Directory.Packages.props ..\.github\workflows\dotnet.yml = ..\.github\workflows\dotnet.yml + Product.props = Product.props EndProjectSection EndProject Global diff --git a/Source/Launchbar.sln.DotSettings b/Source/Launchbar.sln.DotSettings new file mode 100644 index 0000000..391bf9d --- /dev/null +++ b/Source/Launchbar.sln.DotSettings @@ -0,0 +1,6 @@ + + ..\..\ReSharper.Global.DotSettings + True + True + 1 + \ No newline at end of file diff --git a/Source/Launchbar/Launchbar.csproj b/Source/Launchbar/Launchbar.csproj index 50b19e1..ba5cb49 100644 --- a/Source/Launchbar/Launchbar.csproj +++ b/Source/Launchbar/Launchbar.csproj @@ -1,30 +1,31 @@  - net9.0-windows true WinExe - true - Resources\Next.ico - 5.2.0-preview.4 - Launchbar - RunIT to the next level. - Copyright © Mertsch $([System.DateTime]::UtcNow.Year) + true false + + true + Resources\Next.ico + RunIT to the next level. + + + PublicResXFileCodeGenerator diff --git a/Source/Launchbar/Menu.cs b/Source/Launchbar/Menu.cs index c0a65df..209e806 100644 --- a/Source/Launchbar/Menu.cs +++ b/Source/Launchbar/Menu.cs @@ -1,4 +1,4 @@ -using System.Collections.ObjectModel; +using System.Collections.ObjectModel; using System.Windows.Threading; namespace Launchbar; @@ -20,7 +20,7 @@ public sealed class Menu : NotifyBase /// public MenuEntryCollection? Entries { - get { return this.entries; } + get => this.entries; set { if (this.entries == value) diff --git a/Source/Launchbar/MenuEntry.cs b/Source/Launchbar/MenuEntry.cs index 274f8a7..50063a0 100644 --- a/Source/Launchbar/MenuEntry.cs +++ b/Source/Launchbar/MenuEntry.cs @@ -1,4 +1,4 @@ -using System.Xml.Serialization; +using System.Xml.Serialization; namespace Launchbar; @@ -13,22 +13,20 @@ public class MenuEntry : NotifyBase { public const string IsSelectedProperty = "IsSelected"; - private bool isSelected; - /// /// Gets or sets whether this object is selected. /// [XmlIgnore] public bool IsSelected { - get { return this.isSelected; } + get; set { - if (this.isSelected == value) + if (field == value) { return; } - this.isSelected = value; + field = value; this.OnPropertyChanged(IsSelectedProperty); } } diff --git a/Source/Launchbar/MenuEntryAdvanced.cs b/Source/Launchbar/MenuEntryAdvanced.cs index 8c1f2ff..2d2f609 100644 --- a/Source/Launchbar/MenuEntryAdvanced.cs +++ b/Source/Launchbar/MenuEntryAdvanced.cs @@ -1,4 +1,4 @@ -using Launchbar.Win32; +using Launchbar.Win32; using System.Windows.Media; using System.Xml.Serialization; @@ -13,16 +13,10 @@ public class MenuEntryAdvanced : MenuEntry { #region Fields - private string? text; - private string? iconPath; private int iconIndex; - private ImageSource? icon; - - private IconType iconType = IconType.Default; - #endregion #region Properties @@ -32,14 +26,14 @@ public class MenuEntryAdvanced : MenuEntry /// public string? Text { - get { return this.text; } + get; set { - if (this.text == value) + if (field == value) { return; } - this.text = value; + field = value; this.OnPropertyChanged(nameof(this.Text)); } } @@ -49,7 +43,7 @@ public string? Text /// public string? IconPath { - get { return this.iconPath; } + get => this.iconPath; set { if (value == string.Empty) @@ -71,7 +65,7 @@ public string? IconPath /// public int IconIndex { - get { return this.iconIndex; } + get => this.iconIndex; set { if (this.iconIndex == value) @@ -90,17 +84,17 @@ public int IconIndex [XmlIgnore] public IconType IconType { - get { return this.iconType; } + get; private set { - if (this.iconType == value) + if (field == value) { return; } - this.iconType = value; + field = value; this.OnPropertyChanged(nameof(this.IconType)); } - } + } = IconType.Default; /// /// Gets the icon to display when is set to . @@ -108,14 +102,14 @@ private set [XmlIgnore] public ImageSource? Icon { - get { return this.icon; } + get; private set { - if (this.icon == value) + if (field == value) { return; } - this.icon = value; + field = value; this.OnPropertyChanged(nameof(this.Icon)); } } diff --git a/Source/Launchbar/Program.cs b/Source/Launchbar/Program.cs index fdc4ec2..5e8377c 100644 --- a/Source/Launchbar/Program.cs +++ b/Source/Launchbar/Program.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using System.IO; using System.Windows; using System.Windows.Input; @@ -12,14 +12,10 @@ public sealed class Program : MenuEntryAdvanced, ICommand { #region Fields - private string? path; - private string? pathAbsolute; private string? arguments; - private ProcessPriorityClass priority = ProcessPriorityClass.Normal; - #endregion #region Properties @@ -29,18 +25,18 @@ public sealed class Program : MenuEntryAdvanced, ICommand /// public string? Path { - get { return this.path; } + get; set { if (value == string.Empty) { value = null; } - if (this.path == value) + if (field == value) { return; } - this.path = value; + field = value; this.pathAbsolute = value == null ? null : Environment.ExpandEnvironmentVariables(value); this.OnPropertyChanged(nameof(this.Path)); @@ -81,17 +77,17 @@ public string? Arguments /// public ProcessPriorityClass Priority { - get { return this.priority; } + get; set { - if (this.priority == value) + if (field == value) { return; } - this.priority = value; + field = value; this.OnPropertyChanged(nameof(this.Priority)); } - } + } = ProcessPriorityClass.Normal; /// /// Does the specified path point to an existing file? diff --git a/Source/Launchbar/Submenu.cs b/Source/Launchbar/Submenu.cs index 1f541e6..23d63a8 100644 --- a/Source/Launchbar/Submenu.cs +++ b/Source/Launchbar/Submenu.cs @@ -1,4 +1,4 @@ -using System.Xml.Serialization; +using System.Xml.Serialization; namespace Launchbar; @@ -11,8 +11,6 @@ public sealed class Submenu : MenuEntryAdvanced private MenuEntryCollection entries; - private bool isExpanded; - #endregion /// @@ -21,14 +19,14 @@ public sealed class Submenu : MenuEntryAdvanced [XmlIgnore] public bool IsExpanded { - get { return this.isExpanded; } + get; set { - if (this.isExpanded == value) + if (field == value) { return; } - this.isExpanded = value; + field = value; this.OnPropertyChanged(nameof(this.IsExpanded)); } } diff --git a/Source/Product.props b/Source/Product.props new file mode 100644 index 0000000..9db75c2 --- /dev/null +++ b/Source/Product.props @@ -0,0 +1,11 @@ + + + + Launchbar + 5.2.0-preview.4 + 5.2.0.4 + + Copyright © Mertsch $([System.DateTime]::UtcNow.Year) + + + \ No newline at end of file From bf46ab8e8b91b6502a159b691e4c996ef8005a0f Mon Sep 17 00:00:00 2001 From: Mertsch Date: Wed, 18 Jun 2025 12:54:41 +0200 Subject: [PATCH 13/18] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7c8716..4524006 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [5.2.0] - 2025-01-15 +## [5.2.0] - 2026-06-18 ### Changed - Upgrade to .NET 9.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/9.0/runtime) to run +- A lot of internal refactoring to use modern .NET 8.0 and .NET 9.0 features. ## [5.1.0] - 2023-01-01 ### Changed From 8403f8dbd02ac87d8ab19fe3089c43808c818b5f Mon Sep 17 00:00:00 2001 From: Mertsch Date: Wed, 18 Jun 2025 13:45:49 +0200 Subject: [PATCH 14/18] Update readme and build on tags --- .github/workflows/dotnet.yml | 8 ++++++++ README.md | 11 +++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index a6219a0..af493ab 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -4,6 +4,8 @@ on: push: branches: - '*' + tags: + - '*' pull_request: branches: - '*' @@ -14,18 +16,24 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: 9.x + - name: Restore dependencies run: dotnet restore Source/Launchbar.sln + - name: Build run: dotnet build Source/Launchbar.sln --no-restore --configuration Release + - name: Test run: dotnet test Source/Launchbar.sln --no-build --verbosity normal + - name: Publish run: dotnet publish Source/Launchbar.sln --no-build --configuration Release + - name: Upload uses: actions/upload-artifact@v4 with: diff --git a/README.md b/README.md index 72ec1de..e94c71f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# Launchbar +Launchbar +=== Access all your favorite applications and files with only 2 clicks. No precise mouse movement required, no bloat, no extensions, just a simple launcher. @@ -9,8 +10,6 @@ No precise mouse movement required, no bloat, no extensions, just a simple launc ### What do others say? Check out these sites for a pretty accurate description of Launchbar. -http://www.freewaregenius.com/looking-for-a-simple-practical-launcher-try-launchbar-4-for-windows -http://www.addictivetips.com/windows-tips/launchbar-a-powerful-application-launcher-with-multi-monitor-support - -http://www.softpedia.com/get/System/Launchers-Shutdown-Tools/Launchbar.shtml -https://www.windows7download.com/win7-launchbar/fqgtfajl.html +- [Looking for a simple, practical launcher? Try Launchbar 4 for Windows](https://www.freewaregenius.com/looking-for-a-simple-practical-launcher-try-launchbar-4-for-windows) +- [Launchbar: A Powerful Application Launcher With Multi-Monitor Support](https://www.addictivetips.com/windows-tips/launchbar-a-powerful-application-launcher-with-multi-monitor-support) +- [An efficient and intuitive Windows 7 software for lightning-fast app launching.](https://www.windows7download.com/win7-launchbar/fqgtfajl.html) From 72e92de58ba1a373b290668a1ce749b4890985c6 Mon Sep 17 00:00:00 2001 From: Mertsch Date: Wed, 18 Jun 2025 14:02:22 +0200 Subject: [PATCH 15/18] Update readme --- README.md | 4 +++- Screenshot 01.png => Screenshot.png | Bin 2 files changed, 3 insertions(+), 1 deletion(-) rename Screenshot 01.png => Screenshot.png (100%) diff --git a/README.md b/README.md index e94c71f..941aae9 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,13 @@ No precise mouse movement required, no bloat, no extensions, just a simple launc **[Download Launchbar here](https://github.com/Mertsch/Launchbar/releases)** -![Launchbar in action](https://raw.githubusercontent.com/Mertsch/Launchbar/master/Screenshot%2001.png) +![Launchbar in action]() ### What do others say? Check out these sites for a pretty accurate description of Launchbar. - [Looking for a simple, practical launcher? Try Launchbar 4 for Windows](https://www.freewaregenius.com/looking-for-a-simple-practical-launcher-try-launchbar-4-for-windows) - [Launchbar: A Powerful Application Launcher With Multi-Monitor Support](https://www.addictivetips.com/windows-tips/launchbar-a-powerful-application-launcher-with-multi-monitor-support) +- [Launchbar: Streamline Your Windows 10 Experience!](https://www.windows10download.com/launchbar/) - [An efficient and intuitive Windows 7 software for lightning-fast app launching.](https://www.windows7download.com/win7-launchbar/fqgtfajl.html) +- [Launchbar is a handy utility that you can use to deploy any program with a simple click.](https://www.top4download.com/launchbar/xppdsttt.html) diff --git a/Screenshot 01.png b/Screenshot.png similarity index 100% rename from Screenshot 01.png rename to Screenshot.png From 925b04ae662866a6d736d9466c1203329f4eb8e4 Mon Sep 17 00:00:00 2001 From: Mertsch Date: Fri, 21 Nov 2025 10:26:11 +0100 Subject: [PATCH 16/18] upgrade to .NET 10 --- .editorconfig | 141 ++++++++++++++---- .github/workflows/Launchbar-CI.yaml | 39 +++++ .github/workflows/dotnet.yml | 42 ------ CHANGELOG.md | 15 +- ReSharper.Global.DotSettings | 1 + Source/Directory.Packages.props | 4 +- Source/Launchbar.sln | 35 ----- Source/Launchbar.slnx | 12 ++ ...DotSettings => Launchbar.slnx.DotSettings} | 0 Source/Launchbar/App.xaml | 23 ++- Source/Launchbar/App.xaml.cs | 9 +- Source/Launchbar/Launchbar.csproj | 2 +- Source/Launchbar/Resources/Aero.Extended.xaml | 4 +- Source/Launchbar/Shapes/ShapeApplication.xaml | 34 +++-- .../Launchbar/Shapes/ShapeApplication.xaml.cs | 7 +- Source/Launchbar/Shapes/ShapeClose.xaml | 40 ++--- Source/Launchbar/Shapes/ShapeClose.xaml.cs | 7 +- Source/Launchbar/Shapes/ShapeDelete.xaml | 22 +-- Source/Launchbar/Shapes/ShapeDelete.xaml.cs | 10 +- Source/Launchbar/Shapes/ShapeFolder.xaml | 54 +++---- Source/Launchbar/Shapes/ShapeFolder.xaml.cs | 8 +- Source/Launchbar/Shapes/ShapeFolderGoTo.xaml | 41 ++--- .../Launchbar/Shapes/ShapeFolderGoTo.xaml.cs | 7 +- Source/Launchbar/Shapes/ShapeMonitor.xaml | 58 +++---- Source/Launchbar/Shapes/ShapeMonitor.xaml.cs | 7 +- Source/Launchbar/Shapes/ShapeNext.xaml | 55 +++---- Source/Launchbar/Shapes/ShapeNext.xaml.cs | 7 +- Source/Launchbar/Shapes/ShapePlus.xaml | 12 +- Source/Launchbar/Shapes/ShapePlus.xaml.cs | 3 - Source/Launchbar/Shapes/ShapeWarning.xaml | 49 +++--- Source/Launchbar/Shapes/ShapeWarning.xaml.cs | 7 +- Source/Launchbar/WindowBar.xaml | 16 +- Source/Launchbar/WindowSettings.xaml | 34 +++-- Source/NuGet.config | 10 -- Source/Product.props | 4 +- Source/global.json | 6 + 36 files changed, 443 insertions(+), 382 deletions(-) create mode 100644 .github/workflows/Launchbar-CI.yaml delete mode 100644 .github/workflows/dotnet.yml delete mode 100644 Source/Launchbar.sln create mode 100644 Source/Launchbar.slnx rename Source/{Launchbar.sln.DotSettings => Launchbar.slnx.DotSettings} (100%) delete mode 100644 Source/NuGet.config create mode 100644 Source/global.json diff --git a/.editorconfig b/.editorconfig index 79c5cd1..51c5e5f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,12 +1,47 @@ -[*.cs] +root = true # Do NOT inherit any higher level settings. + +[*.cs] +# IDE0005: Remove unnecessary using directives (https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005) +dotnet_diagnostic.IDE0005.severity = suggestion +# IDE0017: Object initialization can be simplified (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0017) +dotnet_diagnostic.IDE0017.severity = suggestion +# IDE0022: Use expression body for methods (https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0022) +dotnet_diagnostic.IDE0022.severity = silent # IDE0028: Simplify collection initialization dotnet_diagnostic.IDE0028.severity = silent # IDE0037: Use inferred member name dotnet_diagnostic.IDE0037.severity = none -# IDE0063: Use simple 'using' statement -csharp_prefer_simple_using_statement = true:none +# IDE0045: 'if' statement can be simplified (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0045) +dotnet_diagnostic.IDE0045.severity = silent +# IDE0046: Use conditional expression for return (https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0046) +dotnet_diagnostic.IDE0046.severity = none +# IDE0055: Formatting rule (https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0055) +dotnet_diagnostic.IDE0055.severity = none +# IDE0057: Substring can be simplified (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0057) +dotnet_diagnostic.IDE0057.severity = suggestion +# IDE0058: Expression value is never used (https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0058) +dotnet_diagnostic.IDE0058.severity = none +# IDE0063: Use simple 'using' statement (https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0063) +csharp_prefer_simple_using_statement = false +dotnet_diagnostic.IDE0063.severity = none +# IDE0078: Use pattern matching (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0078) +dotnet_diagnostic.IDE0078.severity = warning # IDE0090: Use 'new(...)' dotnet_diagnostic.IDE0090.severity = silent +# IDE0220: Add explicit cast (https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0220) +dotnet_diagnostic.IDE0220.severity = warning +# IDE0220: Add explicit cast (https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0220#dotnet_style_prefer_foreach_explicit_cast_in_source) +dotnet_style_prefer_foreach_explicit_cast_in_source = always +# IDE0270: Null check can be simplified (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0270) +dotnet_diagnostic.IDE0270.severity = suggestion +# IDE0280: Use 'nameof' +dotnet_diagnostic.IDE0280.severity = warning +# IDE0290: Use primary constructor - It's a case by case choice. +dotnet_diagnostic.IDE0290.severity = silent +# IDE0305: Collection initialization can be simplified (https://github.com/dotnet/roslyn/issues/70656) +dotnet_diagnostic.IDE0305.severity = silent # Some suggestions are bad. +# IDE1006: Naming rule violation - Sadly, the 'Naming styles' are not sufficient enough, use ReSharper! +dotnet_diagnostic.IDE1006.severity = none # CA1024: Use properties where appropriate dotnet_diagnostic.CA1024.severity = none @@ -38,67 +73,100 @@ dotnet_diagnostic.CA1822.severity = silent dotnet_diagnostic.CA1847.severity = warning # CA1848: Use the LoggerMessage delegates dotnet_diagnostic.CA1848.severity = silent +# CA1863: Use 'CompositeFormat' - The default is warning and in some cases it's not true +dotnet_diagnostic.CA1863.severity = suggestion # CA2007: Consider calling ConfigureAwait on the awaited task dotnet_diagnostic.CA2007.severity = none +# CA2016: Forward the 'CancellationToken' parameter to methods +dotnet_diagnostic.CA2016.severity = suggestion # R# is better at this, pointing to the corect method, instead of the whole call. # CA2201: Do not raise reserved exception types dotnet_diagnostic.CA2201.severity = error # CA2234: Pass system uri objects instead of strings dotnet_diagnostic.CA2234.severity = none -# CS8602: Dereference of a possibly null reference. +# CS1591: Missing XML comment for publicly visible type or member (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs1591) +dotnet_diagnostic.CS1591.severity = none +# CS8602: Dereference of a possibly null reference (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/nullable-warnings#possible-dereference-of-null) dotnet_diagnostic.CS8602.severity = error +# MSTEST0016: Test class should have test method (https://learn.microsoft.com/en-us/dotnet/core/testing/mstest-analyzers/mstest0016) +dotnet_diagnostic.MSTEST0016.severity = warning +# MSTEST0039: Use newer methods to assert exceptions (https://learn.microsoft.com/en-us/dotnet/core/testing/mstest-analyzers/mstest0039) +dotnet_diagnostic.MSTEST0039.severity = warning +# MSTEST0042: Avoid duplicated 'DataRow' entries (https://learn.microsoft.com/en-us/dotnet/core/testing/mstest-analyzers/mstest0042) +dotnet_diagnostic.MSTEST0042.severity = warning +# MSTEST0049: Flow TestContext.CancellationToken to async operations (https://learn.microsoft.com/en-us/dotnet/core/testing/mstest-analyzers/mstest0049) +dotnet_diagnostic.MSTEST0049.severity = warning + [*.{cs,vb}] -dotnet_style_qualification_for_field=true:silent -dotnet_style_qualification_for_property=true:silent -dotnet_style_qualification_for_method=true:silent -dotnet_style_qualification_for_event=true:silent +csharp_style_expression_bodied_methods = when_on_single_line +csharp_style_expression_bodied_accessors = when_on_single_line # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0027 +csharp_style_expression_bodied_operators = when_on_single_line # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0023 +csharp_style_namespace_declarations = file_scoped + +dotnet_sort_system_directives_first = false + +dotnet_style_qualification_for_field = true:silent +dotnet_style_qualification_for_property = true:silent +dotnet_style_qualification_for_method = true:silent +dotnet_style_qualification_for_event = true:silent -# ■■■ Naming rules ■■■ +# ■■■ Naming styles ■■■ + +# ■■ Non-functional Rules (matching only happens on the 'symbols' (Specification), not the 'style' (Suffix)). -# Dependency Property backend field - public static readonly DependencyProperty MyProperty = DependencyProperty.Register(...) +# ■ Dependency Property backend field - public static readonly DependencyProperty MyProperty = DependencyProperty.Register(...) dotnet_naming_rule.PublicStaticReadonlyField.severity = warning -dotnet_naming_rule.PublicStaticReadonlyField.symbols = public_static_readonly_field +dotnet_naming_rule.PublicStaticReadonlyField.symbols = public_static_readonly_fields dotnet_naming_rule.PublicStaticReadonlyField.style = PascalCaseProperty -# Public static readonly field (Default) - public static readonly TypeOfField MyFieldName = ... +# ■ Public static readonly field (Default) - public static readonly TypeOfField MyFieldName = ... dotnet_naming_rule.PublicStaticReadonlyField.severity = warning -dotnet_naming_rule.PublicStaticReadonlyField.symbols = public_static_readonly_field +dotnet_naming_rule.PublicStaticReadonlyField.symbols = public_static_readonly_fields dotnet_naming_rule.PublicStaticReadonlyField.style = PascalCase -# Dependency Property backend field - private static readonly DependencyPropertyKey MyPropertyKey = DependencyProperty.RegisterReadOnly(...) +# ■ Dependency Property backend field - private static readonly DependencyPropertyKey MyPropertyKey = DependencyProperty.RegisterReadOnly(...) dotnet_naming_rule.PrivateStaticReadonlyField.severity = warning # Should be warning -dotnet_naming_rule.PrivateStaticReadonlyField.symbols = private_static_readonly_field +dotnet_naming_rule.PrivateStaticReadonlyField.symbols = private_static_readonly_fields dotnet_naming_rule.PrivateStaticReadonlyField.style = PascalCasePropertyKey -# Private static readonly field (Default) - private static readonly TypeOfField myFieldName = ... +# ■ Private static readonly field (Default) - private static readonly TypeOfField myFieldName = ... dotnet_naming_rule.PrivateStaticReadonlyField.severity = information # Should be warning -dotnet_naming_rule.PrivateStaticReadonlyField.symbols = private_static_readonly_field +dotnet_naming_rule.PrivateStaticReadonlyField.symbols = private_static_readonly_fields dotnet_naming_rule.PrivateStaticReadonlyField.style = CamelCase +# ■■ End of Non-functional Rules + dotnet_naming_rule.InstanceField.severity = suggestion -dotnet_naming_rule.InstanceField.symbols = instance_fields +dotnet_naming_rule.InstanceField.symbols = all_fields dotnet_naming_rule.InstanceField.style = CamelCase dotnet_naming_rule.ConstantField.severity = suggestion dotnet_naming_rule.ConstantField.symbols = const_fields dotnet_naming_rule.ConstantField.style = PascalCase +dotnet_naming_rule.NonPrivateField.severity = suggestion +dotnet_naming_rule.NonPrivateField.symbols = non_private_fields +dotnet_naming_rule.NonPrivateField.style = PascalCase + # ■■■ Symbol specifications ■■■ -dotnet_naming_symbols.instance_fields.applicable_kinds = field +dotnet_naming_symbols.all_fields.applicable_kinds = field dotnet_naming_symbols.const_fields.applicable_kinds = field dotnet_naming_symbols.const_fields.required_modifiers = const -dotnet_naming_symbols.public_field.applicable_kinds = field -dotnet_naming_symbols.public_field.applicable_accessibilities = public +dotnet_naming_symbols.public_fields.applicable_kinds = field +dotnet_naming_symbols.public_fields.applicable_accessibilities = public + +dotnet_naming_symbols.non_private_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_fields.applicable_accessibilities = public, internal, protected, protected_internal -dotnet_naming_symbols.private_static_readonly_field.applicable_kinds = field -dotnet_naming_symbols.private_static_readonly_field.applicable_accessibilities = private -dotnet_naming_symbols.private_static_readonly_field.required_modifiers = readonly, static +dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private +dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readonly, static -dotnet_naming_symbols.public_static_readonly_field.applicable_kinds = field -dotnet_naming_symbols.public_static_readonly_field.applicable_accessibilities = public -dotnet_naming_symbols.public_static_readonly_field.required_modifiers = readonly, static +dotnet_naming_symbols.public_static_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.public_static_readonly_fields.applicable_accessibilities = public +dotnet_naming_symbols.public_static_readonly_fields.required_modifiers = readonly, static # ■■■ Naming styles ■■■ @@ -123,8 +191,19 @@ dotnet_naming_style.PascalCaseProperty.capitalization = pascal_case dotnet_naming_style.PascalCasePropertyKey.required_suffix = PropertyKey dotnet_naming_style.PascalCasePropertyKey.capitalization = pascal_case +# ■■■ RESX Formatter ■■■ + [*.resx] -resx_formatter_sort_entries=true -resx_formatter_remove_xsd_schema=false -resx_formatter_remove_documentation_comment=true -resx_formatter_sort_comparer=OrdinalIgnoreCase \ No newline at end of file +resx_formatter_sort_entries = true +resx_formatter_remove_xsd_schema = false +resx_formatter_remove_documentation_comment = true +resx_formatter_sort_comparer = OrdinalIgnoreCase + +# ■■■ MAUI Rules ■■■ + +[*.cs] +# CsWinRT1028: Class should be marked partial +dotnet_diagnostic.CsWinRT1028.severity = warning + +# MVVMTK0034: Direct field reference to [ObservableProperty] backing field +dotnet_diagnostic.MVVMTK0034.severity = error \ No newline at end of file diff --git a/.github/workflows/Launchbar-CI.yaml b/.github/workflows/Launchbar-CI.yaml new file mode 100644 index 0000000..1d95c77 --- /dev/null +++ b/.github/workflows/Launchbar-CI.yaml @@ -0,0 +1,39 @@ +name: Build Launchbar + +on: + push: + branches: + - '*' + tags: + - '*' + pull_request: + branches: + - '*' + +jobs: + build: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v6 # https://github.com/marketplace/actions/checkout + + - name: Setup .NET + uses: actions/setup-dotnet@v5 # https://github.com/marketplace/actions/setup-net-core-sdk + with: + global-json-file: Source/global.json + + - name: Build + run: dotnet build Source/Launchbar.slnx --configuration Release + + - name: Test + run: dotnet test Source/Launchbar.slnx --configuration Release + + - name: Publish + run: dotnet publish Source/Launchbar.slnx --configuration Release + + - name: Upload + uses: actions/upload-artifact@v4 # https://github.com/marketplace/actions/upload-a-build-artifact + with: + name: Launchbar + path: Source/artifacts/publish/Launchbar/release/** + if-no-files-found: error diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml deleted file mode 100644 index af493ab..0000000 --- a/.github/workflows/dotnet.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Build Launchbar - -on: - push: - branches: - - '*' - tags: - - '*' - pull_request: - branches: - - '*' - -jobs: - build: - runs-on: windows-latest - - steps: - - uses: actions/checkout@v4 - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 9.x - - - name: Restore dependencies - run: dotnet restore Source/Launchbar.sln - - - name: Build - run: dotnet build Source/Launchbar.sln --no-restore --configuration Release - - - name: Test - run: dotnet test Source/Launchbar.sln --no-build --verbosity normal - - - name: Publish - run: dotnet publish Source/Launchbar.sln --no-build --configuration Release - - - name: Upload - uses: actions/upload-artifact@v4 - with: - name: Launchbar - path: Source/artifacts/publish/Launchbar/release/** - if-no-files-found: error diff --git a/CHANGELOG.md b/CHANGELOG.md index 4524006..a3da0dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,19 +3,24 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [5.2.0] - 2026-06-18 +## [5.3.0] - 2025-11-21 ### Changed -- Upgrade to .NET 9.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/9.0/runtime) to run +- Upgrade to .NET 10.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/10.0/runtime) to run. + +## [5.2.0] - 2025-06-18 +### Changed +- Upgrade to .NET 9.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/9.0/runtime) to run. - A lot of internal refactoring to use modern .NET 8.0 and .NET 9.0 features. ## [5.1.0] - 2023-01-01 ### Changed -- Upgrade to .NET 7.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/7.0/runtime) to run +- Upgrade to .NET 7.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/7.0/runtime) to run. ## [5.0.0] - 2021-12-15 ### Changed -- Upgrade to .NET 6.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/6.0/runtime) to run -- Changelog is now rendered with Markdown +- Upgrade to .NET 6.0, requires the [.NET Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/6.0/runtime) to run. +- Changelog is now rendered with Markdown. + ### Removed - Assembly Strong Name diff --git a/ReSharper.Global.DotSettings b/ReSharper.Global.DotSettings index dd83859..dc857ba 100644 --- a/ReSharper.Global.DotSettings +++ b/ReSharper.Global.DotSettings @@ -9,6 +9,7 @@ 1000 True $Value$ + True True True True diff --git a/Source/Directory.Packages.props b/Source/Directory.Packages.props index 35c58a7..62f7726 100644 --- a/Source/Directory.Packages.props +++ b/Source/Directory.Packages.props @@ -4,8 +4,8 @@ true - - + + diff --git a/Source/Launchbar.sln b/Source/Launchbar.sln deleted file mode 100644 index 6f7ae62..0000000 --- a/Source/Launchbar.sln +++ /dev/null @@ -1,35 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Launchbar", "Launchbar\Launchbar.csproj", "{55B26A32-A0F3-4E58-8B0F-D992D199069F}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2EDD5948-9BFA-47F7-AC71-5E19EF7522D0}" - ProjectSection(SolutionItems) = preProject - ..\.editorconfig = ..\.editorconfig - ..\CHANGELOG.md = ..\CHANGELOG.md - Directory.Build.props = Directory.Build.props - Directory.Packages.props = Directory.Packages.props - ..\.github\workflows\dotnet.yml = ..\.github\workflows\dotnet.yml - Product.props = Product.props - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {55B26A32-A0F3-4E58-8B0F-D992D199069F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {55B26A32-A0F3-4E58-8B0F-D992D199069F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {55B26A32-A0F3-4E58-8B0F-D992D199069F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {55B26A32-A0F3-4E58-8B0F-D992D199069F}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {C53CD7C1-6ECD-4648-BEC9-B2106234D6B9} - EndGlobalSection -EndGlobal diff --git a/Source/Launchbar.slnx b/Source/Launchbar.slnx new file mode 100644 index 0000000..a925400 --- /dev/null +++ b/Source/Launchbar.slnx @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/Source/Launchbar.sln.DotSettings b/Source/Launchbar.slnx.DotSettings similarity index 100% rename from Source/Launchbar.sln.DotSettings rename to Source/Launchbar.slnx.DotSettings diff --git a/Source/Launchbar/App.xaml b/Source/Launchbar/App.xaml index bb552a7..7648ebe 100644 --- a/Source/Launchbar/App.xaml +++ b/Source/Launchbar/App.xaml @@ -2,6 +2,7 @@ x:Class="Launchbar.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:lb="clr-namespace:Launchbar" xmlns:shapes="clr-namespace:Launchbar.Shapes" xmlns:p="clr-namespace:Launchbar.Properties"> @@ -25,8 +26,7 @@ + IsOpen="{Binding Path=(MenuItem.IsSubmenuOpen), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MenuItem}}}"/> @@ -66,7 +66,7 @@ - - - + ProgramStyle="{StaticResource StyleProgram}" + SubmenuStyle="{StaticResource StyleSubmenu}" + SeparatorStyle="{StaticResource StyleSeparator}" + SettingsStyle="{StaticResource StyleSettings}" + ExitStyle="{StaticResource StyleExit}"/> ()) { - if (w is WindowSettings) - { - w.Activate(); - return; - } + w.Activate(); + return; } } new WindowSettings().Show(); diff --git a/Source/Launchbar/Launchbar.csproj b/Source/Launchbar/Launchbar.csproj index ba5cb49..ab0ec1c 100644 --- a/Source/Launchbar/Launchbar.csproj +++ b/Source/Launchbar/Launchbar.csproj @@ -1,6 +1,6 @@  - net9.0-windows + net10.0-windows true WinExe diff --git a/Source/Launchbar/Resources/Aero.Extended.xaml b/Source/Launchbar/Resources/Aero.Extended.xaml index 1997360..867b5b3 100644 --- a/Source/Launchbar/Resources/Aero.Extended.xaml +++ b/Source/Launchbar/Resources/Aero.Extended.xaml @@ -283,7 +283,7 @@ VerticalAlignment="Center" ContentSource="Icon" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> - - + + - + - - + + @@ -23,26 +25,26 @@ - - + + - + - + - + @@ -50,7 +52,7 @@ - + @@ -59,11 +61,11 @@ - - + + - + \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapeApplication.xaml.cs b/Source/Launchbar/Shapes/ShapeApplication.xaml.cs index c479eef..3ed605f 100644 --- a/Source/Launchbar/Shapes/ShapeApplication.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeApplication.xaml.cs @@ -3,9 +3,6 @@ namespace Launchbar.Shapes; -/// -/// Interaction logic for ShapeApplications.xaml -/// public sealed partial class ShapeApplication : UserControl { public ShapeApplication() @@ -13,8 +10,10 @@ public ShapeApplication() this.InitializeComponent(); } - private void sizeChanged(object sender, SizeChangedEventArgs e) + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) { + base.OnRenderSizeChanged(sizeInfo); + this.scaler.ScaleX = this.ActualWidth / this.shape.Width; this.scaler.ScaleY = this.ActualHeight / this.shape.Height; } diff --git a/Source/Launchbar/Shapes/ShapeClose.xaml b/Source/Launchbar/Shapes/ShapeClose.xaml index bcdb8c2..a187de5 100644 --- a/Source/Launchbar/Shapes/ShapeClose.xaml +++ b/Source/Launchbar/Shapes/ShapeClose.xaml @@ -1,10 +1,10 @@  - + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + + @@ -24,21 +24,22 @@ - - + + - + - - + + @@ -47,8 +48,8 @@ - - + + @@ -70,21 +71,22 @@ - - + + - + - - + + @@ -93,8 +95,8 @@ - - + + @@ -104,7 +106,7 @@ - + diff --git a/Source/Launchbar/Shapes/ShapeClose.xaml.cs b/Source/Launchbar/Shapes/ShapeClose.xaml.cs index 2f24f86..03665b5 100644 --- a/Source/Launchbar/Shapes/ShapeClose.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeClose.xaml.cs @@ -5,9 +5,6 @@ namespace Launchbar.Shapes; -/// -/// Interaction logic for ShapeClose.xaml -/// public sealed partial class ShapeClose : UserControl { /// @@ -27,8 +24,10 @@ public ShapeClose() this.InitializeComponent(); } - private void sizeChanged(object sender, SizeChangedEventArgs e) + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) { + base.OnRenderSizeChanged(sizeInfo); + this.scaler.ScaleX = this.ActualWidth / this.shape.Width; this.scaler.ScaleY = this.ActualHeight / this.shape.Height; } diff --git a/Source/Launchbar/Shapes/ShapeDelete.xaml b/Source/Launchbar/Shapes/ShapeDelete.xaml index 8a00519..5b89062 100644 --- a/Source/Launchbar/Shapes/ShapeDelete.xaml +++ b/Source/Launchbar/Shapes/ShapeDelete.xaml @@ -1,38 +1,38 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + - + - - - + + + - + - - - + + + - + \ No newline at end of file diff --git a/Source/Launchbar/Shapes/ShapeDelete.xaml.cs b/Source/Launchbar/Shapes/ShapeDelete.xaml.cs index 3c3fe03..2375004 100644 --- a/Source/Launchbar/Shapes/ShapeDelete.xaml.cs +++ b/Source/Launchbar/Shapes/ShapeDelete.xaml.cs @@ -3,21 +3,17 @@ namespace Launchbar.Shapes; -/// -/// Interaction logic for ShapeDelete.xaml -/// public sealed partial class ShapeDelete : UserControl { - /// - /// Create a new instance of this class. - /// public ShapeDelete() { this.InitializeComponent(); } - private void sizeChanged(object sender, SizeChangedEventArgs e) + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) { + base.OnRenderSizeChanged(sizeInfo); + this.scaler.ScaleX = this.ActualWidth / this.shape.Width; this.scaler.ScaleY = this.ActualHeight / this.shape.Height; } diff --git a/Source/Launchbar/Shapes/ShapeFolder.xaml b/Source/Launchbar/Shapes/ShapeFolder.xaml index 8fbeee8..0edaecd 100644 --- a/Source/Launchbar/Shapes/ShapeFolder.xaml +++ b/Source/Launchbar/Shapes/ShapeFolder.xaml @@ -1,8 +1,10 @@ - - + + + @@ -10,21 +12,21 @@ - + - - + + - - + + @@ -35,7 +37,7 @@ diff --git a/Source/Product.props b/Source/Product.props index aeab39f..e1e440c 100644 --- a/Source/Product.props +++ b/Source/Product.props @@ -2,8 +2,8 @@ Launchbar - 5.3.0-preview.1 - 5.3.0.1 + 5.3.0-preview.2 + 5.3.0.2 Copyright © Mertsch $([System.DateTime]::UtcNow.Year) From ff442ad2b3d8b9d5aacbbcb919ebe2ee1ba788c3 Mon Sep 17 00:00:00 2001 From: Mertsch Date: Fri, 21 Nov 2025 10:52:25 +0100 Subject: [PATCH 18/18] 5.3.0 --- Source/Product.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Product.props b/Source/Product.props index e1e440c..44b898a 100644 --- a/Source/Product.props +++ b/Source/Product.props @@ -2,8 +2,8 @@ Launchbar - 5.3.0-preview.2 - 5.3.0.2 + 5.3.0 + 5.3.0.3 Copyright © Mertsch $([System.DateTime]::UtcNow.Year)