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;
if (MenuBuilderHandler is not null)
((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
{
clearListMenuItemImage = value ?? throw new ArgumentException("Must be of type Image.");
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
{
if (MenuBuilderHandler is not null)
((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?.Invoke(item.Tag?.ToString()!);
}
}
}