tomboy r1920 - in trunk: . Mono.Addins/Mono.Addins Mono.Addins/Mono.Addins.Gui Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui Mono.Addins/Mono.Addins.Gui/gtk-gui Mono.Addins/Mono.Addins.Gui/icons Mono.Addins/Mono.Addins.Setup Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup Mono.Addins/Mono.Addins/Mono.Addins Mono.Addins/Mono.Addins/Mono.Addins.Database Mono.Addins/Mono.Addins/Mono.Addins.Description Mono.Addins/Mono.Addins/Mono.Addins.Localization



Author: sharm
Date: Sun Mar  2 21:23:19 2008
New Revision: 1920
URL: http://svn.gnome.org/viewvc/tomboy?rev=1920&view=rev

Log:
* Mono.Addins: Upgrade bundled Mono.Addins from version 0.2 to version 0.3.

Added:
   trunk/Mono.Addins/Mono.Addins.Gui/icons/system-software-update.png   (contents, props changed)
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/GettextDomain.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/GettextLocalizer.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/IAddinLocalizer.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/IAddinLocalizerFactory.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/IPluralAddinLocalizer.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/NullLocalizer.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/StringResourceLocalizer.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/StringTableLocalizer.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinLocalizer.cs
Removed:
   trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/NativePackage.cs
Modified:
   trunk/ChangeLog
   trunk/Mono.Addins/Mono.Addins.Gui/AssemblyInfo.cs
   trunk/Mono.Addins/Mono.Addins.Gui/Makefile.am
   trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinInstallDialog.cs
   trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinManagerDialog.cs
   trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinManagerWindow.cs
   trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/NewSiteDialog.cs
   trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInfoDialog.cs
   trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInstallDialog.cs
   trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInstallerDialog.cs
   trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinManagerDialog.cs
   trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.ErrorDialog.cs
   trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.ManageSitesDialog.cs
   trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.NewSiteDialog.cs
   trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/generated.cs
   trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/gui.stetic
   trunk/Mono.Addins/Mono.Addins.Setup/AssemblyInfo.cs
   trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/AddinPackage.cs
   trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/RepositoryRegistry.cs
   trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/SetupTool.cs
   trunk/Mono.Addins/Mono.Addins/AssemblyInfo.cs
   trunk/Mono.Addins/Mono.Addins/Makefile.am
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinHostIndex.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinScanFolderInfo.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinScanner.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinUpdateData.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/FileDatabase.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/SetupProcess.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/AddinDescription.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/Extension.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeDescription.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeDescriptionCollection.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeSet.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeType.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/NodeTypeAttribute.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/Addin.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinManager.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinRegistry.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinSessionService.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionContext.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionNode.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionTree.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/NodeAttributeAttribute.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/NodeElement.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/RuntimeAddin.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/TreeNode.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/TreeNodeCollection.cs
   trunk/Mono.Addins/Mono.Addins/Mono.Addins/TypeExtensionNode.cs

Modified: trunk/Mono.Addins/Mono.Addins.Gui/AssemblyInfo.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/AssemblyInfo.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/AssemblyInfo.cs	Sun Mar  2 21:23:19 2008
@@ -17,4 +17,4 @@
 // You can specify all values by your own or you can build default build and revision
 // numbers with the '*' character (the default):
 
-[assembly: AssemblyVersion("0.2.0.0")]
+[assembly: AssemblyVersion("0.3.0.0")]

Modified: trunk/Mono.Addins/Mono.Addins.Gui/Makefile.am
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/Makefile.am	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/Makefile.am	Sun Mar  2 21:23:19 2008
@@ -7,12 +7,15 @@
 	$(srcdir)/gtk-gui/generated.cs 					\
 	$(srcdir)/gtk-gui/Mono.Addins.Gui.AddinInfoDialog.cs 		\
 	$(srcdir)/gtk-gui/Mono.Addins.Gui.AddinInstallDialog.cs 	\
+	$(srcdir)/gtk-gui/Mono.Addins.Gui.AddinInstallerDialog.cs 	\
 	$(srcdir)/gtk-gui/Mono.Addins.Gui.AddinManagerDialog.cs 	\
 	$(srcdir)/gtk-gui/Mono.Addins.Gui.ErrorDialog.cs 		\
 	$(srcdir)/gtk-gui/Mono.Addins.Gui.ManageSitesDialog.cs 		\
 	$(srcdir)/gtk-gui/Mono.Addins.Gui.NewSiteDialog.cs 		\
 	$(srcdir)/Mono.Addins.Gui/AddinInfoDialog.cs 			\
 	$(srcdir)/Mono.Addins.Gui/AddinInstallDialog.cs 		\
+	$(srcdir)/Mono.Addins.Gui/AddinInstaller.cs 		\
+	$(srcdir)/Mono.Addins.Gui/AddinInstallerDialog.cs 		\
 	$(srcdir)/Mono.Addins.Gui/AddinManagerDialog.cs 		\
 	$(srcdir)/Mono.Addins.Gui/AddinManagerWindow.cs 		\
 	$(srcdir)/Mono.Addins.Gui/AddinTreeWidget.cs 			\
@@ -36,6 +39,7 @@
 	-resource:$(srcdir)/icons/package-x-generic.png 	\
 	-resource:$(srcdir)/icons/package-x-generic_16.png 	\
 	-resource:$(srcdir)/icons/package-x-generic_22.png 	\
+	-resource:$(srcdir)/icons/system-software-update.png \
 	-resource:$(srcdir)/icons/user-package.png 
 
 CSC_EXTRA_FLAGS =  -noconfig -codepage:utf8 -warn:4 -debug -d:DEBUG
@@ -60,6 +64,7 @@
 	$(srcdir)/icons/package-x-generic.png 		\
 	$(srcdir)/icons/package-x-generic_16.png 	\
 	$(srcdir)/icons/package-x-generic_22.png 	\
+	$(srcdir)/icons/system-software-update.png 	\
 	$(srcdir)/icons/user-package.png 
 
 CLEANFILES =			\

Modified: trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinInstallDialog.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinInstallDialog.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinInstallDialog.cs	Sun Mar  2 21:23:19 2008
@@ -32,6 +32,7 @@
 using System.Threading;
 using System.Collections;
 using System.Collections.Specialized;
+using System.Diagnostics;
 using Mono.Unix;
 
 using Gtk;
@@ -122,11 +123,14 @@
 			else
 				reps = service.Repositories.GetAvailableAddins (rep);
 			
-			foreach (AddinRepositoryEntry arep in reps) {
-				Addin sinfo = AddinManager.Registry.GetAddin (arep.Addin.Id);
+			foreach (AddinRepositoryEntry arep in reps)
+			{
 				if (!Services.InApplicationNamespace (service, arep.Addin.Id))
 					continue;
 				
+				// Find whatever version is installed
+				Addin sinfo = AddinManager.Registry.GetAddin (Addin.GetIdName (arep.Addin.Id));
+				
 				if (sinfo == null) {
 					if (showNotInstalled)
 						tree.AddAddin (arep.Addin, arep, true);
@@ -191,6 +195,7 @@
 		protected void OnManageSites (object sender, EventArgs e)
 		{
 			ManageSitesDialog dlg = new ManageSitesDialog (service);
+			dlg.TransientFor = this;
 			try {
 				dlg.Run ();
 				FillRepos ();
@@ -258,7 +263,7 @@
 				return;
 				
 			if (info.Url != "")
-				Gnome.Url.Show (info.Url);
+				Process.Start (info.Url);
 		}
 		
 		protected void OnShowInfo (object sender, EventArgs e)
@@ -426,6 +431,7 @@
 			string txt;
 			string okmessage;
 			string errmessage;
+			string warnmessage;
 			
 			installMonitor = new InstallMonitor (progressLabel, progressBar, mainProgressBar);
 			ThreadStart oper;
@@ -434,10 +440,12 @@
 				oper = new ThreadStart (RunInstall);
 				okmessage = Catalog.GetString ("The installation has been successfully completed.");
 				errmessage = Catalog.GetString ("The installation failed!");
+				warnmessage = Catalog.GetString ("The installation has completed with warnings.");
 			} else {
 				oper = new ThreadStart (RunUninstall);
 				okmessage = Catalog.GetString ("The uninstallation has been successfully completed.");
 				errmessage = Catalog.GetString ("The uninstallation failed!");
+				warnmessage = Catalog.GetString ("The uninstallation has completed with warnings.");
 			}
 			
 			Thread t = new Thread (oper);
@@ -449,16 +457,25 @@
 			
 			wizardNotebook.NextPage ();
 
-			if (installMonitor.Success) {
+			if (installMonitor.Success && installMonitor.Warnings.Count == 0) {
+				imageWarn.Visible = false;
 				imageError.Visible = false;
 				imageInfo.Visible = true;
 				txt = "<b>" + okmessage + "</b>\n\n";
+			} else if (installMonitor.Success) {
+				imageWarn.Visible = true;
+				imageInfo.Visible = false;
+				imageError.Visible = false;
+				txt = "<b>" + warnmessage + "</b>\n\n";
+				foreach (string s in installMonitor.Warnings)
+					txt += GLib.Markup.EscapeText (s) + "\n";
 			} else {
-				imageError.Visible = true;
+				imageWarn.Visible = false;
 				imageInfo.Visible = false;
+				imageError.Visible = true;
 				txt = "<span foreground=\"red\"><b>" + errmessage + "</b></span>\n\n";
 				foreach (string s in installMonitor.Errors)
-					txt += s + "\n";
+					txt += GLib.Markup.EscapeText (s) + "\n";
 			}
 			
 			labelResult.Markup = txt;

Modified: trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinManagerDialog.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinManagerDialog.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinManagerDialog.cs	Sun Mar  2 21:23:19 2008
@@ -38,12 +38,20 @@
 		AddinTreeWidget tree;
 		SetupService service = new SetupService ();
 		
+		internal bool AllowInstall
+		{
+			set {
+				this.btnInstall.Visible = value;
+				this.btnRepositories.Visible = value;
+				this.hseparator4.Visible = value;
+				this.btnUninstall.Visible = value;
+			}
+		}
+		
 		public AddinManagerDialog (Window parent)
 		{
 			Build ();
 			TransientFor = parent;
-			imageInstall.Stock = "md-software-update";
-			imageInstall.IconSize = (int)IconSize.Dialog;
 
 			tree = new AddinTreeWidget (addinTree);
 			LoadAddins ();
@@ -134,6 +142,7 @@
 		internal void OnManageRepos (object sender, EventArgs e)
 		{
 			ManageSitesDialog dlg = new ManageSitesDialog (service);
+			dlg.TransientFor = this;
 			try {
 				dlg.Run ();
 			} finally {

Modified: trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinManagerWindow.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinManagerWindow.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/AddinManagerWindow.cs	Sun Mar  2 21:23:19 2008
@@ -33,13 +33,27 @@
 {
 	public class AddinManagerWindow
 	{
+		private static bool mAllowInstall = true;
+		
+		public static bool AllowInstall
+		{
+			get { return mAllowInstall; }
+			set { mAllowInstall = value; }
+		}
+		
 		private AddinManagerWindow()
 		{
 		}
 		
+		private static void InitDialog (AddinManagerDialog dlg)
+		{
+			dlg.AllowInstall = AllowInstall;
+		}
+		
 		public static Gtk.Window Show (Gtk.Window parent)
 		{
 			AddinManagerDialog dlg = new AddinManagerDialog (parent);
+			InitDialog (dlg);
 			dlg.Show ();
 			return dlg;
 		}
@@ -48,6 +62,7 @@
 		{
 			AddinManagerDialog dlg = new AddinManagerDialog (parent);
 			try {
+				InitDialog (dlg);
 				dlg.Run ();
 			} finally {
 				dlg.Destroy ();

Modified: trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/NewSiteDialog.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/NewSiteDialog.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/Mono.Addins.Gui/NewSiteDialog.cs	Sun Mar  2 21:23:19 2008
@@ -51,10 +51,10 @@
 			get {
 				if (btnOnlineRep.Active)
 					return urlText.Text;
-				else if (pathEntry.Text != "")
+				else if (pathEntry.Text.Length > 0)
 					return "file://" + pathEntry.Text;
 				else
-					return "";
+					return string.Empty;
 			}
 		}
 		
@@ -106,5 +106,10 @@
 		{
 			CheckValues ();
 		}
+
+		protected virtual void OnUrlTextChanged (object sender, System.EventArgs e)
+		{
+			CheckValues ();
+		}
 	}
 }

Modified: trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInfoDialog.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInfoDialog.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInfoDialog.cs	Sun Mar  2 21:23:19 2008
@@ -26,22 +26,23 @@
         private Gtk.Button closebutton3;
         
         protected virtual void Build() {
-            Stetic.Gui.Initialize();
+            Stetic.Gui.Initialize(this);
             // Widget Mono.Addins.Gui.AddinInfoDialog
             this.Name = "Mono.Addins.Gui.AddinInfoDialog";
-            this.Title = Mono.Unix.Catalog.GetString("MonoDevelop Package");
+            this.Title = Mono.Unix.Catalog.GetString("Package");
             this.TypeHint = ((Gdk.WindowTypeHint)(1));
+            this.BorderWidth = ((uint)(6));
             this.DefaultWidth = 550;
             this.DefaultHeight = 400;
             // Internal child Mono.Addins.Gui.AddinInfoDialog.VBox
             Gtk.VBox w1 = this.VBox;
             w1.Name = "dialog-vbox12";
-            w1.BorderWidth = ((uint)(2));
+            w1.Spacing = 6;
             // Container child dialog-vbox12.Gtk.Box+BoxChild
             this.hbox81 = new Gtk.HBox();
             this.hbox81.Name = "hbox81";
             this.hbox81.Spacing = 12;
-            this.hbox81.BorderWidth = ((uint)(12));
+            this.hbox81.BorderWidth = ((uint)(6));
             // Container child hbox81.Gtk.Box+BoxChild
             this.vbox94 = new Gtk.VBox();
             this.vbox94.Name = "vbox94";
@@ -66,7 +67,6 @@
             this.scrolledwindow22.HscrollbarPolicy = ((Gtk.PolicyType)(1));
             // Container child scrolledwindow22.Gtk.Container+ContainerChild
             Gtk.Viewport w4 = new Gtk.Viewport();
-            w4.Name = "viewport4";
             w4.ShadowType = ((Gtk.ShadowType)(0));
             // Container child viewport4.Gtk.Container+ContainerChild
             this.infoLabel = new Gtk.Label();
@@ -90,7 +90,7 @@
             Gtk.HButtonBox w9 = this.ActionArea;
             w9.Name = "dialog-action_area12";
             w9.Spacing = 10;
-            w9.BorderWidth = ((uint)(5));
+            w9.BorderWidth = ((uint)(6));
             w9.LayoutStyle = ((Gtk.ButtonBoxStyle)(4));
             // Container child dialog-action_area12.Gtk.ButtonBox+ButtonBoxChild
             this.closebutton3 = new Gtk.Button();

Modified: trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInstallDialog.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInstallDialog.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInstallDialog.cs	Sun Mar  2 21:23:19 2008
@@ -81,6 +81,8 @@
         
         private Gtk.Image imageError;
         
+        private Gtk.Image imageWarn;
+        
         private Gtk.Image imageInfo;
         
         private Gtk.HBox hbox71;
@@ -101,28 +103,28 @@
         
         private Gtk.Button btnOk;
         
-        private Gtk.HSeparator hseparator3;
-        
         protected virtual void Build() {
-            Stetic.Gui.Initialize();
+            Stetic.Gui.Initialize(this);
             // Widget Mono.Addins.Gui.AddinInstallDialog
             this.Name = "Mono.Addins.Gui.AddinInstallDialog";
             this.Title = Mono.Unix.Catalog.GetString("Add-in Installation");
             this.TypeHint = ((Gdk.WindowTypeHint)(1));
             this.Modal = true;
+            this.BorderWidth = ((uint)(6));
             this.DefaultWidth = 725;
             this.DefaultHeight = 550;
             // Internal child Mono.Addins.Gui.AddinInstallDialog.VBox
             Gtk.VBox w1 = this.VBox;
             w1.Name = "dialog-vbox9";
+            w1.Spacing = 6;
             w1.BorderWidth = ((uint)(2));
             // Container child dialog-vbox9.Gtk.Box+BoxChild
             this.wizardNotebook = new Gtk.Notebook();
             this.wizardNotebook.CanFocus = true;
             this.wizardNotebook.Name = "wizardNotebook";
-            this.wizardNotebook.CurrentPage = 0;
+            this.wizardNotebook.CurrentPage = 3;
             this.wizardNotebook.ShowBorder = false;
-            this.wizardNotebook.BorderWidth = ((uint)(12));
+            this.wizardNotebook.BorderWidth = ((uint)(6));
             // Container child wizardNotebook.Gtk.Notebook+NotebookChild
             this.vbox82 = new Gtk.VBox();
             this.vbox82.Name = "vbox82";
@@ -204,6 +206,7 @@
             this.addinTree = new Gtk.TreeView();
             this.addinTree.CanFocus = true;
             this.addinTree.Name = "addinTree";
+            this.addinTree.HeadersClickable = true;
             this.scrolledwindow18.Add(this.addinTree);
             this.vbox92.Add(this.scrolledwindow18);
             Gtk.Box.BoxChild w9 = ((Gtk.Box.BoxChild)(this.vbox92[this.scrolledwindow18]));
@@ -279,6 +282,7 @@
             this.label108.Name = "label108";
             this.label108.LabelProp = "label108";
             this.wizardNotebook.SetTabLabel(this.vbox82, this.label108);
+            this.label108.ShowAll();
             // Container child wizardNotebook.Gtk.Notebook+NotebookChild
             this.scrolledwindow19 = new Gtk.ScrolledWindow();
             this.scrolledwindow19.CanFocus = true;
@@ -287,7 +291,6 @@
             this.scrolledwindow19.HscrollbarPolicy = ((Gtk.PolicyType)(1));
             // Container child scrolledwindow19.Gtk.Container+ContainerChild
             Gtk.Viewport w18 = new Gtk.Viewport();
-            w18.Name = "viewport1";
             // Container child viewport1.Gtk.Container+ContainerChild
             this.hbox82 = new Gtk.HBox();
             this.hbox82.Name = "hbox82";
@@ -298,7 +301,7 @@
             this.imageInstall.Name = "imageInstall";
             this.imageInstall.Xalign = 0F;
             this.imageInstall.Yalign = 0F;
-            this.imageInstall.Pixbuf = Stetic.IconLoader.LoadIcon("gtk-dialog-warning", 48);
+            this.imageInstall.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-dialog-warning", Gtk.IconSize.Dialog, 48);
             this.hbox82.Add(this.imageInstall);
             Gtk.Box.BoxChild w19 = ((Gtk.Box.BoxChild)(this.hbox82[this.imageInstall]));
             w19.Position = 0;
@@ -330,6 +333,7 @@
             this.label124.Name = "label124";
             this.label124.LabelProp = Mono.Unix.Catalog.GetString("label124");
             this.wizardNotebook.SetTabLabel(this.scrolledwindow19, this.label124);
+            this.label124.ShowAll();
             // Container child wizardNotebook.Gtk.Notebook+NotebookChild
             this.vbox86 = new Gtk.VBox();
             this.vbox86.Name = "vbox86";
@@ -348,7 +352,7 @@
             // Container child vbox86.Gtk.Box+BoxChild
             this.mainProgressBar = new Gtk.ProgressBar();
             this.mainProgressBar.Name = "mainProgressBar";
-            this.mainProgressBar.PulseStep = 0.10000000149;
+            this.mainProgressBar.PulseStep = 10000000149;
             this.vbox86.Add(this.mainProgressBar);
             Gtk.Box.BoxChild w25 = ((Gtk.Box.BoxChild)(this.vbox86[this.mainProgressBar]));
             w25.Position = 1;
@@ -376,7 +380,7 @@
             // Container child vbox86.Gtk.Box+BoxChild
             this.progressBar = new Gtk.ProgressBar();
             this.progressBar.Name = "progressBar";
-            this.progressBar.PulseStep = 0.10000000149;
+            this.progressBar.PulseStep = 10000000149;
             this.vbox86.Add(this.progressBar);
             Gtk.Box.BoxChild w28 = ((Gtk.Box.BoxChild)(this.vbox86[this.progressBar]));
             w28.Position = 4;
@@ -391,6 +395,7 @@
             this.label110.Name = "label110";
             this.label110.LabelProp = "label110";
             this.wizardNotebook.SetTabLabel(this.vbox86, this.label110);
+            this.label110.ShowAll();
             // Container child wizardNotebook.Gtk.Notebook+NotebookChild
             this.scrolledwindow20 = new Gtk.ScrolledWindow();
             this.scrolledwindow20.CanFocus = true;
@@ -399,7 +404,6 @@
             this.scrolledwindow20.HscrollbarPolicy = ((Gtk.PolicyType)(1));
             // Container child scrolledwindow20.Gtk.Container+ContainerChild
             Gtk.Viewport w30 = new Gtk.Viewport();
-            w30.Name = "viewport3";
             // Container child viewport3.Gtk.Container+ContainerChild
             this.vbox91 = new Gtk.VBox();
             this.vbox91.Name = "vbox91";
@@ -414,7 +418,7 @@
             this.imageError = new Gtk.Image();
             this.imageError.Name = "imageError";
             this.imageError.Yalign = 1F;
-            this.imageError.Pixbuf = Stetic.IconLoader.LoadIcon("gtk-dialog-error", 48);
+            this.imageError.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-dialog-error", Gtk.IconSize.Dialog, 48);
             this.vbox91.Add(this.imageError);
             Gtk.Box.BoxChild w32 = ((Gtk.Box.BoxChild)(this.vbox91[this.imageError]));
             w32.Position = 1;
@@ -422,15 +426,25 @@
             w32.Fill = false;
             w32.Padding = ((uint)(5));
             // Container child vbox91.Gtk.Box+BoxChild
+            this.imageWarn = new Gtk.Image();
+            this.imageWarn.Name = "imageWarn";
+            this.imageWarn.Yalign = 1F;
+            this.imageWarn.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-dialog-warning", Gtk.IconSize.Dialog, 48);
+            this.vbox91.Add(this.imageWarn);
+            Gtk.Box.BoxChild w33 = ((Gtk.Box.BoxChild)(this.vbox91[this.imageWarn]));
+            w33.Position = 2;
+            w33.Expand = false;
+            w33.Fill = false;
+            // Container child vbox91.Gtk.Box+BoxChild
             this.imageInfo = new Gtk.Image();
             this.imageInfo.Name = "imageInfo";
             this.imageInfo.Yalign = 1F;
-            this.imageInfo.Pixbuf = Stetic.IconLoader.LoadIcon("gtk-dialog-info", 48);
+            this.imageInfo.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-dialog-info", Gtk.IconSize.Dialog, 48);
             this.vbox91.Add(this.imageInfo);
-            Gtk.Box.BoxChild w33 = ((Gtk.Box.BoxChild)(this.vbox91[this.imageInfo]));
-            w33.Position = 2;
-            w33.Expand = false;
-            w33.Fill = false;
+            Gtk.Box.BoxChild w34 = ((Gtk.Box.BoxChild)(this.vbox91[this.imageInfo]));
+            w34.Position = 3;
+            w34.Expand = false;
+            w34.Fill = false;
             // Container child vbox91.Gtk.Box+BoxChild
             this.hbox71 = new Gtk.HBox();
             this.hbox71.Name = "hbox71";
@@ -445,35 +459,36 @@
             this.labelResult.Wrap = true;
             this.labelResult.Justify = ((Gtk.Justification)(2));
             this.hbox71.Add(this.labelResult);
-            Gtk.Box.BoxChild w34 = ((Gtk.Box.BoxChild)(this.hbox71[this.labelResult]));
-            w34.PackType = ((Gtk.PackType)(1));
-            w34.Position = 0;
+            Gtk.Box.BoxChild w35 = ((Gtk.Box.BoxChild)(this.hbox71[this.labelResult]));
+            w35.PackType = ((Gtk.PackType)(1));
+            w35.Position = 0;
             this.vbox91.Add(this.hbox71);
-            Gtk.Box.BoxChild w35 = ((Gtk.Box.BoxChild)(this.vbox91[this.hbox71]));
-            w35.Position = 3;
-            w35.Expand = false;
-            w35.Fill = false;
+            Gtk.Box.BoxChild w36 = ((Gtk.Box.BoxChild)(this.vbox91[this.hbox71]));
+            w36.Position = 4;
+            w36.Expand = false;
+            w36.Fill = false;
             // Container child vbox91.Gtk.Box+BoxChild
             this.label131 = new Gtk.Label();
             this.label131.Name = "label131";
             this.label131.LabelProp = "";
             this.vbox91.Add(this.label131);
-            Gtk.Box.BoxChild w36 = ((Gtk.Box.BoxChild)(this.vbox91[this.label131]));
-            w36.Position = 4;
+            Gtk.Box.BoxChild w37 = ((Gtk.Box.BoxChild)(this.vbox91[this.label131]));
+            w37.Position = 5;
             w30.Add(this.vbox91);
             this.scrolledwindow20.Add(w30);
             this.wizardNotebook.Add(this.scrolledwindow20);
-            Gtk.Notebook.NotebookChild w39 = ((Gtk.Notebook.NotebookChild)(this.wizardNotebook[this.scrolledwindow20]));
-            w39.Position = 3;
-            w39.TabExpand = false;
+            Gtk.Notebook.NotebookChild w40 = ((Gtk.Notebook.NotebookChild)(this.wizardNotebook[this.scrolledwindow20]));
+            w40.Position = 3;
+            w40.TabExpand = false;
             // Notebook tab
             this.label111 = new Gtk.Label();
             this.label111.Name = "label111";
             this.label111.LabelProp = "label111";
             this.wizardNotebook.SetTabLabel(this.scrolledwindow20, this.label111);
+            this.label111.ShowAll();
             w1.Add(this.wizardNotebook);
-            Gtk.Box.BoxChild w40 = ((Gtk.Box.BoxChild)(w1[this.wizardNotebook]));
-            w40.Position = 0;
+            Gtk.Box.BoxChild w41 = ((Gtk.Box.BoxChild)(w1[this.wizardNotebook]));
+            w41.Position = 0;
             // Container child dialog-vbox9.Gtk.Box+BoxChild
             this.dialog_action_area9 = new Gtk.HButtonBox();
             this.dialog_action_area9.Name = "dialog_action_area9";
@@ -498,8 +513,8 @@
             this.btnPrev.UseUnderline = true;
             this.btnPrev.Label = "gtk-go-back";
             this.dialog_action_area9.Add(this.btnPrev);
-            Gtk.ButtonBox.ButtonBoxChild w42 = ((Gtk.ButtonBox.ButtonBoxChild)(this.dialog_action_area9[this.btnPrev]));
-            w42.Position = 1;
+            Gtk.ButtonBox.ButtonBoxChild w43 = ((Gtk.ButtonBox.ButtonBoxChild)(this.dialog_action_area9[this.btnPrev]));
+            w43.Position = 1;
             // Container child dialog_action_area9.Gtk.ButtonBox+ButtonBoxChild
             this.btnNext = new Gtk.Button();
             this.btnNext.CanDefault = true;
@@ -509,8 +524,8 @@
             this.btnNext.UseUnderline = true;
             this.btnNext.Label = "gtk-go-forward";
             this.dialog_action_area9.Add(this.btnNext);
-            Gtk.ButtonBox.ButtonBoxChild w43 = ((Gtk.ButtonBox.ButtonBoxChild)(this.dialog_action_area9[this.btnNext]));
-            w43.Position = 2;
+            Gtk.ButtonBox.ButtonBoxChild w44 = ((Gtk.ButtonBox.ButtonBoxChild)(this.dialog_action_area9[this.btnNext]));
+            w44.Position = 2;
             // Container child dialog_action_area9.Gtk.ButtonBox+ButtonBoxChild
             this.btnOk = new Gtk.Button();
             this.btnOk.CanDefault = true;
@@ -520,21 +535,12 @@
             this.btnOk.UseUnderline = true;
             this.btnOk.Label = "gtk-ok";
             this.dialog_action_area9.Add(this.btnOk);
-            Gtk.ButtonBox.ButtonBoxChild w44 = ((Gtk.ButtonBox.ButtonBoxChild)(this.dialog_action_area9[this.btnOk]));
-            w44.Position = 3;
+            Gtk.ButtonBox.ButtonBoxChild w45 = ((Gtk.ButtonBox.ButtonBoxChild)(this.dialog_action_area9[this.btnOk]));
+            w45.Position = 3;
             w1.Add(this.dialog_action_area9);
-            Gtk.Box.BoxChild w45 = ((Gtk.Box.BoxChild)(w1[this.dialog_action_area9]));
-            w45.PackType = ((Gtk.PackType)(1));
-            w45.Position = 2;
-            w45.Expand = false;
-            w45.Fill = false;
-            // Container child dialog-vbox9.Gtk.Box+BoxChild
-            this.hseparator3 = new Gtk.HSeparator();
-            this.hseparator3.Name = "hseparator3";
-            w1.Add(this.hseparator3);
-            Gtk.Box.BoxChild w46 = ((Gtk.Box.BoxChild)(w1[this.hseparator3]));
+            Gtk.Box.BoxChild w46 = ((Gtk.Box.BoxChild)(w1[this.dialog_action_area9]));
             w46.PackType = ((Gtk.PackType)(1));
-            w46.Position = 3;
+            w46.Position = 2;
             w46.Expand = false;
             w46.Fill = false;
             // Internal child Mono.Addins.Gui.AddinInstallDialog.ActionArea
@@ -547,6 +553,7 @@
                 this.Child.ShowAll();
             }
             this.btnOk.Hide();
+            w47.Hide();
             this.Show();
             this.repoCombo.Changed += new System.EventHandler(this.OnRepoChanged);
             this.button1.Clicked += new System.EventHandler(this.OnUpdateRepo);

Modified: trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInstallerDialog.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInstallerDialog.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinInstallerDialog.cs	Sun Mar  2 21:23:19 2008
@@ -30,21 +30,23 @@
         private Gtk.Button buttonOk;
         
         protected virtual void Build() {
-            Stetic.Gui.Initialize();
+            Stetic.Gui.Initialize(this);
             // Widget Mono.Addins.Gui.AddinInstallerDialog
             this.Name = "Mono.Addins.Gui.AddinInstallerDialog";
             this.Title = Mono.Unix.Catalog.GetString("Add-in Manager");
             this.WindowPosition = ((Gtk.WindowPosition)(4));
+            this.BorderWidth = ((uint)(6));
             this.HasSeparator = false;
             // Internal child Mono.Addins.Gui.AddinInstallerDialog.VBox
             Gtk.VBox w1 = this.VBox;
             w1.Name = "dialog1_VBox";
+            w1.Spacing = 6;
             w1.BorderWidth = ((uint)(2));
             // Container child dialog1_VBox.Gtk.Box+BoxChild
             this.vbox2 = new Gtk.VBox();
             this.vbox2.Name = "vbox2";
             this.vbox2.Spacing = 6;
-            this.vbox2.BorderWidth = ((uint)(12));
+            this.vbox2.BorderWidth = ((uint)(6));
             // Container child vbox2.Gtk.Box+BoxChild
             this.label1 = new Gtk.Label();
             this.label1.Name = "label1";
@@ -74,7 +76,6 @@
             this.scrolledwindow1.ShadowType = ((Gtk.ShadowType)(1));
             // Container child scrolledwindow1.Gtk.Container+ContainerChild
             Gtk.Viewport w4 = new Gtk.Viewport();
-            w4.Name = "GtkViewport";
             w4.ShadowType = ((Gtk.ShadowType)(0));
             // Container child GtkViewport.Gtk.Container+ContainerChild
             this.addinList = new Gtk.Label();
@@ -105,7 +106,7 @@
             Gtk.HButtonBox w10 = this.ActionArea;
             w10.Name = "dialog1_ActionArea";
             w10.Spacing = 10;
-            w10.BorderWidth = ((uint)(5));
+            w10.BorderWidth = ((uint)(6));
             w10.LayoutStyle = ((Gtk.ButtonBoxStyle)(4));
             // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
             this.buttonCancel = new Gtk.Button();

Modified: trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinManagerDialog.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinManagerDialog.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.AddinManagerDialog.cs	Sun Mar  2 21:23:19 2008
@@ -37,7 +37,7 @@
         
         private Gtk.Button btnInstall;
         
-        private Gtk.Button button3;
+        private Gtk.Button btnRepositories;
         
         private Gtk.HSeparator hseparator4;
         
@@ -52,22 +52,24 @@
         private Gtk.Button btnClose;
         
         protected virtual void Build() {
-            Stetic.Gui.Initialize();
+            Stetic.Gui.Initialize(this);
             // Widget Mono.Addins.Gui.AddinManagerDialog
             this.Name = "Mono.Addins.Gui.AddinManagerDialog";
-            this.Title = Mono.Unix.Catalog.GetString("MonoDevelop Add-in Manager");
+            this.Title = Mono.Unix.Catalog.GetString("Add-in Manager");
             this.TypeHint = ((Gdk.WindowTypeHint)(1));
+            this.BorderWidth = ((uint)(6));
             this.DefaultWidth = 700;
             this.DefaultHeight = 550;
             // Internal child Mono.Addins.Gui.AddinManagerDialog.VBox
             Gtk.VBox w1 = this.VBox;
             w1.Name = "dialog-vbox8";
+            w1.Spacing = 3;
             w1.BorderWidth = ((uint)(2));
             // Container child dialog-vbox8.Gtk.Box+BoxChild
             this.vbox93 = new Gtk.VBox();
             this.vbox93.Name = "vbox93";
             this.vbox93.Spacing = 6;
-            this.vbox93.BorderWidth = ((uint)(12));
+            this.vbox93.BorderWidth = ((uint)(6));
             // Container child vbox93.Gtk.Box+BoxChild
             this.hbox85 = new Gtk.HBox();
             this.hbox85.Name = "hbox85";
@@ -76,7 +78,7 @@
             this.imageInstall = new Gtk.Image();
             this.imageInstall.Name = "imageInstall";
             this.imageInstall.Yalign = 0F;
-            this.imageInstall.Pixbuf = Stetic.IconLoader.LoadIcon("gtk-dialog-warning", 48);
+            this.imageInstall.Pixbuf = Gdk.Pixbuf.LoadFromResource("system-software-update.png");
             this.hbox85.Add(this.imageInstall);
             Gtk.Box.BoxChild w2 = ((Gtk.Box.BoxChild)(this.hbox85[this.imageInstall]));
             w2.Position = 0;
@@ -85,7 +87,7 @@
             // Container child hbox85.Gtk.Box+BoxChild
             this.label144 = new Gtk.Label();
             this.label144.Name = "label144";
-            this.label144.LabelProp = Mono.Unix.Catalog.GetString("<big><b>MonoDevelop Add-in Manager</b></big>");
+            this.label144.LabelProp = Mono.Unix.Catalog.GetString("<big><b>Add-in Manager</b></big>");
             this.label144.UseMarkup = true;
             this.hbox85.Add(this.label144);
             Gtk.Box.BoxChild w3 = ((Gtk.Box.BoxChild)(this.hbox85[this.label144]));
@@ -135,6 +137,7 @@
             this.addinTree = new Gtk.TreeView();
             this.addinTree.CanFocus = true;
             this.addinTree.Name = "addinTree";
+            this.addinTree.HeadersClickable = true;
             this.scrolledwindow13.Add(this.addinTree);
             this.hbox72.Add(this.scrolledwindow13);
             Gtk.Box.BoxChild w8 = ((Gtk.Box.BoxChild)(this.hbox72[this.scrolledwindow13]));
@@ -150,19 +153,15 @@
             this.btnInstall.UseUnderline = true;
             // Container child btnInstall.Gtk.Container+ContainerChild
             Gtk.Alignment w9 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
-            w9.Name = "GtkAlignment";
             // Container child GtkAlignment.Gtk.Container+ContainerChild
             Gtk.HBox w10 = new Gtk.HBox();
-            w10.Name = "GtkHBox";
             w10.Spacing = 2;
             // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Image w11 = new Gtk.Image();
-            w11.Name = "image5";
-            w11.Pixbuf = Stetic.IconLoader.LoadIcon("gtk-add", 20);
+            w11.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-add", Gtk.IconSize.Button, 20);
             w10.Add(w11);
             // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Label w13 = new Gtk.Label();
-            w13.Name = "GtkLabel";
             w13.LabelProp = Mono.Unix.Catalog.GetString("_Install Add-ins...");
             w13.UseUnderline = true;
             w10.Add(w13);
@@ -174,13 +173,13 @@
             w17.Expand = false;
             w17.Fill = false;
             // Container child vbox933.Gtk.Box+BoxChild
-            this.button3 = new Gtk.Button();
-            this.button3.CanFocus = true;
-            this.button3.Name = "button3";
-            this.button3.UseUnderline = true;
-            this.button3.Label = Mono.Unix.Catalog.GetString("_Repositories...");
-            this.vbox933.Add(this.button3);
-            Gtk.Box.BoxChild w18 = ((Gtk.Box.BoxChild)(this.vbox933[this.button3]));
+            this.btnRepositories = new Gtk.Button();
+            this.btnRepositories.CanFocus = true;
+            this.btnRepositories.Name = "btnRepositories";
+            this.btnRepositories.UseUnderline = true;
+            this.btnRepositories.Label = Mono.Unix.Catalog.GetString("_Repositories...");
+            this.vbox933.Add(this.btnRepositories);
+            Gtk.Box.BoxChild w18 = ((Gtk.Box.BoxChild)(this.vbox933[this.btnRepositories]));
             w18.Position = 1;
             w18.Expand = false;
             w18.Fill = false;
@@ -199,19 +198,15 @@
             this.btnUninstall.UseUnderline = true;
             // Container child btnUninstall.Gtk.Container+ContainerChild
             Gtk.Alignment w20 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
-            w20.Name = "GtkAlignment1";
             // Container child GtkAlignment1.Gtk.Container+ContainerChild
             Gtk.HBox w21 = new Gtk.HBox();
-            w21.Name = "GtkHBox1";
             w21.Spacing = 2;
             // Container child GtkHBox1.Gtk.Container+ContainerChild
             Gtk.Image w22 = new Gtk.Image();
-            w22.Name = "image6";
-            w22.Pixbuf = Stetic.IconLoader.LoadIcon("gtk-remove", 20);
+            w22.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-remove", Gtk.IconSize.Button, 20);
             w21.Add(w22);
             // Container child GtkHBox1.Gtk.Container+ContainerChild
             Gtk.Label w24 = new Gtk.Label();
-            w24.Name = "GtkLabel2";
             w24.LabelProp = Mono.Unix.Catalog.GetString("_Uninstall...");
             w24.UseUnderline = true;
             w21.Add(w24);
@@ -229,19 +224,15 @@
             this.btnEnable.UseUnderline = true;
             // Container child btnEnable.Gtk.Container+ContainerChild
             Gtk.Alignment w29 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
-            w29.Name = "GtkAlignment2";
             // Container child GtkAlignment2.Gtk.Container+ContainerChild
             Gtk.HBox w30 = new Gtk.HBox();
-            w30.Name = "GtkHBox2";
             w30.Spacing = 2;
             // Container child GtkHBox2.Gtk.Container+ContainerChild
             Gtk.Image w31 = new Gtk.Image();
-            w31.Name = "image7";
-            w31.Pixbuf = Stetic.IconLoader.LoadIcon("gtk-yes", 20);
+            w31.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-yes", Gtk.IconSize.Button, 20);
             w30.Add(w31);
             // Container child GtkHBox2.Gtk.Container+ContainerChild
             Gtk.Label w33 = new Gtk.Label();
-            w33.Name = "GtkLabel3";
             w33.LabelProp = Mono.Unix.Catalog.GetString("Enable");
             w33.UseUnderline = true;
             w30.Add(w33);
@@ -259,19 +250,15 @@
             this.btnDisable.UseUnderline = true;
             // Container child btnDisable.Gtk.Container+ContainerChild
             Gtk.Alignment w38 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
-            w38.Name = "GtkAlignment3";
             // Container child GtkAlignment3.Gtk.Container+ContainerChild
             Gtk.HBox w39 = new Gtk.HBox();
-            w39.Name = "GtkHBox3";
             w39.Spacing = 2;
             // Container child GtkHBox3.Gtk.Container+ContainerChild
             Gtk.Image w40 = new Gtk.Image();
-            w40.Name = "image8";
-            w40.Pixbuf = Stetic.IconLoader.LoadIcon("gtk-no", 20);
+            w40.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-no", Gtk.IconSize.Button, 20);
             w39.Add(w40);
             // Container child GtkHBox3.Gtk.Container+ContainerChild
             Gtk.Label w42 = new Gtk.Label();
-            w42.Name = "GtkLabel4";
             w42.LabelProp = Mono.Unix.Catalog.GetString("Disable");
             w42.UseUnderline = true;
             w39.Add(w42);
@@ -329,7 +316,7 @@
             this.Show();
             this.addinTree.CursorChanged += new System.EventHandler(this.OnSelectionChanged);
             this.btnInstall.Clicked += new System.EventHandler(this.OnInstall);
-            this.button3.Clicked += new System.EventHandler(this.OnManageRepos);
+            this.btnRepositories.Clicked += new System.EventHandler(this.OnManageRepos);
             this.btnUninstall.Clicked += new System.EventHandler(this.OnUninstall);
             this.btnEnable.Clicked += new System.EventHandler(this.OnEnable);
             this.btnDisable.Clicked += new System.EventHandler(this.OnDisable);

Modified: trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.ErrorDialog.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.ErrorDialog.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.ErrorDialog.cs	Sun Mar  2 21:23:19 2008
@@ -34,16 +34,16 @@
         private Gtk.Button okButton;
         
         protected virtual void Build() {
-            Stetic.Gui.Initialize();
+            Stetic.Gui.Initialize(this);
             // Widget Mono.Addins.Gui.ErrorDialog
             this.Name = "Mono.Addins.Gui.ErrorDialog";
-            this.Title = Mono.Unix.Catalog.GetString("MonoDevelop");
+            this.Title = Mono.Unix.Catalog.GetString("Error");
             this.TypeHint = ((Gdk.WindowTypeHint)(1));
             this.BorderWidth = ((uint)(6));
             // Internal child Mono.Addins.Gui.ErrorDialog.VBox
             Gtk.VBox w1 = this.VBox;
             w1.Name = "dialog-vbox5";
-            w1.BorderWidth = ((uint)(2));
+            w1.Spacing = 6;
             // Container child dialog-vbox5.Gtk.Box+BoxChild
             this.hbox59 = new Gtk.HBox();
             this.hbox59.Name = "hbox59";
@@ -55,7 +55,7 @@
             // Container child vbox72.Gtk.Box+BoxChild
             this.icon = new Gtk.Image();
             this.icon.Name = "icon";
-            this.icon.Pixbuf = Stetic.IconLoader.LoadIcon("gtk-dialog-error", 48);
+            this.icon.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-dialog-error", Gtk.IconSize.Dialog, 48);
             this.vbox72.Add(this.icon);
             Gtk.Box.BoxChild w2 = ((Gtk.Box.BoxChild)(this.vbox72[this.icon]));
             w2.Position = 0;
@@ -137,8 +137,8 @@
             if ((this.Child != null)) {
                 this.Child.ShowAll();
             }
-            this.DefaultWidth = 628;
-            this.DefaultHeight = 145;
+            this.DefaultWidth = 632;
+            this.DefaultHeight = 155;
             this.Show();
         }
     }

Modified: trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.ManageSitesDialog.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.ManageSitesDialog.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.ManageSitesDialog.cs	Sun Mar  2 21:23:19 2008
@@ -28,22 +28,23 @@
         private Gtk.Button closebutton2;
         
         protected virtual void Build() {
-            Stetic.Gui.Initialize();
+            Stetic.Gui.Initialize(this);
             // Widget Mono.Addins.Gui.ManageSitesDialog
             this.Name = "Mono.Addins.Gui.ManageSitesDialog";
             this.Title = Mono.Unix.Catalog.GetString("Add-in Repository Management");
             this.TypeHint = ((Gdk.WindowTypeHint)(1));
+            this.BorderWidth = ((uint)(6));
             this.DefaultWidth = 600;
             this.DefaultHeight = 300;
             // Internal child Mono.Addins.Gui.ManageSitesDialog.VBox
             Gtk.VBox w1 = this.VBox;
             w1.Name = "dialog-vbox10";
-            w1.BorderWidth = ((uint)(2));
+            w1.Spacing = 6;
             // Container child dialog-vbox10.Gtk.Box+BoxChild
             this.hbox67 = new Gtk.HBox();
             this.hbox67.Name = "hbox67";
             this.hbox67.Spacing = 12;
-            this.hbox67.BorderWidth = ((uint)(12));
+            this.hbox67.BorderWidth = ((uint)(6));
             // Container child hbox67.Gtk.Box+BoxChild
             this.scrolledwindow17 = new Gtk.ScrolledWindow();
             this.scrolledwindow17.CanFocus = true;
@@ -56,6 +57,7 @@
             this.repoTree.CanFocus = true;
             this.repoTree.Name = "repoTree";
             this.repoTree.HeadersVisible = false;
+            this.repoTree.HeadersClickable = true;
             this.scrolledwindow17.Add(this.repoTree);
             this.hbox67.Add(this.scrolledwindow17);
             Gtk.Box.BoxChild w3 = ((Gtk.Box.BoxChild)(this.hbox67[this.scrolledwindow17]));
@@ -100,7 +102,7 @@
             Gtk.HButtonBox w8 = this.ActionArea;
             w8.Name = "dialog-action_area10";
             w8.Spacing = 10;
-            w8.BorderWidth = ((uint)(5));
+            w8.BorderWidth = ((uint)(6));
             w8.LayoutStyle = ((Gtk.ButtonBoxStyle)(4));
             // Container child dialog-action_area10.Gtk.ButtonBox+ButtonBoxChild
             this.closebutton2 = new Gtk.Button();

Modified: trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.NewSiteDialog.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.NewSiteDialog.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/Mono.Addins.Gui.NewSiteDialog.cs	Sun Mar  2 21:23:19 2008
@@ -46,21 +46,23 @@
         private Gtk.Button btnOk;
         
         protected virtual void Build() {
-            Stetic.Gui.Initialize();
+            Stetic.Gui.Initialize(this);
             // Widget Mono.Addins.Gui.NewSiteDialog
             this.Name = "Mono.Addins.Gui.NewSiteDialog";
             this.Title = Mono.Unix.Catalog.GetString("Add New Repository");
             this.TypeHint = ((Gdk.WindowTypeHint)(1));
+            this.BorderWidth = ((uint)(6));
             this.DefaultWidth = 550;
             // Internal child Mono.Addins.Gui.NewSiteDialog.VBox
             Gtk.VBox w1 = this.VBox;
             w1.Name = "dialog-vbox11";
+            w1.Spacing = 6;
             w1.BorderWidth = ((uint)(2));
             // Container child dialog-vbox11.Gtk.Box+BoxChild
             this.vbox89 = new Gtk.VBox();
             this.vbox89.Name = "vbox89";
             this.vbox89.Spacing = 6;
-            this.vbox89.BorderWidth = ((uint)(12));
+            this.vbox89.BorderWidth = ((uint)(6));
             // Container child vbox89.Gtk.Box+BoxChild
             this.label121 = new Gtk.Label();
             this.label121.Name = "label121";
@@ -220,9 +222,10 @@
             if ((this.Child != null)) {
                 this.Child.ShowAll();
             }
-            this.DefaultHeight = 235;
+            this.DefaultHeight = 249;
             this.Show();
             this.btnOnlineRep.Clicked += new System.EventHandler(this.OnOptionClicked);
+            this.urlText.Changed += new System.EventHandler(this.OnUrlTextChanged);
             this.btnLocalRep.Clicked += new System.EventHandler(this.OnOptionClicked);
             this.pathEntry.Changed += new System.EventHandler(this.OnPathEntryChanged);
             this.buttonBrowse.Clicked += new System.EventHandler(this.OnButtonBrowseClicked);

Modified: trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/generated.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/generated.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/generated.cs	Sun Mar  2 21:23:19 2008
@@ -15,7 +15,7 @@
         
         private static bool initialized;
         
-        internal static void Initialize() {
+        internal static void Initialize(Gtk.Widget iconRenderer) {
             if ((Stetic.Gui.initialized == false)) {
                 Stetic.Gui.initialized = true;
             }
@@ -24,26 +24,32 @@
     
     internal class IconLoader {
         
-        public static Gdk.Pixbuf LoadIcon(string name, int sz) {
-            try {
-                return Gtk.IconTheme.Default.LoadIcon(name, sz, 0);
+        public static Gdk.Pixbuf LoadIcon(Gtk.Widget widget, string name, Gtk.IconSize size, int sz) {
+            Gdk.Pixbuf res = widget.RenderIcon(name, size, null);
+            if ((res != null)) {
+                return res;
             }
-            catch (System.Exception ) {
-                if ((name != "gtk-missing-image")) {
-                    return Stetic.IconLoader.LoadIcon("gtk-missing-image", sz);
+            else {
+                try {
+                    return Gtk.IconTheme.Default.LoadIcon(name, sz, 0);
                 }
-                else {
-                    Gdk.Pixmap pmap = new Gdk.Pixmap(Gdk.Screen.Default.RootWindow, sz, sz);
-                    Gdk.GC gc = new Gdk.GC(pmap);
-                    gc.RgbFgColor = new Gdk.Color(255, 255, 255);
-                    pmap.DrawRectangle(gc, true, 0, 0, sz, sz);
-                    gc.RgbFgColor = new Gdk.Color(0, 0, 0);
-                    pmap.DrawRectangle(gc, false, 0, 0, (sz - 1), (sz - 1));
-                    gc.SetLineAttributes(3, Gdk.LineStyle.Solid, Gdk.CapStyle.Round, Gdk.JoinStyle.Round);
-                    gc.RgbFgColor = new Gdk.Color(255, 0, 0);
-                    pmap.DrawLine(gc, (sz / 4), (sz / 4), ((sz - 1) - (sz / 4)), ((sz - 1) - (sz / 4)));
-                    pmap.DrawLine(gc, ((sz - 1) - (sz / 4)), (sz / 4), (sz / 4), ((sz - 1) - (sz / 4)));
-                    return Gdk.Pixbuf.FromDrawable(pmap, pmap.Colormap, 0, 0, 0, 0, sz, sz);
+                catch (System.Exception ) {
+                    if ((name != "gtk-missing-image")) {
+                        return Stetic.IconLoader.LoadIcon(widget, "gtk-missing-image", size, sz);
+                    }
+                    else {
+                        Gdk.Pixmap pmap = new Gdk.Pixmap(Gdk.Screen.Default.RootWindow, sz, sz);
+                        Gdk.GC gc = new Gdk.GC(pmap);
+                        gc.RgbFgColor = new Gdk.Color(255, 255, 255);
+                        pmap.DrawRectangle(gc, true, 0, 0, sz, sz);
+                        gc.RgbFgColor = new Gdk.Color(0, 0, 0);
+                        pmap.DrawRectangle(gc, false, 0, 0, (sz - 1), (sz - 1));
+                        gc.SetLineAttributes(3, Gdk.LineStyle.Solid, Gdk.CapStyle.Round, Gdk.JoinStyle.Round);
+                        gc.RgbFgColor = new Gdk.Color(255, 0, 0);
+                        pmap.DrawLine(gc, (sz / 4), (sz / 4), ((sz - 1) - (sz / 4)), ((sz - 1) - (sz / 4)));
+                        pmap.DrawLine(gc, ((sz - 1) - (sz / 4)), (sz / 4), (sz / 4), ((sz - 1) - (sz / 4)));
+                        return Gdk.Pixbuf.FromDrawable(pmap, pmap.Colormap, 0, 0, 0, 0, sz, sz);
+                    }
                 }
             }
         }

Modified: trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/gui.stetic
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/gui.stetic	(original)
+++ trunk/Mono.Addins/Mono.Addins.Gui/gtk-gui/gui.stetic	Sun Mar  2 21:23:19 2008
@@ -1,12 +1,13 @@
 ï<?xml version="1.0" encoding="utf-8"?>
 <stetic-interface>
   <configuration>
-    <images-root-path>../</images-root-path>
+    <images-root-path>..</images-root-path>
+    <target-gtk-version>2.8.3</target-gtk-version>
   </configuration>
-  <widget class="Gtk.Dialog" id="Mono.Addins.Gui.ErrorDialog" design-size="628 145">
+  <widget class="Gtk.Dialog" id="Mono.Addins.Gui.ErrorDialog" design-size="632 155">
     <property name="MemberName" />
     <property name="GeneratePublic">False</property>
-    <property name="Title" translatable="yes">MonoDevelop</property>
+    <property name="Title" translatable="yes">Error</property>
     <property name="TypeHint">Dialog</property>
     <property name="BorderWidth">6</property>
     <property name="Buttons">1</property>
@@ -14,7 +15,7 @@
     <child internal-child="VBox">
       <widget class="Gtk.VBox" id="dialog-vbox5">
         <property name="MemberName" />
-        <property name="BorderWidth">2</property>
+        <property name="Spacing">6</property>
         <child>
           <widget class="Gtk.HBox" id="hbox59">
             <property name="MemberName" />
@@ -133,7 +134,7 @@
             <property name="UseStock">True</property>
             <property name="Type">StockItem</property>
             <property name="StockId">gtk-ok</property>
-            <property name="IsDialogButton">False</property>
+            <property name="ResponseId">-5</property>
             <property name="label">gtk-ok</property>
           </widget>
         </child>
@@ -143,8 +144,9 @@
   <widget class="Gtk.Dialog" id="Mono.Addins.Gui.AddinManagerDialog" design-size="524 432">
     <property name="MemberName" />
     <property name="GeneratePublic">False</property>
-    <property name="Title" translatable="yes">MonoDevelop Add-in Manager</property>
+    <property name="Title" translatable="yes">Add-in Manager</property>
     <property name="TypeHint">Dialog</property>
+    <property name="BorderWidth">6</property>
     <property name="DefaultWidth">700</property>
     <property name="DefaultHeight">550</property>
     <property name="Buttons">1</property>
@@ -152,12 +154,13 @@
     <child internal-child="VBox">
       <widget class="Gtk.VBox" id="dialog-vbox8">
         <property name="MemberName" />
+        <property name="Spacing">3</property>
         <property name="BorderWidth">2</property>
         <child>
           <widget class="Gtk.VBox" id="vbox93">
             <property name="MemberName" />
             <property name="Spacing">6</property>
-            <property name="BorderWidth">12</property>
+            <property name="BorderWidth">6</property>
             <child>
               <widget class="Gtk.HBox" id="hbox85">
                 <property name="MemberName" />
@@ -166,7 +169,7 @@
                   <widget class="Gtk.Image" id="imageInstall">
                     <property name="MemberName" />
                     <property name="Yalign">0</property>
-                    <property name="Pixbuf">stock:gtk-dialog-warning Dialog</property>
+                    <property name="Pixbuf">resource:system-software-update.png</property>
                   </widget>
                   <packing>
                     <property name="Position">0</property>
@@ -178,7 +181,7 @@
                 <child>
                   <widget class="Gtk.Label" id="label144">
                     <property name="MemberName" />
-                    <property name="LabelProp" translatable="yes">&lt;big&gt;&lt;b&gt;MonoDevelop Add-in Manager&lt;/b&gt;&lt;/big&gt;</property>
+                    <property name="LabelProp" translatable="yes">&lt;big&gt;&lt;b&gt;Add-in Manager&lt;/b&gt;&lt;/big&gt;</property>
                     <property name="UseMarkup">True</property>
                   </widget>
                   <packing>
@@ -262,7 +265,6 @@
                             <property name="Icon">stock:gtk-add Button</property>
                             <property name="Label" translatable="yes">_Install Add-ins...</property>
                             <property name="UseUnderline">True</property>
-                            <property name="IsDialogButton">False</property>
                             <signal name="Clicked" handler="OnInstall" />
                           </widget>
                           <packing>
@@ -273,13 +275,12 @@
                           </packing>
                         </child>
                         <child>
-                          <widget class="Gtk.Button" id="button3">
+                          <widget class="Gtk.Button" id="btnRepositories">
                             <property name="MemberName" />
                             <property name="CanFocus">True</property>
                             <property name="Type">TextOnly</property>
                             <property name="Label" translatable="yes">_Repositories...</property>
                             <property name="UseUnderline">True</property>
-                            <property name="IsDialogButton">False</property>
                             <signal name="Clicked" handler="OnManageRepos" />
                           </widget>
                           <packing>
@@ -308,7 +309,6 @@
                             <property name="Icon">stock:gtk-remove Button</property>
                             <property name="Label" translatable="yes">_Uninstall...</property>
                             <property name="UseUnderline">True</property>
-                            <property name="IsDialogButton">False</property>
                             <signal name="Clicked" handler="OnUninstall" />
                           </widget>
                           <packing>
@@ -326,7 +326,6 @@
                             <property name="Icon">stock:gtk-yes Button</property>
                             <property name="Label" translatable="yes">Enable</property>
                             <property name="UseUnderline">True</property>
-                            <property name="IsDialogButton">False</property>
                             <signal name="Clicked" handler="OnEnable" />
                           </widget>
                           <packing>
@@ -344,7 +343,6 @@
                             <property name="Icon">stock:gtk-no Button</property>
                             <property name="Label" translatable="yes">Disable</property>
                             <property name="UseUnderline">True</property>
-                            <property name="IsDialogButton">False</property>
                             <signal name="Clicked" handler="OnDisable" />
                           </widget>
                           <packing>
@@ -361,7 +359,6 @@
                             <property name="UseStock">True</property>
                             <property name="Type">StockItem</property>
                             <property name="StockId">gtk-dialog-info</property>
-                            <property name="IsDialogButton">False</property>
                             <signal name="Clicked" handler="OnShowInfo" />
                             <property name="label">gtk-dialog-info</property>
                           </widget>
@@ -415,19 +412,20 @@
             <property name="UseStock">True</property>
             <property name="Type">StockItem</property>
             <property name="StockId">gtk-close</property>
-            <property name="IsDialogButton">False</property>
+            <property name="ResponseId">-7</property>
             <property name="label">gtk-close</property>
           </widget>
         </child>
       </widget>
     </child>
   </widget>
-  <widget class="Gtk.Dialog" id="Mono.Addins.Gui.AddinInstallDialog" design-size="698 517">
+  <widget class="Gtk.Dialog" id="Mono.Addins.Gui.AddinInstallDialog" design-size="698 521">
     <property name="MemberName" />
     <property name="GeneratePublic">False</property>
     <property name="Title" translatable="yes">Add-in Installation</property>
     <property name="TypeHint">Dialog</property>
     <property name="Modal">True</property>
+    <property name="BorderWidth">6</property>
     <property name="DefaultWidth">725</property>
     <property name="DefaultHeight">550</property>
     <property name="Buttons">0</property>
@@ -435,14 +433,15 @@
     <child internal-child="VBox">
       <widget class="Gtk.VBox" id="dialog-vbox9">
         <property name="MemberName" />
+        <property name="Spacing">6</property>
         <property name="BorderWidth">2</property>
         <child>
           <widget class="Gtk.Notebook" id="wizardNotebook">
             <property name="MemberName" />
             <property name="CanFocus">True</property>
-            <property name="CurrentPage">0</property>
+            <property name="CurrentPage">3</property>
             <property name="ShowBorder">False</property>
-            <property name="BorderWidth">12</property>
+            <property name="BorderWidth">6</property>
             <child>
               <widget class="Gtk.VBox" id="vbox82">
                 <property name="MemberName" />
@@ -496,7 +495,6 @@
                         <property name="UseStock">True</property>
                         <property name="Type">StockItem</property>
                         <property name="StockId">gtk-refresh</property>
-                        <property name="IsDialogButton">False</property>
                         <signal name="Clicked" handler="OnUpdateRepo" />
                         <property name="label">gtk-refresh</property>
                       </widget>
@@ -514,7 +512,6 @@
                         <property name="Type">TextOnly</property>
                         <property name="Label" translatable="yes">_Repositories...</property>
                         <property name="UseUnderline">True</property>
-                        <property name="IsDialogButton">False</property>
                         <signal name="Clicked" handler="OnManageSites" />
                       </widget>
                       <packing>
@@ -588,7 +585,6 @@
                                 <property name="UseStock">True</property>
                                 <property name="Type">StockItem</property>
                                 <property name="StockId">gtk-dialog-info</property>
-                                <property name="IsDialogButton">False</property>
                                 <signal name="Clicked" handler="OnShowInfo" />
                                 <property name="label">gtk-dialog-info</property>
                               </widget>
@@ -607,7 +603,6 @@
                                 <property name="Type">TextOnly</property>
                                 <property name="Label" translatable="yes">_Unselect All</property>
                                 <property name="UseUnderline">True</property>
-                                <property name="IsDialogButton">False</property>
                                 <signal name="Clicked" handler="OnUnselectAll" />
                               </widget>
                               <packing>
@@ -625,7 +620,6 @@
                                 <property name="Type">TextOnly</property>
                                 <property name="Label" translatable="yes">Select _All</property>
                                 <property name="UseUnderline">True</property>
-                                <property name="IsDialogButton">False</property>
                                 <signal name="Clicked" handler="OnSelectAll" />
                               </widget>
                               <packing>
@@ -779,7 +773,7 @@
                 <child>
                   <widget class="Gtk.ProgressBar" id="mainProgressBar">
                     <property name="MemberName" />
-                    <property name="PulseStep">0,10000000149</property>
+                    <property name="PulseStep">10000000149</property>
                   </widget>
                   <packing>
                     <property name="Position">1</property>
@@ -816,7 +810,7 @@
                 <child>
                   <widget class="Gtk.ProgressBar" id="progressBar">
                     <property name="MemberName" />
-                    <property name="PulseStep">0,10000000149</property>
+                    <property name="PulseStep">10000000149</property>
                   </widget>
                   <packing>
                     <property name="Position">4</property>
@@ -877,13 +871,26 @@
                           </packing>
                         </child>
                         <child>
+                          <widget class="Gtk.Image" id="imageWarn">
+                            <property name="MemberName" />
+                            <property name="Yalign">1</property>
+                            <property name="Pixbuf">stock:gtk-dialog-warning Dialog</property>
+                          </widget>
+                          <packing>
+                            <property name="Position">2</property>
+                            <property name="AutoSize">True</property>
+                            <property name="Expand">False</property>
+                            <property name="Fill">False</property>
+                          </packing>
+                        </child>
+                        <child>
                           <widget class="Gtk.Image" id="imageInfo">
                             <property name="MemberName" />
                             <property name="Yalign">1</property>
                             <property name="Pixbuf">stock:gtk-dialog-info Dialog</property>
                           </widget>
                           <packing>
-                            <property name="Position">2</property>
+                            <property name="Position">3</property>
                             <property name="AutoSize">False</property>
                             <property name="Expand">False</property>
                             <property name="Fill">False</property>
@@ -911,7 +918,7 @@
                             </child>
                           </widget>
                           <packing>
-                            <property name="Position">3</property>
+                            <property name="Position">4</property>
                             <property name="AutoSize">False</property>
                             <property name="Expand">False</property>
                             <property name="Fill">False</property>
@@ -923,7 +930,7 @@
                             <property name="LabelProp" translatable="yes" />
                           </widget>
                           <packing>
-                            <property name="Position">4</property>
+                            <property name="Position">5</property>
                             <property name="AutoSize">False</property>
                           </packing>
                         </child>
@@ -967,7 +974,6 @@
                 <property name="UseStock">True</property>
                 <property name="Type">StockItem</property>
                 <property name="StockId">gtk-cancel</property>
-                <property name="IsDialogButton">False</property>
                 <signal name="Clicked" handler="OnCancel" />
                 <property name="label">gtk-cancel</property>
               </widget>
@@ -980,7 +986,6 @@
                 <property name="UseStock">True</property>
                 <property name="Type">StockItem</property>
                 <property name="StockId">gtk-go-back</property>
-                <property name="IsDialogButton">False</property>
                 <signal name="Clicked" handler="OnPrevPage" />
                 <property name="label">gtk-go-back</property>
               </widget>
@@ -996,7 +1001,6 @@
                 <property name="UseStock">True</property>
                 <property name="Type">StockItem</property>
                 <property name="StockId">gtk-go-forward</property>
-                <property name="IsDialogButton">False</property>
                 <signal name="Clicked" handler="OnNextPage" />
                 <property name="label">gtk-go-forward</property>
               </widget>
@@ -1013,7 +1017,6 @@
                 <property name="UseStock">True</property>
                 <property name="Type">StockItem</property>
                 <property name="StockId">gtk-ok</property>
-                <property name="IsDialogButton">False</property>
                 <signal name="Clicked" handler="OnOk" />
                 <property name="label">gtk-ok</property>
               </widget>
@@ -1030,23 +1033,12 @@
             <property name="Fill">False</property>
           </packing>
         </child>
-        <child>
-          <widget class="Gtk.HSeparator" id="hseparator3">
-            <property name="MemberName" />
-          </widget>
-          <packing>
-            <property name="PackType">End</property>
-            <property name="Position">3</property>
-            <property name="AutoSize">False</property>
-            <property name="Expand">False</property>
-            <property name="Fill">False</property>
-          </packing>
-        </child>
       </widget>
     </child>
     <child internal-child="ActionArea">
       <widget class="Gtk.HButtonBox" id="hbuttonbox1">
         <property name="MemberName" />
+        <property name="Visible">False</property>
         <property name="Spacing">10</property>
         <property name="BorderWidth">5</property>
         <property name="Size">0</property>
@@ -1054,11 +1046,12 @@
       </widget>
     </child>
   </widget>
-  <widget class="Gtk.Dialog" id="Mono.Addins.Gui.ManageSitesDialog" design-size="537 327">
+  <widget class="Gtk.Dialog" id="Mono.Addins.Gui.ManageSitesDialog" design-size="538 357">
     <property name="MemberName" />
     <property name="GeneratePublic">False</property>
     <property name="Title" translatable="yes">Add-in Repository Management</property>
     <property name="TypeHint">Dialog</property>
+    <property name="BorderWidth">6</property>
     <property name="DefaultWidth">600</property>
     <property name="DefaultHeight">300</property>
     <property name="Buttons">1</property>
@@ -1066,12 +1059,12 @@
     <child internal-child="VBox">
       <widget class="Gtk.VBox" id="dialog-vbox10">
         <property name="MemberName" />
-        <property name="BorderWidth">2</property>
+        <property name="Spacing">6</property>
         <child>
           <widget class="Gtk.HBox" id="hbox67">
             <property name="MemberName" />
             <property name="Spacing">12</property>
-            <property name="BorderWidth">12</property>
+            <property name="BorderWidth">6</property>
             <child>
               <widget class="Gtk.ScrolledWindow" id="scrolledwindow17">
                 <property name="MemberName" />
@@ -1104,7 +1097,6 @@
                     <property name="UseStock">True</property>
                     <property name="Type">StockItem</property>
                     <property name="StockId">gtk-add</property>
-                    <property name="IsDialogButton">False</property>
                     <signal name="Clicked" handler="OnAdd" />
                     <property name="label">gtk-add</property>
                   </widget>
@@ -1122,7 +1114,6 @@
                     <property name="UseStock">True</property>
                     <property name="Type">StockItem</property>
                     <property name="StockId">gtk-delete</property>
-                    <property name="IsDialogButton">False</property>
                     <signal name="Clicked" handler="OnRemove" />
                     <property name="label">gtk-delete</property>
                   </widget>
@@ -1153,7 +1144,7 @@
       <widget class="Gtk.HButtonBox" id="dialog-action_area10">
         <property name="MemberName" />
         <property name="Spacing">10</property>
-        <property name="BorderWidth">5</property>
+        <property name="BorderWidth">6</property>
         <property name="Size">1</property>
         <property name="LayoutStyle">End</property>
         <child>
@@ -1164,30 +1155,32 @@
             <property name="UseStock">True</property>
             <property name="Type">StockItem</property>
             <property name="StockId">gtk-close</property>
-            <property name="IsDialogButton">False</property>
+            <property name="ResponseId">-7</property>
             <property name="label">gtk-close</property>
           </widget>
         </child>
       </widget>
     </child>
   </widget>
-  <widget class="Gtk.Dialog" id="Mono.Addins.Gui.NewSiteDialog" design-size="576 235">
+  <widget class="Gtk.Dialog" id="Mono.Addins.Gui.NewSiteDialog" design-size="576 249">
     <property name="MemberName" />
     <property name="GeneratePublic">False</property>
     <property name="Title" translatable="yes">Add New Repository</property>
     <property name="TypeHint">Dialog</property>
+    <property name="BorderWidth">6</property>
     <property name="DefaultWidth">550</property>
     <property name="Buttons">2</property>
     <property name="HelpButton">False</property>
     <child internal-child="VBox">
       <widget class="Gtk.VBox" id="dialog-vbox11">
         <property name="MemberName" />
+        <property name="Spacing">6</property>
         <property name="BorderWidth">2</property>
         <child>
           <widget class="Gtk.VBox" id="vbox89">
             <property name="MemberName" />
             <property name="Spacing">6</property>
-            <property name="BorderWidth">12</property>
+            <property name="BorderWidth">6</property>
             <child>
               <widget class="Gtk.Label" id="label121">
                 <property name="MemberName" />
@@ -1255,6 +1248,7 @@
                     <property name="CanFocus">True</property>
                     <property name="IsEditable">True</property>
                     <property name="InvisibleChar">â</property>
+                    <signal name="Changed" handler="OnUrlTextChanged" />
                   </widget>
                   <packing>
                     <property name="Position">2</property>
@@ -1340,7 +1334,6 @@
                         <property name="Type">TextOnly</property>
                         <property name="Label" translatable="yes">Browse...</property>
                         <property name="UseUnderline">True</property>
-                        <property name="IsDialogButton">False</property>
                         <signal name="Clicked" handler="OnButtonBrowseClicked" />
                       </widget>
                       <packing>
@@ -1387,7 +1380,7 @@
             <property name="UseStock">True</property>
             <property name="Type">StockItem</property>
             <property name="StockId">gtk-cancel</property>
-            <property name="IsDialogButton">False</property>
+            <property name="ResponseId">-6</property>
             <property name="label">gtk-cancel</property>
           </widget>
         </child>
@@ -1399,7 +1392,7 @@
             <property name="UseStock">True</property>
             <property name="Type">StockItem</property>
             <property name="StockId">gtk-ok</property>
-            <property name="IsDialogButton">False</property>
+            <property name="ResponseId">-5</property>
             <property name="label">gtk-ok</property>
           </widget>
           <packing>
@@ -1412,8 +1405,9 @@
   <widget class="Gtk.Dialog" id="Mono.Addins.Gui.AddinInfoDialog" design-size="496 368">
     <property name="MemberName" />
     <property name="GeneratePublic">False</property>
-    <property name="Title" translatable="yes">MonoDevelop Package</property>
+    <property name="Title" translatable="yes">Package</property>
     <property name="TypeHint">Dialog</property>
+    <property name="BorderWidth">6</property>
     <property name="DefaultWidth">550</property>
     <property name="DefaultHeight">400</property>
     <property name="Buttons">1</property>
@@ -1421,12 +1415,12 @@
     <child internal-child="VBox">
       <widget class="Gtk.VBox" id="dialog-vbox12">
         <property name="MemberName" />
-        <property name="BorderWidth">2</property>
+        <property name="Spacing">6</property>
         <child>
           <widget class="Gtk.HBox" id="hbox81">
             <property name="MemberName" />
             <property name="Spacing">12</property>
-            <property name="BorderWidth">12</property>
+            <property name="BorderWidth">6</property>
             <child>
               <widget class="Gtk.VBox" id="vbox94">
                 <property name="MemberName" />
@@ -1494,7 +1488,7 @@
       <widget class="Gtk.HButtonBox" id="dialog-action_area12">
         <property name="MemberName" />
         <property name="Spacing">10</property>
-        <property name="BorderWidth">5</property>
+        <property name="BorderWidth">6</property>
         <property name="Size">1</property>
         <property name="LayoutStyle">End</property>
         <child>
@@ -1505,7 +1499,7 @@
             <property name="UseStock">True</property>
             <property name="Type">StockItem</property>
             <property name="StockId">gtk-close</property>
-            <property name="IsDialogButton">False</property>
+            <property name="ResponseId">-7</property>
             <property name="label">gtk-close</property>
           </widget>
         </child>
@@ -1517,18 +1511,20 @@
     <property name="GeneratePublic">False</property>
     <property name="Title" translatable="yes">Add-in Manager</property>
     <property name="WindowPosition">CenterOnParent</property>
+    <property name="BorderWidth">6</property>
     <property name="Buttons">2</property>
     <property name="HelpButton">False</property>
     <property name="HasSeparator">False</property>
     <child internal-child="VBox">
       <widget class="Gtk.VBox" id="dialog1_VBox">
         <property name="MemberName" />
+        <property name="Spacing">6</property>
         <property name="BorderWidth">2</property>
         <child>
           <widget class="Gtk.VBox" id="vbox2">
             <property name="MemberName" />
             <property name="Spacing">6</property>
-            <property name="BorderWidth">12</property>
+            <property name="BorderWidth">6</property>
             <child>
               <widget class="Gtk.Label" id="label1">
                 <property name="MemberName" />
@@ -1609,7 +1605,7 @@
       <widget class="Gtk.HButtonBox" id="dialog1_ActionArea">
         <property name="MemberName" />
         <property name="Spacing">10</property>
-        <property name="BorderWidth">5</property>
+        <property name="BorderWidth">6</property>
         <property name="Size">2</property>
         <property name="LayoutStyle">End</property>
         <child>
@@ -1620,7 +1616,6 @@
             <property name="UseStock">True</property>
             <property name="Type">StockItem</property>
             <property name="StockId">gtk-cancel</property>
-            <property name="IsDialogButton">True</property>
             <property name="ResponseId">-6</property>
             <property name="label">gtk-cancel</property>
           </widget>
@@ -1637,7 +1632,6 @@
             <property name="UseStock">True</property>
             <property name="Type">StockItem</property>
             <property name="StockId">gtk-ok</property>
-            <property name="IsDialogButton">True</property>
             <property name="ResponseId">-1</property>
             <signal name="Clicked" handler="OnButtonOkClicked" />
             <property name="label">gtk-ok</property>

Added: trunk/Mono.Addins/Mono.Addins.Gui/icons/system-software-update.png
==============================================================================
Binary file. No diff available.

Modified: trunk/Mono.Addins/Mono.Addins.Setup/AssemblyInfo.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Setup/AssemblyInfo.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Setup/AssemblyInfo.cs	Sun Mar  2 21:23:19 2008
@@ -17,4 +17,4 @@
 // You can specify all values by your own or you can build default build and revision
 // numbers with the '*' character (the default):
 
-[assembly: AssemblyVersion("0.2.0.0")]
+[assembly: AssemblyVersion("0.3.0.0")]

Modified: trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/AddinPackage.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/AddinPackage.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/AddinPackage.cs	Sun Mar  2 21:23:19 2008
@@ -186,7 +186,7 @@
 		
 		internal override void Resolve (IProgressMonitor monitor, AddinStore service, PackageCollection toInstall, PackageCollection toUninstall, PackageCollection installedRequired, DependencyCollection unresolved)
 		{
-			Addin ia = service.Registry.GetAddin (info.Id);
+			Addin ia = service.Registry.GetAddin (Mono.Addins.Addin.GetIdName (info.Id));
 			
 			if (ia != null) {
 				Package p = AddinPackage.FromInstalledAddin (ia);

Modified: trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/RepositoryRegistry.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/RepositoryRegistry.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/RepositoryRegistry.cs	Sun Mar  2 21:23:19 2008
@@ -58,7 +58,7 @@
 			if (rr != null)
 				return rr;
 
-			RegisterRepository (url, false);
+			rr = RegisterRepository (url, false);
 			
 			try {
 				if (updateNow) {

Modified: trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/SetupTool.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/SetupTool.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins.Setup/Mono.Addins.Setup/SetupTool.cs	Sun Mar  2 21:23:19 2008
@@ -28,6 +28,7 @@
 
 
 using System;
+using System.Xml;
 using System.Collections;
 using Mono.Addins;
 using Mono.Addins.Setup.ProgressMonitoring;
@@ -46,6 +47,7 @@
 		AddinRegistry registry;
 		ArrayList commands = new ArrayList ();
 		string setupAppName = "";
+		int uniqueId = 0;
 		
 		bool verbose;
 		
@@ -382,21 +384,197 @@
 		
 		void PrintAddinInfo (string[] args)
 		{
-			if (args.Length == 0)
+			bool generateXml = false;
+			bool generateAll = false;
+			bool pickNamespace = false;
+			bool extensionModel = true;
+			
+			ArrayList addins = new ArrayList ();
+			ArrayList namespaces = new ArrayList ();
+			
+			foreach (string a in args) {
+				if (pickNamespace) {
+					namespaces.Add (a);
+					pickNamespace = false;
+					continue;
+				}
+				if (a == "--xml") {
+					generateXml = true;
+					continue;
+				}
+				if (a == "--namespace" || a == "-n") {
+					pickNamespace = true;
+					continue;
+				}
+				if (a == "--all") {
+					generateAll = true;
+					continue;
+				}
+				if (a == "--full") {
+					extensionModel = false;
+					continue;
+				}
+				AddinDescription desc = null;
+				if (File.Exists (args[0]))
+					desc = registry.GetAddinDescription (new Mono.Addins.ConsoleProgressStatus (verbose), args[0]);
+				else {
+					Addin addin = registry.GetAddin (args [0]);
+					if (addin != null)
+						desc = addin.Description;
+				}
+				if (desc == null)
+					throw new InstallException (string.Format ("Add-in '{0}' not found.", a));
+				if (desc != null)
+					addins.Add (desc);
+			}
+			
+			if (generateAll) {
+				ArrayList list = new ArrayList ();
+				list.AddRange (registry.GetAddinRoots ());
+				list.AddRange (registry.GetAddins ());
+				foreach (Addin addin in list) {
+					if (namespaces.Count > 0) {
+						foreach (string ns in namespaces) {
+							if (addin.Id.StartsWith (ns + ".")) {
+								addins.Add (addin.Description);
+								break;
+							}
+						}
+					} else {
+						addins.Add (addin.Description);
+					}
+				}
+			}
+			
+			if (addins.Count == 0)
 				throw new InstallException ("A file name or add-in ID is required.");
 			
-			AddinDescription desc = null;
-			if (File.Exists (args[0]))
-				desc = registry.GetAddinDescription (new Mono.Addins.ConsoleProgressStatus (verbose), args[0]);
+			
+			if (generateXml) {
+				XmlTextWriter tw = new XmlTextWriter (Console.Out);
+				tw.Formatting = Formatting.Indented;
+				tw.WriteStartElement ("Addins");
+				foreach (AddinDescription desc in addins) {
+					if (extensionModel && desc.ExtensionPoints.Count == 0)
+						continue;
+					PrintAddinXml (tw, desc);
+				}
+				tw.Close ();
+			}
 			else {
-				Addin addin = registry.GetAddin (args [0]);
-				if (addin != null)
-					desc = addin.Description;
+				foreach (AddinDescription des in addins)
+					PrintAddin (des);
 			}
+		}
+		
+		void PrintAddinXml (XmlWriter tw, AddinDescription desc)
+		{
+			tw.WriteStartElement ("Addin");
+			tw.WriteAttributeString ("name", desc.Name);
+			tw.WriteAttributeString ("addinId", desc.LocalId);
+			tw.WriteAttributeString ("fullId", desc.AddinId);
+			tw.WriteAttributeString ("id", "addin_" + uniqueId);
+			uniqueId++;
+			if (desc.Namespace.Length > 0)
+				tw.WriteAttributeString ("namespace", desc.Namespace);
+			tw.WriteAttributeString ("isroot", desc.IsRoot.ToString ());
+
+			tw.WriteAttributeString ("version", desc.Version);
+			if (desc.CompatVersion.Length > 0)
+				tw.WriteAttributeString ("compatVersion", desc.CompatVersion);
 			
-			if (desc == null)
-				throw new InstallException ("Add-in not found.");
+			if (desc.Author.Length > 0)
+				tw.WriteAttributeString ("author", desc.Author);
+			if (desc.Category.Length > 0)
+				tw.WriteAttributeString ("category", desc.Category);
+			if (desc.Copyright.Length > 0)
+				tw.WriteAttributeString ("copyright", desc.Copyright);
+			if (desc.Url.Length > 0)
+				tw.WriteAttributeString ("url", desc.Url);
+
+			if (desc.Description.Length > 0)
+				tw.WriteElementString ("Description", desc.Description);
 			
+			if (desc.ExtensionPoints.Count > 0) {
+				ArrayList list = new ArrayList ();
+				Hashtable visited = new Hashtable ();
+				foreach (ExtensionPoint ep in desc.ExtensionPoints) {
+					tw.WriteStartElement ("ExtensionPoint");
+					tw.WriteAttributeString ("path", ep.Path);
+					if (ep.Name.Length > 0)
+						tw.WriteAttributeString ("name", ep.Name);
+					else
+						tw.WriteAttributeString ("name", ep.Path);
+					if (ep.Description.Length > 0)
+						tw.WriteElementString ("Description", ep.Description);
+					PrintExtensionNodeSetXml (tw, desc, ep.NodeSet, list, visited);
+					tw.WriteEndElement ();
+				}
+				
+				for (int n=0; n<list.Count; n++) {
+					
+					ExtensionNodeType nt = (ExtensionNodeType) list [n];
+					
+					tw.WriteStartElement ("ExtensionNodeType");
+					tw.WriteAttributeString ("name", nt.Id);
+					tw.WriteAttributeString ("id", visited [nt.Id + " " + nt.TypeName].ToString ());
+					
+					if (nt.Description.Length > 0)
+						tw.WriteElementString ("Description", nt.Description);
+					
+					if (nt.Attributes.Count > 0) {
+						tw.WriteStartElement ("Attributes");
+						foreach (NodeTypeAttribute att in nt.Attributes) {
+							tw.WriteStartElement ("Attribute");
+							tw.WriteAttributeString ("name", att.Name);
+							tw.WriteAttributeString ("type", att.Type);
+							tw.WriteAttributeString ("required", att.Required.ToString ());
+							tw.WriteAttributeString ("localizable", att.Localizable.ToString ());
+							if (att.Description.Length > 0)
+								tw.WriteElementString ("Description", att.Description);
+							tw.WriteEndElement ();
+						}
+						tw.WriteEndElement ();
+					}
+					
+					if (nt.NodeTypes.Count > 0 || nt.NodeSets.Count > 0) {
+						tw.WriteStartElement ("ChildNodes");
+						PrintExtensionNodeSetXml (tw, desc, nt, list, visited);
+						tw.WriteEndElement ();
+					}
+					tw.WriteEndElement ();
+				}
+			}
+			tw.WriteEndElement ();
+		}
+		
+		void PrintExtensionNodeSetXml (XmlWriter tw, AddinDescription desc, ExtensionNodeSet nset, ArrayList list, Hashtable visited)
+		{
+			foreach (ExtensionNodeType nt in nset.GetAllowedNodeTypes ()) {
+				tw.WriteStartElement ("ExtensionNode");
+				tw.WriteAttributeString ("name", nt.Id);
+				string id = RegisterNodeXml (nt, list, visited);
+				tw.WriteAttributeString ("id", id.ToString ());
+				if (nt.Description.Length > 0)
+					tw.WriteElementString ("Description", nt.Description);
+				tw.WriteEndElement ();
+			}
+		}
+		
+		string RegisterNodeXml (ExtensionNodeType nt, ArrayList list, Hashtable visited)
+		{
+			string key = nt.Id + " " + nt.TypeName;
+			if (visited.Contains (key))
+				return (string) visited [key];
+			string k = "ntype_" + uniqueId;
+			uniqueId++;
+			visited [key] = k;
+			list.Add (nt);
+			return k;
+		}
+		
+		void PrintAddin (AddinDescription desc)
+		{
 			Console.WriteLine ();
 			Console.WriteLine ("Addin Header");
 			Console.WriteLine ("------------");
@@ -697,7 +875,7 @@
 			cmd.AppendDesc ("New add-ins will be added and deleted add-ins will be removed.");
 			commands.Add (cmd);
 
-			cmd = new SetupCommand (cat, "reg-build", "rgu", new SetupCommandHandler (RepairRegistry));
+			cmd = new SetupCommand (cat, "reg-build", "rgb", new SetupCommandHandler (RepairRegistry));
 			cmd.Description = "Rebuilds the add-in registry.";
 			cmd.AppendDesc ("Regenerates the add-in registry");
 			commands.Add (cmd);

Modified: trunk/Mono.Addins/Mono.Addins/AssemblyInfo.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/AssemblyInfo.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/AssemblyInfo.cs	Sun Mar  2 21:23:19 2008
@@ -17,4 +17,4 @@
 // You can specify all values by your own or you can build default build and revision
 // numbers with the '*' character (the default):
 
-[assembly: AssemblyVersion("0.2.0.0")]
+[assembly: AssemblyVersion("0.3.0.0")]

Modified: trunk/Mono.Addins/Mono.Addins/Makefile.am
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Makefile.am	(original)
+++ trunk/Mono.Addins/Mono.Addins/Makefile.am	Sun Mar  2 21:23:19 2008
@@ -39,6 +39,14 @@
 	$(srcdir)/Mono.Addins.Description/NodeTypeAttributeCollection.cs 	\
 	$(srcdir)/Mono.Addins.Description/ObjectDescription.cs 			\
 	$(srcdir)/Mono.Addins.Description/ObjectDescriptionCollection.cs 	\
+	$(srcdir)/Mono.Addins.Localization/GettextDomain.cs \
+	$(srcdir)/Mono.Addins.Localization/GettextLocalizer.cs \
+	$(srcdir)/Mono.Addins.Localization/IAddinLocalizer.cs \
+	$(srcdir)/Mono.Addins.Localization/IAddinLocalizerFactory.cs \
+	$(srcdir)/Mono.Addins.Localization/IPluralAddinLocalizer.cs \
+	$(srcdir)/Mono.Addins.Localization/NullLocalizer.cs \
+	$(srcdir)/Mono.Addins.Localization/StringResourceLocalizer.cs \
+	$(srcdir)/Mono.Addins.Localization/StringTableLocalizer.cs \
 	$(srcdir)/Mono.Addins.Serialization/BinaryXmlReader.cs 			\
 	$(srcdir)/Mono.Addins.Serialization/BinaryXmlTypeMap.cs 		\
 	$(srcdir)/Mono.Addins.Serialization/BinaryXmlWriter.cs 			\
@@ -49,6 +57,7 @@
 	$(srcdir)/Mono.Addins/AddinErrorEventArgs.cs 				\
 	$(srcdir)/Mono.Addins/AddinEventArgs.cs 				\
 	$(srcdir)/Mono.Addins/AddinInfo.cs 					\
+	$(srcdir)/Mono.Addins/AddinLocalizer.cs				\
 	$(srcdir)/Mono.Addins/AddinManager.cs 					\
 	$(srcdir)/Mono.Addins/AddinRegistry.cs 					\
 	$(srcdir)/Mono.Addins/AddinRootAttribute.cs 				\

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs	Sun Mar  2 21:23:19 2008
@@ -40,9 +40,13 @@
 {
 	class AddinDatabase
 	{
-		const string VersionTag = "000";
+		public const string GlobalDomain = "global";
+		
+		public const string VersionTag = "001";
 
+		ArrayList allSetupInfos;
 		ArrayList addinSetupInfos;
+		ArrayList rootSetupInfos;
 		internal static bool RunningSetupProcess;
 		bool fatalDatabseError;
 		Hashtable cachedAddinSetupInfos = new Hashtable ();
@@ -52,6 +56,7 @@
 		string addinDbDir;
 		DatabaseConfiguration config = null;
 		AddinRegistry registry;
+		int lastDomainId;
 		
 		public AddinDatabase (AddinRegistry registry)
 		{
@@ -76,6 +81,10 @@
 			get { return Path.Combine (AddinDbDir, "addin-priv-data"); }
 		}
 		
+		public string HostsPath {
+			get { return Path.Combine (AddinDbDir, "hosts"); }
+		}
+		
 		string HostIndexFile {
 			get { return Path.Combine (AddinDbDir, "host-index"); }
 		}
@@ -98,27 +107,19 @@
 				Directory.Delete (AddinFolderCachePath, true);
 		}
 		
-		public ExtensionNodeSet FindNodeSet (string addinId, string id)
+		public ExtensionNodeSet FindNodeSet (string domain, string addinId, string id)
 		{
-			return FindNodeSet (addinId, id, new Hashtable ());
+			return FindNodeSet (domain, addinId, id, new Hashtable ());
 		}
 		
-		ExtensionNodeSet FindNodeSet (string addinId, string id, Hashtable visited)
+		ExtensionNodeSet FindNodeSet (string domain, string addinId, string id, Hashtable visited)
 		{
 			if (visited.Contains (addinId))
 				return null;
 			visited.Add (addinId, addinId);
-			Addin addin = GetInstalledAddin (addinId, true, false);
-			if (addin == null) {
-				foreach (Addin root in GetAddinRoots ()) {
-					if (root.Id == addinId) {
-						addin = root;
-						break;
-					}
-				}
-				if (addin == null)
-					return null;
-			}
+			Addin addin = GetInstalledAddin (domain, addinId, true, false);
+			if (addin == null)
+				return null;
 			AddinDescription desc = addin.Description;
 			if (desc == null)
 				return null;
@@ -133,78 +134,129 @@
 				if (adep == null) continue;
 				
 				string aid = Addin.GetFullId (desc.Namespace, adep.AddinId, adep.Version);
-				ExtensionNodeSet nset = FindNodeSet (aid, id, visited);
+				ExtensionNodeSet nset = FindNodeSet (domain, aid, id, visited);
 				if (nset != null)
 					return nset;
 			}
 			return null;
 		}
 		
-		public AddinDescription GetDescription (string id)
+		public ArrayList GetInstalledAddins (string domain, AddinType type)
 		{
-			InternalCheck ();
-			IDisposable dblock = fileDatabase.LockRead ();
-			try {
-				string path = GetDescriptionPath (id);
-				AddinDescription desc = AddinDescription.ReadBinary (fileDatabase, path);
-				if (desc != null)
-					desc.OwnerDatabase = this;
-				return desc;
+			if (type == AddinType.All) {
+				if (allSetupInfos != null)
+					return allSetupInfos;
+			}
+			else if (type == AddinType.Addin) {
+				if (addinSetupInfos != null)
+					return addinSetupInfos;
 			}
-			catch (FileNotFoundException) {
-				throw new InvalidOperationException ("Add-in not found: " + id);
-			} finally {
-				dblock.Dispose ();
+			else {
+				if (rootSetupInfos != null)
+					return rootSetupInfos;
 			}
+		
+			InternalCheck (domain);
+			
+			using (fileDatabase.LockRead ()) {
+				return InternalGetInstalledAddins (domain, null, type);
+			}
+		}
+		
+		ArrayList InternalGetInstalledAddins (string domain, AddinType type)
+		{
+			return InternalGetInstalledAddins (domain, null, type);
 		}
 		
-		public ArrayList GetInstalledAddins ()
+		ArrayList InternalGetInstalledAddins (string domain, string idFilter, AddinType type)
 		{
-			if (addinSetupInfos != null)
-				return addinSetupInfos;
+			if (allSetupInfos == null) {
+				ArrayList alist = new ArrayList ();
+
+				// Global add-ins are valid for any private domain
+				if (domain != AddinDatabase.GlobalDomain)
+					FindInstalledAddins (alist, AddinDatabase.GlobalDomain, idFilter);
+
+				FindInstalledAddins (alist, domain, idFilter);
+				if (idFilter != null)
+					return alist;
+				allSetupInfos = alist;
+			}
+			if (type == AddinType.All)
+				return FilterById (allSetupInfos, idFilter);
 			
-			InternalCheck ();
-			using (fileDatabase.LockRead ()) {
-				return InternalGetInstalledAddins ();
+			if (type == AddinType.Addin) {
+				if (addinSetupInfos == null) {
+					addinSetupInfos = new ArrayList ();
+					foreach (Addin adn in allSetupInfos)
+						if (!adn.Description.IsRoot)
+							addinSetupInfos.Add (adn);
+				}
+				return FilterById (addinSetupInfos, idFilter);
+			}
+			else {
+				if (rootSetupInfos == null) {
+					rootSetupInfos = new ArrayList ();
+					foreach (Addin adn in allSetupInfos)
+						if (adn.Description.IsRoot)
+							rootSetupInfos.Add (adn);
+				}
+				return FilterById (rootSetupInfos, idFilter);
 			}
 		}
 		
-		public ArrayList GetAddinRoots ()
+		ArrayList FilterById (ArrayList addins, string id)
 		{
+			if (id == null)
+				return addins;
 			ArrayList list = new ArrayList ();
-			foreach (string file in fileDatabase.GetDirectoryFiles (AddinCachePath, "*.mroot")) {
-				list.Add (new Addin (this, file));
+			foreach (Addin adn in addins) {
+				if (Addin.GetIdName (adn.Id) == id)
+					list.Add (adn);
 			}
 			return list;
 		}
-		
-		ArrayList InternalGetInstalledAddins ()
-		{
-			if (addinSetupInfos != null)
-				return addinSetupInfos;
 
-			addinSetupInfos = new ArrayList ();
-			
-			foreach (string file in fileDatabase.GetDirectoryFiles (AddinCachePath, "*.maddin")) {
-				addinSetupInfos.Add (new Addin (this, file));
+		void FindInstalledAddins (ArrayList result, string domain, string idFilter)
+		{
+			if (idFilter == null) 
+				idFilter = "*";
+			string dir = Path.Combine (AddinCachePath, domain);
+			if (Directory.Exists (dir)) {
+				foreach (string file in fileDatabase.GetDirectoryFiles (dir, idFilter + ",*.maddin")) {
+					string id = Path.GetFileNameWithoutExtension (file);
+					result.Add (GetInstalledDomainAddin (domain, id, true, false, false));
+				}
 			}
-			return addinSetupInfos;
+		}
+
+		public Addin GetInstalledAddin (string domain, string id)
+		{
+			return GetInstalledAddin (domain, id, false, false);
 		}
 		
-		public Addin GetInstalledAddin (string id)
+		public Addin GetInstalledAddin (string domain, string id, bool exactVersionMatch)
 		{
-			return GetInstalledAddin (id, false, false);
+			return GetInstalledAddin (domain, id, exactVersionMatch, false);
 		}
 		
-		public Addin GetInstalledAddin (string id, bool exactVersionMatch)
+		public Addin GetInstalledAddin (string domain, string id, bool exactVersionMatch, bool enabledOnly)
 		{
-			return GetInstalledAddin (id, exactVersionMatch, false);
+			// Try the given domain, and if not found, try the shared domain
+			Addin ad = GetInstalledDomainAddin (domain, id, exactVersionMatch, enabledOnly, true);
+			if (ad != null)
+				return ad;
+			if (domain != AddinDatabase.GlobalDomain)
+				return GetInstalledDomainAddin (AddinDatabase.GlobalDomain, id, exactVersionMatch, enabledOnly, true);
+			else
+				return null;
 		}
 		
-		public Addin GetInstalledAddin (string id, bool exactVersionMatch, bool enabledOnly)
+		Addin GetInstalledDomainAddin (string domain, string id, bool exactVersionMatch, bool enabledOnly, bool dbLockCheck)
 		{
 			Addin sinfo = null;
-			object ob = cachedAddinSetupInfos [id];
+			string idd = id + " " + domain;
+			object ob = cachedAddinSetupInfos [idd];
 			if (ob != null) {
 				sinfo = ob as Addin;
 				if (sinfo != null) {
@@ -218,19 +270,20 @@
 					return null;
 			}
 		
-			InternalCheck ();
+			if (dbLockCheck)
+				InternalCheck (domain);
 			
-			using (fileDatabase.LockRead ())
+			using ((dbLockCheck ? fileDatabase.LockRead () : null))
 			{
-				string path = GetDescriptionPath (id);
+				string path = GetDescriptionPath (domain, id);
 				if (sinfo == null && fileDatabase.Exists (path)) {
 					sinfo = new Addin (this, path);
-					cachedAddinSetupInfos [id] = sinfo;
+					cachedAddinSetupInfos [idd] = sinfo;
 					if (!enabledOnly || sinfo.Enabled)
 						return sinfo;
 					if (exactVersionMatch) {
 						// Cache lookups with negative result
-						cachedAddinSetupInfos [id] = this;
+						cachedAddinSetupInfos [idd] = this;
 						return null;
 					}
 				}
@@ -241,11 +294,9 @@
 					string version, name, bestVersion = null;
 					Addin.GetIdParts (id, out name, out version);
 					
-					// FIXME: Not very efficient, will load all descriptions
-					foreach (Addin ia in InternalGetInstalledAddins ()) 
+					foreach (Addin ia in InternalGetInstalledAddins (domain, name, AddinType.All)) 
 					{
-						if (Addin.GetIdName (ia.Id) == name && 
-						    (!enabledOnly || ia.Enabled) &&
+						if ((!enabledOnly || ia.Enabled) &&
 						    (version.Length == 0 || ia.SupportsVersion (version)) && 
 						    (bestVersion == null || Addin.CompareVersions (bestVersion, ia.Version) > 0)) 
 						{
@@ -254,7 +305,7 @@
 						}
 					}
 					if (sinfo != null) {
-						cachedAddinSetupInfos [id] = sinfo;
+						cachedAddinSetupInfos [idd] = sinfo;
 						return sinfo;
 					}
 				}
@@ -262,82 +313,72 @@
 				// Cache lookups with negative result
 				// Ignore the 'not installed' flag when disabled add-ins are allowed
 				if (enabledOnly)
-					cachedAddinSetupInfos [id] = this;
+					cachedAddinSetupInfos [idd] = this;
 				return null;
 			}
 		}
 		
-		public Addin GetInstalledAddin (string id, string version)
-		{
-			foreach (Addin ia in GetInstalledAddins ()) {
-				if ((id == null || ia.Id == id) && (version == null || ia.Version == version))
-					return ia;
-			}
-			return null;
-		}
-		
 		public void Shutdown ()
 		{
-			addinSetupInfos = null;
+			ResetCachedData ();
 		}
 		
-		public Addin GetAddinForHostAssembly (string assemblyLocation)
+		public Addin GetAddinForHostAssembly (string domain, string assemblyLocation)
 		{
-			InternalCheck ();
+			InternalCheck (domain);
 			Addin ainfo = null;
 			
 			object ob = cachedAddinSetupInfos [assemblyLocation];
-			if (ob != null) {
-				ainfo = ob as Addin;
-				if (ainfo != null)
-					return ainfo;
-				else
-					return null;
-			}
+			if (ob != null)
+				return ob as Addin; // Don't use a cast here is ob may not be an Addin.
 
 			AddinHostIndex index = GetAddinHostIndex ();
-			string addin, addinFile;
-			if (index.GetAddinForAssembly (assemblyLocation, out addin, out addinFile)) {
-				ainfo = new Addin (this, addin, addinFile);
+			string addin, addinFile, rdomain;
+			if (index.GetAddinForAssembly (assemblyLocation, out addin, out addinFile, out rdomain)) {
+				string sid = addin + " " + rdomain;
+				ainfo = cachedAddinSetupInfos [sid] as Addin;
+				if (ainfo == null)
+					ainfo = new Addin (this, GetDescriptionPath (rdomain, addin));
 				cachedAddinSetupInfos [assemblyLocation] = ainfo;
+				cachedAddinSetupInfos [addin + " " + rdomain] = ainfo;
 			}
 			
 			return ainfo;
 		}
 		
 		
-		public bool IsAddinEnabled (string id)
+		public bool IsAddinEnabled (string domain, string id)
 		{
-			Addin ainfo = GetInstalledAddin (id);
+			Addin ainfo = GetInstalledAddin (domain, id);
 			if (ainfo != null)
 				return ainfo.Enabled;
 			else
 				return false;
 		}
 		
-		internal bool IsAddinEnabled (string id, bool exactVersionMatch)
+		internal bool IsAddinEnabled (string domain, string id, bool exactVersionMatch)
 		{
 			if (!exactVersionMatch)
-				return IsAddinEnabled (id);
-			Addin ainfo = GetInstalledAddin (id, exactVersionMatch, false);
+				return IsAddinEnabled (domain, id);
+			Addin ainfo = GetInstalledAddin (domain, id, exactVersionMatch, false);
 			if (ainfo == null)
 				return false;
 			return Configuration.IsEnabled (id, ainfo.AddinInfo.EnabledByDefault);
 		}
 		
-		public void EnableAddin (string id)
+		public void EnableAddin (string domain, string id)
 		{
-			EnableAddin (id, true);
+			EnableAddin (domain, id, true);
 		}
 		
-		internal void EnableAddin (string id, bool exactVersionMatch)
+		internal void EnableAddin (string domain, string id, bool exactVersionMatch)
 		{
-			Addin ainfo = GetInstalledAddin (id, exactVersionMatch, false);
+			Addin ainfo = GetInstalledAddin (domain, id, exactVersionMatch, false);
 			if (ainfo == null)
 				// It may be an add-in root
 				return;
 
-			if (IsAddinEnabled (id))
+			if (IsAddinEnabled (domain, id))
 				return;
 			
 			// Enable required add-ins
@@ -346,7 +387,7 @@
 				if (dep is AddinDependency) {
 					AddinDependency adep = dep as AddinDependency;
 					string adepid = Addin.GetFullId (ainfo.AddinInfo.Namespace, adep.AddinId, adep.Version);
-					EnableAddin (adepid, false);
+					EnableAddin (domain, adepid, false);
 				}
 			}
 
@@ -357,13 +398,13 @@
 				AddinManager.SessionService.ActivateAddin (id);
 		}
 		
-		public void DisableAddin (string id)
+		public void DisableAddin (string domain, string id)
 		{
-			Addin ai = GetInstalledAddin (id, true);
+			Addin ai = GetInstalledAddin (domain, id, true);
 			if (ai == null)
 				throw new InvalidOperationException ("Add-in '" + id + "' not installed.");
 
-			if (!IsAddinEnabled (id))
+			if (!IsAddinEnabled (domain, id))
 				return;
 			
 			Configuration.SetStatus (id, false, ai.AddinInfo.EnabledByDefault);
@@ -374,7 +415,7 @@
 			try {
 				string idName = Addin.GetIdName (id);
 				
-				foreach (Addin ainfo in GetInstalledAddins ()) {
+				foreach (Addin ainfo in GetInstalledAddins (domain, AddinType.Addin)) {
 					foreach (Dependency dep in ainfo.AddinInfo.Dependencies) {
 						AddinDependency adep = dep as AddinDependency;
 						if (adep == null)
@@ -388,10 +429,10 @@
 						// if there is an older version available. Check it now.
 						
 						adepid = Addin.GetFullId (ainfo.AddinInfo.Namespace, adep.AddinId, adep.Version);
-						Addin adepinfo = GetInstalledAddin (adepid, false, true);
+						Addin adepinfo = GetInstalledAddin (domain, adepid, false, true);
 						
 						if (adepinfo == null) {
-							DisableAddin (ainfo.Id);
+							DisableAddin (domain, ainfo.Id);
 							break;
 						}
 					}
@@ -408,12 +449,12 @@
 				AddinManager.SessionService.UnloadAddin (id);
 		}		
 
-		internal string GetDescriptionPath (string id)
+		internal string GetDescriptionPath (string domain, string id)
 		{
-			return Path.Combine (AddinCachePath, id + ".maddin");
+			return Path.Combine (Path.Combine (AddinCachePath, domain), id + ".maddin");
 		}
 		
-		void InternalCheck ()
+		void InternalCheck (string domain)
 		{
 			// If the database is broken, don't try to regenerate it at every check.
 			if (fatalDatabseError)
@@ -426,19 +467,19 @@
 				}
 			}
 			if (update)
-				Update (null);
+				Update (null, domain);
 		}
 		
 		void GenerateAddinExtensionMapsInternal (IProgressStatus monitor, ArrayList addinsToUpdate, ArrayList removedAddins)
 		{
-			AddinUpdateData updateData = new AddinUpdateData (this);
+			AddinUpdateData updateData = new AddinUpdateData (this, monitor);
 			
 			// Clear cached data
 			cachedAddinSetupInfos.Clear ();
 			
 			// Collect all information
 			
-			Hashtable addinHash = new Hashtable ();
+			AddinIndex addinHash = new AddinIndex ();
 			
 			if (monitor.LogLevel > 1)
 				monitor.Log ("Generating add-in extension maps");
@@ -448,25 +489,41 @@
 			ArrayList files = new ArrayList ();
 			
 			bool partialGeneration = addinsToUpdate != null;
+			string[] domains = GetDomains ();
 			
 			// Get the files to be updated
 			
 			if (partialGeneration) {
 				changedAddins = new Hashtable ();
-				foreach (string s in addinsToUpdate) {
-					changedAddins [s] = s;
-					string mp = GetDescriptionPath (s);
-					if (fileDatabase.Exists (mp))
-						files.Add (mp);
-					else
-						files.AddRange (fileDatabase.GetObjectSharedFiles (this.AddinCachePath, s, ".mroot"));
+				foreach (string sa in addinsToUpdate) {
+					changedAddins [sa] = sa;
+					
+					// Look for all versions of the add-in, because this id may be the id of a reference,
+					// and the exact reference version may not be installed.
+					string s = sa;
+					int i = s.LastIndexOf (',');
+					if (i != -1)
+						s = s.Substring (0, i);
+					s += ",*";
+					
+					// Look for the add-in in any of the existing folders
+					foreach (string domain in domains) {
+						string mp = GetDescriptionPath (domain, s);
+						string dir = Path.GetDirectoryName (mp);
+						string pat = Path.GetFileName (mp);
+						foreach (string fmp in fileDatabase.GetDirectoryFiles (dir, pat)) {
+							files.Add (fmp);
+							string an = Path.GetFileNameWithoutExtension (fmp);
+							changedAddins [an] = an;
+						}
+					}
 				}
 				foreach (string s in removedAddins)
 					changedAddins [s] = s;
 			}
 			else {
-				files.AddRange (fileDatabase.GetDirectoryFiles (AddinCachePath, "*.maddin"));
-				files.AddRange (fileDatabase.GetDirectoryFiles (AddinCachePath, "*.mroot"));
+				foreach (string dom in domains)
+					files.AddRange (fileDatabase.GetDirectoryFiles (Path.Combine (AddinCachePath, dom), "*.maddin"));
 			}
 			
 			// Load the descriptions.
@@ -490,40 +547,20 @@
 				conf.UnmergeExternalData (changedAddins);
 				descriptionsToSave.Add (conf);
 				
-				// Register extension points and node sets from root add-ins
-				if (conf.IsRoot) {
-					foreach (ExtensionPoint ep in conf.ExtensionPoints)
-						updateData.RegisterAddinRootExtensionPoint (conf, ep);
-					foreach (ExtensionNodeSet ns in conf.ExtensionNodeSets)
-						updateData.RegisterAddinRootNodeSet (conf, ns);
-				}
-				else
-					addinHash [conf.AddinId] = conf;
+				addinHash.Add (conf);
 			}
+
+			// Sort the add-ins, to make sure add-ins are processed before
+			// all their dependencies
+			ArrayList sorted = addinHash.GetSortedAddins ();
+
+			// Register extension points and node sets
+			foreach (AddinDescription conf in sorted)
+				CollectExtensionPointData (conf, updateData);
 			
-			foreach (AddinDescription conf in addinHash.Values) {
+			// Register extensions
+			foreach (AddinDescription conf in sorted)
 				CollectExtensionData (conf, updateData);
-			}
-			
-			updateData.ResolveExtensions (monitor, addinHash);
-			
-			// Update the extension points defined by this add-in			
-			foreach (ExtensionPoint ep in updateData.GetUnresolvedExtensionPoints ()) {
-				AddinDescription am = (AddinDescription) addinHash [ep.RootAddin];
-				ExtensionPoint amep = am.ExtensionPoints [ep.Path];
-				if (amep != null) {
-					amep.MergeWith (am.AddinId, ep);
-					amep.RootAddin = ep.RootAddin;
-				}
-			}
-
-			// Now update the node sets
-			foreach (ExtensionPoint ep in updateData.GetUnresolvedExtensionSets ()) {
-				AddinDescription am = (AddinDescription) addinHash [ep.RootAddin];
-				ExtensionNodeSet nset = am.ExtensionNodeSets [ep.Path];
-				if (nset != null)
-					nset.MergeWith (am.AddinId, ep.NodeSet);
-			}
 			
 			// Save the maps
 			foreach (AddinDescription conf in descriptionsToSave)
@@ -542,7 +579,7 @@
 		// Collects extension data in a hash table. The key is the path, the value is a list
 		// of add-ins ids that extend that path
 		
-		void CollectExtensionData (AddinDescription conf, AddinUpdateData updateData)
+		void CollectExtensionPointData (AddinDescription conf, AddinUpdateData updateData)
 		{
 			foreach (ExtensionNodeSet nset in conf.ExtensionNodeSets) {
 				try {
@@ -561,7 +598,10 @@
 					throw new InvalidOperationException ("Error reading extension point: " + ep.Path, ex);
 				}
 			}
-			
+		}
+		
+		void CollectExtensionData (AddinDescription conf, AddinUpdateData updateData)
+		{
 			foreach (ModuleDescription module in conf.AllModules) {
 				foreach (Extension ext in module.Extensions) {
 					updateData.RelExtensions++;
@@ -586,18 +626,50 @@
 					AddChildExtensions (conf, module, updateData, path + "/" + id, node.ChildNodes, node.NodeName == "Condition");
 			}
 		}
+		
+		string[] GetDomains ()
+		{
+			string[] dirs = fileDatabase.GetDirectories (AddinCachePath);
+			string[] ids = new string [dirs.Length];
+			for (int n=0; n<dirs.Length; n++)
+				ids [n] = Path.GetFileName (dirs [n]);
+			return ids;
+		}
 
+		public string GetUniqueDomainId ()
+		{
+			if (lastDomainId != 0) {
+				lastDomainId++;
+				return lastDomainId.ToString ();
+			}
+			lastDomainId = 1;
+			foreach (string s in fileDatabase.GetDirectories (AddinCachePath)) {
+				string dn = Path.GetFileName (s);
+				if (dn == GlobalDomain)
+					continue;
+				try {
+					int n = int.Parse (dn);
+					if (n >= lastDomainId)
+						lastDomainId = n + 1;
+				} catch {
+				}
+			}
+			return lastDomainId.ToString ();
+		}
+		
 		internal void ResetCachedData ()
 		{
+			allSetupInfos = null;
 			addinSetupInfos = null;
+			rootSetupInfos = null;
 			hostIndex = null;
 			cachedAddinSetupInfos.Clear ();
 		}
 		
 		
-		public bool AddinDependsOn (string id1, string id2)
+		public bool AddinDependsOn (string domain, string id1, string id2)
 		{
-			Addin addin1 = GetInstalledAddin (id1, false);
+			Addin addin1 = GetInstalledAddin (domain, id1, false);
 			
 			// We can assumbe that if the add-in is not returned here, it may be a root addin.
 			if (addin1 == null)
@@ -611,13 +683,13 @@
 				string depid = Addin.GetFullId (addin1.AddinInfo.Namespace, adep.AddinId, null);
 				if (depid == id2)
 					return true;
-				else if (AddinDependsOn (depid, id2))
+				else if (AddinDependsOn (domain, depid, id2))
 					return true;
 			}
 			return false;
 		}
 		
-		public void Repair (IProgressStatus monitor)
+		public void Repair (IProgressStatus monitor, string domain)
 		{
 			using (fileDatabase.LockWrite ()) {
 				try {
@@ -632,10 +704,10 @@
 					monitor.ReportError ("The add-in registry could not be rebuilt. It may be due to lack of write permissions to the directory: " + AddinDbDir, ex);
 				}
 			}
-			Update (monitor);
+			Update (monitor, domain);
 		}
 		
-		public void Update (IProgressStatus monitor)
+		public void Update (IProgressStatus monitor, string domain)
 		{
 			if (monitor == null)
 				monitor = new ConsoleProgressStatus (false);
@@ -660,24 +732,28 @@
 				// Something has changed, the add-ins need to be re-scanned, but it has
 				// to be done in an external process
 				
-				using (fileDatabase.LockRead ()) {
-					foreach (Addin ainfo in InternalGetInstalledAddins ()) {
-						installed [ainfo.Id] = ainfo.Id;
+				if (domain != null) {
+					using (fileDatabase.LockRead ()) {
+						foreach (Addin ainfo in InternalGetInstalledAddins (domain, AddinType.Addin)) {
+							installed [ainfo.Id] = ainfo.Id;
+						}
 					}
 				}
 				
 				RunScannerProcess (monitor);
 			
 				ResetCachedData ();
+				
+				registry.NotifyDatabaseUpdated ();
 			}
 			
 			if (fatalDatabseError)
 				monitor.ReportError ("The add-in database could not be updated. It may be due to file corruption. Try running the setup repair utility", null);
 			
 			// Update the currently loaded add-ins
-			if (changesFound && AddinManager.IsInitialized && AddinManager.Registry.RegistryPath == registry.RegistryPath) {
+			if (changesFound && domain != null && AddinManager.IsInitialized && AddinManager.Registry.RegistryPath == registry.RegistryPath) {
 				Hashtable newInstalled = new Hashtable ();
-				foreach (Addin ainfo in GetInstalledAddins ()) {
+				foreach (Addin ainfo in GetInstalledAddins (domain, AddinType.Addin)) {
 					newInstalled [ainfo.Id] = ainfo.Id;
 				}
 				
@@ -894,9 +970,9 @@
 			
 			foreach (string dir in registry.AddinDirectories) {
 				if (dir == registry.DefaultAddinsFolder)
-					scanner.ScanFolderRec (monitor, dir, scanResult);
+					scanner.ScanFolderRec (monitor, dir, GlobalDomain, scanResult);
 				else
-					scanner.ScanFolder (monitor, dir, scanResult);
+					scanner.ScanFolder (monitor, dir, GlobalDomain, scanResult);
 				if (scanResult.CheckOnly) {
 					if (scanResult.ChangesFound || monitor.IsCanceled)
 						return;
@@ -961,12 +1037,9 @@
 				AddinScanFolderInfo finfo;
 				if (GetFolderInfoForPath (progressStatus, Path.GetDirectoryName (file), out finfo) && finfo != null) {
 					AddinFileInfo afi = finfo.GetAddinFileInfo (file);
-					if (afi != null && afi.AddinId != null) {
+					if (afi != null && afi.IsAddin) {
 						AddinDescription adesc;
-						if (afi.IsRoot)
-							GetHostDescription (progressStatus, afi.AddinId, file, out adesc);
-						else
-							GetAddinDescription (progressStatus, afi.AddinId, out adesc);
+						GetAddinDescription (progressStatus, afi.Domain, afi.AddinId, out adesc);
 						if (adesc != null)
 							adesc.Save (outFile);
 						return;
@@ -996,13 +1069,24 @@
 			}
 		}
 		
+		public string GetFolderDomain (IProgressStatus progressStatus, string path)
+		{
+			AddinScanFolderInfo folderInfo;
+			if (GetFolderInfoForPath (progressStatus, path, out folderInfo) && folderInfo != null && !folderInfo.SharedFolder)
+				return folderInfo.Domain;
+			else
+				return GlobalDomain;
+		}
+		
 		Assembly OnResolveAddinAssembly (object s, ResolveEventArgs args)
 		{
 			string file = currentScanResult.GetAssemblyLocation (args.Name);
 			if (file != null)
 				return Util.LoadAssemblyForReflection (file);
-			else
+			else {
+				Console.WriteLine ("Assembly not found: " + args.Name);
 				return null;
+			}
 		}
 		
 		public string GetFolderConfigFile (string path)
@@ -1017,23 +1101,13 @@
 			return Path.Combine (AddinFolderCachePath, s + ".data");
 		}
 		
-		internal void UninstallAddin (IProgressStatus monitor, string addinId, AddinScanResult scanResult)
+		internal void UninstallAddin (IProgressStatus monitor, string domain, string addinId, AddinScanResult scanResult)
 		{
 			scanResult.AddRemovedAddin (addinId);
-			string file = GetDescriptionPath (addinId);
-			DeleteAddin (monitor, file, scanResult);
-		}
-		
-		internal void UninstallRootAddin (IProgressStatus monitor, string addinId, string addinFile, AddinScanResult scanResult)
-		{
-			string file = fileDatabase.GetSharedObjectFile (AddinCachePath, addinId, ".mroot", addinFile);
-			DeleteAddin (monitor, file, scanResult);
-		}
-		
-		void DeleteAddin (IProgressStatus monitor, string file, AddinScanResult scanResult)
-		{
-			if (!fileDatabase.Exists (file))
+			string file = GetDescriptionPath (domain, addinId);
+			if (!fileDatabase.Exists (file)) {
 				return;
+			}
 			
 			// Add-in already existed. The dependencies of the old add-in need to be re-analized
 
@@ -1047,29 +1121,15 @@
 				scanResult.RegenerateRelationData = true;
 
 			SafeDelete (monitor, file);
+			string dir = Path.GetDirectoryName (file);
+			if (fileDatabase.DirectoryIsEmpty (dir))
+				SafeDeleteDir (monitor, dir);
 			SafeDeleteDir (monitor, Path.Combine (AddinPrivateDataPath, Path.GetFileNameWithoutExtension (file)));
 		}
 		
-		public bool GetHostDescription (IProgressStatus monitor, string addinId, string fileName, out AddinDescription description)
+		public bool GetAddinDescription (IProgressStatus monitor, string domain, string addinId, out AddinDescription description)
 		{
-			try {
-				description = AddinDescription.ReadHostBinary (fileDatabase, AddinCachePath, addinId, fileName);
-				if (description != null)
-					description.OwnerDatabase = this;
-				return true;
-			}
-			catch (Exception ex) {
-				if (monitor == null)
-					throw;
-				description = null;
-				monitor.ReportError ("Could not read folder info file", ex);
-				return false;
-			}
-		}
-		
-		public bool GetAddinDescription (IProgressStatus monitor, string addinId, out AddinDescription description)
-		{
-			string file = GetDescriptionPath (addinId);
+			string file = GetDescriptionPath (domain, addinId);
 			return ReadAddinDescription (monitor, file, out description);
 		}
 		
@@ -1095,10 +1155,13 @@
 			try {
 				if (replaceFileName != null)
 					desc.SaveBinary (fileDatabase, replaceFileName);
-				else if (desc.IsRoot)
-					desc.SaveHostBinary (fileDatabase, AddinCachePath);
-				else
-					desc.SaveBinary (fileDatabase, GetDescriptionPath (desc.AddinId));
+				else {
+					string file = GetDescriptionPath (desc.Domain, desc.AddinId);
+					string dir = Path.GetDirectoryName (file);
+					if (!fileDatabase.DirExists (dir))
+						fileDatabase.CreateDir (dir);
+					desc.SaveBinary (fileDatabase, file);
+				}
 				return true;
 			}
 			catch (Exception ex) {
@@ -1107,14 +1170,10 @@
 			}
 		}
 		
-		public bool AddinDescriptionExists (string addinId)
+		public bool AddinDescriptionExists (string domain, string addinId)
 		{
-			return fileDatabase.Exists (GetDescriptionPath (addinId));
-		}
-		
-		public bool HostDescriptionExists (string addinId, string sourceFile)
-		{
-			return fileDatabase.SharedObjectExists (AddinCachePath, addinId, ".mroot", sourceFile);
+			string file = GetDescriptionPath (domain, addinId);
+			return fileDatabase.Exists (file);
 		}
 		
 		public bool ReadFolderInfo (IProgressStatus monitor, string file, out AddinScanFolderInfo folderInfo)
@@ -1138,7 +1197,8 @@
 			}
 			catch (Exception ex) {
 				folderInfo = null;
-				monitor.ReportError ("Could not read folder info file", ex);
+				if (monitor != null)
+					monitor.ReportError ("Could not read folder info file", ex);
 				return false;
 			}
 		}
@@ -1225,7 +1285,7 @@
 				return name;
 			
 			int n = 1;
-			while (fileDatabase.Exists (GetDescriptionPath (id))) {
+			while (AddinIdExists (id)) {
 				name = baseId + "_" + n;
 				id = Addin.GetFullId (ns, name, version);
 				n++;
@@ -1233,6 +1293,15 @@
 			return name;
 		}
 		
+		bool AddinIdExists (string id)
+		{
+			foreach (string d in fileDatabase.GetDirectories (AddinCachePath)) {
+				if (fileDatabase.Exists (Path.Combine (d, id + ".addin")))
+				    return true;
+			}
+			return false;
+		}
+		
 		public void ResetConfiguration ()
 		{
 			if (File.Exists (ConfigFile))
@@ -1284,7 +1353,7 @@
 				scanResult.LocateAssembliesOnly = true;
 			
 				foreach (string dir in registry.AddinDirectories)
-					scanner.ScanFolder (progressStatus, dir, scanResult);
+					scanner.ScanFolder (progressStatus, dir, AddinDatabase.GlobalDomain, scanResult);
 			}
 		
 			string afile = scanResult.GetAssemblyLocation (args.Name);
@@ -1294,6 +1363,102 @@
 				return null;
 		}
 	}
+	
+	class AddinIndex
+	{
+		Hashtable addins = new Hashtable ();
+		
+		public void Add (AddinDescription desc)
+		{
+			string id = Addin.GetFullId (desc.Namespace, desc.LocalId, null);
+			ArrayList list = (ArrayList) addins [id];
+			if (list == null) {
+				list = new ArrayList (); 
+				addins [id] = list;
+			}
+			list.Add (desc);
+		}
+		
+		ArrayList FindDescriptions (string domain, string fullid)
+		{
+			// Returns all registered add-ins which are compatible with the provided
+			// fullid. Compatible means that the id is the same and the version is within
+			// the range of compatible versions of the add-in.
+			
+			ArrayList res = new ArrayList ();
+			string id = Addin.GetIdName (fullid);
+			ArrayList list = (ArrayList) addins [id];
+			if (list == null)
+				return res;
+			string version = Addin.GetIdVersion (fullid);
+			foreach (AddinDescription desc in list) {
+				if ((desc.Domain == domain || domain == AddinDatabase.GlobalDomain) && desc.SupportsVersion (version))
+					res.Add (desc);
+			}
+			return res;
+		}
+		
+		public ArrayList GetSortedAddins ()
+		{
+			Hashtable inserted = new Hashtable ();
+			Hashtable lists = new Hashtable ();
+			
+			foreach (ArrayList dlist in addins.Values) {
+				foreach (AddinDescription desc in dlist)
+					InsertSortedAddin (inserted, lists, desc);
+			}
+			
+			// Merge all domain lists into a single list.
+			// Make sure the global domain is inserted the last
+			
+			ArrayList global = (ArrayList) lists [AddinDatabase.GlobalDomain];
+			lists.Remove (AddinDatabase.GlobalDomain);
+			
+			ArrayList list = new ArrayList ();
+			foreach (ArrayList dl in lists.Values) {
+				list.AddRange (dl);
+			}
+			if (global != null)
+				list.AddRange (global);
+			return list;
+		}
+
+		void InsertSortedAddin (Hashtable inserted, Hashtable lists, AddinDescription desc)
+		{
+			string sid = desc.AddinId + " " + desc.Domain;
+			if (inserted.ContainsKey (sid))
+				return;
+			inserted [sid] = desc;
+			foreach (ModuleDescription mod in desc.AllModules) {
+				foreach (Dependency dep in mod.Dependencies) {
+					AddinDependency adep = dep as AddinDependency;
+					if (adep == null)
+						continue;
+					ArrayList descs = FindDescriptions (desc.Domain, adep.FullAddinId);
+					if (descs.Count > 0) {
+						foreach (AddinDescription sd in descs)
+							InsertSortedAddin (inserted, lists, sd);
+					}
+//					else 
+//						Console.WriteLine ("NOT FOUND: " + adep.FullAddinId + " " + desc.Domain + " from " + sid);
+				}
+			}
+			ArrayList list = (ArrayList) lists [desc.Domain];
+			if (list == null) {
+				list = new ArrayList ();
+				lists [desc.Domain] = list;
+			}
+			
+			list.Add (desc);
+		}
+	}
+	
+	enum AddinType
+	{
+		Addin,
+		Root,
+		All
+	}
 }
 
 

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinHostIndex.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinHostIndex.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinHostIndex.cs	Sun Mar  2 21:23:19 2008
@@ -39,35 +39,38 @@
 		
 		Hashtable index = new Hashtable ();
 		
-		public void RegisterAssembly (string assemblyLocation, string addinId, string addinLocation)
+		public void RegisterAssembly (string assemblyLocation, string addinId, string addinLocation, string domain)
 		{
 			assemblyLocation = NormalizeFileName (assemblyLocation);
-			index [Util.GetFullPath (assemblyLocation)] = addinId + " " + addinLocation;
+			index [Util.GetFullPath (assemblyLocation)] = addinId + " " + addinLocation + " " + domain;
 		}
 		
-		public bool GetAddinForAssembly (string assemblyLocation, out string addinId, out string addinLocation)
+		public bool GetAddinForAssembly (string assemblyLocation, out string addinId, out string addinLocation, out string domain)
 		{
 			assemblyLocation = NormalizeFileName (assemblyLocation);
 			string s = index [Util.GetFullPath (assemblyLocation)] as string;
 			if (s == null) {
 				addinId = null;
 				addinLocation = null;
+				domain = null;
 				return false;
 			}
 			else {
 				int i = s.IndexOf (' ');
+				int j = s.LastIndexOf (' ');
 				addinId = s.Substring (0, i);
-				addinLocation = s.Substring (i+1);
+				addinLocation = s.Substring (i+1, j-i-1);
+				domain = s.Substring (j+1);
 				return true;
 			}
 		}
 		
 		public void RemoveHostData (string addinId, string addinLocation)
 		{
-			string loc = addinId + " " + Util.GetFullPath (addinLocation);
+			string loc = addinId + " " + Util.GetFullPath (addinLocation) + " ";
 			ArrayList todelete = new ArrayList ();
 			foreach (DictionaryEntry e in index) {
-				if (((string)e.Value) == loc)
+				if (((string)e.Value).StartsWith (loc))
 					todelete.Add (e.Key);
 			}
 			foreach (string s in todelete)

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinScanFolderInfo.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinScanFolderInfo.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinScanFolderInfo.cs	Sun Mar  2 21:23:19 2008
@@ -39,6 +39,8 @@
 		Hashtable files = new Hashtable ();
 		string folder;
 		string fileName;
+		string domain;
+		bool sharedFolder = true;
 		
 		static BinaryXmlTypeMap typeMap = new BinaryXmlTypeMap (
 			typeof(AddinScanFolderInfo),
@@ -69,13 +71,13 @@
 		public static AddinScanFolderInfo Read (FileDatabase filedb, string basePath, string folderPath)
 		{
 			string fileName;
-			AddinScanFolderInfo finfo = (AddinScanFolderInfo) filedb.ReadSharedObject (basePath, GetFolderId (folderPath), ".data", Util.GetFullPath (folderPath), typeMap, out fileName);
+			AddinScanFolderInfo finfo = (AddinScanFolderInfo) filedb.ReadSharedObject (basePath, GetDomain (folderPath), ".data", Util.GetFullPath (folderPath), typeMap, out fileName);
 			if (finfo != null)
 				finfo.fileName = fileName;
 			return finfo;
 		}
 		
-		static string GetFolderId (string path)
+		static string GetDomain (string path)
 		{
 			path = Util.GetFullPath (path);
 			string s = path.Replace (Path.DirectorySeparatorChar, '_');
@@ -89,12 +91,60 @@
 		
 		public void Write (FileDatabase filedb, string basePath)
 		{
-			filedb.WriteSharedObject (basePath, GetFolderId (folder), ".data", Util.GetFullPath (folder), fileName, typeMap, this);
+			filedb.WriteSharedObject (basePath, GetDomain (folder), ".data", Util.GetFullPath (folder), fileName, typeMap, this);
+		}
+		
+		public string GetExistingLocalDomain ()
+		{
+			foreach (AddinFileInfo info in files.Values) {
+				if (info.Domain != null && info.Domain != AddinDatabase.GlobalDomain)
+					return info.Domain;
+			}
+			return AddinDatabase.GlobalDomain;
 		}
 		
 		public string Folder {
 			get { return folder; }
 		}
+
+		public string Domain {
+			get {
+				if (sharedFolder)
+					return AddinDatabase.GlobalDomain;
+				else
+					return domain;
+			}
+			set {
+				domain = value;
+				sharedFolder = true;
+			}
+		}
+		
+		public string RootsDomain {
+			get {
+				return domain;
+			}
+			set {
+				domain = value;
+			}
+		}
+		
+		public string GetDomain (bool isRoot)
+		{
+			if (isRoot)
+				return RootsDomain;
+			else
+				return Domain;
+		}
+		
+		public bool SharedFolder {
+			get {
+				return sharedFolder;
+			}
+			set {
+				sharedFolder = value;
+			}
+		}
 		
 		public DateTime GetLastScanTime (string file)
 		{
@@ -122,6 +172,10 @@
 			info.AddinId = addinId;
 			info.IsRoot = isRoot;
 			info.ScanError = scanError;
+			if (addinId != null)
+				info.Domain = GetDomain (isRoot);
+			else
+				info.Domain = null;
 		}
 		
 		public ArrayList GetMissingAddins ()
@@ -131,7 +185,7 @@
 			if (!Directory.Exists (folder)) {
 				// All deleted
 				foreach (AddinFileInfo info in files.Values) {
-					if (info.AddinId != null && info.AddinId.Length > 0)
+					if (info.IsAddin)
 						missing.Add (info);
 				}
 				files.Clear ();
@@ -140,10 +194,13 @@
 			ArrayList toDelete = new ArrayList ();
 			foreach (AddinFileInfo info in files.Values) {
 				if (!File.Exists (info.File)) {
-					if (info.AddinId != null && info.AddinId.Length > 0)
+					if (info.IsAddin)
 						missing.Add (info);
 					toDelete.Add (info.File);
 				}
+				else if (info.IsAddin && info.Domain != GetDomain (info.IsRoot)) {
+					missing.Add (info);
+				}
 			}
 			foreach (string file in toDelete)
 				files.Remove (file);
@@ -153,14 +210,22 @@
 		
 		void IBinaryXmlElement.Write (BinaryXmlWriter writer)
 		{
+			if (files.Count == 0) {
+				domain = null;
+				sharedFolder = true;
+			}
 			writer.WriteValue ("folder", folder);
 			writer.WriteValue ("files", files);
+			writer.WriteValue ("domain", domain);
+			writer.WriteValue ("sharedFolder", sharedFolder);
 		}
 		
 		void IBinaryXmlElement.Read (BinaryXmlReader reader)
 		{
 			folder = reader.ReadStringValue ("folder");
 			reader.ReadValue ("files", files);
+			domain = reader.ReadStringValue ("domain");
+			sharedFolder = reader.ReadBooleanValue ("sharedFolder");
 		}
 	}
 	
@@ -172,6 +237,11 @@
 		public string AddinId;
 		public bool IsRoot;
 		public bool ScanError;
+		public string Domain;
+		
+		public bool IsAddin {
+			get { return AddinId != null && AddinId.Length != 0; }
+		}
 		
 		void IBinaryXmlElement.Write (BinaryXmlWriter writer)
 		{
@@ -180,6 +250,7 @@
 			writer.WriteValue ("AddinId", AddinId);
 			writer.WriteValue ("IsRoot", IsRoot);
 			writer.WriteValue ("ScanError", ScanError);
+			writer.WriteValue ("Domain", Domain);
 		}
 		
 		void IBinaryXmlElement.Read (BinaryXmlReader reader)
@@ -189,6 +260,7 @@
 			AddinId = reader.ReadStringValue ("AddinId");
 			IsRoot = reader.ReadBooleanValue ("IsRoot");
 			ScanError = reader.ReadBooleanValue ("ScanError");
+			Domain = reader.ReadStringValue ("Domain");
 		}
 	}
 }

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinScanner.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinScanner.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinScanner.cs	Sun Mar  2 21:23:19 2008
@@ -49,7 +49,7 @@
 			this.database = database;
 		}
 		
-		public void ScanFolder (IProgressStatus monitor, string path, AddinScanResult scanResult)
+		public void ScanFolder (IProgressStatus monitor, string path, string domain, AddinScanResult scanResult)
 		{
 			path = Util.GetFullPath (path);
 			
@@ -71,9 +71,32 @@
 					return;
 			}
 			
+			// if domain is null it means that a new domain has to be created.
+			
+			bool sharedFolder = domain == AddinDatabase.GlobalDomain;
+			
 			if (folderInfo == null)
 				folderInfo = new AddinScanFolderInfo (path);
 			
+			if (!sharedFolder && (folderInfo.SharedFolder || folderInfo.Domain != domain)) {
+				// If the folder already has a domain, reuse it
+				if (domain == null && folderInfo.RootsDomain != null && folderInfo.RootsDomain != AddinDatabase.GlobalDomain)
+					domain = folderInfo.RootsDomain;
+				else if (domain == null) {
+					folderInfo.Domain = domain = database.GetUniqueDomainId ();
+					scanResult.RegenerateRelationData = true;
+				}
+				else {
+					folderInfo.Domain = domain;
+					scanResult.RegenerateRelationData = true;
+				}
+			}
+			else if (!folderInfo.SharedFolder && sharedFolder) {
+				scanResult.RegenerateRelationData = true;
+			}
+			
+			folderInfo.SharedFolder = sharedFolder;
+			
 			if (Directory.Exists (path))
 			{
 				string[] files = Directory.GetFiles (path);
@@ -95,7 +118,7 @@
 						scanResult.AddAssemblyLocation (file);
 						break;
 					case ".addins":
-						ScanAddinsFile (monitor, file, scanResult);
+						ScanAddinsFile (monitor, file, domain, scanResult);
 						break;
 					}
 				}
@@ -128,10 +151,7 @@
 					return;
 					
 				foreach (AddinFileInfo info in missing) {
-					if (info.IsRoot)
-						database.UninstallRootAddin (monitor, info.AddinId, info.File, scanResult);
-					else
-						database.UninstallAddin (monitor, info.AddinId, scanResult);
+					database.UninstallAddin (monitor, info.Domain, info.AddinId, scanResult);
 				}
 			}
 		}
@@ -144,7 +164,7 @@
 			AddinFileInfo finfo = folderInfo.GetAddinFileInfo (file);
 			bool added = false;
 			   
-			if (finfo != null && File.GetLastWriteTime (file) == finfo.LastScan && !scanResult.RegenerateAllData) {
+			if (finfo != null && (!finfo.IsAddin || finfo.Domain == folderInfo.GetDomain (finfo.IsRoot)) && File.GetLastWriteTime (file) == finfo.LastScan && !scanResult.RegenerateAllData) {
 				if (finfo.ScanError) {
 					// Always schedule the file for scan if there was an error in a previous scan.
 					// However, don't set ChangesFound=true, in this way if there isn't any other
@@ -153,15 +173,10 @@
 					added = true;
 				}
 			
-				if (finfo.AddinId == null || finfo.AddinId.Length == 0)
+				if (!finfo.IsAddin)
+					return;
+				if (database.AddinDescriptionExists (finfo.Domain, finfo.AddinId))
 					return;
-				if (!finfo.IsRoot) {
-					if (database.AddinDescriptionExists (finfo.AddinId))
-						return;
-				} else {
-					if (database.HostDescriptionExists (finfo.AddinId, file))
-						return;
-				}
 			}
 			
 			scanResult.ChangesFound = true;
@@ -239,12 +254,7 @@
 					// Also, the dependencies of the old add-in need to be re-analized
 					
 					AddinDescription existingDescription = null;
-					bool res;
-					
-					if (config.IsRoot)
-						res = database.GetHostDescription (monitor, config.AddinId, config.AddinFile, out existingDescription);
-					else
-						res = database.GetAddinDescription (monitor, config.AddinId, out existingDescription);
+					bool res = database.GetAddinDescription (monitor, folderInfo.Domain, config.AddinId, out existingDescription);
 					
 					// If we can't get information about the old assembly, just regenerate all relation data
 					if (!res)
@@ -261,11 +271,8 @@
 					
 					// If the scanned file results in an add-in version different from the one obtained from
 					// previous scans, the old add-in needs to be uninstalled.
-					if (fi != null && fi.AddinId != null && fi.AddinId != config.AddinId) {
-						if (fi.IsRoot)
-							database.UninstallRootAddin (monitor, fi.AddinId, file, scanResult);
-						else
-							database.UninstallAddin (monitor, fi.AddinId, scanResult);
+					if (fi != null && fi.IsAddin && fi.AddinId != config.AddinId) {
+						database.UninstallAddin (monitor, folderInfo.Domain, fi.AddinId, scanResult);
 						
 						// If the add-in version has changed, regenerate everything again since old data can't be reused
 						if (Addin.GetIdName (fi.AddinId) == Addin.GetIdName (config.AddinId))
@@ -274,6 +281,23 @@
 					
 					// If a description could be generated, save it now (if the scan was successful)
 					if (scanSuccessful) {
+						
+						// Assign the domain
+						if (config.IsRoot) {
+							if (folderInfo.RootsDomain == null)
+								folderInfo.RootsDomain = database.GetUniqueDomainId ();
+							config.Domain = folderInfo.RootsDomain;
+						} else
+							config.Domain = folderInfo.Domain;
+						
+						if (config.IsRoot && scanResult.HostIndex != null) {
+							// If the add-in is a root, register its assemblies
+							foreach (string f in config.MainModule.Assemblies) {
+								string asmFile = Path.Combine (config.BasePath, f);
+								scanResult.HostIndex.RegisterAssembly (asmFile, config.AddinId, config.AddinFile, config.Domain);
+							}
+						}
+						
 						if (database.SaveDescription (monitor, config, replaceFileName)) {
 							// The new dependencies also have to be updated
 							Util.AddDependencies (config, scanResult);
@@ -331,11 +355,11 @@
 			return config;
 		}
 		
-		public void ScanAddinsFile (IProgressStatus monitor, string file, AddinScanResult scanResult)
+		public void ScanAddinsFile (IProgressStatus monitor, string file, string domain, AddinScanResult scanResult)
 		{
 			XmlTextReader r = null;
-			StringCollection directories = new StringCollection ();
-			StringCollection directoriesWithSubdirs = new StringCollection ();
+			ArrayList directories = new ArrayList ();
+			ArrayList directoriesWithSubdirs = new ArrayList ();
 			try {
 				r = new XmlTextReader (new StreamReader (file));
 				r.MoveToContent ();
@@ -346,20 +370,31 @@
 				while (r.NodeType != XmlNodeType.EndElement) {
 					if (r.NodeType == XmlNodeType.Element && r.LocalName == "Directory") {
 						string subs = r.GetAttribute ("include-subdirs");
+						string sdom;
+						string share = r.GetAttribute ("shared");
+						if (share == "true")
+							sdom = AddinDatabase.GlobalDomain;
+						else if (share == "false")
+							sdom = null;
+						else
+							sdom = domain; // Inherit the domain
+						
 						string path = r.ReadElementString ().Trim ();
 						if (path.Length > 0) {
 							if (subs == "true")
-								directoriesWithSubdirs.Add (path);
+								directoriesWithSubdirs.Add (new string[] {path, sdom});
 							else
-								directories.Add (path);
+								directories.Add (new string[] {path, sdom});
 						}
 					}
 					else if (r.NodeType == XmlNodeType.Element && r.LocalName == "GacAssembly") {
 						string aname = r.ReadElementString ().Trim ();
 						if (aname.Length > 0) {
 							aname = Util.GetGacPath (aname);
-							if (aname != null)
-								directories.Add (aname);
+							if (aname != null) {
+								// Gac assemblies always use the global domain
+								directories.Add (new string[] {aname, AddinDatabase.GlobalDomain});
+							}
 						}
 					}
 					else
@@ -373,29 +408,29 @@
 				if (r != null)
 					r.Close ();
 			}
-			foreach (string d in directories) {
-				string dir = d;
+			foreach (string[] d in directories) {
+				string dir = d[0];
 				if (!Path.IsPathRooted (dir))
 					dir = Path.Combine (Path.GetDirectoryName (file), dir);
-				ScanFolder (monitor, dir, scanResult);
+				ScanFolder (monitor, dir, d[1], scanResult);
 			}
-			foreach (string d in directoriesWithSubdirs) {
-				string dir = d;
+			foreach (string[] d in directoriesWithSubdirs) {
+				string dir = d[0];
 				if (!Path.IsPathRooted (dir))
 					dir = Path.Combine (Path.GetDirectoryName (file), dir);
-				ScanFolderRec (monitor, dir, scanResult);
+				ScanFolderRec (monitor, dir, d[1], scanResult);
 			}
 		}
 		
-		public void ScanFolderRec (IProgressStatus monitor, string dir, AddinScanResult scanResult)
+		public void ScanFolderRec (IProgressStatus monitor, string dir, string domain, AddinScanResult scanResult)
 		{
-			ScanFolder (monitor, dir, scanResult);
+			ScanFolder (monitor, dir, domain, scanResult);
 			
 			if (!Directory.Exists (dir))
 				return;
 				
 			foreach (string sd in Directory.GetDirectories (dir))
-				ScanFolderRec (monitor, sd, scanResult);
+				ScanFolderRec (monitor, sd, domain, scanResult);
 		}
 		
 		bool ScanConfigAssemblies (IProgressStatus monitor, string filePath, AddinScanResult scanResult, out AddinDescription config)
@@ -503,16 +538,8 @@
 				foreach (Assembly asm in assemblies)
 					ScanAssemblyContents (config, asm, hostExtensionClasses, scanResult);
 				
-				if (config.IsRoot && scanResult.HostIndex != null) {
-					// If the add-in is a root, register its assemblies
-					foreach (string asmFile in asmFiles)
-						scanResult.HostIndex.RegisterAssembly (asmFile, config.AddinId, config.AddinFile);
-				}
-				
 			} catch (Exception ex) {
-				if (monitor.LogLevel > 1)
-					monitor.Log ("Could not load some add-in assemblies: " + ex.Message);
-				scanResult.AddFileToWithFailure (config.AddinFile);
+				ReportReflectionException (monitor, ex, config, scanResult);
 				return false;
 			}
 			
@@ -524,7 +551,9 @@
 			
 			Hashtable internalNodeSets = new Hashtable ();
 			
-			foreach (ExtensionNodeSet eset in config.ExtensionNodeSets)
+			ArrayList setsCopy = new ArrayList ();
+			setsCopy.AddRange (config.ExtensionNodeSets);
+			foreach (ExtensionNodeSet eset in setsCopy)
 				ScanNodeSet (config, eset, assemblies, internalNodeSets);
 			
 			foreach (ExtensionPoint ep in config.ExtensionPoints) {
@@ -547,23 +576,30 @@
 						}
 						foreach (Assembly asm in assemblies)
 							ScanAssemblyContents (config, asm, null, scanResult);
-				
-						if (config.IsRoot && scanResult.HostIndex != null) {
-							// If the add-in is a root, register its assemblies
-							foreach (string asmFile in asmFiles)
-								scanResult.HostIndex.RegisterAssembly (asmFile, config.AddinId, config.AddinFile);
-						}
 						
 					} catch (Exception ex) {
-						if (monitor.LogLevel > 1)
-							monitor.Log ("Could not load some add-in assemblies: " + ex.Message);
-						scanResult.AddFileToWithFailure (config.AddinFile);
+						ReportReflectionException (monitor, ex, config, scanResult);
 					}
 				}
 			}
 			
+			config.StoreFileInfo ();
 			return true;
 		}
+
+		void ReportReflectionException (IProgressStatus monitor, Exception ex, AddinDescription config, AddinScanResult scanResult)
+		{
+			scanResult.AddFileToWithFailure (config.AddinFile);
+			monitor.ReportWarning ("[" + config.AddinId + "] Could not load some add-in assemblies: " + ex.Message);
+			if (monitor.LogLevel <= 1)
+			    return;
+			
+			ReflectionTypeLoadException rex = ex as ReflectionTypeLoadException;
+			if (rex != null) {
+				foreach (Exception e in rex.LoaderExceptions)
+					monitor.Log ("Load exception: " + e);
+			}
+		}
 		
 		void ScanAssemblyAddinHeaders (AddinDescription config, Assembly asm, AddinScanResult scanResult)
 		{

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinUpdateData.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinUpdateData.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/AddinUpdateData.cs	Sun Mar  2 21:23:19 2008
@@ -57,213 +57,129 @@
 			public ExtensionPoint ExtensionPoint;
 		}
 		
-		AddinDatabase database;
+		IProgressStatus monitor;
 		
-		public AddinUpdateData (AddinDatabase database)
+		public AddinUpdateData (AddinDatabase database, IProgressStatus monitor)
 		{
-			this.database = database;
+			this.monitor = monitor;
 		}
 		
-		public void RegisterAddinRootExtensionPoint (AddinDescription description, ExtensionPoint ep)
+		public void RegisterNodeSet (AddinDescription description, ExtensionNodeSet nset)
 		{
-			RelExtensionPoints++;
-			ArrayList list = (ArrayList) pathHash [ep.Path];
-			if (list == null) {
-				list = new ArrayList ();
-				pathHash [ep.Path] = list;
+			ArrayList extensions = (ArrayList) nodeSetHash [nset.Id];
+			if (extensions != null) {
+				// Extension point already registered
+				ArrayList compatExtensions = GetCompatibleExtensionPoints (nset.Id, description, description.MainModule, extensions);
+				if (compatExtensions.Count > 0) {
+					foreach (ExtensionPoint einfo in compatExtensions)
+						einfo.NodeSet.MergeWith (null, nset);
+					return;
+				}
 			}
-			
+			// Create a new extension set
 			RootExtensionPoint rep = new RootExtensionPoint ();
+			rep.ExtensionPoint = new ExtensionPoint ();
+			rep.ExtensionPoint.SetNodeSet (nset);
+			rep.ExtensionPoint.RootAddin = description.AddinId;
+			rep.ExtensionPoint.Path = nset.Id;
 			rep.Description = description;
-			rep.ExtensionPoint = ep;
-			ep.RootAddin = description.AddinId;
-			list.Add (rep);
+			if (extensions == null) {
+				extensions = new ArrayList ();
+				nodeSetHash [nset.Id] = extensions;
+			}
+			extensions.Add (rep);
 		}
-
-		public void RegisterAddinRootNodeSet (AddinDescription description, ExtensionNodeSet nodeSet)
+		
+		public void RegisterExtensionPoint (AddinDescription description, ExtensionPoint ep)
 		{
-			ArrayList list = (ArrayList) nodeSetHash [nodeSet.Id];
-			if (list == null) {
-				list = new ArrayList ();
-				nodeSetHash [nodeSet.Id] = list;
+			ArrayList extensions = (ArrayList) pathHash [ep.Path];
+			if (extensions != null) {
+				// Extension point already registered
+				ArrayList compatExtensions = GetCompatibleExtensionPoints (ep.Path, description, description.MainModule, extensions);
+				if (compatExtensions.Count > 0) {
+					foreach (ExtensionPoint einfo in compatExtensions)
+						einfo.MergeWith (null, ep);
+					RegisterObjectTypes (ep);
+					return;
+				}
 			}
-			
+			// Create a new extension
 			RootExtensionPoint rep = new RootExtensionPoint ();
-			rep.Description = description;
-			ExtensionPoint ep = new ExtensionPoint ();
-			ep.RootAddin = description.AddinId;
-			ep.SetNodeSet (nodeSet);
 			rep.ExtensionPoint = ep;
-			list.Add (rep);
-		}
-
-		public void RegisterNodeSet (AddinDescription description, ExtensionNodeSet nset)
-		{
-			string id = Addin.GetFullId (description.Namespace, nset.Id, description.Version);
-			foreach (ExtensionPoint einfo in GetExtensionInfo (nodeSetHash, id, description, description.MainModule, false)) {
-				if (einfo.RootAddin == null || database.AddinDependsOn (einfo.RootAddin, description.AddinId))
-					einfo.RootAddin = description.AddinId;
-				einfo.NodeSet.MergeWith (null, nset);
+			rep.ExtensionPoint.RootAddin = description.AddinId;
+			rep.Description = description;
+			if (extensions == null) {
+				extensions = new ArrayList ();
+				pathHash [ep.Path] = extensions;
 			}
+			extensions.Add (rep);
+			RegisterObjectTypes (ep);
 		}
-		
-		public void RegisterExtensionPoint (AddinDescription description, ExtensionPoint ep)
+			
+		void RegisterObjectTypes (ExtensionPoint ep)
 		{
-			foreach (ExtensionPoint einfo in GetExtensionInfo (pathHash, ep.Path, description, description.MainModule, false)) {
-				if (einfo.RootAddin == null || database.AddinDependsOn (einfo.RootAddin, description.AddinId))
-					einfo.RootAddin = description.AddinId;
-				einfo.MergeWith (null, ep);
+			// Register extension points bound to a node type
+			
+			foreach (ExtensionNodeType nt in ep.NodeSet.NodeTypes) {
+				if (nt.ObjectTypeName.Length > 0) {
+					ArrayList list = (ArrayList) objectTypeExtensions [nt.ObjectTypeName];
+					if (list == null) {
+						list = new ArrayList ();
+						objectTypeExtensions [nt.ObjectTypeName] = list;
+					}
+					list.Add (ep);
+				}
 			}
 		}
 
 		public void RegisterExtension (AddinDescription description, ModuleDescription module, Extension extension)
 		{
 			if (extension.Path.StartsWith ("$")) {
-				UnresolvedObjectTypeExtension extData = new UnresolvedObjectTypeExtension ();
-				extData.Description = description;
-				extData.ModuleDescription = module;
-				extData.Extension = extension;
 				string[] objectTypes = extension.Path.Substring (1).Split (',');
+				bool found = false;
 				foreach (string s in objectTypes) {
 					ArrayList list = (ArrayList) objectTypeExtensions [s];
-					if (list == null) {
-						list = new ArrayList ();
-						objectTypeExtensions [s] = list;
-					}
-					list.Add (extData);
-				}
-			}
-		}
-		
-		void CollectObjectTypeExtensions (AddinDescription desc, ExtensionPoint ep, string objectTypeName)
-		{
-			ArrayList list = (ArrayList) objectTypeExtensions [objectTypeName];
-			if (list == null)
-				return;
-			
-			foreach (UnresolvedObjectTypeExtension data in list) {
-				if (IsAddinCompatible (desc, data.Description, data.ModuleDescription)) {
-					data.Extension.Path = ep.Path;
-					RegisterExtension (data.Description, data.ModuleDescription, ep.Path);
-					data.FoundExtensionPoint = true;
-				}
-			}
-		}
-		
-		public void RegisterExtension (AddinDescription description, ModuleDescription module, string path)
-		{
-			foreach (ExtensionPoint einfo in GetExtensionInfo (pathHash, path, description, module, true)) {
-				if (!einfo.Addins.Contains (description.AddinId))
-					einfo.Addins.Add (description.AddinId);
-			}
-		}
-		
-		public IEnumerable GetUnresolvedExtensionPoints ()
-		{
-			ArrayList list = new ArrayList ();
-			foreach (object ob in pathHash.Values)
-				if (ob is ExtensionPoint)
-					list.Add (ob);
-			return list;
-		}
-
-		public IEnumerable GetUnresolvedExtensionSets ()
-		{
-			ArrayList list = new ArrayList ();
-			foreach (object ob in nodeSetHash.Values)
-				if (ob is ExtensionPoint)
-					list.Add (ob);
-			return list;
-		}
-		
-		public void ResolveExtensions (IProgressStatus monitor, Hashtable descriptions)
-		{
-			// Make a copy of the extensions found, sice the hash may change while being scanned
-			object[] extensionPointsFound = new object [pathHash.Count];
-			pathHash.Values.CopyTo (extensionPointsFound, 0);
-
-			foreach (object ob in extensionPointsFound) {
-				ExtensionPoint ep = ob as ExtensionPoint;
-				
-				if (ep == null) {
-					// It is a list of extension from a root add-in
-					ArrayList rootExtensionPoints = (ArrayList) ob;
-					foreach (RootExtensionPoint rep in rootExtensionPoints) {
-						foreach (ExtensionNodeType nt in rep.ExtensionPoint.NodeSet.NodeTypes) {
-							if (nt.ObjectTypeName.Length > 0)
-								CollectObjectTypeExtensions (rep.Description, rep.ExtensionPoint, nt.ObjectTypeName);
-						}
-					}
-					continue;
-				}
-				
-				if (ep.RootAddin == null) {
-					// Ignore class extensions
-					if (!ep.Path.StartsWith ("$")) {
-						// No add-in has defined this extension point, but some add-in
-						// is trying to extend it. A parent extension may exist. Check it now.
-						ExtensionPoint pep = GetParentExtensionPoint (ep.Path);
-						if (pep != null) {
-							foreach (string a in ep.Addins)
-								if (!pep.Addins.Contains (a))
-									pep.Addins.Add (a);
-						} else {
-							foreach (string s in ep.Addins)
-								monitor.ReportWarning ("The add-in '" + s + "' is trying to extend '" + ep.Path + "', but there isn't any add-in defining this extension point");
+					if (list != null) {
+						found = true;
+						foreach (ExtensionPoint ep in list) {
+							if (IsAddinCompatible (ep.ParentAddinDescription, description, module)) {
+								extension.Path = ep.Path;
+								RegisterExtension (description, module, ep.Path);
+							}
 						}
 					}
-					pathHash.Remove (ep.Path);
-				}
-				else {
-					foreach (ExtensionNodeType nt in ep.NodeSet.NodeTypes) {
-						if (nt.ObjectTypeName.Length > 0) {
-							AddinDescription desc = (AddinDescription) descriptions [ep.RootAddin];
-							CollectObjectTypeExtensions (desc, ep, nt.ObjectTypeName);
-						}
-					}
-				}
-			}
-			
-			foreach (ArrayList list in objectTypeExtensions.Values) {
-				foreach (UnresolvedObjectTypeExtension data in list) {
-					if (!data.FoundExtensionPoint) {
-						monitor.ReportWarning ("The add-in '" + data.Description.AddinId + "' is trying to register the class '" + data.Extension.Path + "', but there isn't any add-in defining a suitable extension point");
-						// The type extensions may be registered using different base classes.
-						// Make sure the warning is shown only once
-						data.FoundExtensionPoint = true;
-					}
 				}
+				if (!found)
+					monitor.ReportWarning ("The add-in '" + description.AddinId + "' is trying to register the class '" + extension.Path.Substring (1) + "', but there isn't any add-in defining a suitable extension point");
 			}
 		}
 		
-		IEnumerable GetExtensionInfo (Hashtable hash, string path, AddinDescription description, ModuleDescription module, bool lookInParents)
+		public void RegisterExtension (AddinDescription description, ModuleDescription module, string path)
 		{
-			ArrayList list = new ArrayList ();
-			
-			object data = hash [path];
-			if (data == null && lookInParents) {
+			ArrayList extensions = (ArrayList) pathHash [path];
+			if (extensions == null) {
 				// Root add-in extension points are registered before any other kind of extension,
 				// so we should find it now.
-				data = GetParentExtensionInfo (path);
+				extensions = GetParentExtensionInfo (path);
+			}
+			if (extensions == null) {
+				monitor.ReportWarning ("The add-in '" + description.AddinId + "' is trying to extend '" + path + "', but there isn't any add-in defining this extension point");
+				return;
 			}
 			
-			if (data is ArrayList) {
-				// Extension point which belongs to a root assembly.
-				list.AddRange (GetRootExtensionInfo (hash, path, description, module, (ArrayList) data));
-			}
-			else {
-				ExtensionPoint info = (ExtensionPoint) data;
-				if (info == null) {
-					info = new ExtensionPoint ();
-					info.Path = path;
-					hash [path] = info;
+			bool found = false;
+			foreach (RootExtensionPoint einfo in extensions) {
+				if (IsAddinCompatible (einfo.Description, description, module)) {
+					if (!einfo.ExtensionPoint.Addins.Contains (description.AddinId))
+						einfo.ExtensionPoint.Addins.Add (description.AddinId);
+					found = true;
 				}
-				list.Add (info);
 			}
-			return list;
+			if (!found)
+				monitor.ReportWarning ("The add-in '" + description.AddinId + "' is trying to extend '" + path + "', but there isn't any compatible add-in defining this extension point");
 		}
-	
-		ArrayList GetRootExtensionInfo (Hashtable hash, string path, AddinDescription description, ModuleDescription module, ArrayList rootExtensionPoints)
+		
+		ArrayList GetCompatibleExtensionPoints (string path, AddinDescription description, ModuleDescription module, ArrayList rootExtensionPoints)
 		{
 			ArrayList list = new ArrayList ();
 			foreach (RootExtensionPoint rep in rootExtensionPoints) {
@@ -275,18 +191,13 @@
 			return list;
 		}
 		
-		ExtensionPoint GetParentExtensionPoint (string path)
-		{
-			return GetParentExtensionInfo (path) as ExtensionPoint;
-		}
-		
-		object GetParentExtensionInfo (string path)
+		ArrayList GetParentExtensionInfo (string path)
 		{
 			int i = path.LastIndexOf ('/');
 			if (i == -1)
 				return null;
 			string np = path.Substring (0, i);
-			object ep = pathHash [np];
+			ArrayList ep = (ArrayList) pathHash [np];
 			if (ep != null)
 				return ep;
 			else
@@ -295,6 +206,14 @@
 		
 		bool IsAddinCompatible (AddinDescription installedDescription, AddinDescription description, ModuleDescription module)
 		{
+			if (installedDescription == description)
+				return true;
+			if (installedDescription.Domain != AddinDatabase.GlobalDomain) {
+				if (description.Domain != AddinDatabase.GlobalDomain && description.Domain != installedDescription.Domain)
+					return false;
+			} else if (description.Domain != AddinDatabase.GlobalDomain)
+				return false;
+				
 			string addinId = Addin.GetFullId (installedDescription.Namespace, installedDescription.LocalId, null);
 			string requiredVersion = null;
 			
@@ -317,12 +236,4 @@
 			return true;
 		}
 	}
-	
-	class UnresolvedObjectTypeExtension
-	{
-		public AddinDescription Description;
-		public ModuleDescription ModuleDescription;
-		public Extension Extension;
-		public bool FoundExtensionPoint;
-	}
 }

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/FileDatabase.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/FileDatabase.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/FileDatabase.cs	Sun Mar  2 21:23:19 2008
@@ -205,6 +205,30 @@
 			return File.Exists (fileName);
 		}
 		
+		public bool DirExists (string dir)
+		{
+			return Directory.Exists (dir);
+		}
+		
+		public void CreateDir (string dir)
+		{
+			Directory.CreateDirectory (dir);
+		}
+		
+		public string[] GetDirectories (string dir)
+		{
+			return Directory.GetDirectories (dir);
+		}
+		
+		public bool DirectoryIsEmpty (string dir)
+		{
+			foreach (string f in Directory.GetFiles (dir)) {
+				if (!inTransaction || !deletedFiles.Contains (f))
+					return false;
+			}
+			return true;
+		}
+		
 		public string[] GetDirectoryFiles (string dir, string pattern)
 		{
 			if (pattern == null || pattern.Length == 0 || pattern.EndsWith ("*"))

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/SetupProcess.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/SetupProcess.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Database/SetupProcess.cs	Sun Mar  2 21:23:19 2008
@@ -52,8 +52,10 @@
 			Process process = new Process ();
 			if (Util.IsWindows)
 				process.StartInfo = new ProcessStartInfo (asm, sb.ToString ());
-			else
+			else {
+				asm = asm.Replace(" ", @"\ ");
 				process.StartInfo = new ProcessStartInfo ("mono", "--debug " + asm + " " + sb.ToString ());
+			}
 			process.StartInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
 			process.StartInfo.UseShellExecute = false;
 			process.StartInfo.RedirectStandardInput = true;

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/AddinDescription.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/AddinDescription.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/AddinDescription.cs	Sun Mar  2 21:23:19 2008
@@ -43,7 +43,6 @@
 	{
 		XmlDocument configDoc;
 		string configFile;
-		bool fromBinaryFile;
 		AddinDatabase ownerDatabase;
 		
 		string id;
@@ -62,12 +61,15 @@
 		bool hasUserId;
 		bool canWrite = true;
 		bool defaultEnabled = true;
+		string domain;
 		
 		ModuleDescription mainModule;
 		ModuleCollection optionalModules;
 		ExtensionNodeSetCollection nodeSets;
 		ConditionTypeDescriptionCollection conditionTypes;
 		ExtensionPointCollection extensionPoints;
+		ExtensionNodeDescription localizer;
+		object[] fileInfo;
 		
 		internal static BinaryXmlTypeMap typeMap;
 		
@@ -86,6 +88,7 @@
 			typeMap.RegisterType (typeof(AddinDependency), "AddinDependency");
 			typeMap.RegisterType (typeof(AssemblyDependency), "AssemblyDependency");
 			typeMap.RegisterType (typeof(NodeTypeAttribute), "NodeTypeAttribute");
+			typeMap.RegisterType (typeof(AddinFileInfo), "FileInfo");
 		}
 		
 		internal AddinDatabase OwnerDatabase {
@@ -181,6 +184,12 @@
 			set { hasUserId = value; }
 		}
 		
+		internal bool SupportsVersion (string ver)
+		{
+			return Addin.CompareVersions (ver, Version) >= 0 &&
+				   (CompatVersion.Length == 0 || Addin.CompareVersions (ver, CompatVersion) <= 0);
+		}
+		
 		public StringCollection AllFiles {
 			get {
 				StringCollection col = new StringCollection ();
@@ -270,6 +279,11 @@
 			}
 		}
 		
+		public ExtensionNodeDescription Localizer {
+			get { return localizer; }
+			set { localizer = value; }
+		}
+		
 		public ExtensionPoint AddExtensionPoint (string path)
 		{
 			ExtensionPoint ep = new ExtensionPoint ();
@@ -307,7 +321,7 @@
 			foreach (Dependency dep in MainModule.Dependencies) {
 				AddinDependency adep = dep as AddinDependency;
 				if (adep == null) continue;
-				Addin ad = OwnerDatabase.GetInstalledAddin (adep.FullAddinId);
+				Addin ad = OwnerDatabase.GetInstalledAddin (Domain, adep.FullAddinId);
 				if (ad != null && ad.Description != null) {
 					ExtensionNodeDescription node = ad.Description.FindExtensionNode (path, false);
 					if (node != null)
@@ -331,6 +345,41 @@
 			set { configFile = value; }
 		}
 		
+		internal string Domain {
+			get { return domain; }
+			set { domain = value; }
+		}
+		
+		internal void StoreFileInfo ()
+		{
+			ArrayList list = new ArrayList ();
+			foreach (string f in AllFiles) {
+				string file = Path.Combine (this.BasePath, f);
+				AddinFileInfo fi = new AddinFileInfo ();
+				fi.FileName = f;
+				fi.Timestamp = File.GetLastWriteTime (file);
+				list.Add (fi);
+			}
+			fileInfo = list.ToArray ();
+		}
+		
+		internal bool FilesChanged ()
+		{
+			// Checks if the files of the add-in have changed.
+			if (fileInfo == null)
+				return true;
+			
+			foreach (AddinFileInfo f in fileInfo) {
+				string file = Path.Combine (this.BasePath, f.FileName);
+				if (!File.Exists (file))
+					return true;
+				if (f.Timestamp != File.GetLastWriteTime (file))
+					return true;
+			}
+			
+			return false;
+		}
+		
 		public void Save (string fileName)
 		{
 			configFile = fileName;
@@ -424,7 +473,16 @@
 				elem.SetAttribute ("category", category);
 			else
 				elem.RemoveAttribute ("category");
-				
+			
+			if (localizer == null || localizer.Element == null) {
+				// Remove old element if it exists
+				XmlElement oldLoc = (XmlElement) elem.SelectSingleNode ("Localizer");
+				if (oldLoc != null)
+					elem.RemoveChild (oldLoc);
+			}
+			if (localizer != null)
+				localizer.SaveXml (elem);
+			
 			if (mainModule != null) {
 				mainModule.Element = elem;
 				mainModule.SaveXml (elem);
@@ -459,7 +517,7 @@
 				config.configDoc = new XmlDocument ();
 				config.configDoc.Load (stream);
 			} catch (Exception ex) {
-				throw new InvalidOperationException ("The add-in configuration file is invalid.", ex);
+				throw new InvalidOperationException ("The add-in configuration file is invalid: " + ex.Message, ex);
 			}
 			
 			XmlElement elem = config.configDoc.DocumentElement;
@@ -482,6 +540,10 @@
 			s = elem.GetAttribute ("defaultEnabled");
 			config.defaultEnabled = s.Length == 0 || s == "true" || s == "yes";
 			
+			XmlElement localizerElem = (XmlElement) elem.SelectSingleNode ("Localizer");
+			if (localizerElem != null)
+				config.localizer = new ExtensionNodeDescription (localizerElem);
+			
 			if (config.id.Length > 0)
 				config.hasUserId = true;
 			
@@ -493,19 +555,6 @@
 			AddinDescription description = (AddinDescription) fdb.ReadSharedObject (configFile, typeMap);
 			if (description != null) {
 				description.FileName = configFile;
-				description.fromBinaryFile = true;
-				description.canWrite = !fdb.IgnoreDescriptionData;
-			}
-			return description;
-		}
-		
-		internal static AddinDescription ReadHostBinary (FileDatabase fdb, string basePath, string addinId, string addinFile)
-		{
-			string fileName;
-			AddinDescription description = (AddinDescription) fdb.ReadSharedObject (basePath, addinId, ".mroot", Util.GetFullPath (addinFile), typeMap, out fileName);
-			if (description != null) {
-				description.FileName = fileName;
-				description.fromBinaryFile = true;
 				description.canWrite = !fdb.IgnoreDescriptionData;
 			}
 			return description;
@@ -525,15 +574,6 @@
 //			BinaryXmlReader.DumpFile (configFile);
 		}
 		
-		internal void SaveHostBinary (FileDatabase fdb, string basePath)
-		{
-			if (!canWrite)
-				throw new InvalidOperationException ("Can't write incomplete description.");
-			if (!fromBinaryFile)
-				FileName = null;
-			FileName = fdb.WriteSharedObject (basePath, AddinId, ".mroot", AddinFile, FileName, typeMap, this);
-		}
-		
 		public StringCollection Verify ()
 		{
 			StringCollection errors = new StringCollection ();
@@ -541,8 +581,6 @@
 			if (IsRoot) {
 				if (OptionalModules.Count > 0)
 					errors.Add ("Root add-in hosts can't have optional modules.");
-				if (MainModule.Dependencies.Count > 0)
-					errors.Add ("Root add-in hosts can't have dependencies.");
 			}
 			
 			if (AddinId.Length == 0 || Version.Length == 0) {
@@ -577,6 +615,10 @@
 				}
 			}
 			
+			if (localizer != null && localizer.GetAttribute ("type").Length == 0) {
+				errors.Add ("The attribute 'type' in the Location element is required.");
+			}
+			
 			return errors;
 		}
 		
@@ -632,11 +674,14 @@
 			writer.WriteValue ("basePath", basePath);
 			writer.WriteValue ("sourceAddinFile", sourceAddinFile);
 			writer.WriteValue ("defaultEnabled", defaultEnabled);
+			writer.WriteValue ("domain", domain);
 			writer.WriteValue ("MainModule", MainModule);
 			writer.WriteValue ("OptionalModules", OptionalModules);
 			writer.WriteValue ("NodeSets", ExtensionNodeSets);
 			writer.WriteValue ("ExtensionPoints", ExtensionPoints);
 			writer.WriteValue ("ConditionTypes", ConditionTypes);
+			writer.WriteValue ("FilesInfo", fileInfo);
+			writer.WriteValue ("Localizer", localizer);
 		}
 		
 		void IBinaryXmlElement.Read (BinaryXmlReader reader)
@@ -656,14 +701,54 @@
 			basePath = reader.ReadStringValue ("basePath");
 			sourceAddinFile = reader.ReadStringValue ("sourceAddinFile");
 			defaultEnabled = reader.ReadBooleanValue ("defaultEnabled");
+			domain = reader.ReadStringValue ("domain");
 			mainModule = (ModuleDescription) reader.ReadValue ("MainModule");
 			optionalModules = (ModuleCollection) reader.ReadValue ("OptionalModules", new ModuleCollection (this));
 			nodeSets = (ExtensionNodeSetCollection) reader.ReadValue ("NodeSets", new ExtensionNodeSetCollection (this));
 			extensionPoints = (ExtensionPointCollection) reader.ReadValue ("ExtensionPoints", new ExtensionPointCollection (this));
 			conditionTypes = (ConditionTypeDescriptionCollection) reader.ReadValue ("ConditionTypes", new ConditionTypeDescriptionCollection (this));
+			fileInfo = (object[]) reader.ReadValue ("FilesInfo", null);
+			localizer = (ExtensionNodeDescription) reader.ReadValue ("Localizer");
 			
 			if (mainModule != null)
 				mainModule.SetParent (this);
 		}
 	}
+	
+	class AddinFileInfo: IBinaryXmlElement
+	{
+		string fileName;
+		DateTime timestamp;
+		
+		public string FileName {
+			get {
+				return fileName;
+			}
+			set {
+				fileName = value;
+			}
+		}
+
+		public System.DateTime Timestamp {
+			get {
+				return timestamp;
+			}
+			set {
+				timestamp = value;
+			}
+		}
+		
+		public void Read (BinaryXmlReader reader)
+		{
+			fileName = reader.ReadStringValue ("fileName");
+			timestamp = reader.ReadDateTimeValue ("timestamp");
+		}
+
+		public void Write (BinaryXmlWriter writer)
+		{
+			writer.WriteValue ("fileName", fileName);
+			writer.WriteValue ("timestamp", timestamp);
+		}
+
+	}
 }

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/Extension.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/Extension.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/Extension.cs	Sun Mar  2 21:23:19 2008
@@ -60,7 +60,7 @@
 				foreach (Dependency dep in desc.MainModule.Dependencies) {
 					AddinDependency adep = dep as AddinDependency;
 					if (adep == null) continue;
-					Addin ad = desc.OwnerDatabase.GetInstalledAddin (adep.FullAddinId);
+					Addin ad = desc.OwnerDatabase.GetInstalledAddin (ParentAddinDescription.Domain, adep.FullAddinId);
 					if (ad != null && ad.Description != null) {
 						ep = FindExtensionPoint (ad.Description, path);
 						if (ep != null)

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeDescription.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeDescription.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeDescription.cs	Sun Mar  2 21:23:19 2008
@@ -209,6 +209,10 @@
 			}
 		}
 		
+		NodeElementCollection NodeElement.ChildNodes {
+			get { return ChildNodes; }
+		}
+		
 		void SaveXmlAttributes ()
 		{
 			attributes = new string [Element.Attributes.Count * 2];

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeDescriptionCollection.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeDescriptionCollection.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeDescriptionCollection.cs	Sun Mar  2 21:23:19 2008
@@ -32,7 +32,7 @@
 
 namespace Mono.Addins.Description
 {
-	public class ExtensionNodeDescriptionCollection: ObjectDescriptionCollection
+	public class ExtensionNodeDescriptionCollection: ObjectDescriptionCollection, NodeElementCollection
 	{
 		public ExtensionNodeDescriptionCollection ()
 		{
@@ -54,5 +54,9 @@
 				return null;
 			}
 		}
+		
+		NodeElement NodeElementCollection.this [int n] {
+			get { return (NodeElement) List [n]; }
+		}
 	}
 }

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeSet.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeSet.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeSet.cs	Sun Mar  2 21:23:19 2008
@@ -161,7 +161,7 @@
 				string startAddin = ns [1];
 				if (startAddin == null || startAddin.Length == 0)
 					startAddin = desc.AddinId;
-				ExtensionNodeSet nset = desc.OwnerDatabase.FindNodeSet (startAddin, ns[0]);
+				ExtensionNodeSet nset = desc.OwnerDatabase.FindNodeSet (ParentAddinDescription.Domain, startAddin, ns[0]);
 				if (nset != null)
 					nset.GetAllowedNodeTypes (visitedSets, col);
 			}

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeType.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeType.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeType.cs	Sun Mar  2 21:23:19 2008
@@ -31,6 +31,7 @@
 using System.Xml;
 using System.Collections;
 using System.Collections.Specialized;
+using System.Reflection;
 using Mono.Addins.Serialization;
 
 namespace Mono.Addins.Description
@@ -50,7 +51,12 @@
 		// Cached serializable fields
 		[NonSerialized]
 		internal Hashtable Fields;
-		internal string[] RequiredFields;
+		
+		internal class FieldData {
+			public FieldInfo Field;
+			public bool Required;
+			public bool Localizable;
+		}
 		
 		// Addin where this extension type is implemented
 		internal string AddinId {

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/NodeTypeAttribute.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/NodeTypeAttribute.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Description/NodeTypeAttribute.cs	Sun Mar  2 21:23:19 2008
@@ -39,6 +39,7 @@
 		string name;
 		string type;
 		bool required;
+		bool localizable;
 		string description;
 	
 		public NodeTypeAttribute()
@@ -55,6 +56,11 @@
 			set { required = value; }
 		}
 		
+		public bool Localizable {
+			get { return localizable; }
+			set { localizable = value; }
+		}
+		
 		public string Type {
 			get { return type != null ? type : string.Empty; }
 			set { type = value; }
@@ -75,6 +81,7 @@
 			name = elem.GetAttribute ("name");
 			type = elem.GetAttribute ("type");
 			required = elem.GetAttribute ("required").ToLower () == "true";
+			localizable = elem.GetAttribute ("localizable").ToLower () == "true";
 			description = ReadXmlDescription ();
 		}
 		
@@ -93,6 +100,11 @@
 			else
 				Element.RemoveAttribute ("required");
 			
+			if (localizable)
+				Element.SetAttribute ("localizable", "True");
+			else
+				Element.RemoveAttribute ("localizable");
+			
 			SaveXmlDescription (description);
 		}
 		
@@ -102,6 +114,7 @@
 			writer.WriteValue ("type", type);
 			writer.WriteValue ("required", required);
 			writer.WriteValue ("description", description);
+			writer.WriteValue ("localizable", localizable);
 		}
 		
 		internal override void Read (BinaryXmlReader reader)
@@ -111,6 +124,7 @@
 			required = reader.ReadBooleanValue ("required");
 			if (!reader.IgnoreDescriptionData)
 				description = reader.ReadStringValue ("description");
+			localizable = reader.ReadBooleanValue ("localizable");
 		}
 	}
 }

Added: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/GettextDomain.cs
==============================================================================
--- (empty file)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/GettextDomain.cs	Sun Mar  2 21:23:19 2008
@@ -0,0 +1,140 @@
+//
+// GettextDomain.cs: Wrappers for the libintl library.
+//
+// Authors:
+//   Edd Dumbill (edd usefulinc com)
+//   Jonathan Pryor (jonpryor vt edu)
+//   Lluis Sanchez Gual (lluis novell com)
+//
+// (C) 2004 Edd Dumbill
+// (C) 2005-2006 Jonathan Pryor
+// 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.Runtime.InteropServices;
+using System.IO;
+using System.Text;
+
+namespace Mono.Addins.Localization
+{
+	class GettextDomain
+	{
+		[DllImport("intl")]
+		static extern IntPtr bindtextdomain (IntPtr domainname, IntPtr dirname);
+		[DllImport("intl")]
+		static extern IntPtr bind_textdomain_codeset (IntPtr domainname, IntPtr codeset);
+		[DllImport("intl")]
+		static extern IntPtr dgettext (IntPtr domainname, IntPtr instring);
+		[DllImport("intl")]
+		static extern IntPtr dngettext (IntPtr domainname, IntPtr instring, IntPtr plural, int n);
+		
+		IntPtr ipackage;
+		
+		public void Init (String package, string localedir)
+		{
+			if (localedir == null) {
+				localedir = System.Reflection.Assembly.GetEntryAssembly ().CodeBase;
+				FileInfo f = new FileInfo (localedir);
+				string prefix = f.Directory.Parent.Parent.Parent.ToString ();
+				prefix = Path.Combine (Path.Combine (prefix, "share"), "locale");
+			}
+			
+			ipackage = StringToPtr (package);
+			IntPtr ilocaledir = StringToPtr (localedir);
+			IntPtr iutf8 = StringToPtr ("UTF-8");
+			
+			try {
+				if (bindtextdomain (ipackage, ilocaledir) == IntPtr.Zero)
+					throw new InvalidOperationException ("Gettext localizer: bindtextdomain failed");
+				if (bind_textdomain_codeset (ipackage, iutf8) == IntPtr.Zero)
+					throw new InvalidOperationException ("Gettext localizer: bind_textdomain_codeset failed");
+			}
+			finally {
+				Marshal.FreeHGlobal (ilocaledir);
+				Marshal.FreeHGlobal (iutf8);
+			}
+		}
+		
+		~GettextDomain ()
+		{
+			Marshal.FreeHGlobal (ipackage);
+		}
+
+		public String GetString (String s)
+		{
+			IntPtr ints = StringToPtr (s);
+			try {
+				// gettext(3) returns the input pointer if no translation is found
+				IntPtr r = dgettext (ipackage, ints);
+				if (r != ints)
+					return PtrToString (r);
+				return s;
+			}
+			finally {
+				Marshal.FreeHGlobal (ints);
+			}
+		}
+		
+		public String GetPluralString (String singular, String defaultPlural, int n)
+		{
+			IntPtr ints = StringToPtr (singular);
+			IntPtr intp = StringToPtr (defaultPlural);
+			try {
+				// gettext(3) returns the input pointer if no translation is found
+				IntPtr r = dngettext (ipackage, ints, intp, n);
+				if (r == ints)
+					return singular;
+				if (r == intp)
+					return defaultPlural;
+				return PtrToString (r);
+			}
+			finally {
+				Marshal.FreeHGlobal (ints);
+				Marshal.FreeHGlobal (intp);
+			}
+		}
+		
+		static IntPtr StringToPtr (string s)
+		{
+			if (s == null)
+				return IntPtr.Zero;
+            byte[] marshal = Encoding.UTF8.GetBytes (s);
+            IntPtr mem = Marshal.AllocHGlobal (marshal.Length + 1);
+            Marshal.Copy (marshal, 0, mem, marshal.Length);
+            Marshal.WriteByte (mem, marshal.Length, 0);
+            return mem;		
+		}
+		
+		static string PtrToString (IntPtr ptr)
+		{
+            if (ptr == IntPtr.Zero)
+                return null;
+			int sz = 0;
+			while (Marshal.ReadByte (ptr, sz) != 0)
+				sz++;
+            byte[] bytes = new byte [sz];
+            Marshal.Copy (ptr, bytes, 0, sz);
+            return Encoding.UTF8.GetString (bytes);
+		}
+	}
+}

Added: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/GettextLocalizer.cs
==============================================================================
--- (empty file)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/GettextLocalizer.cs	Sun Mar  2 21:23:19 2008
@@ -0,0 +1,62 @@
+// GettextLocalizer.cs
+//
+// Author:
+//   Lluis Sanchez Gual
+//
+// 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 Mono.Addins;
+
+namespace Mono.Addins.Localization
+{
+	class GettextLocalizer: IAddinLocalizerFactory, IAddinLocalizer, IPluralAddinLocalizer
+	{
+		GettextDomain domain;
+		
+		public IAddinLocalizer CreateLocalizer (RuntimeAddin addin, NodeElement element)
+		{
+			string pkg = element.GetAttribute ("catalog");
+			if (pkg.Length == 0)
+				pkg = addin.Id;
+			string dir = element.GetAttribute ("location");
+			if (dir.Length == 0)
+				dir = "locale";
+			dir = addin.GetFilePath (dir);
+			domain = new GettextDomain ();
+			domain.Init (pkg, dir);
+			return this;
+		}
+
+		public string GetString (string msgid)
+		{
+			return domain.GetString (msgid);
+		}
+		
+		public string GetPluralString (string singular, string defaultPlural, int n)
+		{
+			return domain.GetPluralString (singular, defaultPlural, n);
+		}
+
+	}
+}

Added: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/IAddinLocalizer.cs
==============================================================================
--- (empty file)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/IAddinLocalizer.cs	Sun Mar  2 21:23:19 2008
@@ -0,0 +1,37 @@
+//
+// IAddinLocalizer.cs
+//
+// Author:
+//   Lluis Sanchez Gual
+//
+// 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;
+
+namespace Mono.Addins.Localization
+{
+	public interface IAddinLocalizer
+	{
+		string GetString (string msgid);
+	}
+}

Added: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/IAddinLocalizerFactory.cs
==============================================================================
--- (empty file)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/IAddinLocalizerFactory.cs	Sun Mar  2 21:23:19 2008
@@ -0,0 +1,37 @@
+//
+// IAddinLocalizerFactory.cs
+//
+// Author:
+//   Lluis Sanchez Gual
+//
+// 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;
+
+namespace Mono.Addins.Localization
+{
+	public interface IAddinLocalizerFactory
+	{
+		IAddinLocalizer CreateLocalizer (RuntimeAddin addin, NodeElement element);
+	}
+}

Added: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/IPluralAddinLocalizer.cs
==============================================================================
--- (empty file)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/IPluralAddinLocalizer.cs	Sun Mar  2 21:23:19 2008
@@ -0,0 +1,36 @@
+// IPluralAddinLocalizer.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis novell com>
+//
+// 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;
+
+namespace Mono.Addins.Localization
+{
+	public interface IPluralAddinLocalizer
+	{
+		string GetPluralString (string singular, String defaultPlural, int n);
+	}
+}

Added: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/NullLocalizer.cs
==============================================================================
--- (empty file)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/NullLocalizer.cs	Sun Mar  2 21:23:19 2008
@@ -0,0 +1,41 @@
+// NullLocalizer.cs
+//
+// Author:
+//   Lluis Sanchez Gual
+//
+// 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;
+
+namespace Mono.Addins.Localization
+{
+	class NullLocalizer: IAddinLocalizer
+	{
+		public static AddinLocalizer Instance = new AddinLocalizer (new NullLocalizer ());
+		
+		public string GetString (string msgid)
+		{
+			return msgid;
+		}
+	}
+}

Added: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/StringResourceLocalizer.cs
==============================================================================
--- (empty file)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/StringResourceLocalizer.cs	Sun Mar  2 21:23:19 2008
@@ -0,0 +1,52 @@
+// StringResourceLocalizer.cs
+//
+// Author:
+//   Lluis Sanchez Gual
+//
+// 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 Mono.Addins;
+
+namespace Mono.Addins.Localization
+{
+	class StringResourceLocalizer: IAddinLocalizerFactory, IAddinLocalizer
+	{
+		RuntimeAddin addin;
+		
+		public IAddinLocalizer CreateLocalizer (RuntimeAddin addin, NodeElement element)
+		{
+			this.addin = addin;
+			return this;
+		}
+
+		public string GetString (string msgid)
+		{
+			string s = addin.GetResourceString (msgid, false, System.Threading.Thread.CurrentThread.CurrentCulture);
+			if (s == null)
+				return msgid;
+			else
+				return s;
+		}
+	}
+}

Added: trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/StringTableLocalizer.cs
==============================================================================
--- (empty file)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins.Localization/StringTableLocalizer.cs	Sun Mar  2 21:23:19 2008
@@ -0,0 +1,95 @@
+// StringTableLocalizer.cs
+//
+// Author:
+//   Lluis Sanchez Gual
+//
+// 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;
+using Mono.Addins;
+
+namespace Mono.Addins.Localization
+{
+	class StringTableLocalizer: IAddinLocalizerFactory, IAddinLocalizer
+	{
+		Hashtable locales = new Hashtable ();
+		static Hashtable nullLocale = new Hashtable ();
+		
+		public IAddinLocalizer CreateLocalizer (RuntimeAddin addin, NodeElement element)
+		{
+			foreach (NodeElement nloc in element.ChildNodes) {
+				if (nloc.NodeName != "Locale")
+					throw new InvalidOperationException ("Invalid element found: '" + nloc.NodeName + "'. Expected: 'Locale'");
+				string ln = nloc.GetAttribute ("id");
+				if (ln.Length == 0)
+					throw new InvalidOperationException ("Locale id not specified");
+				ln = ln.Replace ('_','-');
+				Hashtable messages = new Hashtable ();
+				foreach (NodeElement nmsg in nloc.ChildNodes) {
+					if (nmsg.NodeName != "Msg")
+						throw new InvalidOperationException ("Locale '" + ln + "': Invalid element found: '" + nmsg.NodeName + "'. Expected: 'Msg'");
+					string id = nmsg.GetAttribute ("id");
+					if (id.Length == 0)
+						throw new InvalidOperationException ("Locale '" + ln + "': Message id not specified");
+					messages [id] = nmsg.GetAttribute ("str");
+				}
+				locales [ln] = messages;
+			}
+			return this;
+		}
+		
+		public string GetString (string id)
+		{
+			string cname = System.Threading.Thread.CurrentThread.CurrentCulture.Name;
+			Hashtable loc = (Hashtable) locales [cname];
+			if (loc == null) {
+				string sn = cname.Substring (0, 2);
+				loc = (Hashtable) locales [sn];
+				if (loc != null)
+					locales [cname] = loc;
+				else {
+					locales [cname] = nullLocale;
+					return id;
+				}
+			}
+			string msg = (string) loc [id];
+			if (msg == null) {
+				if (cname.Length > 2) {
+					// Try again without the country
+					cname = cname.Substring (0, 2);
+					loc = (Hashtable) locales [cname];
+					if (loc != null) {
+						msg = (string) loc [id];
+						if (msg != null)
+							return msg;
+					}
+				}
+				return id;
+			}
+			else
+				return msg;
+		}
+	}
+}
+

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/Addin.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/Addin.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/Addin.cs	Sun Mar  2 21:23:19 2008
@@ -42,7 +42,6 @@
 		AddinInfo addin;
 		string configFile;
 		string sourceFile;
-		string hostId;
 		WeakReference desc;
 		AddinDatabase database;
 		
@@ -52,15 +51,12 @@
 			configFile = file;
 		}
 		
-		internal Addin (AddinDatabase database, string hostId, string hostSourceFile)
-		{
-			this.database = database;
-			this.hostId = hostId;
-			this.sourceFile = hostSourceFile;
-		}
-		
 		public string Id {
-			get { return this.AddinInfo.Id; }
+			get {
+				if (configFile != null)
+					return Path.GetFileNameWithoutExtension (configFile);
+				return this.AddinInfo.Id; 
+			}
 		}
 		
 		public string Namespace {
@@ -88,6 +84,11 @@
 			return AddinInfo.SupportsVersion (version);
 		}
 		
+		public override string ToString ()
+		{
+			return Id;
+		}
+		
 		internal AddinInfo AddinInfo {
 			get {
 				if (addin == null) {
@@ -102,12 +103,12 @@
 		}
 		
 		public bool Enabled {
-			get { return AddinInfo.IsRoot ? true : database.IsAddinEnabled (AddinInfo.Id, true); }
+			get { return AddinInfo.IsRoot ? true : database.IsAddinEnabled (Description.Domain, AddinInfo.Id, true); }
 			set {
 				if (value)
-					database.EnableAddin (AddinInfo.Id, true);
+					database.EnableAddin (Description.Domain, AddinInfo.Id, true);
 				else
-					database.DisableAddin (AddinInfo.Id);
+					database.DisableAddin (Description.Domain, AddinInfo.Id);
 			}
 		}
 		
@@ -143,13 +144,9 @@
 					if (d != null)
 						return d;
 				}
-				
+
 				AddinDescription m;
-				
-				if (hostId != null)
-					database.GetHostDescription (null, hostId, sourceFile, out m);
-				else
-					database.ReadAddinDescription (null, configFile, out m);
+				database.ReadAddinDescription (null, configFile, out m);
 				
 				if (m == null)
 					throw new InvalidOperationException ("Could not read add-in description");
@@ -162,15 +159,17 @@
 			}
 		}
 			
-		
+		// returns -1 if v1 > v2
 		public static int CompareVersions (string v1, string v2)
 		{
 			string[] a1 = v1.Split ('.');
 			string[] a2 = v2.Split ('.');
 			
 			for (int n=0; n<a1.Length; n++) {
-				if (a1[n] == "") {
-					if (a2[n] != "")
+				if (n >= a2.Length)
+					return -1;
+				if (a1[n].Length == 0) {
+					if (a2[n].Length != 0)
 						return 1;
 					continue;
 				}
@@ -185,6 +184,8 @@
 					return 1;
 				}
 			}
+			if (a2.Length > a1.Length)
+				return 1;
 			return 0;
 		}
 		

Added: trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinLocalizer.cs
==============================================================================
--- (empty file)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinLocalizer.cs	Sun Mar  2 21:23:19 2008
@@ -0,0 +1,72 @@
+//
+// AddinLocalizer.cs
+//
+// Author:
+//   Lluis Sanchez Gual
+//
+// 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 Mono.Addins.Localization;
+
+namespace Mono.Addins
+{
+	public class AddinLocalizer
+	{
+		IAddinLocalizer localizer;
+		IPluralAddinLocalizer pluralLocalizer;
+		
+		internal AddinLocalizer (IAddinLocalizer localizer)
+		{
+			this.localizer = localizer;
+			pluralLocalizer = localizer as IPluralAddinLocalizer;
+		}
+		
+		public string GetString (string msgid)
+		{
+			return localizer.GetString (msgid);
+		}
+		
+		public string GetString (string msgid, params string[] args)
+		{
+			return string.Format (localizer.GetString (msgid), args);
+		}
+		
+		public string GetPluralString (string msgid, string defaultPlural, int n)
+		{
+			// If the localizer does not support plural forms, just use GetString to
+			// get a translation. It is not correct to check 'n' in this case because
+			// there is no guarantee that 'defaultPlural' will be translated.
+			
+			if (pluralLocalizer != null)
+				return pluralLocalizer.GetPluralString (msgid, defaultPlural, n);
+			else
+				return GetString (msgid);
+		}
+		
+		public string GetPluralString (string singular, string defaultPlural, int n, params string[] args)
+		{
+			return string.Format (GetPluralString (singular, defaultPlural, n), args);
+		}
+	}
+}

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinManager.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinManager.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinManager.cs	Sun Mar  2 21:23:19 2008
@@ -31,7 +31,7 @@
 using System.Reflection;
 using System.Collections;
 
-using Mono.Addins;
+using Mono.Addins.Localization;
 
 namespace Mono.Addins
 {
@@ -43,7 +43,7 @@
 		static string startupDirectory;
 		static bool initialized;
 		static IAddinInstaller installer;
-		
+
 		public static event AddinErrorEventHandler AddinLoadError;
 		public static event AddinEventHandler AddinLoaded;
 		public static event AddinEventHandler AddinUnloaded;
@@ -62,8 +62,11 @@
 			if (initialized)
 				return;
 			
-			startupDirectory = new Uri (Assembly.GetCallingAssembly ().CodeBase).LocalPath;
-			startupDirectory = Path.GetDirectoryName (startupDirectory);
+			Assembly asm = Assembly.GetEntryAssembly ();
+			if (asm == null) asm = Assembly.GetCallingAssembly ();
+			string asmFile = new Uri (asm.CodeBase).LocalPath;
+			
+			startupDirectory = Path.GetDirectoryName (asmFile);
 			
 			string customDir = Environment.GetEnvironmentVariable ("MONO_ADDINS_REGISTRY");
 			if (customDir != null && customDir.Length > 0)
@@ -74,9 +77,6 @@
 			else
 				registry = new AddinRegistry (configDir, startupDirectory);
 
-			Assembly asm = Assembly.GetEntryAssembly ();
-			if (asm == null) asm = Assembly.GetCallingAssembly ();
-			string asmFile = new Uri (asm.CodeBase).LocalPath;
 			if (registry.CreateHostAddinsFile (asmFile))
 				registry.Update (new ConsoleProgressStatus (false));
 			
@@ -94,6 +94,12 @@
 			initialized = false;
 		}
 		
+		public static void InitializeDefaultLocalizer (IAddinLocalizer localizer)
+		{
+			CheckInitialized ();
+			SessionService.InitializeDefaultLocalizer (localizer);
+		}
+		
 		internal static string StartupDirectory {
 			get { return startupDirectory; }
 		}
@@ -107,6 +113,31 @@
 			set { installer = value; }
 		}
 		
+		public static AddinLocalizer DefaultLocalizer {
+			get {
+				CheckInitialized ();
+				return SessionService.DefaultLocalizer;
+			}
+		}
+		
+		public static AddinLocalizer CurrentLocalizer {
+			get {
+				CheckInitialized ();
+				RuntimeAddin addin = SessionService.GetAddinForAssembly (Assembly.GetCallingAssembly ());
+				if (addin != null)
+					return addin.Localizer;
+				else
+					return SessionService.DefaultLocalizer;
+			}
+		}
+		
+		public static RuntimeAddin CurrentAddin {
+			get {
+				CheckInitialized ();
+				return SessionService.GetAddinForAssembly (Assembly.GetCallingAssembly ());
+			}
+		}
+		
 		internal static AddinSessionService SessionService {
 			get {
 				if (sessionService == null)
@@ -250,8 +281,11 @@
 		{
 			if (AddinLoadError != null)
 				AddinLoadError (null, new AddinErrorEventArgs (message, addinId, exception));
-			else
+			else {
 				Console.WriteLine (message);
+				if (exception != null)
+					Console.WriteLine (exception);
+			}
 		}
 		
 		internal static void ReportAddinLoad (string id)

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinRegistry.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinRegistry.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinRegistry.cs	Sun Mar  2 21:23:19 2008
@@ -42,17 +42,30 @@
 		AddinDatabase database;
 		StringCollection addinDirs;
 		string basePath;
+		string currentDomain;
+		string startupDirectory;
 		
 		public AddinRegistry (string registryPath): this (registryPath, null)
 		{
 		}
 		
-		internal AddinRegistry (string registryPath, string startupDirectory)
+		public AddinRegistry (string registryPath, string startupDirectory)
 		{
 			basePath = Util.GetFullPath (registryPath);
 			database = new AddinDatabase (this);
+
+			// Look for add-ins in the hosts directory and in the default
+			// addins directory
 			addinDirs = new StringCollection ();
-			addinDirs.Add (Path.Combine (basePath, "addins"));
+			addinDirs.Add (database.HostsPath);
+			addinDirs.Add (DefaultAddinsFolder);
+			
+			// Get the domain corresponding to the startup folder
+			if (startupDirectory != null) {
+				this.startupDirectory = startupDirectory;
+				currentDomain = database.GetFolderDomain (null, startupDirectory);
+			} else
+				currentDomain = AddinDatabase.GlobalDomain;
 		}
 		
 		public static AddinRegistry GetGlobalRegistry ()
@@ -96,23 +109,23 @@
 		
 		public Addin GetAddin (string id)
 		{
-			return database.GetInstalledAddin (id);
+			return database.GetInstalledAddin (currentDomain, id);
 		}
 		
 		public Addin GetAddin (string id, bool exactVersionMatch)
 		{
-			return database.GetInstalledAddin (id, exactVersionMatch);
+			return database.GetInstalledAddin (currentDomain, id, exactVersionMatch);
 		}
 		
 		public Addin[] GetAddins ()
 		{
-			ArrayList list = database.GetInstalledAddins ();
+			ArrayList list = database.GetInstalledAddins (currentDomain, AddinType.Addin);
 			return (Addin[]) list.ToArray (typeof(Addin));
 		}
 		
 		public Addin[] GetAddinRoots ()
 		{
-			ArrayList list = database.GetAddinRoots ();
+			ArrayList list = database.GetInstalledAddins (currentDomain, AddinType.Root);
 			return (Addin[]) list.ToArray (typeof(Addin));
 		}
 		
@@ -153,17 +166,17 @@
 		
 		public bool IsAddinEnabled (string id)
 		{
-			return database.IsAddinEnabled (id);
+			return database.IsAddinEnabled (currentDomain, id);
 		}
 		
 		public void EnableAddin (string id)
 		{
-			database.EnableAddin (id, true);
+			database.EnableAddin (currentDomain, id, true);
 		}
 		
 		public void DisableAddin (string id)
 		{
-			database.DisableAddin (id);
+			database.DisableAddin (currentDomain, id);
 		}
 		
 		public void DumpFile (string file)
@@ -175,25 +188,31 @@
 		{
 			database.ResetConfiguration ();
 		}
+		
+		internal void NotifyDatabaseUpdated ()
+		{
+			if (startupDirectory != null)
+				currentDomain = database.GetFolderDomain (null, startupDirectory);
+		}
 
 		public void Update (IProgressStatus monitor)
 		{
-			database.Update (monitor);
+			database.Update (monitor, currentDomain);
 		}
 
 		public void Rebuild (IProgressStatus monitor)
 		{
-			database.Repair (monitor);
+			database.Repair (monitor, currentDomain);
 		}
 		
 		internal Addin GetAddinForHostAssembly (string filePath)
 		{
-			return database.GetAddinForHostAssembly (filePath);
+			return database.GetAddinForHostAssembly (currentDomain, filePath);
 		}
 		
 		internal bool AddinDependsOn (string id1, string id2)
 		{
-			return database.AddinDependsOn (id1, id2);
+			return database.AddinDependsOn (currentDomain, id1, id2);
 		}
 		
 		internal void ScanFolders (IProgressStatus monitor, string folderToScan, StringCollection filesToIgnore)
@@ -218,10 +237,10 @@
 		{
 			hostFile = Util.GetFullPath (hostFile);
 			string baseName = Path.GetFileNameWithoutExtension (hostFile);
-			if (!Directory.Exists (DefaultAddinsFolder))
-				Directory.CreateDirectory (DefaultAddinsFolder);
+			if (!Directory.Exists (database.HostsPath))
+				Directory.CreateDirectory (database.HostsPath);
 			
-			foreach (string s in Directory.GetFiles (DefaultAddinsFolder, baseName + "*.host.addins")) {
+			foreach (string s in Directory.GetFiles (database.HostsPath, baseName + "*.addins")) {
 				try {
 					using (StreamReader sr = new StreamReader (s)) {
 						XmlTextReader tr = new XmlTextReader (sr);
@@ -236,10 +255,10 @@
 				}
 			}
 			
-			string file = Path.Combine (DefaultAddinsFolder, baseName) + ".host.addins";
+			string file = Path.Combine (database.HostsPath, baseName) + ".addins";
 			int n=1;
 			while (File.Exists (file)) {
-				file = Path.Combine (DefaultAddinsFolder, baseName) + "_" + n + ".host.addins";
+				file = Path.Combine (database.HostsPath, baseName) + "_" + n + ".addins";
 				n++;
 			}
 			
@@ -248,11 +267,39 @@
 				tw.Formatting = Formatting.Indented;
 				tw.WriteStartElement ("Addins");
 				tw.WriteAttributeString ("host-reference", hostFile);
-				tw.WriteElementString ("Directory", Path.GetDirectoryName (hostFile));
+				tw.WriteStartElement ("Directory");
+				tw.WriteAttributeString ("shared", "false");
+				tw.WriteString (Path.GetDirectoryName (hostFile));
 				tw.WriteEndElement ();
 				tw.Close ();
 			}
 			return true;
 		}
+		
+		internal static string[] GetRegisteredStartupFolders (string registryPath)
+		{
+			string dbDir = Path.Combine (registryPath, "addin-db-" + AddinDatabase.VersionTag);
+			dbDir = Path.Combine (dbDir, "hosts");
+			
+			if (!Directory.Exists (dbDir))
+				return new string [0];
+			
+			ArrayList dirs = new ArrayList ();
+			
+			foreach (string s in Directory.GetFiles (dbDir, "*.addins")) {
+				try {
+					using (StreamReader sr = new StreamReader (s)) {
+						XmlTextReader tr = new XmlTextReader (sr);
+						tr.MoveToContent ();
+						string host = tr.GetAttribute ("host-reference");
+						dirs.Add (Path.GetDirectoryName (host));
+					}
+				}
+				catch {
+					// Ignore this file
+				}
+			}
+			return (string[]) dirs.ToArray (typeof(string));
+		}
 	}
 }

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinSessionService.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinSessionService.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/AddinSessionService.cs	Sun Mar  2 21:23:19 2008
@@ -34,6 +34,7 @@
 
 using Mono.Addins.Description;
 using Mono.Addins.Database;
+using Mono.Addins.Localization;
 
 namespace Mono.Addins
 {
@@ -44,6 +45,8 @@
 		ExtensionContext defaultContext;
 		Hashtable nodeSets = new Hashtable ();
 		Hashtable autoExtensionTypes = new Hashtable ();
+		Hashtable loadedAssemblies = new Hashtable ();
+		AddinLocalizer defaultLocalizer;
 		
 		internal void Initialize ()
 		{
@@ -57,13 +60,54 @@
 			AppDomain.CurrentDomain.AssemblyLoad -= new AssemblyLoadEventHandler (OnAssemblyLoaded);
 			defaultContext = null;
 			loadedAddins.Clear ();
+			loadedAssemblies.Clear ();
 			defaultContext = null;
 		}
 		
+		public void InitializeDefaultLocalizer (IAddinLocalizer localizer)
+		{
+			if (localizer != null)
+				defaultLocalizer = new AddinLocalizer (localizer);
+			else
+				defaultLocalizer = null;
+		}
+		
+		public AddinLocalizer DefaultLocalizer {
+			get {
+				if (defaultLocalizer != null)
+					return defaultLocalizer; 
+				else
+					return NullLocalizer.Instance;
+			}
+		}
+		
 		internal ExtensionContext DefaultContext {
 			get { return defaultContext; }
 		}
 		
+		public AddinLocalizer CurrentLocalizer {
+			get {
+				Assembly asm = Assembly.GetCallingAssembly ();
+				RuntimeAddin addin = GetAddinForAssembly (asm);
+				if (addin != null)
+					return addin.Localizer;
+				else
+					return DefaultLocalizer;
+			}
+		}
+		
+		public RuntimeAddin CurrentAddin {
+			get {
+				Assembly asm = Assembly.GetCallingAssembly ();
+				return GetAddinForAssembly (asm);
+			}
+		}
+		
+		internal RuntimeAddin GetAddinForAssembly (Assembly asm)
+		{
+			return (RuntimeAddin) loadedAssemblies [asm];
+		}
+		
 		// Enables or disables conflict checking while loading assemblies.
 		// Disabling makes loading faster, but less safe.
 		public bool CheckAssemblyLoadConflicts {
@@ -94,6 +138,8 @@
 			if (addin != null) {
 				addin.UnloadExtensions ();
 				loadedAddins.Remove (Addin.GetIdName (id));
+				foreach (Assembly asm in addin.Assemblies)
+					loadedAssemblies.Remove (asm);
 				AddinManager.ReportAddinUnload (id);
 			}
 		}
@@ -174,6 +220,9 @@
 				foreach (ExtensionPoint ep in description.ExtensionPoints)
 					InsertExtensionPoint (p, ep);
 				
+				foreach (Assembly asm in p.Assemblies)
+					loadedAssemblies [asm] = p;
+				
 				// Fire loaded event
 				defaultContext.NotifyAddinLoaded (p);
 				AddinManager.ReportAddinLoad (p.Id);
@@ -327,8 +376,18 @@
 				return;
 			string asmFile = new Uri (asm.CodeBase).LocalPath;
 			Addin ainfo = AddinManager.Registry.GetAddinForHostAssembly (asmFile);
-			if (ainfo != null && !IsAddinLoaded (ainfo.Id))
-				InsertAddin (null, ainfo);
+			if (ainfo != null && !IsAddinLoaded (ainfo.Id)) {
+				if (ainfo.Description.FilesChanged ()) {
+					// If the add-in has changed, update the add-in database.
+					// We do it here because once loaded, add-in roots can't be
+					// reloaded like regular add-ins.
+					AddinManager.Registry.Update (null);
+					ainfo = AddinManager.Registry.GetAddinForHostAssembly (asmFile);
+					if (ainfo == null)
+						return;
+				}
+				LoadAddin (null, ainfo.Id, false);
+			}
 		}
 	}
 		

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionContext.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionContext.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionContext.cs	Sun Mar  2 21:23:19 2008
@@ -29,6 +29,7 @@
 
 using System;
 using System.Collections;
+using System.Collections.Specialized;
 using Mono.Addins.Description;
 
 namespace Mono.Addins
@@ -42,6 +43,9 @@
 		ExtensionTree tree;
 		bool fireEvents = false;
 		
+		ArrayList runTimeEnabledAddins;
+		ArrayList runTimeDisabledAddins;
+		
 		public event ExtensionEventHandler ExtensionChanged;
 		
 		~ExtensionContext ()
@@ -372,12 +376,15 @@
 					AddinManager.ReportError ("Required add-in not found", id, null, false);
 					return;
 				}
+				// Take note that his add-in has been enabled at run-time
+				// Needed because loaded add-in descriptions may not include this add-in. 
+				RegisterRuntimeEnabledAddin (id);
 				
 				// Look for loaded extension points
 				Hashtable eps = new Hashtable ();
 				foreach (ModuleDescription mod in addin.Description.AllModules) {
 					foreach (Extension ext in mod.Extensions) {
-						ExtensionPoint ep = tree.FindExtensionPoint (ext.Path);
+						ExtensionPoint ep = tree.FindLoadedExtensionPoint (ext.Path);
 						if (ep != null && !eps.Contains (ep))
 							eps.Add (ep, ep);
 					}
@@ -426,6 +433,10 @@
 		internal void RemoveAddinExtensions (string id)
 		{
 			try {
+				// Registers this add-in as disabled, so from now on extension from this
+				// add-in will be ignored
+				RegisterRuntimeDisabledAddin (id);
+				
 				fireEvents = true;
 
 				// This method removes all extension nodes added by the add-in
@@ -457,6 +468,55 @@
 			}
 		}
 		
+		void RegisterRuntimeDisabledAddin (string addinId)
+		{
+			if (runTimeDisabledAddins == null)
+				runTimeDisabledAddins = new ArrayList ();
+			if (!runTimeDisabledAddins.Contains (addinId))
+				runTimeDisabledAddins.Add (addinId);
+			
+			if (runTimeEnabledAddins != null)
+				runTimeEnabledAddins.Remove (addinId);
+		}
+		
+		void RegisterRuntimeEnabledAddin (string addinId)
+		{
+			if (runTimeEnabledAddins == null)
+				runTimeEnabledAddins = new ArrayList ();
+			if (!runTimeEnabledAddins.Contains (addinId))
+				runTimeEnabledAddins.Add (addinId);
+			
+			if (runTimeDisabledAddins != null)
+				runTimeDisabledAddins.Remove (addinId);
+		}
+		
+		internal ICollection GetAddinsForPath (string path, StringCollection col)
+		{
+			ArrayList newlist = null;
+			
+			// Always consider add-ins which have been enabled at runtime since
+			// they may contain extensioin for this path.
+			// Ignore addins disabled at run-time.
+			
+			if (runTimeEnabledAddins != null && runTimeEnabledAddins.Count > 0) {
+				newlist = new ArrayList ();
+				newlist.AddRange (col);
+				foreach (string s in runTimeEnabledAddins)
+					if (!newlist.Contains (s))
+						newlist.Add (s);
+			}
+			
+			if (runTimeDisabledAddins != null && runTimeDisabledAddins.Count > 0) {
+				if (newlist == null) {
+					newlist = new ArrayList ();
+					newlist.AddRange (col);
+				}
+				foreach (string s in runTimeDisabledAddins)
+					newlist.Remove (s);
+			}
+			
+			return newlist != null ? (ICollection)newlist : (ICollection)col;
+		}
 		
 		// Load the extension nodes at the specified path. If the path
 		// contains extension nodes implemented in an add-in which is
@@ -477,7 +537,7 @@
 				
 				ArrayList loadData = new ArrayList ();
 				
-				foreach (string addin in ep.Addins) {
+				foreach (string addin in GetAddinsForPath (ep.Path, ep.Addins)) {
 					ExtensionLoadData ed = GetAddinExtensions (addin, ep);
 					if (ed != null) {
 						// Insert the addin data taking into account dependencies.
@@ -652,7 +712,6 @@
 		{
 			return tree.FindExtensionPathByType (monitor, type, nodeName, out path, out pathNodeName);
 		}
-		
 	}
 	
 	class ConditionInfo

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionNode.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionNode.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionNode.cs	Sun Mar  2 21:23:19 2008
@@ -53,6 +53,19 @@
 			get { return treeNode != null ? treeNode.GetPath () : string.Empty; }
 		}
 		
+		public ExtensionNode Parent {
+			get {
+				if (treeNode != null && treeNode.Parent != null)
+					return treeNode.Parent.ExtensionNode;
+				else
+					return null;
+			}
+		}
+		
+		public ExtensionContext ExtensionContext {
+			get { return treeNode.Context; }
+		}
+		
 		public bool HasId {
 			get { return !Id.StartsWith (ExtensionTree.AutoIdPrefix); }
 		}
@@ -92,8 +105,13 @@
 		public event ExtensionNodeEventHandler ExtensionNodeChanged {
 			add {
 				extensionNodeChanged += value;
-				foreach (ExtensionNode node in ChildNodes)
-					extensionNodeChanged (this, new ExtensionNodeEventArgs (ExtensionChange.Add, node));
+				foreach (ExtensionNode node in ChildNodes) {
+					try {
+						extensionNodeChanged (this, new ExtensionNodeEventArgs (ExtensionChange.Add, node));
+					} catch (Exception ex) {
+						AddinManager.ReportError (null, null, ex, false);
+					}
+				}
 			}
 			remove {
 				extensionNodeChanged -= value;
@@ -186,29 +204,25 @@
 				return;
 
 			NodeAttribute[] attributes = elem.Attributes;
-			string[] required = nodeType.RequiredFields != null ? (string[]) nodeType.RequiredFields.Clone () : null;
-			int nreq = required != null ? required.Length : 0;
+			Hashtable fields = (Hashtable) nodeType.Fields.Clone ();
 			
 			foreach (NodeAttribute at in attributes) {
 				
-				FieldInfo f = (FieldInfo) nodeType.Fields [at.name];
+				ExtensionNodeType.FieldData f = (ExtensionNodeType.FieldData) fields [at.name];
 				if (f == null)
 					continue;
-					
-				if (required != null) {
-					int i = Array.IndexOf (required, at.name);
-					if (i != -1) {
-						required [i] = null;
-						nreq--;
-					}
-				}
+				
+				fields.Remove (at.name);
 					
 				object val;
 
-				if (f.FieldType == typeof(string)) {
-					val = at.value;
+				if (f.Field.FieldType == typeof(string)) {
+					if (f.Localizable)
+						val = Addin.Localizer.GetString (at.value);
+					else
+						val = at.value;
 				}
-				else if (f.FieldType == typeof(string[])) {
+				else if (f.Field.FieldType == typeof(string[])) {
 					string[] ss = at.value.Split (',');
 					if (ss.Length == 0 && ss[0].Length == 0)
 						val = new string [0];
@@ -218,23 +232,27 @@
 						val = ss;
 					}
 				}
-				else if (f.FieldType.IsEnum) {
-					val = Enum.Parse (f.FieldType, at.value);
+				else if (f.Field.FieldType.IsEnum) {
+					val = Enum.Parse (f.Field.FieldType, at.value);
 				}
 				else {
 					try {
-						val = Convert.ChangeType (at.Value, f.FieldType);
+						val = Convert.ChangeType (at.Value, f.Field.FieldType);
 					} catch (InvalidCastException) {
-						throw new InvalidOperationException ("Property type not supported by [NodeAttribute]: " + f.DeclaringType + "." + f.Name);
+						throw new InvalidOperationException ("Property type not supported by [NodeAttribute]: " + f.Field.DeclaringType + "." + f.Field.Name);
 					}
 				}
 					
-				f.SetValue (this, val);
+				f.Field.SetValue (this, val);
 			}
-			if (nreq > 0) {
-				foreach (string s in required)
-					if (s != null)
-						throw new InvalidOperationException ("Required attribute '" + s + "' not found.");
+			
+			if (fields.Count > 0) {
+				// Check if one of the remaining fields is mandatory
+				foreach (DictionaryEntry e in fields) {
+					ExtensionNodeType.FieldData f = (ExtensionNodeType.FieldData) e.Value;
+					if (f.Required)
+						throw new InvalidOperationException ("Required attribute '" + e.Key + "' not found.");
+				}
 			}
 		}
 		

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionTree.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionTree.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/ExtensionTree.cs	Sun Mar  2 21:23:19 2008
@@ -208,27 +208,27 @@
 			}
 			
 			Hashtable fields = new Hashtable ();
-			ArrayList reqFields = new ArrayList ();
 			
 			// Check if the type has NodeAttribute attributes applied to fields.
 			foreach (FieldInfo field in ntype.Type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
 				NodeAttributeAttribute at = (NodeAttributeAttribute) Attribute.GetCustomAttribute (field, typeof(NodeAttributeAttribute), true);
 				if (at != null) {
+					ExtensionNodeType.FieldData fdata = new ExtensionNodeType.FieldData ();
+					fdata.Field = field;
+					fdata.Required = at.Required;
+					fdata.Localizable = at.Localizable;
+					
 					string name;
 					if (at.Name != null && at.Name.Length > 0)
 						name = at.Name;
 					else
 						name = field.Name;
 					
-					if (at.Required) reqFields.Add (name);
-					fields [name] = field;
+					fields [name] = fdata;
 				}
 			}
-			if (fields.Count > 0) {
+			if (fields.Count > 0)
 				ntype.Fields = fields;
-				if (reqFields.Count > 0)
-					ntype.RequiredFields = (string[]) reqFields.ToArray (typeof(string));
-			}
 				
 			return true;
 		}

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/NodeAttributeAttribute.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/NodeAttributeAttribute.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/NodeAttributeAttribute.cs	Sun Mar  2 21:23:19 2008
@@ -36,6 +36,7 @@
 	{
 		string name;
 		bool required;
+		bool localizable;
 		Type type;
 		string description;
 		
@@ -107,5 +108,10 @@
 			get { return description != null ? description : string.Empty; }
 			set { description = value; }
 		}
+
+		public bool Localizable {
+			get { return localizable; }
+			set { localizable = value; }
+		}
 	}
 }

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/NodeElement.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/NodeElement.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/NodeElement.cs	Sun Mar  2 21:23:19 2008
@@ -28,6 +28,7 @@
 
 
 using System;
+using System.Collections;
 
 namespace Mono.Addins
 {
@@ -36,6 +37,7 @@
 		string NodeName { get; }
 		string GetAttribute (string key);
 		NodeAttribute[] Attributes { get; }
+		NodeElementCollection ChildNodes { get; }
 	}
 	
 	public class NodeAttribute
@@ -55,4 +57,9 @@
 			get { return value; }
 		}
 	}
+	
+	public interface NodeElementCollection: IList, ICollection, IEnumerable
+	{
+		new NodeElement this [int n] { get; }
+	}
 }

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/RuntimeAddin.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/RuntimeAddin.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/RuntimeAddin.cs	Sun Mar  2 21:23:19 2008
@@ -33,10 +33,12 @@
 using System.IO;
 using System.Reflection;
 using System.Xml;
-using Mono.Addins.Description;
 using System.Resources;
 using System.Globalization;
 
+using Mono.Addins.Description;
+using Mono.Addins.Localization;
+
 namespace Mono.Addins
 {
 	public class RuntimeAddin
@@ -49,6 +51,7 @@
 		Assembly[] assemblies;
 		RuntimeAddin[] depAddins;
 		ResourceManager[] resourceManagers;
+		AddinLocalizer localizer;
 		
 		internal RuntimeAddin()
 		{
@@ -69,6 +72,11 @@
 		internal Addin Addin {
 			get { return ainfo; }
 		}
+		
+		public override string ToString ()
+		{
+			return ainfo.ToString ();
+		}
 
 		void CreateResourceManagers ()
 		{
@@ -115,7 +123,7 @@
 		{
 			if (resourceManagers == null)
 				CreateResourceManagers ();
-
+			
 			// Look in resources of this add-in
 			foreach (ResourceManager manager in resourceManagers)
 			{
@@ -202,6 +210,11 @@
 		
 		public Stream GetResource (string resourceName)
 		{
+			return GetResource (resourceName, false);
+		}
+		
+		public Stream GetResource (string resourceName, bool throwIfNotFound)
+		{
 			// Look in the addin assemblies
 			
 			foreach (Assembly asm in assemblies) {
@@ -217,9 +230,21 @@
 					return res;
 			}
 			
+			if (throwIfNotFound)
+				throw new InvalidOperationException ("Resource '" + resourceName + "' not found in add-in '" + id + "'");
+				
 			return null;
 		}
 		
+		public AddinLocalizer Localizer {
+			get {
+				if (localizer != null)
+					return localizer;
+				else
+					return AddinManager.DefaultLocalizer;
+			}
+		}
+		
 		internal AddinDescription Load (Addin iad)
 		{
 			ainfo = iad;
@@ -243,6 +268,20 @@
 			depAddins = (RuntimeAddin[]) plugList.ToArray (typeof(RuntimeAddin));
 			assemblies = (Assembly[]) asmList.ToArray (typeof(Assembly));
 			
+			if (description.Localizer != null) {
+				string cls = description.Localizer.GetAttribute ("type");
+				
+				// First try getting one of the stock localizers. If none of found try getting the type.
+				object fob = CreateInstance ("Mono.Addins.Localization." + cls + "Localizer", false);
+				if (fob == null)
+					fob = CreateInstance (cls, true);
+				
+				IAddinLocalizerFactory factory = fob as IAddinLocalizerFactory;
+				if (factory == null)
+					throw new InvalidOperationException ("Localizer factory type '" + cls + "' must implement IAddinLocalizerFactory");
+				localizer = new AddinLocalizer (factory.CreateLocalizer (this, description.Localizer));
+			}
+			
 			return description;
 		}
 		
@@ -278,8 +317,13 @@
 			// Collect dependent ids
 			foreach (Dependency dep in module.Dependencies) {
 				AddinDependency pdep = dep as AddinDependency;
-				if (pdep != null)
-					plugList.Add (AddinManager.SessionService.GetAddin (Addin.GetFullId (ns, pdep.AddinId, pdep.Version)));
+				if (pdep != null) {
+					RuntimeAddin adn = AddinManager.SessionService.GetAddin (Addin.GetFullId (ns, pdep.AddinId, pdep.Version));
+					if (adn != null)
+						plugList.Add (adn);
+					else
+						AddinManager.ReportError ("Add-in dependency not loaded: " + pdep.FullAddinId, module.ParentAddinDescription.AddinId, null, false);
+				}
 			}
 		}
 		

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/TreeNode.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/TreeNode.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/TreeNode.cs	Sun Mar  2 21:23:19 2008
@@ -236,12 +236,12 @@
 			if (extensionNode != null && extensionNode.AddinId == ad.Addin.Id)
 				extensionNode.OnAddinLoaded ();
 			if (recursive && childrenLoaded) {
-				foreach (TreeNode node in Children)
+				foreach (TreeNode node in Children.Clone ())
 					node.NotifyAddinLoaded (ad, true);
 			}
 		}
 		
-		public ExtensionPoint FindExtensionPoint (string path)
+		public ExtensionPoint FindLoadedExtensionPoint (string path)
 		{
 			if (path.StartsWith ("/"))
 				path = path.Substring (1);
@@ -253,6 +253,8 @@
 				int i = curNode.Children.IndexOfNode (part);
 				if (i != -1) {
 					curNode = curNode.Children [i];
+					if (!curNode.ChildrenLoaded)
+						return null;
 					if (curNode.ExtensionPoint != null)
 						return curNode.ExtensionPoint;
 					continue;

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/TreeNodeCollection.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/TreeNodeCollection.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/TreeNodeCollection.cs	Sun Mar  2 21:23:19 2008
@@ -72,5 +72,13 @@
 		public int Count {
 			get { return list != null ? list.Count : 0; }
 		}
+		
+		public TreeNodeCollection Clone ()
+		{
+			if (list != null)
+				return new TreeNodeCollection ((ArrayList) list.Clone ());
+			else
+				return Empty;
+		}
 	}
 }

Modified: trunk/Mono.Addins/Mono.Addins/Mono.Addins/TypeExtensionNode.cs
==============================================================================
--- trunk/Mono.Addins/Mono.Addins/Mono.Addins/TypeExtensionNode.cs	(original)
+++ trunk/Mono.Addins/Mono.Addins/Mono.Addins/TypeExtensionNode.cs	Sun Mar  2 21:23:19 2008
@@ -32,8 +32,8 @@
 
 namespace Mono.Addins
 {
-	[ExtensionNode ("Type", Description="Specifies a class that will be used to create an extension object. The name of the class can be provided in the 'class' attribute. If 'class' is not provided, the name will be taken from the 'id' attribute")]
-	[NodeAttribute ("class", typeof(Type), false, Description="Name of the class")]
+	[ExtensionNode ("Type", Description="Specifies a class that will be used to create an extension object.")]
+	[NodeAttribute ("class", typeof(Type), false, Description="Name of the class. If a value is not provided, the class name will be taken from the 'id' attribute")]
 	public class TypeExtensionNode: InstanceExtensionNode
 	{
 		string typeName;



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