using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Vanara.Extensions;
using Vanara.Extensions.Reflection;
using static Vanara.PInvoke.Shell32;
namespace Vanara.Configuration;
/// A class that manages a Most Recently Used file listing.
[DefaultEvent(nameof(RecentFileMenuItemClick))]
public class MRUManager : Component
{
/// This value should contain the appropriate image for the clear list menu item in derived classes.
protected object clearListMenuItemImage;
private const string defClearListMenuItemText = "Clear List";
private const int defMaxHistoryCount = 10;
private MenuPlacement clearListMenuItemPlacement;
private string clearListMenuItemText = defClearListMenuItemText;
private string[] exts;
private IFileListStorage storage;
/// Initializes a new instance of the class.
public MRUManager() { }
/// Initializes a new instance of the class.
/// The file list storage.
/// The menu builder.
public MRUManager(IFileListStorage fileListStorage, IMenuBuilder menuBuilder)
{
StorageHandler = fileListStorage;
MenuBuilderHandler = menuBuilder;
}
/// Occurs when the clear recent files menu item is clicked.
[Category("Behavior"), Description("Occurs when the clear recent files menu item is clicked.")]
public event Action ClearListMenuItemClick;
/// Occurs when [get menu image for file].
[Category("Behavior"), Description("Occurs when a file menu item is about to be drawn and is requesting an image.")]
public event Func GetMenuImageForFile;
/// Occurs when one of the automatically added recent file menu items is clicked.
[Category("Behavior"), Description("Occurs when one of the automatically added recent file menu items is clicked.")]
public event Action RecentFileMenuItemClick;
/// The placement of a menu item in a list.
public enum MenuPlacement
{
/// The bottom of the list, after all items.
Bottom,
/// The top of the list, before all items.
Top
}
/// Defines a class that implements storage for an MRU file list.
public interface IFileListStorage
{
/// Gets or sets the files declared in this storage instance.
/// The file listing. Each file should declare its full path.
IEnumerable Files { get; set; }
/// Adds a new file to the list.
/// The file name with full path.
void AddRecentFile(string fileNameWithFullPath);
/// Initializes this instance and sets up any local settings required for execution.
void Initialize();
/// Removes the file from the list.
/// The file name with full path.
void RemoveRecentFile(string fileNameWithFullPath);
}
/// Defines a class that implements a menu handler for an MRU file list.
public interface IMenuBuilder
{
/// Clears the menu items of all files.
void ClearRecentFiles();
/// 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.
void RebuildMenus(IEnumerable files, Action fileMenuItemClick, string clearListMenuItemText = null, Action clearListMenuItemClick = null, object clearListMenuItemImage = null, bool clearListMenuItemOnTop = false, Func menuImageCallback = null);
}
/// Gets or sets the clear list menu item placement relative to the MRU items.
/// The clear list menu item placement.
[Category("Appearance"), DefaultValue(typeof(MenuPlacement), "Bottom"), Description("The clear list menu item text."), Localizable(true)]
public MenuPlacement ClearListMenuItemPlacement
{
get => clearListMenuItemPlacement;
set { clearListMenuItemPlacement = value; RefreshRecentFilesMenu(); }
}
/// Gets or sets the clear list menu item text.
/// The clear list menu item text. Set this value to null to hide this menu item.
[Category("Appearance"), DefaultValue(defClearListMenuItemText), Description("The clear list menu item text."), Localizable(true)]
public string ClearListMenuItemText
{
get => clearListMenuItemText;
set { clearListMenuItemText = value; RefreshRecentFilesMenu(); }
}
/// Gets or sets the vertical bar ('|') separated list of extensions without periods that are supported.
/// The file extensions.
[DefaultValue(null), Category("Behavior"), Description("Required. Vertical bar ('|') separated list of extensions without periods that are supported.")]
public string FileExtensions
{
get => exts == null ? string.Empty : string.Join("|", exts);
set { exts = value?.ToLower().Replace(".", "").Split('|', ';', ',', ' '); RefreshRecentFilesMenu(); }
}
/// Gets the list of most recently used files.
/// The files in reverse chronological order.
[Browsable(false)]
public IEnumerable Files
{
get
{
// Pre-load with values from local settings
var recentFiles = StorageHandler != null ? new List(StorageHandler.Files) : new List();
// Augment with values from Recently Used Files system folder
if (exts != null && exts.Length > 0)
{
try
{
var type = Type.GetTypeFromProgID("Wscript.Shell");
if (type != null)
{
var script = Activator.CreateInstance(type);
foreach (var file in Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.Recent), "*.lnk").Where(s => exts.Contains(Path.GetExtension(s.Substring(0, s.Length - 4)).Trim('.').ToLower())))
{
var sc = script.InvokeMethod