Tomboy UI/String Change: Notebooks



Hey all,

I'm in the middle of adding notebook support into Tomboy.  The
following strings have been added:

"{0} Notebook Template"
"Create a new notebook"
"Type the name of the notebook you'd like to create."
"N_otebook name:"
"New Note_book Note"
"Create a new note in a notebook"
"New Notebook Note"
"Create a new note in a notebook"
"Place in notebook"
"(none)"
"Notebooks"
"Name"
"_Template Note"
"Really remove this notebook?"
"The notes that belong to this notebook will note be removed, but they
will no longer be associated with this notebook.  This action cannot
be undone."
"Also _delete notebook's template note"

For specifics, please see the attached patch file.

The following UI pieces have been changed:

- "Notebooks" tab added to the preferences dialog
    - This contains a new TreeView and a couple message dialogs
- "Place in notebook" menu item added to the "Tools" menu of every Tomboy note
- "Note Notebook Note" menu item added to Tomboy Tray Icon and the
File menu of the "Search All Notes" window

Since this feature is not completely implemented, I expect some of
this to change and more to be added soon.

Thanks,

Boyd
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1692)
+++ ChangeLog	(working copy)
@@ -1,3 +1,42 @@
+2007-12-19  Boyd Timothy <btimothy gmail com> 
+
+	* Tomboy/Notebooks/NotebookApplicationAddin.cs: Adding this
+	  file too.  Forgot it earlier.  It's responsible for adding
+	  a "New Notebook Note" menu item to the tray icon and also
+	  to the File menu in the Search All Notes window.
+
+2007-12-19  Boyd Timothy <btimothy gmail com> 
+
+	* Tomboy/NoteWindow.cs: Check for system tag before displaying
+	  it in the tag bar.
+
+2007-12-19  Boyd Timothy <btimothy gmail com> 
+
+	* Tomboy.mdp: Added all the new Tomboy/Notebooks/*.cs files.
+	* Tomboy.mds: Guess monodevelop now wants the "./" removed when
+	  specifying Tomboy.mdp.
+	* Tomboy/PreferencesDialog.cs: Added a Notebooks page to allow
+	  the user to define notebooks and open their template notes.
+	* Tomboy/Utils.cs: Modified HIGMessageDialog to provide an
+	  ExtraWidget property so that we don't have to rewrite so much
+	  code when doing simple dialog boxes.
+	* Tomboy/TagManager.cs: Fix the AllTags property to really
+	  return system tags like the comment says so we can access
+	  system tags.
+	* Tomboy/Tray.cs: Reference the TrayNewNote UI action with the
+	  correct path so the accelerator works properly.
+	* Tomboy/Tomboy.addin.xml: Add references for the built-in
+	  Notebook add-ins.
+	* Tomboy/Notebooks/*.cs: The new built-in addin to support
+	  notebooks in Tomboy.
+	* Tomboy/NoteManager.cs: Expose GetNoteTemplateContent () so
+	  that initial notebook templates can share the same text as
+	  is used during a NoteManager.Create ().
+	* Tomboy/Makefile.am: Compile Tomboy/Notebooks/*.cs.
+	* data/UIManagerLayout.csml: Added some <placeholders> around
+	  the new note menuitems so that the Notebook addin has more
+	  control of where its menu item gets placed.
+
 2007-12-18  Boyd Timothy <btimothy gmail com> 
 
 	* Tomboy/PreferencesDialog.cs: Use a Gtk.LinkButton for the Open
Index: Tomboy/NoteWindow.cs
===================================================================
--- Tomboy/NoteWindow.cs	(revision 1692)
+++ Tomboy/NoteWindow.cs	(working copy)
@@ -751,7 +751,8 @@ public NoteWindow (Note note) :
 			tag_entry = new TagEntry(note,false);
 			List<string> str = new List<string>();
 			foreach(Tag t in note.Tags){
-				str.Add(t.Name);
+				if (t.IsSystem == false)
+					str.Add(t.Name);
 			}
 			tag_entry.UpdateFromTagNames(str.ToArray());
 			
Index: Tomboy/Notebooks/NotebookManager.cs
===================================================================
--- Tomboy/Notebooks/NotebookManager.cs	(revision 0)
+++ Tomboy/Notebooks/NotebookManager.cs	(revision 1693)
@@ -0,0 +1,193 @@
+using System;
+using System.Collections.Generic;
+using Tomboy;
+
+namespace Tomboy.Notebooks
+{
+	/// <summary>
+	/// A convenience class for dealing with Notebooks in Tomboy
+	/// </summary>
+	public class NotebookManager
+	{
+		#region Fields
+		static Gtk.ListStore notebooks;
+		static Gtk.TreeModelSort sortedNotebooks;
+		static Dictionary<string, Gtk.TreeIter> notebookMap;
+		static object locker = new object ();
+		#endregion // Fields
+
+		#region Constructors
+		static NotebookManager ()
+		{
+			notebooks = new Gtk.ListStore (typeof (Notebook));
+
+			sortedNotebooks = new Gtk.TreeModelSort (notebooks);
+			sortedNotebooks.SetSortFunc (0, new Gtk.TreeIterCompareFunc (CompareNotebooksSortFunc));
+			sortedNotebooks.SetSortColumnId (0, Gtk.SortType.Ascending);
+
+			// <summary>
+			// The key for this dictionary is Notebook.Name.ToLower ().
+			// </summary>
+			notebookMap = new Dictionary<string, Gtk.TreeIter> ();
+			
+			LoadNotebooks ();
+		}
+		#endregion // Constructors
+		
+		#region Properties
+		public static Gtk.TreeModel Notebooks
+		{
+			get {
+				return sortedNotebooks;
+			}
+		}
+		#endregion // Properties
+		
+		#region Public Methods
+		public static Notebook GetNotebook (string notebookName)
+		{
+			if (notebookName == null)
+				throw new ArgumentNullException ("NotebookManager.GetNotebook () called with a null name.");
+			
+			string normalizedName = notebookName.Trim ().ToLower ();
+			if (normalizedName == String.Empty)
+				throw new ArgumentException ("NotebookManager.GetNotebook () called with an empty name.");
+			
+			if (notebookMap.ContainsKey (normalizedName)) {
+				Gtk.TreeIter iter = notebookMap [normalizedName];
+				return notebooks.GetValue (iter, 0) as Notebook;
+			}
+			
+			return null;
+		}
+		
+		public static Notebook GetOrCreateNotebook (string notebookName)
+		{
+			if (notebookName == null)
+				throw new ArgumentNullException ("NotebookManager.GetNotebook () called with a null name.");
+			
+			Notebook notebook = GetNotebook (notebookName);
+			if (notebook != null)
+				return notebook;
+			
+			Gtk.TreeIter iter = Gtk.TreeIter.Zero;
+			lock (locker) {
+				notebook = GetNotebook (notebookName);
+				if (notebook != null)
+					return notebook;
+				
+				notebook = new Notebook (notebookName);
+				iter = notebooks.Append ();
+				notebooks.SetValue (iter, 0, notebook);
+				notebookMap [notebook.NormalizedName] = iter;
+				
+				// Create the template note so the system tag
+				// that represents the notebook actually gets
+				// saved to a note (and persisted after Tomboy
+				// is shut down).
+				Note templateNote = notebook.GetTemplateNote ();
+				
+				// Make sure the template note has the notebook tag.
+				// Since it's possible for the template note to already
+				// exist, we need to make sure it gets tagged.
+				templateNote.AddTag (notebook.Tag);
+			}
+
+			return notebook;
+		}
+		
+		/// <summary>
+		/// Remove the specified notebook from the system
+		/// </summary>
+		/// <param name="notebook">
+		/// A <see cref="Notebook"/>
+		/// </param>
+		public static void RemoveNotebook (Notebook notebook)
+		{
+			if (notebook == null)
+				throw new ArgumentNullException ("NotebookManager.RemoveNotebook () called with a null argument.");
+			
+			if (notebookMap.ContainsKey (notebook.NormalizedName) == false)
+				return;
+			
+			lock (locker) {
+				if (notebookMap.ContainsKey (notebook.NormalizedName) == false)
+					return;
+				
+				Gtk.TreeIter iter = notebookMap [notebook.NormalizedName];
+				if (notebooks.Remove (ref iter) == true) {
+					Logger.Debug ("NotebookManager: Removed notebook: {0}", notebook.NormalizedName);
+				} else {
+					Logger.Warn ("NotebookManager: Call to remove notebook failed: {0}", notebook.NormalizedName);
+				}
+				
+				notebookMap.Remove (notebook.NormalizedName);
+				
+				// Remove the notebook tag from every note that's in the notebook
+				foreach (Note note in notebook.Tag.Notes) {
+					note.RemoveTag (notebook.Tag);
+				}
+			}
+		}
+		
+		/// <summary>
+		/// Returns the Gtk.TreeIter that points to the specified Notebook.
+		/// </summary>
+		/// <param name="notebook">
+		/// A <see cref="Notebook"/>
+		/// </param>
+		/// <param name="iter">
+		/// A <see cref="Gtk.TreeIter"/>.  Will be set to a valid iter if
+		/// the specified notebook is found.
+		/// </param>
+		/// <returns>
+		/// A <see cref="System.Boolean"/>.  True if the specified notebook
+		/// was found, false otherwise.
+		/// </returns>
+		public static bool GetNotebookIter (Notebook notebook, out Gtk.TreeIter iter)
+		{
+			if (notebookMap.ContainsKey (notebook.NormalizedName) == true) {
+				iter = notebookMap [notebook.NormalizedName];
+				return true;
+			}
+			
+			iter = Gtk.TreeIter.Zero;
+			return false;
+		}
+		#endregion // Public Methods
+		
+		#region Private Methods
+		static int CompareNotebooksSortFunc (Gtk.TreeModel model,
+											 Gtk.TreeIter a,
+											 Gtk.TreeIter b)
+		{
+			Notebook notebook_a = model.GetValue (a, 0) as Notebook;
+			Notebook notebook_b = model.GetValue (b, 0) as Notebook;
+
+			if (notebook_a == null || notebook_b == null)
+				return 0;
+
+			return string.Compare (notebook_a.Name, notebook_b.Name);
+		}
+		
+		/// <summary>
+		/// Loop through the system tags looking for notebooks
+		/// </summary>
+		private static void LoadNotebooks ()
+		{
+			Gtk.TreeIter iter = Gtk.TreeIter.Zero;
+			foreach (Tag tag in TagManager.AllTags) {
+				// Skip over tags that aren't notebooks
+				if (tag.IsSystem == false
+						|| tag.Name.StartsWith (Tag.SYSTEM_TAG_PREFIX + Notebook.NotebookTagPrefix) == false) {
+					continue;
+				}
+				Notebook notebook = new Notebook (tag);
+				iter = notebooks.Append ();
+				notebooks.SetValue (iter, 0, notebook);
+				notebookMap [notebook.NormalizedName] = iter;
+			}
+		}
+		#endregion // Private Methods
+	}
+}
Index: Tomboy/Notebooks/Notebook.cs
===================================================================
--- Tomboy/Notebooks/Notebook.cs	(revision 0)
+++ Tomboy/Notebooks/Notebook.cs	(revision 1693)
@@ -0,0 +1,160 @@
+using System;
+using Mono.Unix;
+using Tomboy;
+
+namespace Tomboy.Notebooks
+{
+	/// <summary>
+	/// An object that represents a notebook in Tomboy
+	/// </summary>
+	public class Notebook
+	{
+		public static string NotebookTagPrefix = "notebook:";
+		
+		#region Fields
+		string name;
+		string normalizedName;
+		string templateNoteTitle;
+		Tag tag;
+		#endregion // Fields
+		
+		#region Constructors
+		/// <summary>
+		/// Construct a new Notebook with a given name
+		/// </summary>
+		/// <param name="name">
+		/// A <see cref="System.String"/>.  This is the name that will be used
+		/// to identify the notebook.
+		/// </param>
+		public Notebook (string name)
+		{
+			Name = name;
+			tag = TagManager.GetOrCreateSystemTag (NotebookTagPrefix + name);
+		}
+		
+		/// <summary>
+		/// Construct a new Notebook with the specified notebook system tag.
+		/// </summary>
+		/// <param name="notebookTag">
+		/// A <see cref="Tag"/>.  This must be a system notebook tag.
+		/// </param>
+		public Notebook (Tag notebookTag)
+		{
+			// Parse the notebook name from the tag name
+			string systemNotebookPrefix = Tag.SYSTEM_TAG_PREFIX + NotebookTagPrefix;
+			string notebookName = notebookTag.Name.Substring (systemNotebookPrefix.Length);
+			Name = notebookName;
+			tag = notebookTag;
+		}
+		
+		/// <summary>
+		/// Default constructor not used
+		/// </summary>
+		private Notebook ()
+		{
+		}
+		
+		#endregion // Constructors
+		
+		#region Properties
+		public string Name
+		{
+			get {
+				return name;
+			}
+			set {
+				if (value != null) {
+					string trimmedName = (value as string).Trim ();
+					if (trimmedName != String.Empty) {
+						name = trimmedName;
+						normalizedName = trimmedName.ToLower ();
+
+						// The templateNoteTite should show the name of the
+						// notebook.  For example, if the name of the notebooks
+						// "Meetings", the templateNoteTitle should be "Meetings
+						// Notebook Template".  Translators should place the
+						// name of the notebook accordingly using "{0}".
+						// TODO: Figure out how to make this note for
+						// translators appear properly.
+						string format = Catalog.GetString ("{0} Notebook Template");
+						templateNoteTitle = string.Format (format, Name);
+					}
+				}
+			}
+		}
+		
+		public string NormalizedName
+		{
+			get {
+				return normalizedName;
+			}
+		}
+		
+		public Tag Tag
+		{
+			get {
+				return tag;
+			}
+		}
+		#endregion // Properties
+		
+		#region Public Methods
+		/// <summary>
+		/// Return the template Tomboy Note that corresponds with
+		/// this Notebook.
+		/// </summary>
+		/// <returns>
+		/// A <see cref="Note"/>
+		/// </returns>
+		public Note GetTemplateNote ()
+		{
+			NoteManager noteManager = Tomboy.DefaultNoteManager;
+			Note note = noteManager.Find (templateNoteTitle);
+			if (note == null) {
+				note =
+					noteManager.Create (templateNoteTitle,
+							NoteManager.GetNoteTemplateContent (templateNoteTitle));
+					
+				// Select the initial text
+				NoteBuffer buffer = note.Buffer;
+				Gtk.TextIter iter = buffer.GetIterAtLineOffset (2, 0);
+				buffer.MoveMark (buffer.SelectionBound, iter);
+				buffer.MoveMark (buffer.InsertMark, buffer.EndIter);
+
+				// Add on the notebook system tag so Tomboy
+				// will persist the tag/notebook across sessions
+				// if no other notes are added to the notebook.
+				Tag tag = TagManager.GetOrCreateSystemTag (NotebookTagPrefix + Name);
+				note.AddTag (tag);
+
+				note.QueueSave (true);
+			}
+			
+			return note;
+		}
+		
+		/// <summary>
+		/// Returns true when the specified note exists in the notebook
+		/// </summary>
+		/// <param name="note">
+		/// A <see cref="Note"/>
+		/// </param>
+		/// <returns>
+		/// A <see cref="System.Boolean"/>
+		/// </returns>
+		public bool ContainsNote (Note note)
+		{
+			// Check the specified note to see if it contains the notebook tag
+			foreach (Tag noteTag in note.Tags) {
+				if (noteTag == tag)
+					return true;
+			}
+			
+			return false;
+		}
+		#endregion // Public Methods
+		
+		#region Private Methods
+		#endregion // Private Methods
+	}
+}
\ No newline at end of file
Index: Tomboy/Notebooks/CreateNotebookDialog.cs
===================================================================
--- Tomboy/Notebooks/CreateNotebookDialog.cs	(revision 0)
+++ Tomboy/Notebooks/CreateNotebookDialog.cs	(revision 1693)
@@ -0,0 +1,68 @@
+using System;
+using Mono.Unix;
+using Tomboy;
+
+namespace Tomboy.Notebooks
+{
+	public class CreateNotebookDialog : HIGMessageDialog
+	{
+		Gtk.Entry nameEntry;
+		
+		public CreateNotebookDialog(Gtk.Window parent,
+									Gtk.DialogFlags flags)
+				: base (parent, flags, Gtk.MessageType.Other,
+						Gtk.ButtonsType.None,
+						Catalog.GetString ("Create a new notebook"),
+						Catalog.GetString ("Type the name of the notebook you'd like to create."))
+		{
+			Gtk.HBox hbox = new Gtk.HBox (false, 6);
+			
+			Gtk.Label label = new Gtk.Label (Catalog.GetString ("N_otebook name:"));
+			label.Xalign = 0;
+			label.UseUnderline = true;
+			label.Show ();
+			
+			nameEntry = new Gtk.Entry ();
+			nameEntry.Changed += OnNameEntryChanged;
+			nameEntry.ActivatesDefault = true;
+			nameEntry.Show ();
+			label.MnemonicWidget = nameEntry;
+			
+			hbox.PackStart (label, false, false, 0);
+			hbox.PackStart (nameEntry, true, true, 0);
+			hbox.Show ();
+			
+			ExtraWidget = hbox;
+			
+			AddButton (Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, false);
+			AddButton (Gtk.Stock.New, Gtk.ResponseType.Ok, true);
+			
+			// Only let the Ok response be sensitive when
+			// there's something in nameEntry
+			SetResponseSensitive (Gtk.ResponseType.Ok, false);
+		}
+		
+		public string NotebookName
+		{
+			get {
+				string name = nameEntry.Text;
+				return name.Trim ();
+			}
+			set {
+				if (value == null || value.Trim () == string.Empty) {
+					nameEntry.Text = string.Empty;
+				} else {
+					nameEntry.Text = value.Trim ();
+				}
+			}
+		}
+		
+		// Enable the Ok response only if there's text in the nameEntry
+		private void OnNameEntryChanged (object sender, EventArgs args)
+		{
+			SetResponseSensitive (
+					Gtk.ResponseType.Ok,
+					NotebookName == string.Empty ? false : true);
+		}
+	}
+}
Index: Tomboy/Notebooks/NotebookMenuItem.cs
===================================================================
--- Tomboy/Notebooks/NotebookMenuItem.cs	(revision 0)
+++ Tomboy/Notebooks/NotebookMenuItem.cs	(revision 1693)
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using Tomboy;
+
+namespace Tomboy.Notebooks
+{
+	public class NotebookMenuItem : Gtk.RadioMenuItem, IComparable<NotebookMenuItem>
+	{
+		Note note;
+		Notebook notebook;
+
+		public NotebookMenuItem (Note note, Notebook notebook) : base (notebook.Name)
+		{
+			this.note = note;
+			this.notebook = notebook;
+			
+			if (notebook.ContainsNote (note))
+				Active = true;
+			
+			Activated += OnActivated;
+		}
+		
+		protected void OnActivated (object sender, EventArgs args)
+		{
+			if (note == null || notebook == null)
+				return;
+			
+			// TODO: In the future we may want to allow notes
+			// to exist in multiple notebooks.  For now, to
+			// alleviate the confusion, only allow a note to
+			// exist in one notebook at a time.
+			List<Tag> tagsToRemove = new List<Tag> ();
+			foreach (Tag tag in note.Tags) {
+				if (tag.NormalizedName.StartsWith (Tag.SYSTEM_TAG_PREFIX + Notebooks.Notebook.NotebookTagPrefix))
+					tagsToRemove.Add (tag);
+			}
+			
+			foreach (Tag tag in tagsToRemove) {
+				note.RemoveTag (tag);
+			}
+			
+			note.AddTag (notebook.Tag);
+		}
+
+		public Note Note
+		{
+			get { return note; }
+		}
+		
+		public Notebook Notebook
+		{
+			get { return notebook; }
+		}
+
+		// IComparable interface
+		public int CompareTo (NotebookMenuItem other)
+		{
+			return notebook.Name.CompareTo (other.Notebook.Name);
+		}
+	}
+}
Index: Tomboy/Notebooks/NotebookNewNoteMenuItem.cs
===================================================================
--- Tomboy/Notebooks/NotebookNewNoteMenuItem.cs	(revision 0)
+++ Tomboy/Notebooks/NotebookNewNoteMenuItem.cs	(revision 1693)
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using Tomboy;
+
+namespace Tomboy.Notebooks
+{
+	public class NotebookNewNoteMenuItem : Gtk.ImageMenuItem, IComparable<NotebookMenuItem>
+	{
+		Notebook notebook;
+		
+		// TODO: Uncomment this code when we have an
+		// icon for creating a new note inside of a notebook
+		//static Gdk.Pixbuf noteIcon;
+		//
+		//static NotebookNewNoteMenuItem ()
+		//{
+		//	noteIcon = GuiUtils.GetIcon ("tomboy-note", 22);
+		//}
+		
+		public NotebookNewNoteMenuItem(Notebook notebook) : base (notebook.Name)
+		{
+			this.notebook = notebook;
+			//this.Image = new Gtk.Image (noteIcon);
+			this.Image = new Gtk.Image (Gtk.Stock.New, Gtk.IconSize.Menu);
+			
+			Activated += OnActivated;
+		}
+
+		protected void OnActivated (object sender, EventArgs args)
+		{
+			if (notebook == null)
+				return;
+			
+			// Look for the template note and create a new note
+			Note templateNote = notebook.GetTemplateNote ();
+			Note note;
+			
+			NoteManager noteManager = Tomboy.DefaultNoteManager;
+			note = noteManager.Create ();
+			if (templateNote != null) {
+				// Use the body from the template note
+				string xmlContent = templateNote.XmlContent.Replace (templateNote.Title, note.Title);
+				note.XmlContent = xmlContent;
+			}
+			
+			note.AddTag (notebook.Tag);
+			note.Window.Show ();
+		}
+
+		public Notebook Notebook
+		{
+			get { return notebook; }
+		}
+
+		// IComparable interface
+		public int CompareTo (NotebookMenuItem other)
+		{
+			return notebook.Name.CompareTo (other.Notebook.Name);
+		}
+	}
+}
Index: Tomboy/Notebooks/NotebookApplicationAddin.cs
===================================================================
--- Tomboy/Notebooks/NotebookApplicationAddin.cs	(revision 0)
+++ Tomboy/Notebooks/NotebookApplicationAddin.cs	(revision 1695)
@@ -0,0 +1,149 @@
+using System;
+using System.Collections.Generic;
+using Mono.Unix;
+using Tomboy;
+
+namespace Tomboy.Notebooks
+{
+	public class NotebookApplicationAddin : ApplicationAddin
+	{
+		static Gtk.ActionGroup actionGroup;
+		static uint notebookUi = 0;
+
+		bool initialized;
+
+		Gtk.Menu trayNotebookMenu;
+		Gtk.Menu mainWindowNotebookMenu;
+		
+		public NotebookApplicationAddin ()
+		{
+			initialized = false;
+		}
+
+		public override void Initialize ()
+		{
+			actionGroup = new Gtk.ActionGroup ("Notebooks");
+			actionGroup.Add (new Gtk.ActionEntry [] {
+				new Gtk.ActionEntry ("NewNotebookMenuAction", Gtk.Stock.New,
+					Catalog.GetString ("New Note_book Note"), null,
+					Catalog.GetString ("Create a new note in a notebook"), null),
+					
+				new Gtk.ActionEntry ("TrayNewNotebookMenuAction", Gtk.Stock.New,
+					Catalog.GetString ("New Notebook Note"), null,
+					Catalog.GetString ("Create a new note in a notebook"), null)
+			});
+			
+			notebookUi = Tomboy.ActionManager.UI.AddUiFromString (@"
+					<ui>
+						<menubar name='MainWindowMenubar'>
+							<menu name='FileMenu' action='FileMenuAction'>
+								<placeholder name='FileMenuNewNotePlaceholder'>
+									<menuitem name='NewNotebookMenu' action='NewNotebookMenuAction' />
+								</placeholder>
+							</menu>
+						</menubar>
+						<popup name='TrayIconMenu' action='TrayIconMenuAction'>
+							<placeholder name='TrayNewNotePlaceholder'>
+								<menuitem name='TrayNewNotebookMenu' action='TrayNewNotebookMenuAction' position='top' />
+							</placeholder>
+						</popup>
+					</ui>
+				");
+			
+			Tomboy.ActionManager.UI.InsertActionGroup (actionGroup, 0);
+			
+			Gtk.MenuItem item = Tomboy.ActionManager.GetWidget (
+				"/TrayIconMenu/TrayNewNotePlaceholder/TrayNewNotebookMenu") as Gtk.MenuItem;
+			if (item != null) {
+				trayNotebookMenu = new Gtk.Menu ();
+				item.Submenu = trayNotebookMenu;
+				trayNotebookMenu.Shown += OnTrayNotebookMenuShown;
+				trayNotebookMenu.Hidden += OnTrayNotebookMenuHidden;
+			}
+			
+			item = Tomboy.ActionManager.GetWidget (
+				"/MainWindowMenubar/FileMenu/FileMenuNewNotePlaceholder/NewNotebookMenu") as Gtk.MenuItem;
+			if (item != null) {
+				mainWindowNotebookMenu = new Gtk.Menu ();
+				item.Submenu = mainWindowNotebookMenu;
+				mainWindowNotebookMenu.Shown += OnNewNotebookMenuShown;
+				mainWindowNotebookMenu.Hidden += OnNewNotebookMenuHidden;
+			}
+			
+			initialized = true;
+		}
+
+		public override void Shutdown ()
+		{
+			try {
+				Tomboy.ActionManager.UI.RemoveActionGroup (actionGroup);
+			} catch {}
+			try {
+				Tomboy.ActionManager.UI.RemoveUi (notebookUi);
+			} catch {}
+			
+			if (trayNotebookMenu != null) {
+				trayNotebookMenu.Shown -= OnTrayNotebookMenuShown;
+				trayNotebookMenu.Hidden -= OnTrayNotebookMenuHidden;
+			}
+			
+			if (mainWindowNotebookMenu != null) {
+				mainWindowNotebookMenu.Shown -= OnNewNotebookMenuShown;
+				mainWindowNotebookMenu.Hidden -= OnNewNotebookMenuHidden;
+			}
+
+			initialized = false;
+		}
+
+		public override bool Initialized
+		{
+			get {
+				return initialized;
+			}
+		}
+		
+		private void OnTrayNotebookMenuShown (object sender, EventArgs args)
+		{
+			AddMenuItems (trayNotebookMenu);
+		}
+
+		private void OnTrayNotebookMenuHidden (object sender, EventArgs args)
+		{
+			RemoveMenuItems (trayNotebookMenu);
+		}
+		
+		private void OnNewNotebookMenuShown (object sender, EventArgs args)
+		{
+			AddMenuItems (mainWindowNotebookMenu);
+		}
+		
+		private void OnNewNotebookMenuHidden (object sender, EventArgs args)
+		{
+			RemoveMenuItems (mainWindowNotebookMenu);
+		}
+		
+		private void AddMenuItems (Gtk.Menu menu)
+		{
+			NotebookNewNoteMenuItem item;
+
+			Gtk.TreeModel model = NotebookManager.Notebooks;
+			Gtk.TreeIter iter;
+			
+			if (model.GetIterFirst (out iter) == true) {
+				do {
+					Notebook notebook = model.GetValue (iter, 0) as Notebook;
+					item = new NotebookNewNoteMenuItem (notebook);
+					item.ShowAll ();
+					menu.Append (item);
+				} while (model.IterNext (ref iter) == true);
+			}
+		}
+		
+		private void RemoveMenuItems (Gtk.Menu menu)
+		{
+			foreach (Gtk.MenuItem child in menu.Children) {
+				menu.Remove (child);
+			}
+		}
+	}
+}
Index: Tomboy/Notebooks/NotebookNoteAddin.cs
===================================================================
--- Tomboy/Notebooks/NotebookNoteAddin.cs	(revision 0)
+++ Tomboy/Notebooks/NotebookNoteAddin.cs	(revision 1693)
@@ -0,0 +1,110 @@
+using System;
+using System.Collections.Generic;
+using Mono.Unix;
+using Tomboy;
+
+namespace Tomboy.Notebooks
+{
+	public class NotebookNoteAddin : NoteAddin
+	{
+		Gtk.ImageMenuItem menuItem;
+		Gtk.Menu menu;
+		bool submenuBuilt;
+
+		public override void Initialize ()
+		{
+			submenuBuilt = false;
+
+			menu = new Gtk.Menu ();
+			menu.Hidden += OnMenuHidden;
+			menu.ShowAll ();
+			menuItem = new Gtk.ImageMenuItem (
+			        Catalog.GetString ("Place in notebook"));
+			menuItem.Image = new Gtk.Image (Gtk.Stock.Paste, Gtk.IconSize.Menu);
+			menuItem.Submenu = menu;
+			menuItem.Activated += OnMenuItemActivated;
+			menuItem.Show ();
+			AddPluginMenuItem (menuItem);
+		}
+
+		public override void Shutdown ()
+		{
+			// Disconnect the event handlers so
+			// there aren't any memory leaks.
+			menu.Hidden -= OnMenuHidden;
+			menuItem.Activated -= OnMenuItemActivated;
+		}
+
+		public override void OnNoteOpened ()
+		{
+			// Do nothing.
+		}
+
+		void OnMenuItemActivated (object sender, EventArgs args)
+		{
+			if (submenuBuilt == true)
+				return; // submenu already built.  do nothing.
+
+			UpdateMenu ();
+		}
+
+		void OnMenuHidden (object sender, EventArgs args)
+		{
+			// FIXME: Figure out how to have this function be called only when
+			// the whole Tools menu is collapsed so that if a user keeps
+			// toggling over the menu item, it doesn't
+			// keep forcing the submenu to rebuild.
+
+			// Force the submenu to rebuild next time it's supposed to show
+			submenuBuilt = false;
+		}
+
+		void UpdateMenu ()
+		{
+			//
+			// Clear out the old list
+			//
+			foreach (Gtk.MenuItem oldItem in menu.Children) {
+				menu.Remove (oldItem);
+			}
+
+			//
+			// Build a new list
+			//
+			foreach (NotebookMenuItem item in GetNotebookMenuItems ()) {
+				item.ShowAll ();
+				menu.Append (item);
+			}
+
+			// If nothing was found, add in a "dummy" item
+			if (menu.Children.Length == 0) {
+				Gtk.MenuItem blankItem = new Gtk.MenuItem (Catalog.GetString ("(none)"));
+				blankItem.Sensitive = false;
+				blankItem.ShowAll ();
+				menu.Append (blankItem);
+			}
+
+			submenuBuilt = true;
+		}
+		
+		List<NotebookMenuItem> GetNotebookMenuItems ()
+		{
+			List<NotebookMenuItem> items = new List<NotebookMenuItem> ();
+			
+			Gtk.TreeModel model = NotebookManager.Notebooks;
+			Gtk.TreeIter iter;
+			
+			if (model.GetIterFirst (out iter) == true) {
+				do {
+					Notebook notebook = model.GetValue (iter, 0) as Notebook;
+					NotebookMenuItem item = new NotebookMenuItem (Note, notebook);
+					items.Add (item);
+				} while (model.IterNext (ref iter) == true);
+			}
+			
+			items.Sort ();
+			
+			return items;
+		}
+	}
+}
Index: Tomboy/PreferencesDialog.cs
===================================================================
--- Tomboy/PreferencesDialog.cs	(revision 1692)
+++ Tomboy/PreferencesDialog.cs	(working copy)
@@ -20,8 +20,12 @@ namespace Tomboy
 		Gtk.Button resetSyncAddinButton;
 		Gtk.Button saveSyncAddinButton;
 		readonly AddinManager addin_manager;
-
-		Type current_extension;
+		
+		Gtk.TreeView notebooksTree;
+		Gtk.TreeViewColumn notebookNameColumn;
+		Gtk.Button openTemplateNoteButton;
+		Gtk.Button addNotebookButton;
+		Gtk.Button removeNotebookButton;
 
 		Gtk.Button font_button;
 		Gtk.Label font_face;
@@ -79,6 +83,8 @@ namespace Tomboy
 			notebook.BorderWidth = 5;
 			notebook.Show ();
 
+			notebook.AppendPage (MakeNotebooksPane (),
+			                     new Gtk.Label (Catalog.GetString ("Notebooks")));
 			notebook.AppendPage (MakeEditingPane (),
 			                     new Gtk.Label (Catalog.GetString ("Editing")));
 			notebook.AppendPage (MakeHotkeysPane (),
@@ -111,6 +117,68 @@ namespace Tomboy
 			AddActionWidget (button, Gtk.ResponseType.Close);
 			DefaultResponse = Gtk.ResponseType.Close;
 		}
+		
+		// Page 0
+		// Notebooks
+		public Gtk.Widget MakeNotebooksPane ()
+		{
+			Gtk.VBox vbox = new Gtk.VBox (false, 6);
+			vbox.BorderWidth = 12;
+			vbox.Show ();
+			
+			notebooksTree = new Gtk.TreeView (Notebooks.NotebookManager.Notebooks);
+			notebooksTree.Selection.Changed += OnNotebooksTreeSelectionChanged;
+			notebooksTree.RowActivated += OnNotebookRowActivated;
+			notebooksTree.Model.RowInserted += OnNotebookAdded;
+			notebooksTree.Show ();
+			
+			Gtk.CellRenderer renderer;
+			notebookNameColumn = new Gtk.TreeViewColumn ();
+			notebookNameColumn.Title = Catalog.GetString ("Name");
+			notebookNameColumn.Sizing = Gtk.TreeViewColumnSizing.Autosize;
+			notebookNameColumn.Resizable = true;
+			
+			renderer = new Gtk.CellRendererText ();
+			notebookNameColumn.PackStart (renderer, true);
+			notebookNameColumn.SetCellDataFunc (renderer,
+									new Gtk.TreeCellDataFunc (NotebookNameColumnDataFunc));
+			notebooksTree.AppendColumn (notebookNameColumn);
+			
+			Gtk.ScrolledWindow sw  = new Gtk.ScrolledWindow ();
+			sw.HscrollbarPolicy = Gtk.PolicyType.Automatic;
+			sw.VscrollbarPolicy = Gtk.PolicyType.Automatic;
+			sw.ShadowType = Gtk.ShadowType.In;
+			sw.Add (notebooksTree);
+			sw.Show ();
+
+			vbox.PackStart (sw, true, true, 0);
+			
+			Gtk.HButtonBox hButtonBox = new Gtk.HButtonBox ();
+			hButtonBox.Layout = Gtk.ButtonBoxStyle.Edge;
+			hButtonBox.Show ();
+			
+			openTemplateNoteButton = new Gtk.Button (Catalog.GetString ("_Template Note"));
+			openTemplateNoteButton.UseUnderline = true;
+			openTemplateNoteButton.Sensitive = false;
+			openTemplateNoteButton.Clicked += OnOpenTemplateNoteButtonClicked;
+			openTemplateNoteButton.Show ();
+			hButtonBox.PackStart (openTemplateNoteButton, false, false, 0);
+			
+			addNotebookButton = new Gtk.Button (Gtk.Stock.Add);
+			addNotebookButton.Clicked += OnAddNotebookButtonClicked;
+			addNotebookButton.Show ();
+			hButtonBox.PackStart (addNotebookButton, false, false, 0);
+			
+			removeNotebookButton = new Gtk.Button (Gtk.Stock.Remove);
+			removeNotebookButton.Clicked += OnRemoveNotebookButtonClicked;
+			removeNotebookButton.Sensitive = false;
+			removeNotebookButton.Show ();
+			hButtonBox.PackStart (removeNotebookButton, false, false, 0);
+
+			vbox.PackStart (hButtonBox, false, false, 0);
+			
+			return vbox;
+		}
 
 		// Page 1
 		// List of editing options
@@ -1046,7 +1114,7 @@ namespace Tomboy
 				                                      "when you save new settings."));
 				int response = dialog.Run ();
 				dialog.Destroy ();
-				if (response == (int) Gtk.ResponseType.No)
+				if (response != (int) Gtk.ResponseType.Yes)
 					return;
 			} else { // FIXME: Weird place for this to go.  User should be able to cancel disabling of addin, anyway
 				HIGMessageDialog dialog =
@@ -1198,6 +1266,156 @@ namespace Tomboy
 			// Open the template note
 			template_note.Window.Show ();
 		}
+		
+		void OnOpenTemplateNoteButtonClicked (object sender, EventArgs args)
+		{
+			Notebooks.Notebook notebook = GetSelectedNotebook ();
+			if (notebook == null)
+				return;
+			
+			Note templateNote = notebook.GetTemplateNote ();
+			if (templateNote == null)
+				return; // something seriously went wrong
+			
+			templateNote.Window.Show ();
+		}
+		
+		void OnAddNotebookButtonClicked (object sender, EventArgs args)
+		{
+			// Prompt the user for the name of a new notebook
+			Notebooks.CreateNotebookDialog dialog =
+				new Notebooks.CreateNotebookDialog (this,
+							Gtk.DialogFlags.Modal
+								| Gtk.DialogFlags.DestroyWithParent
+								| Gtk.DialogFlags.NoSeparator);
+			
+			
+			int response = dialog.Run ();
+			string notebookName = dialog.NotebookName;
+			dialog.Destroy ();
+			if (response != (int) Gtk.ResponseType.Ok)
+				return;
+			
+			Notebooks.Notebook notebook = Notebooks.NotebookManager.GetOrCreateNotebook (notebookName);
+			if (notebook == null) {
+				Logger.Warn ("Could not create notebook: {0}", notebookName);
+			} else {
+				Logger.Debug ("Created the notebook: {0} ({1})", notebook.Name, notebook.NormalizedName);
+			}
+		}
+		
+		// Select the specified notebook in the TreeView
+//		void SelectNotebook (Notebooks.Notebook notebook)
+//		{
+//			Gtk.TreeIter iter;
+//			if (Notebooks.NotebookManager.GetNotebookIter (notebook, out iter) == false)
+//				return; // notebook not found
+//			
+//			notebooksTree.Selection.SelectIter (iter);
+//		}
+
+		void OnRemoveNotebookButtonClicked (object sender, EventArgs args)
+		{
+			Notebooks.Notebook notebook = GetSelectedNotebook ();
+			if (notebook == null)
+				return;
+			
+			// Confirmation Dialog
+			HIGMessageDialog dialog =
+				new HIGMessageDialog (null,
+									  Gtk.DialogFlags.Modal,
+									  Gtk.MessageType.Question,
+									  Gtk.ButtonsType.YesNo,
+									  Catalog.GetString ("Really remove this notebook?"),
+									  Catalog.GetString (
+									  	"The notes that belong to this notebook will note be " +
+									  	"removed, but they will no longer be associated with " +
+									  	"this notebook.  This action cannot be undone."));
+			Gtk.CheckButton removeTemplateNoteButton =
+				new Gtk.CheckButton (Catalog.GetString ("Also _delete notebook's template note"));
+			removeTemplateNoteButton.Show ();
+			dialog.ExtraWidget = removeTemplateNoteButton;
+			int response = dialog.Run ();
+			bool removeTemplateNote = removeTemplateNoteButton.Active;
+			dialog.Destroy ();
+			if (response != (int) Gtk.ResponseType.Yes)
+				return;
+			
+			Notebooks.NotebookManager.RemoveNotebook (notebook);
+			if (removeTemplateNote) {
+				Note templateNote = notebook.GetTemplateNote ();
+				if (templateNote != null) {
+					NoteManager noteManager = Tomboy.DefaultNoteManager;
+					noteManager.Delete (templateNote);
+				}
+			}
+		}
+
+		private void OnNotebooksTreeSelectionChanged (object sender, EventArgs args)
+		{
+			Notebooks.Notebook notebook = GetSelectedNotebook ();
+			
+			if (notebook == null) {
+				openTemplateNoteButton.Sensitive = false;
+				removeNotebookButton.Sensitive = false;
+			} else {
+				openTemplateNoteButton.Sensitive = true;
+				removeNotebookButton.Sensitive = true;
+			}
+		}
+		
+		// Open the notebook's note template when activated
+		private void OnNotebookRowActivated (object sender, Gtk.RowActivatedArgs args)
+		{
+			OnOpenTemplateNoteButtonClicked (sender, EventArgs.Empty);
+		}
+		
+		// Select the inserted notebook
+		private void OnNotebookAdded (object sender, Gtk.RowInsertedArgs args)
+		{
+			notebooksTree.Selection.SelectIter (args.Iter);
+			
+			// TODO: Figure out why we have to include the following
+			// lines instead of the SelectionChanged event taking care of this
+			openTemplateNoteButton.Sensitive = true;
+			removeNotebookButton.Sensitive = true;
+		}
+		
+		protected override void OnHidden ()
+		{
+			// Unregister the RowInserted handler so that
+			// it can't be called when there's no preferences
+			// dialog.
+			notebooksTree.Model.RowInserted -= OnNotebookAdded;
+			base.OnHidden ();
+		}
+
+		private Notebooks.Notebook GetSelectedNotebook ()
+		{
+			Gtk.TreeModel model;
+			Gtk.TreeIter iter;
+			
+			if (notebooksTree.Selection.GetSelected (out model, out iter) == false)
+				return null; // Nothing selected
+			
+			return model.GetValue (iter, 0) as Notebooks.Notebook;
+		}
+
+		private void NotebookNameColumnDataFunc (Gtk.TreeViewColumn column,
+												 Gtk.CellRenderer cell,
+												 Gtk.TreeModel model,
+												 Gtk.TreeIter iter)
+		{
+			Gtk.CellRendererText crt = cell as Gtk.CellRendererText;
+			if (crt == null)
+				return;
+			
+			Notebooks.Notebook notebook = model.GetValue (iter, 0) as Notebooks.Notebook;
+			if (notebook == null)
+				return;
+			
+			crt.Text = notebook.Name;
+		}
 	}
 
 	// TODO: Figure out how to use Mono.Addins.Gui.AddinInfoDialog here instead.
Index: Tomboy/Utils.cs
===================================================================
--- Tomboy/Utils.cs	(revision 1692)
+++ Tomboy/Utils.cs	(working copy)
@@ -226,6 +226,8 @@ namespace Tomboy
 	public class HIGMessageDialog : Gtk.Dialog
 	{
 		Gtk.AccelGroup accel_group;
+		Gtk.VBox extra_widget_vbox;
+		Gtk.Widget extra_widget;
 
 		public HIGMessageDialog (Gtk.Window parent,
 		                         Gtk.DialogFlags flags,
@@ -272,9 +274,11 @@ namespace Tomboy
 				break;
 			}
 
-			image.Show ();
-			image.Yalign = 0;
-			hbox.PackStart (image, false, false, 0);
+			if (image != null) {
+				image.Show ();
+				image.Yalign = 0;
+				hbox.PackStart (image, false, false, 0);
+			}
 
 			Gtk.VBox label_vbox = new Gtk.VBox (false, 0);
 			label_vbox.Show ();
@@ -301,6 +305,10 @@ namespace Tomboy
 			label.SetAlignment (0.0f, 0.5f);
 			label.Show ();
 			label_vbox.PackStart (label, false, false, 0);
+			
+			extra_widget_vbox = new Gtk.VBox (false, 0);
+			extra_widget_vbox.Show();
+			label_vbox.PackStart (extra_widget_vbox, true, true, 12);
 
 			switch (buttons) {
 			case Gtk.ButtonsType.None:
@@ -334,7 +342,7 @@ namespace Tomboy
 				DestroyWithParent = true;
 		}
 
-		void AddButton (string stock_id, Gtk.ResponseType response, bool is_default)
+		protected void AddButton (string stock_id, Gtk.ResponseType response, bool is_default)
 		{
 			Gtk.Button button = new Gtk.Button (stock_id);
 			button.CanDefault = true;
@@ -351,6 +359,22 @@ namespace Tomboy
 				                       Gtk.AccelFlags.Visible);
 			}
 		}
+		
+		public Gtk.Widget ExtraWidget
+		{
+			get {
+				return extra_widget;
+			}
+			set {
+				if (extra_widget != null) {
+					extra_widget_vbox.Remove (extra_widget);
+				}
+				
+				extra_widget = value;
+				extra_widget.ShowAll ();
+				extra_widget_vbox.PackStart (extra_widget, true, true, 0);
+			}
+		}
 	}
 
 	public class UriList : ArrayList
Index: Tomboy/TagManager.cs
===================================================================
--- Tomboy/TagManager.cs	(revision 1692)
+++ Tomboy/TagManager.cs	(working copy)
@@ -218,9 +218,15 @@ namespace Tomboy
 		{
 			get {
 				List<Tag> temp = new List<Tag>();
-				foreach(Gtk.TreeIter iter in tag_map.Values){
+				
+				// Add in the system tags first
+				temp.AddRange (internal_tags.Values);
+				
+				// Now all the other tags
+				foreach (Gtk.TreeIter iter in tag_map.Values){
 					temp.Add(tags.GetValue (iter, 0) as Tag);
 				}
+				
 				return temp;
 			}
 		}
Index: Tomboy/Tray.cs
===================================================================
--- Tomboy/Tray.cs	(revision 1692)
+++ Tomboy/Tray.cs	(working copy)
@@ -254,7 +254,7 @@ namespace Tomboy
 				// Create New Note Keybinding
 				Gtk.MenuItem item =
 				        Tomboy.ActionManager.GetWidget (
-				                "/TrayIconMenu/NewNote") as Gtk.MenuItem;
+				                "/TrayIconMenu/TrayNewNotePlaceholder/TrayNewNote") as Gtk.MenuItem;
 				if (item != null)
 					GConfKeybindingToAccel.AddAccelerator (
 					        item,
Index: Tomboy/Tomboy.addin.xml
===================================================================
--- Tomboy/Tomboy.addin.xml	(revision 1692)
+++ Tomboy/Tomboy.addin.xml	(working copy)
@@ -6,7 +6,7 @@
 	<ExtensionPoint path="/Tomboy/ApplicationAddins">
 		<ExtensionNode name="ApplicationAddin" objectType="Tomboy.ApplicationAddin" />
 	</ExtensionPoint>
-
+	
 	<ExtensionPoint path="/Tomboy/NoteAddins">
 		<ExtensionNode name="NoteAddin" objectType="Tomboy.NoteAddin" />
 	</ExtensionPoint>
@@ -47,4 +47,13 @@
 	<Extension path="/Tomboy/NoteAddins">
 		<NoteAddin type="Tomboy.NoteTagsWatcher" />
 	</Extension>
+	
+	<!-- Other built-in Addins that are not note watchers -->
+	<Extension path="/Tomboy/ApplicationAddins">
+		<ApplicationAddin type="Tomboy.Notebooks.NotebookApplicationAddin" />
+	</Extension>
+	
+	<Extension path="/Tomboy/NoteAddins">
+		<NoteAddin type="Tomboy.Notebooks.NotebookNoteAddin" />
+	</Extension>
 </Addin>
Index: Tomboy/NoteManager.cs
===================================================================
--- Tomboy/NoteManager.cs	(revision 1692)
+++ Tomboy/NoteManager.cs	(working copy)
@@ -464,7 +464,7 @@ public NoteManager (string directory) :
 			return template_note;
 		}
 		
-		private string GetNoteTemplateContent (string title)
+		public static string GetNoteTemplateContent (string title)
 		{
 			const string base_xml =
 			        "<note-content>" +
Index: Tomboy/Makefile.am
===================================================================
--- Tomboy/Makefile.am	(revision 1692)
+++ Tomboy/Makefile.am	(working copy)
@@ -67,6 +67,7 @@ CSFILES = 					\
 	$(srcdir)/Watchers.cs			\
 	$(srcdir)/WrapBox.cs			\
 	$(srcdir)/XKeybinder.cs			\
+	$(srcdir)/Notebooks/*.cs		\
 	$(srcdir)/Synchronization/*.cs		\
 	\
 	$(srcdir)/panelapplet/*.cs		\
Index: Tomboy.mdp
===================================================================
--- Tomboy.mdp	(revision 1692)
+++ Tomboy.mdp	(working copy)
@@ -210,6 +210,13 @@
     <File name="Tomboy/dbus-sharp/dbus-sharp-glib/glib/GLib.IO.cs" subtype="Code" buildaction="Compile" />
     <File name="Tomboy/TagEntry.cs" subtype="Code" buildaction="Compile" />
     <File name="Tomboy/Search.cs" subtype="Code" buildaction="Compile" />
+    <File name="Tomboy/Notebooks/Notebook.cs" subtype="Code" buildaction="Compile" />
+    <File name="Tomboy/Notebooks/NotebookManager.cs" subtype="Code" buildaction="Compile" />
+    <File name="Tomboy/Notebooks/CreateNotebookDialog.cs" subtype="Code" buildaction="Compile" />
+    <File name="Tomboy/Notebooks/NotebookNoteAddin.cs" subtype="Code" buildaction="Compile" />
+    <File name="Tomboy/Notebooks/NotebookMenuItem.cs" subtype="Code" buildaction="Compile" />
+    <File name="Tomboy/Notebooks/NotebookApplicationAddin.cs" subtype="Code" buildaction="Compile" />
+    <File name="Tomboy/Notebooks/NotebookNewNoteMenuItem.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Gac" localcopy="True" refto="gdk-sharp, Version=2.8.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
Index: Tomboy.mds
===================================================================
--- Tomboy.mds	(revision 1692)
+++ Tomboy.mds	(working copy)
@@ -11,6 +11,6 @@
     <Execute type="None" entry="Tomboy" />
   </StartMode>
   <Entries>
-    <Entry filename="./Tomboy.mdp" />
+    <Entry filename="Tomboy.mdp" />
   </Entries>
 </Combine>
\ No newline at end of file
Index: data/UIManagerLayout.xml
===================================================================
--- data/UIManagerLayout.xml	(revision 1692)
+++ data/UIManagerLayout.xml	(working copy)
@@ -1,7 +1,9 @@
 <ui>
     <menubar name="MainWindowMenubar">
         <menu name="FileMenu" action="FileMenuAction">
-            <menuitem name="NewNote" action="NewNoteAction" />
+			<placeholder name="FileMenuNewNotePlaceholder">
+				<menuitem name="NewNote" action="NewNoteAction" />
+			</placeholder>
             <menuitem name="OpenNote" action="OpenNoteAction" />
             <separator />
             <menuitem name="CloseWindow" action="CloseWindowAction" />
@@ -25,7 +27,9 @@
     </popup>
     <popup name="TrayIconMenu" action="TrayIconMenuAction">
     	<placeholder name="TrayIconMenuPlaceholder0" />
-        <menuitem name="TrayNewNote" action="TrayNewNoteAction" />
+    	<placeholder name="TrayNewNotePlaceholder">
+        	<menuitem name="TrayNewNote" action="TrayNewNoteAction" />
+        </placeholder>
         <menuitem name="ShowSearchAllNotes" action="ShowSearchAllNotesAction" />
         <placeholder name="TrayIconMenuPlaceholder1" />
     </popup>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]