diff --git a/.gitignore b/.gitignore index 8a30d25..944d9c1 100644 --- a/.gitignore +++ b/.gitignore @@ -396,3 +396,4 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml +/src/TrayToolbar/Properties/launchSettings.json diff --git a/src/TrayToolbar/Controls/FolderControl.Designer.cs b/src/TrayToolbar/Controls/FolderControl.Designer.cs index cd9ae31..0744dca 100644 --- a/src/TrayToolbar/Controls/FolderControl.Designer.cs +++ b/src/TrayToolbar/Controls/FolderControl.Designer.cs @@ -48,6 +48,7 @@ private void InitializeComponent() FolderComboBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; FolderComboBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend; FolderComboBox.AutoCompleteSource = AutoCompleteSource.FileSystemDirectories; + FolderComboBox.BorderColor = SystemColors.WindowFrame; FolderComboBox.DropDownStyle = ComboBoxStyle.Simple; FolderComboBox.FormattingEnabled = true; FolderComboBox.Location = new Point(3, 3); @@ -55,11 +56,14 @@ private void InitializeComponent() FolderComboBox.Name = "FolderComboBox"; FolderComboBox.Size = new Size(330, 23); FolderComboBox.Sorted = true; - FolderComboBox.TabIndex = 6; + FolderComboBox.TabIndex = 0; FolderComboBox.TextUpdate += FolderComboBox_TextUpdate; // // BrowseFolderButton // + BrowseFolderButton.AccessibleDescription = "Browse for folder"; + BrowseFolderButton.AccessibleName = "Browse"; + BrowseFolderButton.AccessibleRole = AccessibleRole.PushButton; BrowseFolderButton.Anchor = AnchorStyles.Top | AnchorStyles.Right; BrowseFolderButton.BackgroundImage = (Image)resources.GetObject("BrowseFolderButton.BackgroundImage"); BrowseFolderButton.BackgroundImageLayout = ImageLayout.Center; @@ -72,6 +76,9 @@ private void InitializeComponent() // // DeleteFolderButton // + DeleteFolderButton.AccessibleDescription = "Remove folder"; + DeleteFolderButton.AccessibleName = "Remove"; + DeleteFolderButton.AccessibleRole = AccessibleRole.PushButton; DeleteFolderButton.Anchor = AnchorStyles.Top | AnchorStyles.Right; DeleteFolderButton.BackgroundImage = (Image)resources.GetObject("DeleteFolderButton.BackgroundImage"); DeleteFolderButton.BackgroundImageLayout = ImageLayout.Center; @@ -88,7 +95,7 @@ private void InitializeComponent() RecursiveCheckbox.Location = new Point(3, 32); RecursiveCheckbox.Name = "RecursiveCheckbox"; RecursiveCheckbox.Size = new Size(124, 19); - RecursiveCheckbox.TabIndex = 9; + RecursiveCheckbox.TabIndex = 1; RecursiveCheckbox.Text = "Include Subfolders"; RecursiveCheckbox.UseVisualStyleBackColor = true; RecursiveCheckbox.CheckedChanged += RecursiveCheckbox_CheckedChanged; diff --git a/src/TrayToolbar/Extensions/ExtensionMethods.cs b/src/TrayToolbar/Extensions/ExtensionMethods.cs index 179f4ff..8fd29dc 100644 --- a/src/TrayToolbar/Extensions/ExtensionMethods.cs +++ b/src/TrayToolbar/Extensions/ExtensionMethods.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Text.RegularExpressions; namespace TrayToolbar.Extensions { @@ -12,7 +13,7 @@ public static string FileExtension(this string file) public static Icon GetIcon(this string path) { - return ShellIcons.FetchIcon(path, true); + return ShellIcons.FetchIcon(path, false); } public static Bitmap GetImage(this string file) @@ -47,6 +48,12 @@ public static bool IsHttps(this string value) return value.HasValue() && value.StartsWith("https://"); } + public static bool IsMatch(this string? value, string pattern) + { + if (value == null) return false; + return Regex.IsMatch(value, pattern, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + } + public static string Join(this string[] value, string separator = ", ") { return string.Join(separator, value); @@ -67,5 +74,15 @@ public static void ShowContextMenu(this NotifyIcon notifyIcon) MethodInfo? mi = typeof(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.Instance | BindingFlags.NonPublic); mi?.Invoke(notifyIcon, null); } + + public static string[] SplitPaths(this string value, char[]? splitchars = null) + { + return value.Split(splitchars ?? [';', ','], StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); + } + + public static string ToMenuName(this string? value) + { + return value?.Replace("&", "&&") ?? ""; + } } } diff --git a/src/TrayToolbar/Extensions/SystemTheme.cs b/src/TrayToolbar/Extensions/SystemTheme.cs index 719802f..ae7c7a4 100644 --- a/src/TrayToolbar/Extensions/SystemTheme.cs +++ b/src/TrayToolbar/Extensions/SystemTheme.cs @@ -8,10 +8,12 @@ namespace TrayToolbar.Extensions internal class SystemTheme { const string REGKEY_THEMES = @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize"; + static bool? DarkModeEnabled = null; public unsafe static bool UseImmersiveDarkMode(IntPtr handle, bool enabled) { - if (IsDarkModeSupported()) + if (IsDarkModeSupported() && DarkModeEnabled != enabled) { + DarkModeEnabled = enabled; var form = Control.FromHandle(handle); ThemeColors.Current = enabled ? ThemeColors.Dark : ThemeColors.Light; SetThemeColors(form, enabled); diff --git a/src/TrayToolbar/Extensions/ThemeChangeMessageFilter.cs b/src/TrayToolbar/Extensions/ThemeChangeMessageFilter.cs index 6ed1acb..e7963e4 100644 --- a/src/TrayToolbar/Extensions/ThemeChangeMessageFilter.cs +++ b/src/TrayToolbar/Extensions/ThemeChangeMessageFilter.cs @@ -1,6 +1,4 @@ -using System.Diagnostics; - -namespace TrayToolbar.Extensions +namespace TrayToolbar.Extensions { internal class ThemeChangeMessageFilter : IMessageFilter { @@ -16,13 +14,10 @@ public static void Enable(bool enable) Application.AddMessageFilter(Instance); } } - else + else if (Instance != null) { - if (Instance != null) - { - Application.RemoveMessageFilter(Instance); - Instance = null; - } + Application.RemoveMessageFilter(Instance); + Instance = null; } } @@ -32,8 +27,9 @@ public static void Enable(bool enable) public bool PreFilterMessage(ref Message m) { //Debug.WriteLine($"{m.HWnd}: {m.WParam}, {m.LParam}, {m.Msg}"); - if (m.WParam == 0 && m.LParam == 0 && m.Msg == 49832 //not in the WM_* enum - && (DateTime.Now - eventTrigger).TotalMilliseconds > 100) + //TODO: I was expecting to be able to check for WM_SETTINGCHANGE but this doesn't actually consistently happen between Win 10/11 + // Look for updated documentation on how to get a message when the theme changes + if ((DateTime.Now - eventTrigger).TotalMilliseconds > 100) { ThemeChanged?.Invoke(null, EventArgs.Empty); eventTrigger = DateTime.Now; diff --git a/src/TrayToolbar/Models/MenuItemCollection.cs b/src/TrayToolbar/Models/MenuItemCollection.cs index 882f0ee..1ca7eb4 100644 --- a/src/TrayToolbar/Models/MenuItemCollection.cs +++ b/src/TrayToolbar/Models/MenuItemCollection.cs @@ -1,4 +1,5 @@ using System.Collections.ObjectModel; +using TrayToolbar.Extensions; namespace TrayToolbar { @@ -13,7 +14,7 @@ public MenuItemCollection() { } ToolStripMenuItem? parent = null; foreach (var part in parts) { - var added = AddFolder(parent, part, handler, out ToolStripMenuItem? menu); + var added = AddFolder(parent, part.ToMenuName(), handler, out ToolStripMenuItem? menu); parent = menu; if (!added && menu != null) { diff --git a/src/TrayToolbar/Models/TrayToolbarConfiguration.cs b/src/TrayToolbar/Models/TrayToolbarConfiguration.cs index 593a026..f3f6024 100644 --- a/src/TrayToolbar/Models/TrayToolbarConfiguration.cs +++ b/src/TrayToolbar/Models/TrayToolbarConfiguration.cs @@ -5,17 +5,35 @@ namespace TrayToolbar { public class TrayToolbarConfiguration { + public bool HideFileExtensions { get; set; } + + public bool IgnoreAllDotFiles { get; set; } + public string[] IgnoreFiles { get; set; } = [".bak", ".config", ".dll", ".ico", ".ini"]; + [Obsolete("IgnoreFileTypes is obsolete", true)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string[]? IgnoreFileTypes + { + get => null; + set + { + if (value != null) + IgnoreFiles = value; + } + } + + public string[] IgnoreFolders { get; set; } = [".git", ".github"]; + public int MaxRecursionDepth { get; set; } = 3; public int Theme { get; set; } = 0; - [Obsolete] + [Obsolete("Folder is obsolete", true)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string? Folder - { - get => null; + public string? Folder + { + get => null; set { if (value.HasValue()) @@ -31,7 +49,7 @@ public string? Folder public class FolderConfig { public FolderConfig() { } - public FolderConfig(string name) + public FolderConfig(string name) { Name = name; } diff --git a/src/TrayToolbar/NativeMethods.txt b/src/TrayToolbar/NativeMethods.txt index 218925e..79e9038 100644 --- a/src/TrayToolbar/NativeMethods.txt +++ b/src/TrayToolbar/NativeMethods.txt @@ -5,4 +5,5 @@ RegNotifyChangeKeyValue RegOpenKeyEx WM_MOUSE* WM_PAINT +WM_SETTINGCHANGE WINDOW_EX_STYLE \ No newline at end of file diff --git a/src/TrayToolbar/Program.cs b/src/TrayToolbar/Program.cs index d77c2ac..7e2b7b6 100644 --- a/src/TrayToolbar/Program.cs +++ b/src/TrayToolbar/Program.cs @@ -15,7 +15,12 @@ static void Main() ThemeChangeMessageFilter.Enable(true); try { - Application.Run(new SettingsForm()); + var form = new SettingsForm(); + if (Environment.GetCommandLineArgs().Contains("--show")) + { + form.Show(); + } + Application.Run(form); } catch (ObjectDisposedException) { } } diff --git a/src/TrayToolbar/Resources/Resources.Designer.cs b/src/TrayToolbar/Resources/Resources.Designer.cs index 9c4feca..1f8cb2f 100644 --- a/src/TrayToolbar/Resources/Resources.Designer.cs +++ b/src/TrayToolbar/Resources/Resources.Designer.cs @@ -115,7 +115,7 @@ internal static string Error { } /// - /// Looks up a localized string similar to Exclude files. + /// Looks up a localized string similar to Exclude file types. /// internal static string Exclude_files { get { @@ -123,6 +123,15 @@ internal static string Exclude_files { } } + /// + /// Looks up a localized string similar to Exclude folders. + /// + internal static string Exclude_folders { + get { + return ResourceManager.GetString("Exclude folders", resourceCulture); + } + } + /// /// Looks up a localized string similar to Exit. /// diff --git a/src/TrayToolbar/Resources/Resources.resx b/src/TrayToolbar/Resources/Resources.resx index a124bed..65bb4c7 100644 --- a/src/TrayToolbar/Resources/Resources.resx +++ b/src/TrayToolbar/Resources/Resources.resx @@ -136,7 +136,10 @@ Error - Exclude files + Exclude file types + + + Exclude folders Exit diff --git a/src/TrayToolbar/SettingsForm.Designer.cs b/src/TrayToolbar/SettingsForm.Designer.cs index 809fc35..54d7ad6 100644 --- a/src/TrayToolbar/SettingsForm.Designer.cs +++ b/src/TrayToolbar/SettingsForm.Designer.cs @@ -35,6 +35,8 @@ private void InitializeComponent() SaveButton = new Button(); NewVersionLabel = new LinkLabel(); tableLayout = new TableLayoutPanel(); + IgnoreFoldersTextBox = new TextBox(); + label4 = new Label(); label3 = new Label(); label1 = new Label(); label2 = new Label(); @@ -60,7 +62,7 @@ private void InitializeComponent() flowLayoutPanel1.Controls.Add(NewVersionLabel); flowLayoutPanel1.Dock = DockStyle.Bottom; flowLayoutPanel1.FlowDirection = FlowDirection.RightToLeft; - flowLayoutPanel1.Location = new Point(10, 233); + flowLayoutPanel1.Location = new Point(10, 278); flowLayoutPanel1.Name = "flowLayoutPanel1"; flowLayoutPanel1.Padding = new Padding(3); flowLayoutPanel1.Size = new Size(520, 39); @@ -74,7 +76,7 @@ private void InitializeComponent() CancelBtn.MinimumSize = new Size(100, 25); CancelBtn.Name = "CancelBtn"; CancelBtn.Size = new Size(100, 27); - CancelBtn.TabIndex = 0; + CancelBtn.TabIndex = 2; CancelBtn.Text = "Cancel"; CancelBtn.UseVisualStyleBackColor = true; CancelBtn.Click += CancelBtn_Click; @@ -104,7 +106,7 @@ private void InitializeComponent() NewVersionLabel.Name = "NewVersionLabel"; NewVersionLabel.Padding = new Padding(24, 0, 0, 0); NewVersionLabel.Size = new Size(168, 33); - NewVersionLabel.TabIndex = 2; + NewVersionLabel.TabIndex = 0; NewVersionLabel.TabStop = true; NewVersionLabel.Text = "A new version is available!"; NewVersionLabel.TextAlign = ContentAlignment.MiddleLeft; @@ -119,35 +121,60 @@ private void InitializeComponent() tableLayout.ColumnCount = 2; tableLayout.ColumnStyles.Add(new ColumnStyle()); tableLayout.ColumnStyles.Add(new ColumnStyle()); - tableLayout.Controls.Add(label3, 0, 3); + tableLayout.Controls.Add(IgnoreFoldersTextBox, 0, 3); + tableLayout.Controls.Add(label4, 0, 3); + tableLayout.Controls.Add(label3, 0, 4); tableLayout.Controls.Add(label1, 0, 0); tableLayout.Controls.Add(label2, 0, 2); tableLayout.Controls.Add(IgnoreFilesTextBox, 1, 2); - tableLayout.Controls.Add(RunOnLoginCheckbox, 1, 4); + tableLayout.Controls.Add(RunOnLoginCheckbox, 1, 5); tableLayout.Controls.Add(AddFolderButton, 1, 1); tableLayout.Controls.Add(FoldersLayout, 1, 0); - tableLayout.Controls.Add(ThemeToggleButton, 1, 3); + tableLayout.Controls.Add(ThemeToggleButton, 1, 4); tableLayout.Dock = DockStyle.Fill; tableLayout.Location = new Point(10, 10); tableLayout.Margin = new Padding(10); tableLayout.Name = "tableLayout"; - tableLayout.RowCount = 5; + tableLayout.RowCount = 6; tableLayout.RowStyles.Add(new RowStyle()); tableLayout.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F)); tableLayout.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F)); tableLayout.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F)); tableLayout.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F)); - tableLayout.Size = new Size(520, 223); + tableLayout.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F)); + tableLayout.Size = new Size(520, 268); tableLayout.TabIndex = 3; // + // IgnoreFoldersTextBox + // + IgnoreFoldersTextBox.BorderStyle = BorderStyle.FixedSingle; + IgnoreFoldersTextBox.Dock = DockStyle.Top; + IgnoreFoldersTextBox.Location = new Point(117, 128); + IgnoreFoldersTextBox.Name = "IgnoreFoldersTextBox"; + IgnoreFoldersTextBox.PlaceholderText = ".git; .github"; + IgnoreFoldersTextBox.Size = new Size(414, 23); + IgnoreFoldersTextBox.TabIndex = 2; + // + // label4 + // + label4.AutoSize = true; + label4.Dock = DockStyle.Top; + label4.Location = new Point(3, 125); + label4.Name = "label4"; + label4.Padding = new Padding(5); + label4.Size = new Size(108, 25); + label4.TabIndex = 14; + label4.Text = "Exclude folders"; + label4.TextAlign = ContentAlignment.MiddleRight; + // // label3 // label3.AutoSize = true; label3.Dock = DockStyle.Top; - label3.Location = new Point(3, 125); + label3.Location = new Point(3, 175); label3.Name = "label3"; label3.Padding = new Padding(5); - label3.Size = new Size(84, 25); + label3.Size = new Size(108, 25); label3.TabIndex = 12; label3.Text = "Theme"; label3.TextAlign = ContentAlignment.MiddleRight; @@ -159,7 +186,7 @@ private void InitializeComponent() label1.Location = new Point(3, 0); label1.Name = "label1"; label1.Padding = new Padding(5); - label1.Size = new Size(84, 25); + label1.Size = new Size(108, 25); label1.TabIndex = 0; label1.Text = "Folders"; label1.TextAlign = ContentAlignment.MiddleRight; @@ -171,28 +198,28 @@ private void InitializeComponent() label2.Location = new Point(3, 75); label2.Name = "label2"; label2.Padding = new Padding(5); - label2.Size = new Size(84, 25); + label2.Size = new Size(108, 25); label2.TabIndex = 1; - label2.Text = "Exclude Files"; + label2.Text = "Exclude file types"; label2.TextAlign = ContentAlignment.MiddleRight; // // IgnoreFilesTextBox // - IgnoreFilesTextBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; IgnoreFilesTextBox.BorderStyle = BorderStyle.FixedSingle; - IgnoreFilesTextBox.Location = new Point(93, 78); + IgnoreFilesTextBox.Dock = DockStyle.Top; + IgnoreFilesTextBox.Location = new Point(117, 78); IgnoreFilesTextBox.Name = "IgnoreFilesTextBox"; IgnoreFilesTextBox.PlaceholderText = ".bak; .config; .dll; .ico; .ini"; - IgnoreFilesTextBox.Size = new Size(424, 23); - IgnoreFilesTextBox.TabIndex = 3; + IgnoreFilesTextBox.Size = new Size(414, 23); + IgnoreFilesTextBox.TabIndex = 1; // // RunOnLoginCheckbox // RunOnLoginCheckbox.AutoSize = true; - RunOnLoginCheckbox.Location = new Point(93, 178); + RunOnLoginCheckbox.Location = new Point(117, 228); RunOnLoginCheckbox.Name = "RunOnLoginCheckbox"; RunOnLoginCheckbox.Size = new Size(97, 19); - RunOnLoginCheckbox.TabIndex = 8; + RunOnLoginCheckbox.TabIndex = 4; RunOnLoginCheckbox.Text = "Run on log in"; RunOnLoginCheckbox.UseVisualStyleBackColor = true; // @@ -201,11 +228,11 @@ private void InitializeComponent() AddFolderButton.AutoSize = true; AddFolderButton.Image = (Image)resources.GetObject("AddFolderButton.Image"); AddFolderButton.ImageAlign = ContentAlignment.MiddleLeft; - AddFolderButton.Location = new Point(93, 28); + AddFolderButton.Location = new Point(117, 28); AddFolderButton.Name = "AddFolderButton"; AddFolderButton.Padding = new Padding(32, 0, 0, 0); AddFolderButton.Size = new Size(158, 29); - AddFolderButton.TabIndex = 10; + AddFolderButton.TabIndex = 0; AddFolderButton.Text = "Add Folder"; AddFolderButton.UseVisualStyleBackColor = true; AddFolderButton.Click += AddFolderButton_Click; @@ -216,12 +243,12 @@ private void InitializeComponent() FoldersLayout.AutoSize = true; FoldersLayout.AutoSizeMode = AutoSizeMode.GrowAndShrink; FoldersLayout.FlowDirection = FlowDirection.TopDown; - FoldersLayout.Location = new Point(90, 3); + FoldersLayout.Location = new Point(114, 3); FoldersLayout.Margin = new Padding(0, 3, 0, 0); FoldersLayout.MaximumSize = new Size(450, 270); FoldersLayout.MinimumSize = new Size(420, 0); FoldersLayout.Name = "FoldersLayout"; - FoldersLayout.Size = new Size(430, 0); + FoldersLayout.Size = new Size(420, 0); FoldersLayout.TabIndex = 11; FoldersLayout.WrapContents = false; // @@ -229,10 +256,10 @@ private void InitializeComponent() // ThemeToggleButton.AutoSize = true; ThemeToggleButton.AutoSizeMode = AutoSizeMode.GrowAndShrink; - ThemeToggleButton.Location = new Point(93, 128); + ThemeToggleButton.Location = new Point(117, 178); ThemeToggleButton.Name = "ThemeToggleButton"; ThemeToggleButton.Size = new Size(182, 25); - ThemeToggleButton.TabIndex = 13; + ThemeToggleButton.TabIndex = 3; ThemeToggleButton.Theme = Models.ThemeToggleEnum.SYSTEM_THEME; ThemeToggleButton.ThemeChanged += ThemeToggleButton_ThemeChanged; // @@ -255,7 +282,7 @@ private void InitializeComponent() AutoScaleMode = AutoScaleMode.Font; AutoSize = true; AutoSizeMode = AutoSizeMode.GrowAndShrink; - ClientSize = new Size(540, 282); + ClientSize = new Size(540, 327); Controls.Add(tableLayout); Controls.Add(flowLayoutPanel1); FormBorderStyle = FormBorderStyle.FixedDialog; @@ -285,12 +312,14 @@ private void InitializeComponent() private Button CancelBtn; private Button SaveButton; private FolderBrowserDialog FolderDialog; - private CheckBox RunOnLoginCheckbox; private LinkLabel NewVersionLabel; private TableLayoutPanel tableLayout; private Button AddFolderButton; private FlowLayoutPanel FoldersLayout; private Label label3; private Controls.ThemeToggle ThemeToggleButton; + private Label label4; + private TextBox IgnoreFoldersTextBox; + private CheckBox RunOnLoginCheckbox; } } diff --git a/src/TrayToolbar/SettingsForm.cs b/src/TrayToolbar/SettingsForm.cs index 09777d7..3890831 100644 --- a/src/TrayToolbar/SettingsForm.cs +++ b/src/TrayToolbar/SettingsForm.cs @@ -20,23 +20,29 @@ public SettingsForm() LoadResources(); SetupMenu(); PopulateConfig(); + SystemTheme.UseImmersiveDarkMode(0, UseDarkMode()); this.HandleCreated += SettingsForm_HandleCreated; + ThemeChangeMessageFilter.ThemeChanged += SettingsForm_SystemThemeChanged; } private void SettingsForm_HandleCreated(object? sender, EventArgs e) { var darkmode = UseDarkMode(); SystemTheme.UseImmersiveDarkMode(this.Handle, darkmode); - ThemeChangeMessageFilter.ThemeChanged += SettingsForm_SystemThemeChanged; } #region LoadResources + const string Command_Options = "Options"; + const string Command_Open = "Open"; + const string Command_Exit = "Exit"; + private void LoadResources() { label1.Text = R.Folders; label2.Text = R.Exclude_files; label3.Text = R.Theme; + label4.Text = R.Exclude_folders; RunOnLoginCheckbox.Text = R.Run_on_log_in; SaveButton.Text = R.Save; CancelBtn.Text = R.Cancel; @@ -55,9 +61,9 @@ private void LoadResources() }); RightClickMenu.Items.AddRange(new[] { - new ToolStripMenuItem { Text = R.Options, CommandParameter = "Options" }, - new ToolStripMenuItem { Text = R.Open_Folder, CommandParameter = "Open" }, - new ToolStripMenuItem { Text = R.Exit, CommandParameter = "Exit" } + new ToolStripMenuItem { Text = R.Options, CommandParameter = Command_Options }, + new ToolStripMenuItem { Text = R.Open_Folder, CommandParameter = Command_Open }, + new ToolStripMenuItem { Text = R.Exit, CommandParameter = Command_Exit } }); } @@ -183,6 +189,7 @@ private void PopulateConfig() Configuration.Folders.ForEach(f => AddFolder(f, i++)); FoldersUpdated(); IgnoreFilesTextBox.Text = Configuration.IgnoreFiles.Join("; "); + IgnoreFoldersTextBox.Text = Configuration.IgnoreFolders.Join("; "); RunOnLoginCheckbox.Checked = ConfigHelper.GetStartupKey(); if (SystemTheme.IsDarkModeSupported()) { @@ -208,12 +215,13 @@ private void TrayIcon_Click(object? sender, EventArgs e) { var trayIcon = (NotifyIcon)sender!; var folder = (FolderConfig)trayIcon.Tag!; + SettingsForm_SystemThemeChanged(null, EventArgs.Empty); if (((MouseEventArgs)e).Button == MouseButtons.Right) { - SystemTheme.SetThemeColors(RightClickMenu, UseDarkMode()); RightClickMenu.Tag = folder; RightClickMenu.Renderer = new MenuRenderer(); trayIcon.ContextMenuStrip = RightClickMenu; + SystemTheme.SetThemeColors(RightClickMenu, UseDarkMode()); } else { @@ -223,6 +231,7 @@ private void TrayIcon_Click(object? sender, EventArgs e) } LeftClickMenu.Items.Clear(); LeftClickMenu.Items.AddRange(MenuItems[folder].ToArray()); + LeftClickMenu.Renderer = new MenuRenderer(); trayIcon.ContextMenuStrip = LeftClickMenu; SystemTheme.SetThemeColors(LeftClickMenu, UseDarkMode()); @@ -251,12 +260,20 @@ private void ReloadMenuItems(FolderConfig folder, CancellationToken token) var parentPath = Path.GetDirectoryName(file); if (parentPath.HasValue() && !parentPath.Is(folder.Name)) { - if (parentPath.Contains(@"\.")) continue; //it's in a dot folder like .git or it's a dot file + if (Configuration.IgnoreAllDotFiles && parentPath.Contains(@"\.")) + continue; //it's in a dot folder like .git or it's a dot file + if (Configuration.IgnoreFolders.Contains(Path.GetFileName(parentPath))) + continue; //it's in an ignored folder name submenu = menu.CreateFolder(Path.GetRelativePath(folder.Name, parentPath), LeftClickMenu_ItemClicked); } + var menuText = Path.GetFileName(file); + if (Configuration.HideFileExtensions || file.FileExtension().Is(".lnk")) + { + menuText = Path.GetFileNameWithoutExtension(file); + } var entry = new ToolStripMenuItem { - Text = Path.GetFileNameWithoutExtension(file), + Text = menuText.ToMenuName(), CommandParameter = file, Image = file.GetImage() }; @@ -295,7 +312,7 @@ private IEnumerable EnumerateFiles(string path, bool recursive) MaxRecursionDepth = Configuration.MaxRecursionDepth > 0 ? Configuration.MaxRecursionDepth : int.MaxValue, }; return Directory.EnumerateFiles(path, "*.*", options) - .Where(f => !Configuration.IgnoreFiles.Any(i => i.Is(f.FileExtension()))) + .Where(f => !Configuration.IgnoreFiles.Any(i => f.IsMatch("." + i))) .OrderBy(f => f.ToUpper()); } @@ -306,6 +323,12 @@ private void TrayIcon_DoubleClick(object? sender, EventArgs e) private void ShowNormal() { + if (InvokeRequired) + { + Invoke(ShowNormal, []); + return; + } + SettingsForm_SystemThemeChanged(null, EventArgs.Empty); Visible = true; ShowInTaskbar = true; WindowState = FormWindowState.Normal; @@ -350,19 +373,15 @@ private void RightClickMenu_ItemClicked(object sender, ToolStripItemClickedEvent switch (e.ClickedItem.CommandParameter.ToString()) { - case "Options": + case Command_Options: ShowNormal(); break; - case "Open": + case Command_Open: var folder = (FolderConfig?)RightClickMenu.Tag; if (folder?.Name != null) Program.Launch(folder.Name); break; - case "Refresh": - LoadConfiguration(); - Configuration.Folders.ForEach(RefreshMenu); - break; - case "Exit": + case Command_Exit: Quit(); Application.Exit(); break; @@ -423,7 +442,8 @@ private void SaveButton_Click(object sender, EventArgs e) } Configuration.Folders = FolderControls().Select(c => c.Config).ToList(); - Configuration.IgnoreFiles = IgnoreFilesTextBox.Text.Split(";,".ToCharArray(), StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); + Configuration.IgnoreFiles = IgnoreFilesTextBox.Text.SplitPaths(); + Configuration.IgnoreFolders = IgnoreFoldersTextBox.Text.SplitPaths(); Configuration.Theme = (int)ThemeToggleButton.Theme; LoadConfiguration(); if (ConfigHelper.WriteConfiguration(Configuration))