Author: mkrueger
Date: 2007-06-18 11:59:10 -0400 (Mon, 18 Jun 2007)
New Revision: 80015

Added:
   
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFileStorage.cs
   
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentItem.cs
Removed:
   
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFiles.cs
Modified:
   trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/ChangeLog
   trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Makefile.am
   trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui.mdp
   
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui/RecentOpen.cs
Log:
Improved recent file management. The files are now stored only on disc. Still 
TODO: File System Locks (how to use the posix log from .NET) and file system 
watcher.

Modified: trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/ChangeLog
===================================================================
--- trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/ChangeLog   2007-06-18 
15:56:09 UTC (rev 80014)
+++ trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/ChangeLog   2007-06-18 
15:59:10 UTC (rev 80015)
@@ -1,3 +1,7 @@
+2007-06-18  Mike Krüger <[EMAIL PROTECTED]> 
+
+       Improved recent file management. The files are now stored only on disc. 
Still TODO: File System Locks (how to use the posix log from .NET) and file 
system watcher.
+
 2007-05-31  Lluis Sanchez Gual <[EMAIL PROTECTED]> 
 
        * MonoDevelop.Core.Gui.Dialogs/TreeViewOptions.cs: Expand root nodes by

Added: 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFileStorage.cs
===================================================================
--- 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFileStorage.cs
        2007-06-18 15:56:09 UTC (rev 80014)
+++ 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFileStorage.cs
        2007-06-18 15:59:10 UTC (rev 80015)
@@ -0,0 +1,236 @@
+//
+// RecentFileStorage.cs
+//
+// Implementation of Recent File Storage according to 
+// "Recent File Storage Specification v0.2" from freedesktop.org.
+//
+// http://standards.freedesktop.org/recent-file-spec/recent-file-spec-0.2.html
+//
+// Author:
+//   Mike Krüger <[EMAIL PROTECTED]>
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+
+namespace Freedesktop.RecentFiles
+{
+       /// <summary>
+       /// Implementation of Recent File Storage according to 
+       /// "Recent File Storage Specification v0.2" from freedesktop.org.
+       ///
+       /// 
http://standards.freedesktop.org/recent-file-spec/recent-file-spec-0.2.html
+       /// </summary>
+       public sealed class RecentFileStorage
+       {
+               const int MaxRecentItemsCount = 500; // max. items according to 
the spec.
+               static readonly string FileName = Path.Combine 
(Environment.GetFolderPath (Environment.SpecialFolder.Personal), 
".recently-used");
+               
+//             FileSystemWatcher watcher;
+        
+               public RecentFileStorage()
+               {
+/* TODO: watcher
+                       watcher = new FileSystemWatcher (FileName);
+                       watcher.Changed += delegate {
+                               OnRecentFilesChanged (EventArgs.Empty);
+                       };
+                       watcher.EnableRaisingEvents = true;*/
+               }
+               int lockLevel = 0;
+               void ObtainLock ()
+               {
+                       lockLevel++;
+                       // todo
+               }
+               
+               void ReleaseLock ()
+               {
+                       if (lockLevel <= 0)
+                               throw new InvalidOperationException ("not 
locked.");
+                       lockLevel--;
+                       // todo
+               }
+               
+               delegate bool RecentItemPredicate (RecentItem item);
+               delegate void RecentItemOperation (RecentItem item);
+               void FilterOut (RecentItemPredicate pred)
+               {
+                       ObtainLock ();
+                       try {
+                               bool filteredSomething = false;
+                               List<RecentItem> store = ReadStore ();
+                               for (int i = 0; i < store.Count; ++i) {
+                                       if (pred (store[i])) {
+                                               store.RemoveAt (i);
+                                               filteredSomething = true;
+                                               --i;
+                                               continue;
+                                       }
+                               }
+                               if (filteredSomething)
+                                       WriteStore (store);
+                       } finally {
+                               ReleaseLock ();
+                       }
+               }
+               void RunOperation (bool writeBack, RecentItemOperation 
operation)
+               {
+                       ObtainLock ();
+                       try {
+                               List<RecentItem> store = ReadStore ();
+                               for (int i = 0; i < store.Count; ++i) 
+                                       operation (store[i]);
+                               if (writeBack) 
+                                       WriteStore (store);
+                       } finally {
+                               ReleaseLock ();
+                       }
+               }
+               
+               public void ClearGroup (string group)
+               {
+                       FilterOut (delegate(RecentItem item) {
+                               return item.IsInGroup (group);
+                       });
+               }
+               
+               public void RemoveMissingFiles (string group)
+               {
+                       FilterOut (delegate(RecentItem item) {
+                               return item.IsInGroup (group) &&
+                                          item.Uri.StartsWith ("file:") &&
+                                          !File.Exists (new Uri 
(item.Uri).LocalPath);
+                       });
+               }
+               
+
+               public void RemoveItem (Uri uri)
+               {
+                       FilterOut (delegate(RecentItem item) {
+                               return item.Uri == uri.ToString ();
+                       });
+               }
+               
+               public void RemoveItem (RecentItem itemToRemove)
+               {
+                       FilterOut (delegate(RecentItem item) {
+                               return item == itemToRemove;
+                       });
+               }
+               
+               public void RenameItem (Uri oldUri, Uri newUri)
+               {
+                       RunOperation (true, delegate(RecentItem item) {
+                               if (item.Uri == oldUri.ToString ()) {
+                                       item.Uri = newUri.ToString ();
+                                       item.NewTimeStamp ();
+                               }
+                       });
+               }
+               
+               public RecentItem[] GetItemsInGroup (string group)
+               {
+                       List<RecentItem> result = new List<RecentItem> ();
+                       RunOperation (false, delegate(RecentItem item) {
+                               if (item.IsInGroup (group)) 
+                                       result.Add (item);
+                       });
+                       result.Sort ();
+                       return result.ToArray ();
+               }
+               
+               public void AddWithLimit (RecentItem item, string group, int 
max)
+               {
+                       ObtainLock ();
+                       try {
+                               RecentItem[] items = GetItemsInGroup (group);
+                               if (items.Length == max && items.Length > 0)
+                                       this.RemoveItem (items[items.Length - 
1]);
+                               
+                               List<RecentItem> store = ReadStore ();
+                               store.Add (item);
+                               WriteStore (store);
+                       } finally {
+                               ReleaseLock ();
+                       }
+               }
+               
+               static List<RecentItem> ReadStore ()
+               {
+                       List<RecentItem> result = new List<RecentItem> ();
+                       if (!File.Exists (RecentFileStorage.FileName))
+                               return result;
+                       XmlTextReader reader = new XmlTextReader 
(RecentFileStorage.FileName);
+                       try {
+                               while (true) {
+                                       bool read = false;
+                                       try {
+                                               // seems to crash on empty 
files ?
+                                               read = reader.Read ();
+                                       } catch (Exception) { 
+                                               read = false; 
+                                       }
+                                       if (!read)
+                                               break;
+                                       if (reader.IsStartElement () && 
reader.LocalName == RecentItem.Node)
+                                               result.Add (RecentItem.Read 
(reader));
+                               }
+                       } finally {
+                               if (reader != null)
+                                       reader.Close ();
+                       }
+                       return result;
+               }
+               
+               static void WriteStore (List<RecentItem> items)
+               {
+                       items.Sort ();
+                       if (items.Count > MaxRecentItemsCount)
+                               items.RemoveRange (MaxRecentItemsCount, 
items.Count - MaxRecentItemsCount);
+                       XmlTextWriter writer = new XmlTextWriter 
(RecentFileStorage.FileName, System.Text.Encoding.UTF8);
+                       try {
+                               writer.Formatting = Formatting.Indented;
+                               writer.WriteStartDocument();
+                               writer.WriteStartElement ("RecentFiles");
+                               if (items != null) 
+                                       foreach (RecentItem item in items)
+                                               item.Write (writer);
+                               writer.WriteEndElement (); // RecentFiles
+                       } finally {
+                               writer.Close ();
+                       }
+               }
+               
+               void OnRecentFilesChanged (EventArgs e)
+               {
+                       if (this.RecentFilesChanged != null)
+                               this.RecentFilesChanged (this, e);
+               }
+               
+               public event EventHandler RecentFilesChanged;
+       }
+}

Deleted: 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFiles.cs
===================================================================
--- 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFiles.cs
      2007-06-18 15:56:09 UTC (rev 80014)
+++ 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFiles.cs
      2007-06-18 15:59:10 UTC (rev 80015)
@@ -1,521 +0,0 @@
-/*
-Copyright (c) 2004 John Luke
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-using System;
-using System.Collections;
-using System.IO;
-using System.Text;
-using System.Xml;
-using System.Xml.Serialization;
-
-// implementation of the freedesktop.org Recent Files spec
-// http://freedesktop.org/Standards/recent-file-spec/recent-file-spec-0.2.html
-
-// Note: the file may not exist, apps should account for that themselves
-
-// Lets keep things sorted as we go, and reverse before saving it.
-
-namespace Freedesktop.RecentFiles
-{
-       // Currently using XmlSerializer to read/write the recent files list
-       // other methods may be faster.
-    public class RecentFiles
-       {
-               private static XmlSerializer serializer;
-
-               // expose this so consumers can watch it with FileSystemWatcher 
for changes
-               public static readonly string RecentFileStore = Path.Combine 
(Environment.GetFolderPath (Environment.SpecialFolder.Personal), 
".recently-used");
-
-               static RecentFiles ()
-               {
-                       serializer = new XmlSerializer (typeof (RecentFiles));
-               }
-
-               // required by serializer
-               public RecentFiles ()
-               {
-               }
-
-               // currently only emits on our changes
-               // we should probably use FSW and send those events here
-               // for now you have to do it on your own
-               public event EventHandler Changed;
-
-        [XmlElement ("RecentItem")]
-        public RecentItem[] RecentItems;
-
-               public void AddItem (RecentItem item)
-               {
-                       if (RecentItems == null)
-                       {
-                               RecentItems = new RecentItem [] {item};
-                               Save ();
-                               return;
-                       }
-
-                       // check for already existing URI
-                       // if it does update timestamp and return unchanged;
-                       foreach (RecentItem ri in RecentItems)
-                       {
-                               if (ri.Uri == item.Uri)
-                               {
-                                       ri.Timestamp = item.Timestamp;
-                                       if (item.Groups != null)
-                                               ri.AddGroups (item.Groups);
-                                       Save ();
-                                       return;
-                               }
-                       }
-
-                       while (RecentItems.Length > 499)
-                       {
-                               RemoveItem (OldestItem);
-                       }
-
-                       int length = RecentItems.Length;
-                       RecentItem[] newItems = new RecentItem[length + 1];
-                       RecentItems.CopyTo (newItems, 0);
-                       newItems[length] = item;
-                       RecentItems = newItems;
-                       Save ();
-               }
-
-               // ensure that that only max items are kept in group 
-               public void AddWithLimit (RecentItem item, string group, int 
max)
-               {
-                       if (max < 1)
-                               throw new ArgumentException ("max must be > 0");
-
-                       // we add it first in case the Uri is already there
-                       AddItem (item);
-
-                       // then we adjust for the limit
-                       RecentItem[] inGroup = GetItemsInGroup (group);
-                       if (inGroup.Length > max)
-                       {
-                               while (inGroup.Length > max) {
-                                       RemoveItem (GetOldestItem (inGroup));
-                                       inGroup = GetItemsInGroup (group);
-                               }
-                       }
-               }
-
-               public void Clear ()
-               {
-                       RecentItems = null;
-                       Save ();
-               }
-
-               public void ClearGroup (string group)
-               {
-                       if (RecentItems == null)
-                               return;
-
-                       ArrayList list = new ArrayList ();
-                       foreach (RecentItem ri in RecentItems)
-                       {
-                               if ( ri.Groups == null || Array.IndexOf 
(ri.Groups, group) == -1)
-                               {
-                                       list.Add (ri);
-                               }
-                               else
-                               {
-                                       ri.RemoveGroup (group);
-
-                                       // it has other groups so dont delete it
-                                       if (ri.Groups.Length > 0)
-                                               list.Add (ri);
-                               }
-                       }
-
-                       RecentItem[] items = new RecentItem [list.Count];
-                       list.CopyTo (items, 0);
-                       RecentItems = items;
-                       Save ();
-               }
-
-               private void EmitChangedEvent ()
-               {
-                       if (Changed != null)
-                               Changed (this, EventArgs.Empty);        
-               }
-
-               public static RecentFiles GetInstance ()
-               {
-                       try
-                       {
-                               XmlTextReader reader = new XmlTextReader 
(RecentFileStore);
-                               RecentFiles rf = (RecentFiles) 
serializer.Deserialize (reader);
-                               reader.Close ();
-                               rf.Sort ();
-                               return rf;
-                       }
-                       catch (IOException)
-                       {
-                               // FIXME: this is wrong, because if we later 
save it, we blow away what was there
-                               // somehow we should ask for the lock or wait 
for it...
-                               return new RecentFiles ();
-                       }
-                       catch
-                       {
-                               // FIXME: this is wrong, because if we later 
save it, we blow away what was there
-                               return new RecentFiles ();
-                       }
-               }
-
-               public RecentItem[] GetItemsInGroup (string group)
-               {
-                       if (RecentItems == null)
-                               return null;
-
-                       ArrayList list = new ArrayList ();
-                       foreach (RecentItem ri in RecentItems)
-                       {
-                               if (ri.Groups == null)
-                                       continue;
-
-                               if (Array.IndexOf (ri.Groups, group) != -1)
-                                       list.Add (ri);
-                       }
-
-                       RecentItem[] items = new RecentItem [list.Count];
-                       list.CopyTo (items, 0);
-                       return items;
-               }
-               
-               public void Purge (string group)
-               {
-                       // Removes entries for files which don't exist anymore
-                       if (RecentItems == null)
-                               return;
-
-                       ArrayList list = new ArrayList ();
-                       foreach (RecentItem ri in RecentItems)
-                       {
-                               if (ri.Groups == null)
-                                       continue;
-
-                               if (Array.IndexOf (ri.Groups, group) != -1) {
-                                       if (ri.Uri.StartsWith ("file:") && 
!File.Exists (new Uri (ri.Uri).LocalPath))
-                                               list.Add (ri);
-                               }
-                       }
-                       
-                       foreach (RecentItem ri in list) {
-                               RemoveItem (ri);
-                       }
-               }
-
-               public RecentItem[] GetMostRecentInGroup (int count, string 
group)
-               {
-                       if (count < 1)
-                               throw new ArgumentException ("count must be > 
0");
-
-                       RecentItem[] inGroup = GetItemsInGroup (group);
-                       return GetMostRecent (count, inGroup);
-               }
-
-               public RecentItem[] GetMostRecent (int count)
-               {
-                       if (count < 1)
-                               throw new ArgumentException ("count must be > 
0");
-
-                       return GetMostRecent (count, RecentItems);
-               }
-
-               // return the last X items in newest to oldest order
-               private RecentItem[] GetMostRecent (int count, RecentItem[] 
items)
-               {
-                       if (count >= items.Length)
-                       {
-                               return items;
-                       }
-                       else
-                       {
-                               RecentItem[] countedItems = new 
RecentItem[count];
-                               // get the last count items
-                               Array.Copy (items, items.Length - count - 1, 
countedItems, 0, count);
-
-                               return countedItems;
-                       }
-               }
-
-               public static RecentItem GetOldestItem (RecentItem[] items)
-               {
-                       return items[items.Length - 1];
-               }
-
-               public RecentItem OldestItem
-               {
-                       get {
-                               return RecentItems[0];
-                       }
-               }
-
-               public void RemoveItem (RecentItem item)
-               {
-                       if (RecentItems == null)
-                               return;
-
-                       ArrayList l = new ArrayList ();
-                       foreach (RecentItem ri in RecentItems)
-                       {
-                               if (ri == item)
-                               {
-                                       // remove the whole thing
-                               }
-                               else if (ri.Uri == item.Uri)
-                               {
-                                       if (ri.Groups != null)
-                                       {
-                                               // remove the groups
-                                               if (item.Groups != null)
-                                               {
-                                                       foreach (string g in 
item.Groups)
-                                                               ri.RemoveGroup 
(g);
-                                               }
-                                               l.Add (ri);
-                                       }
-                               }
-                               else
-                               {
-                                       // keep it
-                                       l.Add (ri);
-                               }
-                       }
-
-                       RecentItem[] items = new RecentItem [l.Count];
-                       l.CopyTo (items, 0);
-                       RecentItems = items;
-                       Save ();
-               }
-
-               public void RemoveItem (Uri uri)
-               {
-                       if (RecentItems == null)
-                               return;
-
-                       foreach (RecentItem ri in RecentItems)
-                       {
-                               if (ri.Uri == uri.ToString ())
-                                       RemoveItem (ri);
-                       }
-               }
-
-               public void RenameItem (Uri oldUri, Uri newUri)
-               {
-                       // FIXME: throw exception, cant rename non-existant item
-                       if (RecentItems == null)
-                               return;
-
-                       foreach (RecentItem ri in RecentItems)
-                       {
-                               if (ri.Uri == oldUri.ToString ())
-                               {
-                                       ri.Uri = newUri.ToString ();
-                                       ri.Timestamp = RecentItem.NewTimestamp;
-                                       Save ();
-                                       return;
-                               }
-                       }
-               }
-
-               // FIXME: only append new items, instead of re-writing
-               // Save implies EmitChangedEvent (otherwise why would we save?)
-               private void Save ()
-               {
-                       // make sure we are in order
-                       this.Sort ();
-                       // but we need to write in oldest-to-newest order
-                       if (RecentItems != null)
-                               Array.Reverse (RecentItems);
-
-                       // if we specifically set Encoding UTF 8 here it writes 
the BOM
-                       // which confuses others (egg-recent-files) I guess
-                       try {
-                               XmlTextWriter writer = new XmlTextWriter (new 
StreamWriter (RecentFileStore));
-                               writer.Formatting = Formatting.Indented;
-                               serializer.Serialize (writer, this);
-                               writer.Close ();
-                       }
-                       catch {
-                               Console.WriteLine ("WARNING: cannot write to 
~/.recently-used");
-                       }
-                       EmitChangedEvent ();
-
-                       // back to normal
-                       this.Sort ();
-               }
-
-               // this gives us the items in newest-to-oldest order
-               public void Sort ()
-               {
-                       if (RecentItems != null)
-                               Array.Sort (RecentItems);
-               }
-
-               public override string ToString ()
-               {
-                       if (RecentItems == null)
-                               return "0 recent files";
-
-                       StringBuilder sb = new StringBuilder ();
-                       foreach (RecentItem ri in this.RecentItems)
-                       {
-                               sb.Append (ri.Uri);
-                               sb.Append (" ");
-                               sb.Append (ri.MimeType);
-                               sb.Append (" ");
-                               sb.Append (ri.Timestamp);
-                               sb.Append ("\n");
-                       }
-                       sb.Append (RecentItems.Length);
-                       sb.Append (" total recent files\n");
-                       return sb.ToString ();
-               }
-    }
-
-    public class RecentItem : IComparable
-       {
-        [XmlElement ("URI")]
-        public string Uri;
-
-        [XmlElement ("Mime-Type")]
-        public string MimeType;
-
-        public int Timestamp;
-
-        public string Private;
-
-        
[System.Xml.Serialization.XmlArrayItem(ElementName="Group",IsNullable=false)]
-        public string[] Groups;
-
-               // required by serialization
-               public RecentItem ()
-               {
-               }
-
-               public RecentItem (Uri uri, string mimetype) : this (uri, 
mimetype, null)
-               {
-               }
-
-               public RecentItem (Uri uri, string mimetype, string group)
-               {
-                       Uri = uri.ToString ();
-                       MimeType = mimetype;
-                       Timestamp = NewTimestamp;
-
-                       if (group != null)
-                       {
-                               this.Groups = new string[] {group};
-                       }
-               }
-
-               private void AddGroup (string group)
-               {
-                       if (this.Groups == null)
-                       {
-                               Groups = new string[] {group};
-                               return;
-                       }
-
-                       // if it already has this group no need to add it
-                       foreach (string g in Groups)
-                       {
-                               if (g == group)
-                                       return;
-                       }
-
-                       int length = this.Groups.Length;
-                       string[] groups = new string [length + 1];
-                       this.Groups.CopyTo (groups, 0);
-                       groups[length] = group;
-                       this.Groups = groups;
-               }
-
-               public void AddGroups (string[] groups)
-               {
-                       if (this.Groups == null)
-                       {
-                               Groups = groups;
-                               return;
-                       }
-
-                       foreach (string s in groups)
-                               AddGroup (s);
-               }
-
-               // we want newer items first
-               public int CompareTo (object item)
-               {
-                       RecentItem other = item as RecentItem;
-                       if (other == null)
-                               throw new ArgumentException ("item is not of 
type " + typeof (RecentItem));
-
-                       if (this.Timestamp == other.Timestamp)
-                               return 0;
-                       else if (this.Timestamp < other.Timestamp)
-                               return 1; // older
-                       else
-                               return -1; // newer
-               }
-
-               public static int NewTimestamp
-               {
-                       get {
-                               // from the unix epoch
-                               return ((int) (DateTime.UtcNow - new DateTime 
(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds);
-                       }
-               }
-
-               public void RemoveGroup (string group)
-               {
-                       if (Groups == null)
-                               return;
-
-                       ArrayList groups = new ArrayList ();
-                       if (Array.IndexOf (Groups, group) == -1)
-                       {
-                               return; // doesnt have it
-                       }
-                       else
-                       {
-                               foreach (string g in Groups)
-                               {
-                                       if (g != group)
-                                               groups.Add (g);
-                               }
-                       }
-
-                       string[] newGroups = new string [groups.Count];
-                       groups.CopyTo (newGroups, 0);
-                       this.Groups = newGroups;
-               }
-
-               // some apps might depend on this, even though they shouldn't
-               public override string ToString ()
-               {
-                       return this.Uri;
-               }
-    }
-}
-

Added: 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentItem.cs
===================================================================
--- 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentItem.cs
       2007-06-18 15:56:09 UTC (rev 80014)
+++ 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentItem.cs
       2007-06-18 15:59:10 UTC (rev 80015)
@@ -0,0 +1,238 @@
+//
+// RecentItem.cs
+//
+// Author:
+//   Mike Krüger <[EMAIL PROTECTED]>
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Xml;
+
+namespace Freedesktop.RecentFiles
+{
+       /// <summary>
+       /// Implementation of RecentItem according to "Recent File Storage 
Specification v0.2" from 
+       /// the freedesktop.org.
+       /// </summary>
+    public class RecentItem : IComparable
+       {
+        string       uri;
+        string       mimeType;
+        int          timestamp;
+        string       privateData;
+               List<string> groups = new List<string> ();
+
+               public string Uri {
+                       get {
+                               return uri; 
+                       }                       
+                       set {
+                               uri = value; 
+                       }
+               }
+               
+               public string MimeType {
+                       get {
+                               return mimeType; 
+                       }
+                       set {
+                               mimeType = value; 
+                       }
+               }
+               
+               public int Timestamp {
+                       get {
+                               return timestamp;
+                       }
+                       set {
+                               timestamp = value;
+                       }
+               }
+               
+               public string Private {
+                       get {
+                               return privateData;
+                       }
+                       set {
+                               privateData = value;
+                       }
+               }
+               
+               public ReadOnlyCollection<string> Groups {
+                       get {
+                               return groups.AsReadOnly ();
+                       }
+               }
+               
+               RecentItem ()
+               {
+               }
+               
+               public RecentItem (Uri uri, string mimetype) : this (uri, 
mimetype, null)
+               {
+               }
+
+               public RecentItem (Uri uri, string mimetype, string group)
+               {
+                       Debug.Assert (uri != null);
+                       this.uri       = uri != null ? uri.ToString () : "";
+                       this.mimeType  = mimetype;
+                       this.timestamp = CreateTimestamp ();
+                       
+                       if (!String.IsNullOrEmpty (group)) {
+                               this.groups.Add (group);
+                       }
+               }
+               
+               void AddGroup (string group)
+               {
+                       if (String.IsNullOrEmpty (group))
+                               return;
+                       
+                       if (!this.groups.Contains (group))
+                               this.groups.Add (group);
+               }
+
+               public void AddGroups (IEnumerable<string> groups)
+               {
+                       if (groups == null)
+                               return;
+                       foreach (string group in groups)
+                               AddGroup (group);
+               }
+               
+               public void RemoveGroup (string group)
+               {
+                       if (this.groups.Contains (group)) 
+                               this.groups.Remove (group);
+               }
+               
+               public void NewTimeStamp ()
+               {
+                       this.timestamp = CreateTimestamp ();
+               }
+               
+               public bool IsInGroup (string group)
+               {
+                       return this.groups.Contains (group);
+               }
+               
+               public static int CreateTimestamp ()
+               {
+                       return (int) (DateTime.UtcNow - new DateTime (1970, 1, 
1, 0, 0, 0, 0)).TotalSeconds;
+               }
+               
+               public int CompareTo (object o)
+               {
+                       RecentItem item = o as RecentItem;
+                       if (item == null)
+                               throw new ArgumentException ("Can only compare 
items of " + typeof (RecentItem) + " item was: " + o);
+                       return this.Timestamp.CompareTo (item.Timestamp);
+               }
+               
+               public override string ToString ()
+               {
+                       return String.Format ("[Uri={0}, MimeType={1}, 
Timestamp={2}]", this.Uri, this.MimeType, this.Timestamp);
+               }
+               
+#region I/O
+               public const string Node          = "RecentItem";
+               public const string UriNode       = "URI";
+               public const string MimeTypeNode  = "Mime-Type";
+               public const string TimestampNode = "Timestamp";
+               public const string PrivateNode   = "Private";
+               public const string GroupsNode    = "Groups";
+               public const string GroupNode     = "Group";
+               
+               public static RecentItem Read (XmlReader reader)
+               {
+                       Debug.Assert (reader.LocalName == Node);
+                       RecentItem result = new RecentItem ();
+                       bool readGroup = false;
+                       while (reader.Read ()) {
+                               switch (reader.NodeType) {
+                               case XmlNodeType.EndElement:
+                                       if (reader.LocalName == GroupsNode) {
+                                               readGroup = false;
+                                               break;
+                                       }
+                                       if (reader.LocalName == Node)
+                                               return result;
+                                       throw new XmlException ("Found unknown 
end element:" + reader.LocalName);
+                                       break;
+                               case XmlNodeType.Element:
+                                       if (readGroup) {
+                                               result.AddGroup 
(reader.ReadElementString ());
+                                               break;
+                                       }
+                                       switch (reader.LocalName) {
+                                       case "Uri":
+                                       case UriNode:
+                                               result.uri = 
reader.ReadElementString ();
+                                               break;
+                                       case "MimeType":
+                                       case MimeTypeNode:
+                                               result.mimeType = 
reader.ReadElementString ();
+                                               break;
+                                       case TimestampNode:
+                                               result.timestamp = Int32.Parse 
(reader.ReadElementString ());
+                                               break;
+                                       case PrivateNode:
+                                               result.privateData = 
reader.ReadElementString ();
+                                               break;
+                                       case GroupsNode:
+                                               readGroup = true;
+                                               break;
+                                       default:
+                                               throw new XmlException ("Found 
unknown start element:" + reader.LocalName);
+                                       }
+                                       break;
+                               }
+                       }
+                       return null;
+               }
+               
+               public void Write (XmlWriter writer)
+               {
+                       writer.WriteStartElement (Node);
+                       writer.WriteElementString (UriNode, this.uri);
+                       writer.WriteElementString (MimeTypeNode, this.mimeType);
+                       writer.WriteElementString (TimestampNode, 
this.timestamp.ToString ());
+                       if (!String.IsNullOrEmpty (this.privateData))
+                               writer.WriteElementString (PrivateNode, 
this.privateData);
+                       
+                       if (this.Groups.Count > 0) {
+                               writer.WriteStartElement (GroupsNode);
+                               foreach (string group in this.groups)
+                                       writer.WriteElementString (GroupNode, 
group);
+                               writer.WriteEndElement (); // GroupsNode
+                       }
+                       writer.WriteEndElement (); // Node
+               }
+#endregion
+    }
+}

Modified: trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Makefile.am
===================================================================
--- trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Makefile.am 2007-06-18 
15:56:09 UTC (rev 80014)
+++ trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Makefile.am 2007-06-18 
15:59:10 UTC (rev 80015)
@@ -18,7 +18,8 @@
        -r:System.Xml
 
 FILES =  \
-       Freedesktop.RecentFiles/RecentFiles.cs \
+       Freedesktop.RecentFiles/RecentFileStorage.cs \
+       Freedesktop.RecentFiles/RecentItem.cs \
        MonoDevelop.Core.Gui.Codons/CommandCodon.cs \
        MonoDevelop.Core.Gui.Codons/CommandItemCodon.cs \
        MonoDevelop.Core.Gui.Codons/DialogPanelCodon.cs \

Modified: 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui/RecentOpen.cs
===================================================================
--- 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui/RecentOpen.cs
  2007-06-18 15:56:09 UTC (rev 80014)
+++ 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui/RecentOpen.cs
  2007-06-18 15:59:10 UTC (rev 80015)
@@ -31,24 +31,20 @@
                /// </summary>
                const int MAX_LENGTH = 10;
                
-               RecentItem[] lastfile;
-               RecentItem[] lastproject;
-               RecentFiles recentFiles;
+               static RecentFileStorage recentFiles = new RecentFileStorage ();
                
                public event EventHandler RecentFileChanged;
                public event EventHandler RecentProjectChanged;
                
                public RecentItem[] RecentFile {
                        get {
-                               Debug.Assert(lastfile != null, "RecentOpen : 
set string[] LastFile (value == null)");
-                               return lastfile;
+                               return recentFiles.GetItemsInGroup 
("MonoDevelop Files");;
                        }
                }
 
                public RecentItem[] RecentProject {
                        get {
-                               Debug.Assert(lastproject != null, "RecentOpen : 
set string[] LastProject (value == null)");
-                               return lastproject;
+                               return recentFiles.GetItemsInGroup 
("MonoDevelop Projects");
                        }
                }
                
@@ -68,11 +64,10 @@
 
                public RecentOpen()
                {
-                       recentFiles = RecentFiles.GetInstance ();
-                       recentFiles.Purge ("MonoDevelop Files");
-                       recentFiles.Purge ("MonoDevelop Projects");
-                       UpdateLastFile ();
-                       UpdateLastProject ();
+                       recentFiles.RemoveMissingFiles ("MonoDevelop Files");
+                       recentFiles.RemoveMissingFiles ("MonoDevelop Projects");
+                       OnRecentFileChange();
+                       OnRecentProjectChange();
                }
                
                public void AddLastFile (string name, string project)
@@ -84,19 +79,17 @@
                                ri.Private = String.Format ("{0} [{1}]", 
Path.GetFileName (name), project);
 
                        recentFiles.AddWithLimit (ri, "MonoDevelop Files", 
MAX_LENGTH);
-                       UpdateLastFile ();
+                       OnRecentFileChange();
                }
                
                public void ClearRecentFiles()
                {
-                       lastfile = null;
                        recentFiles.ClearGroup ("MonoDevelop Files");
                        OnRecentFileChange();
                }
                
                public void ClearRecentProjects()
                {
-                       lastproject = null;
                        recentFiles.ClearGroup ("MonoDevelop Projects");
                        OnRecentProjectChange();
                }
@@ -106,7 +99,7 @@
                        RecentItem ri = new RecentItem (new Uri (name), 
MimeType.GetMimeTypeForUri (name), "MonoDevelop Projects");
                        ri.Private = projectName;
                        recentFiles.AddWithLimit (ri, "MonoDevelop Projects", 
MAX_LENGTH);
-                       UpdateLastProject ();
+                       OnRecentProjectChange();
                }
                
                public void FileRemoved(object sender, FileEventArgs e)
@@ -115,7 +108,7 @@
                                return;
                        
                        recentFiles.RemoveItem (new Uri (e.FileName));
-                       UpdateLastFile ();
+                       OnRecentFileChange();
                }
                
                public void FileRenamed(object sender, FileEventArgs e)
@@ -127,20 +120,10 @@
                                recentFiles.RenameItem (new Uri (e.SourceFile), 
new Uri (e.TargetFile));
                        else
                                recentFiles.RenameItem (new Uri (e.FileName), 
new Uri (e.TargetFile));
-                       UpdateLastFile ();
-               }
-
-               void UpdateLastFile ()
-               {
-                       lastfile = recentFiles.GetItemsInGroup ("MonoDevelop 
Files");
                        OnRecentFileChange();
                }
 
-               void UpdateLastProject ()
-               {
-                       lastproject = recentFiles.GetItemsInGroup ("MonoDevelop 
Projects");
-                       OnRecentProjectChange();
-               }
+
        }
 }
 

Modified: 
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui.mdp
===================================================================
--- trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui.mdp    
2007-06-18 15:56:09 UTC (rev 80014)
+++ trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui.mdp    
2007-06-18 15:59:10 UTC (rev 80015)
@@ -176,6 +176,8 @@
     <File name="./icons/plugin-22.png" subtype="Code" 
buildaction="EmbedAsResource" />
     <File name="./icons/plugin-32.png" subtype="Code" 
buildaction="EmbedAsResource" />
     <File name="./MonoDevelop.Core.Gui.Dialogs/SetupApp.cs" subtype="Code" 
buildaction="Compile" />
+    <File name="./Freedesktop.RecentFiles/RecentItem.cs" subtype="Code" 
buildaction="Compile" />
+    <File name="./Freedesktop.RecentFiles/RecentFileStorage.cs" subtype="Code" 
buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Gac" localcopy="False" refto="gecko-sharp, 
Version=2.0.0.0, Culture=neutral, PublicKeyToken=ccf7d78a55e9f021" />

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to