using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Windows.Forms; using Vanara.Configuration; namespace Vanara.Windows.Forms; /// /// A class that manages a Most Recently Used file listing and interacts with a MenuStrip to display a menu list of the files. By /// default, the application settings are used to store the history. Optionally a constructor can be used to provide an alternate class /// to handle that work. /// [DefaultProperty("RecentFileMenuItem")] public class MenuStripMRUManager : MRUManager { /// Initializes a new instance of the class. public MenuStripMRUManager() : base(new AppSettingsFileListStorage(), new MenuStripMenuBuilder()) { } /// Initializes a new instance of the class. /// The extensions of files to find in system MRU list. /// The parent "Recent Files" menu item. /// Action to run when The on recent file click. /// Optional. The on clear recent files click. /// Optional. The storage handler. public MenuStripMRUManager(string extensions, ToolStripMenuItem parentMenuItem, Action onRecentFileClick, Action onClearRecentFilesClick = null, IFileListStorage storageHandler = null) : base(storageHandler ?? new AppSettingsFileListStorage(), new MenuStripMenuBuilder()) { FileExtensions = extensions; ((MenuStripMenuBuilder)MenuBuilderHandler).RecentFileMenuItem = parentMenuItem; if (onRecentFileClick != null) RecentFileMenuItemClick += onRecentFileClick; if (onClearRecentFilesClick != null) ClearListMenuItemClick += onClearRecentFilesClick; RefreshRecentFilesMenu(); } /// Gets or sets the clear list menu item image. /// The clear list menu item image. [Category("Appearance"), DefaultValue(null), Description("The clear list menu item icon."), Localizable(true)] public Image ClearListMenuItemImage { get => clearListMenuItemImage as Image; set { if (value is null) throw new ArgumentException("Must be of type Image."); clearListMenuItemImage = value; RefreshRecentFilesMenu(); } } /// Gets or sets the recent file menu item. /// The recent file menu item. [DefaultValue(null), Category("Behavior"), Description("The recent file menu item.")] public ToolStripMenuItem RecentFileMenuItem { get => ((MenuStripMenuBuilder)MenuBuilderHandler).RecentFileMenuItem; set { ((MenuStripMenuBuilder)MenuBuilderHandler).RecentFileMenuItem = value; RefreshRecentFilesMenu(); } } /// Builds a menu within a MenuStrip. private class MenuStripMenuBuilder : IMenuBuilder { private Action fileMenuItemClickAction; /// Gets or sets the recent file menu item. /// The recent file menu item. public ToolStripMenuItem RecentFileMenuItem { get; set; } /// Clears the recent files. public void ClearRecentFiles() { if (RecentFileMenuItem == null) return; RecentFileMenuItem.DropDownItems.Clear(); RecentFileMenuItem.Enabled = false; } /// Rebuilds the menus. /// The file listing. /// The handler for when one of the automatically added recent file menu items is clicked.. /// /// The clear list menu item text. A null value indicates that this menu item should not be shown. /// /// The handler for when the clear recent files menu item is clicked. /// /// The clear list menu item image. A null value indicates that this menu item's image should not be shown. /// /// if set to , the clear list menu item precedes the files. /// The menu image callback delegate. public void RebuildMenus(IEnumerable files, Action fileMenuItemClick, string clearListMenuItemText = null, Action clearListMenuItemClick = null, object clearListMenuItemImage = null, bool clearListMenuItemOnTop = false, Func menuImageCallback = null) { if (RecentFileMenuItem == null) return; RecentFileMenuItem.DropDownItems.Clear(); if (files is null || !files.Any()) { RecentFileMenuItem.Enabled = false; return; } if (clearListMenuItemOnTop && !string.IsNullOrEmpty(clearListMenuItemText)) { RecentFileMenuItem.DropDownItems.Add(clearListMenuItemText, clearListMenuItemImage as Image, (o, e) => clearListMenuItemClick?.Invoke()); RecentFileMenuItem.DropDownItems.Add("-"); } fileMenuItemClickAction = fileMenuItemClick; foreach (var f in files) { RecentFileMenuItem.DropDownItems.Add(new ToolStripMenuItem(CompactPath(RecentFileMenuItem.GetCurrentParent().CreateGraphics(), f, RecentFileMenuItem.Font, RecentFileMenuItem.Width), menuImageCallback?.Invoke(f) as Image, OnFileMenuItemClick) { Tag = f }); } if (!clearListMenuItemOnTop && !string.IsNullOrEmpty(clearListMenuItemText)) { RecentFileMenuItem.DropDownItems.Add("-"); RecentFileMenuItem.DropDownItems.Add(clearListMenuItemText, clearListMenuItemImage as Image, (o, e) => clearListMenuItemClick?.Invoke()); } RecentFileMenuItem.Enabled = true; } /// Compacts the path. /// The Graphics instance to use. /// The string to compact. /// The font. /// The maximum width in PTS. /// The compacted string. private static string CompactPath(Graphics g, string stringToCompact, Font font, int maxWidthInPts) { var sb = new StringBuilder(stringToCompact); g.MeasureText(sb, font, new Size(maxWidthInPts, 0), TextFormatFlags.PathEllipsis | TextFormatFlags.ModifyString); return sb.ToString(); // string.Concat(stringToCompact.TakeWhile(c => c != '\0')); } private void OnFileMenuItemClick(object sender, EventArgs e) { if (sender is ToolStripMenuItem item) fileMenuItemClickAction(item.Tag.ToString()); } } }