// // RecentFileManager.cs - provides a simple way of tracking recently-accessed files // // Author: // Michael Becker // // Copyright (c) 2011-2021 Mike Becker's Software // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . using System; using System.Collections.Generic; using UniversalEditor.ObjectModels.Markup; using UniversalEditor.DataFormats.Markup.XML; using UniversalEditor.Accessors; namespace UniversalEditor.UserInterface { /// /// Provides a simple way of tracking recently-accessed files, including /// appending new filenames to the list and retrieving the previously-stored /// filenames in the appropriate order. /// public class RecentFileManager { private struct RecentItemReference { public string FileName { get; private set; } public DateTime LastAccessDateTime { get; private set; } public RecentItemReference(string filename, DateTime lastAccessDateTime) { FileName = filename; LastAccessDateTime = lastAccessDateTime; } } /// /// The backing store for the list of file names. This could be a S.C.G. /// List`1 or a Specialized StringCollection. However, changing this /// IMPLEMENTATION DETAIL should not change the public-facing API of /// . /// /// Implementation detail. private Dictionary FileDatas { get; } = new Dictionary(); private List FileNames { get; } = new List(); /// /// Appends the given to the end of the /// Recent Files list, if it does not already exist. The position of the /// existing file name in the list is unmodified. /// /// true, if the file name was newly appended to the list; /// false if the file name already existed in the list. /// The file name to append to the list. public bool AppendFileName(string filename) { if (!FileNames.Contains(filename)) { FileNames.Add(filename); FileDatas[filename] = new RecentItemReference(filename, DateTime.Now); return true; } return false; } /// /// Retrieves the list of Recent Files in the correct order (i.e., most /// recently-added file name first). /// /// The sorted list of recent file names. public string[] GetFileNames() { List list = new List(FileNames); list.Reverse(); // stored in reverse order return list.ToArray(); } public DateTime? GetLastAccessDateTime(string FileName) { if (FileDatas.ContainsKey(FileName)) { return FileDatas[FileName].LastAccessDateTime; } return null; } /// /// Gets or sets the maximum number of file names that can be stored in /// this . When a unique file name is /// added to the list with the /// method, the oldest file name in the list is discarded. /// /// /// The maximum number of file names tracked by this /// . /// public int MaximumDocumentFileNames { get; set; } = 5; /// /// Gets or sets the full path to the XML file where the /// data is stored. /// /// /// The full path to the XML file where the /// data is stored. /// public string DataFileName { get; set; } = String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[] { Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Mike Becker's Software", "Universal Editor", "RecentItems.xml" }); /// /// Gets the of the XML serialization format used. /// private Version mvarFormatVersion = new Version(1, 0); /// /// Loads the Recent File data from the XML file specified by /// . /// public void Load() { MarkupObjectModel mom = new MarkupObjectModel(); XMLDataFormat xml = new XMLDataFormat(); if (!System.IO.File.Exists(DataFileName)) return; Document.Load(mom, xml, new FileAccessor(DataFileName, false, false, true)); MarkupTagElement tagRecentItems = (mom.Elements["RecentItems"] as MarkupTagElement); if (tagRecentItems == null) return; MarkupAttribute attVersion = tagRecentItems.Attributes["Version"]; if (attVersion != null) { mvarFormatVersion = new Version(attVersion.Value); } MarkupTagElement tagSolutions = (tagRecentItems.Elements["Solutions"] as MarkupTagElement); MarkupTagElement tagDocuments = (tagRecentItems.Elements["Documents"] as MarkupTagElement); if (tagDocuments != null) { MarkupAttribute attDocumentsMaximum = tagDocuments.Attributes["Maximum"]; if (attDocumentsMaximum != null) { MaximumDocumentFileNames = Int32.Parse(attDocumentsMaximum.Value); } foreach (MarkupElement elDocument in tagDocuments.Elements) { MarkupTagElement tagDocument = (elDocument as MarkupTagElement); if (tagDocument == null) continue; if (tagDocument.FullName != "Document") continue; MarkupAttribute attFileName = tagDocument.Attributes["FileName"]; if (attFileName == null) continue; DateTime lastAccessDateTime = DateTime.Now; MarkupAttribute attLastAccessDateTime = tagDocument.Attributes["LastAccessDateTime"]; if (attLastAccessDateTime != null) { lastAccessDateTime = DateTime.Parse(attLastAccessDateTime.Value); } FileNames.Insert(0, attFileName.Value); FileDatas[attFileName.Value] = new RecentItemReference(attFileName.Value, lastAccessDateTime); } } } /// /// Saves the Recent File data to the XML file specified by /// . /// public void Save() { MarkupObjectModel mom = new MarkupObjectModel(); XMLDataFormat xml = new XMLDataFormat(); MarkupPreprocessorElement xmlp = new MarkupPreprocessorElement(); xmlp.FullName = "xml"; xmlp.Value = "version=\"1.0\" encoding=\"UTF-8\""; mom.Elements.Add(xmlp); MarkupTagElement tagRecentItems = new MarkupTagElement(); tagRecentItems.FullName = "RecentItems"; tagRecentItems.Attributes.Add("Version", mvarFormatVersion.ToString()); mom.Elements.Add(tagRecentItems); if (FileNames.Count > 0) { MarkupTagElement tagDocuments = new MarkupTagElement(); tagDocuments.FullName = "Documents"; tagDocuments.Attributes.Add("Maximum", MaximumDocumentFileNames.ToString()); for (int i = 0; i < Math.Min(FileNames.Count, MaximumDocumentFileNames); i++) { MarkupTagElement tagDocument = new MarkupTagElement(); tagDocument.FullName = "Document"; string filename = FileNames[FileNames.Count - i - 1]; tagDocument.Attributes.Add("FileName", filename); if (FileDatas.ContainsKey(filename)) { tagDocument.Attributes.Add("LastAccessDateTime", FileDatas[filename].LastAccessDateTime.ToString()); } tagDocuments.Elements.Add(tagDocument); } tagRecentItems.Elements.Add(tagDocuments); } string dir = System.IO.Path.GetDirectoryName(DataFileName); if (!System.IO.Directory.Exists (dir)) { System.IO.Directory.CreateDirectory (dir); } Document.Save(mom, xml, new FileAccessor(DataFileName, true, true), true); } } }