Index: /trunk/sources/HeuristicLab.Operators.Programmable/3.2/ProgrammableOperator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Operators.Programmable/3.2/ProgrammableOperator.cs	(revision 2667)
+++ /trunk/sources/HeuristicLab.Operators.Programmable/3.2/ProgrammableOperator.cs	(revision 2668)
@@ -35,4 +35,5 @@
 using System.Data.Linq;
 using System.Xml.XPath;
+using HeuristicLab.PluginInfrastructure;
 
 namespace HeuristicLab.Operators.Programmable {
@@ -65,4 +66,6 @@
     private object syncRoot = new object();
 
+    public readonly Dictionary<string, List<Assembly>> Plugins;
+
     protected Dictionary<Assembly, bool> Assemblies;
     public IEnumerable<Assembly> AvailableAssemblies {
@@ -84,9 +87,11 @@
 
     public void SelectAssembly(Assembly a) {
-      Assemblies[a] = true;
+      if (a != null && Assemblies.ContainsKey(a))
+        Assemblies[a] = true;
     }
 
     public void UnselectAssembly(Assembly a) {
-      Assemblies[a] = false;
+      if (a != null && Assemblies.ContainsKey(a))
+        Assemblies[a] = false;
     }
 
@@ -132,4 +137,24 @@
       Assemblies = DiscoverAssemblies();
       namespaces = new HashSet<string>(DiscoverNamespaces());
+      Plugins = GroupAssemblies();
+    }
+
+    private Dictionary<string, List<Assembly>> GroupAssemblies() {
+      var plugins = new Dictionary<string, List<Assembly>>();
+      var assemblyNames = Assemblies.ToDictionary(a => a.Key.Location, a => a.Key);
+      foreach (var plugin in ApplicationManager.Manager.Plugins) {
+        var aList = new List<Assembly>();
+        foreach (var aName in plugin.Assemblies) {
+          Assembly a;
+          assemblyNames.TryGetValue(aName, out a);
+          if (a != null) {
+            aList.Add(a);
+            assemblyNames.Remove(aName);
+          }
+        }
+        plugins[plugin.Name] = aList;
+      }
+      plugins["other"] = assemblyNames.Values.ToList();
+      return plugins;
     }
 
@@ -248,5 +273,5 @@
       foreach (var ns in Namespaces)
         if (possibleNamespaces.Contains(ns))
-          yield return ns;      
+          yield return ns;
     }
 
Index: /trunk/sources/HeuristicLab.Operators.Programmable/3.2/ProgrammableOperatorView.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Operators.Programmable/3.2/ProgrammableOperatorView.Designer.cs	(revision 2667)
+++ /trunk/sources/HeuristicLab.Operators.Programmable/3.2/ProgrammableOperatorView.Designer.cs	(revision 2668)
@@ -49,8 +49,8 @@
       System.Windows.Forms.GroupBox groupBox1;
       System.Windows.Forms.GroupBox groupBox2;
-      this.assembliesListBox = new System.Windows.Forms.CheckedListBox();
-      this.namespacesListBox = new System.Windows.Forms.CheckedListBox();
+      this.assembliesTreeView = new System.Windows.Forms.TreeView();
       this.groupBox3 = new System.Windows.Forms.GroupBox();
       this.showCodeButton = new System.Windows.Forms.Button();
+      this.codeEditor = new HeuristicLab.CodeEditor.CodeEditor();
       this.compileButton = new System.Windows.Forms.Button();
       this.tabControl = new System.Windows.Forms.TabControl();
@@ -66,5 +66,5 @@
       this.descriptionTabPage = new System.Windows.Forms.TabPage();
       this.descriptionTextBox = new System.Windows.Forms.TextBox();
-      this.codeEditor = new HeuristicLab.CodeEditor.CodeEditor();
+      this.namespacesTreeView = new System.Windows.Forms.TreeView();
       splitContainer1 = new System.Windows.Forms.SplitContainer();
       splitContainer2 = new System.Windows.Forms.SplitContainer();
@@ -125,5 +125,5 @@
       // groupBox1
       // 
-      groupBox1.Controls.Add(this.assembliesListBox);
+      groupBox1.Controls.Add(this.assembliesTreeView);
       groupBox1.Dock = System.Windows.Forms.DockStyle.Fill;
       groupBox1.Location = new System.Drawing.Point(0, 0);
@@ -134,19 +134,17 @@
       groupBox1.Text = "Assemblies";
       // 
-      // assembliesListBox
-      // 
-      this.assembliesListBox.CheckOnClick = true;
-      this.assembliesListBox.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.assembliesListBox.FormattingEnabled = true;
-      this.assembliesListBox.Location = new System.Drawing.Point(3, 16);
-      this.assembliesListBox.Name = "assembliesListBox";
-      this.assembliesListBox.Size = new System.Drawing.Size(334, 64);
-      this.assembliesListBox.Sorted = true;
-      this.assembliesListBox.TabIndex = 0;
-      this.assembliesListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.assembliesListBox_ItemCheck);
+      // assembliesTreeView
+      // 
+      this.assembliesTreeView.CheckBoxes = true;
+      this.assembliesTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.assembliesTreeView.Location = new System.Drawing.Point(3, 16);
+      this.assembliesTreeView.Name = "assembliesTreeView";
+      this.assembliesTreeView.Size = new System.Drawing.Size(334, 66);
+      this.assembliesTreeView.TabIndex = 1;
+      this.assembliesTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.assembliesTreeView_AfterCheck);
       // 
       // groupBox2
       // 
-      groupBox2.Controls.Add(this.namespacesListBox);
+      groupBox2.Controls.Add(this.namespacesTreeView);
       groupBox2.Dock = System.Windows.Forms.DockStyle.Fill;
       groupBox2.Location = new System.Drawing.Point(0, 0);
@@ -157,15 +155,14 @@
       groupBox2.Text = "Namespaces";
       // 
-      // namespacesListBox
-      // 
-      this.namespacesListBox.CheckOnClick = true;
-      this.namespacesListBox.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.namespacesListBox.FormattingEnabled = true;
-      this.namespacesListBox.Location = new System.Drawing.Point(3, 16);
-      this.namespacesListBox.Name = "namespacesListBox";
-      this.namespacesListBox.Size = new System.Drawing.Size(343, 64);
-      this.namespacesListBox.Sorted = true;
-      this.namespacesListBox.TabIndex = 1;
-      this.namespacesListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.namespacesListBox_ItemCheck);
+      // namespacesTreeView
+      // 
+      this.namespacesTreeView.CheckBoxes = true;
+      this.namespacesTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.namespacesTreeView.Location = new System.Drawing.Point(3, 16);
+      this.namespacesTreeView.Name = "namespacesTreeView";
+      this.namespacesTreeView.PathSeparator = ".";
+      this.namespacesTreeView.Size = new System.Drawing.Size(343, 66);
+      this.namespacesTreeView.TabIndex = 2;
+      this.namespacesTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.namespacesTreeView_AfterCheck);
       // 
       // groupBox3
@@ -194,5 +191,5 @@
       this.showCodeButton.Name = "showCodeButton";
       this.showCodeButton.Size = new System.Drawing.Size(133, 23);
-      this.showCodeButton.TabIndex = 7;
+      this.showCodeButton.TabIndex = 4;
       this.showCodeButton.Text = "Show Generated Code";
       this.showCodeButton.UseVisualStyleBackColor = true;
@@ -360,5 +357,5 @@
       this.codeEditor.Size = new System.Drawing.Size(675, 309);
       this.codeEditor.Suffix = "\n    return null;\n  }\n}";
-      this.codeEditor.TabIndex = 6;
+      this.codeEditor.TabIndex = 0;
       this.codeEditor.UserCode = "\n\n\n";
       this.codeEditor.TextEditorValidated += new System.EventHandler(this.codeEditor_Validated);
@@ -405,6 +402,6 @@
     private System.Windows.Forms.Button removeVariableInfoButton;
     private System.Windows.Forms.Button addVariableInfoButton;
-    private System.Windows.Forms.CheckedListBox assembliesListBox;
-    private System.Windows.Forms.CheckedListBox namespacesListBox;
+    private System.Windows.Forms.TreeView assembliesTreeView;
+    private System.Windows.Forms.TreeView namespacesTreeView;
     private System.Windows.Forms.GroupBox groupBox3;
     private HeuristicLab.CodeEditor.CodeEditor codeEditor;
@@ -412,4 +409,5 @@
     private System.Windows.Forms.Button showCodeButton;
 
+
   }
 }
Index: /trunk/sources/HeuristicLab.Operators.Programmable/3.2/ProgrammableOperatorView.cs
===================================================================
--- /trunk/sources/HeuristicLab.Operators.Programmable/3.2/ProgrammableOperatorView.cs	(revision 2667)
+++ /trunk/sources/HeuristicLab.Operators.Programmable/3.2/ProgrammableOperatorView.cs	(revision 2668)
@@ -51,5 +51,5 @@
       ProgrammableOperator = programmableOperator;
     }
-    
+
     protected override void RemoveItemEvents() {
       operatorBaseVariableInfosView.Operator = null;
@@ -82,11 +82,12 @@
 
 public class Operator {
-  public static IOperation Execute(IOperator op, IScope scope, parameters ...) {";
+  public static IOperation Execute(IOperator op, IScope scope, parameters ...) {
+";
         codeEditor.Suffix = @"
     return null;
   }
-}";   
-        assembliesListBox.DataSource = null;
-      } else {        
+}";
+        assembliesTreeView.Nodes.Clear();
+      } else {
         codeEditor.Enabled = true;
         addVariableInfoButton.Enabled = true;
@@ -108,8 +109,8 @@
         }
         codeEditor.ScrollAfterPrefix();
-      }      
-    }
-
-    
+      }
+    }
+
+
     private string GetGeneratedPrefix() {
       StringBuilder prefix = new StringBuilder();
@@ -119,5 +120,5 @@
       prefix.AppendLine();
       prefix.Append("public class ").Append(ProgrammableOperator.CompiledTypeName).AppendLine(" {");
-      prefix.Append("  ").Append(ProgrammableOperator.Signature).Append(" {");
+      prefix.Append("  ").Append(ProgrammableOperator.Signature).AppendLine(" {");
       return prefix.ToString();
     }
@@ -140,5 +141,5 @@
         } else {
           ProgrammableOperator.AddVariableInfo(dialog.VariableInfo);
-          Recompile();          
+          Recompile();
         }
       }
@@ -151,9 +152,10 @@
       for (int i = 0; i < selected.Length; i++)
         ProgrammableOperator.RemoveVariableInfo(selected[i].FormalName);
+      Recompile();
     }
 
     private void Recompile() {
       try {
-        ProgrammableOperator.Compile();        
+        ProgrammableOperator.Compile();
         MessageBox.Show("Compilation successful", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
       } catch (Exception ex) {
@@ -161,10 +163,10 @@
       }
       UpdateControls();
-      codeEditor.ShowCompileErrors(ProgrammableOperator.CompileErrors, "ProgrammableOperator");      
+      codeEditor.ShowCompileErrors(ProgrammableOperator.CompileErrors, "ProgrammableOperator");
     }
 
     private void compileButton_Click(object sender, EventArgs e) {
       Recompile();
-    }    
+    }
 
     #region ProgrammableOperator Events
@@ -177,22 +179,22 @@
     #endregion
 
-    public static Assembly GetAssembly(CheckedListBox box, int index) {
-      return (Assembly)(((CheckedListBoxItem)box.Items[index]).Tag);
-    }
-
-    private void assembliesListBox_ItemCheck(object sender, ItemCheckEventArgs e) {
+    private void assembliesTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
       if (initializing)
         return;
-      Assembly a = GetAssembly(assembliesListBox, e.Index);
-      if (e.NewValue == CheckState.Checked) {                
-        ProgrammableOperator.SelectAssembly(a);
-        codeEditor.AddAssembly(a);
-      } else if (e.NewValue == CheckState.Unchecked) {
-        ProgrammableOperator.UnselectAssembly(a);
-        codeEditor.RemoveAssembly(a);
-      } else {
+      Assembly a = e.Node.Tag as Assembly;
+      if (a == null && e.Node.Nodes.Count > 0) {
+        foreach (TreeNode n in e.Node.Nodes)
+          n.Checked = e.Node.Checked;
         return;
-      }
-      InitializeNamespacesList();      
+      } else {
+        if (e.Node.Checked) {
+          ProgrammableOperator.SelectAssembly(a);
+          codeEditor.AddAssembly(a);
+        } else {
+          ProgrammableOperator.UnselectAssembly(a);
+          codeEditor.RemoveAssembly(a);
+        }
+      }
+      InitializeNamespacesList();
       codeEditor.Prefix = GetGeneratedPrefix();
     }
@@ -200,12 +202,25 @@
     private bool initializing = false;
     private void InitializeAssemblyList() {
-      assembliesListBox.Items.Clear();
+      initializing = true;
+      assembliesTreeView.BeginUpdate();
+      assembliesTreeView.Nodes.Clear();
       var selectedAssemblies = new HashSet<Assembly>(ProgrammableOperator.SelectedAssemblies);
-      initializing = true;
-      foreach (var a in ProgrammableOperator.AvailableAssemblies.ToList()) {
-        assembliesListBox.Items.Add(
-          new CheckedListBoxItem(a.GetName().Name, a),
-          selectedAssemblies.Contains(a));
-      }
+      foreach (var p in ProgrammableOperator.Plugins) {
+        var node = assembliesTreeView.Nodes.Add(p.Key);
+        node.Tag = p;
+        foreach (var a in p.Value) {
+          var aNode = node.Nodes.Add(a.GetName().Name);
+          aNode.Tag = a;
+          if (selectedAssemblies.Contains(a))
+            aNode.Checked = true;
+        }
+        if (node.Nodes.Count == 1 && node.Nodes[0].Name == node.Nodes[0].Name) {
+          node.Tag = node.Nodes[0].Tag;
+          node.Nodes.Clear();
+        } else if (node.Nodes.Count > 0 && node.Nodes.Cast<TreeNode>().All(n => n.Checked)) {
+          node.Checked = true;
+        }
+      }
+      assembliesTreeView.EndUpdate();
       initializing = false;
     }
@@ -213,20 +228,38 @@
     private void InitializeNamespacesList() {
       initializing = true;
-      namespacesListBox.Items.Clear();
+      namespacesTreeView.Nodes.Clear();
       var selectedNamespaces = new HashSet<string>(ProgrammableOperator.Namespaces);
-      foreach (var ns in ProgrammableOperator.GetAllNamespaces(true)) {
-        namespacesListBox.Items.Add(ns, selectedNamespaces.Contains(ns));
-      }
+      foreach (var ns in ProgrammableOperator.GetAllNamespaces(true))
+        AddNamespace(namespacesTreeView.Nodes, ns, selectedNamespaces.Contains(ns));
       codeEditor.Prefix = GetGeneratedPrefix();
       initializing = false;
     }
 
-    private void namespacesListBox_ItemCheck(object sender, ItemCheckEventArgs e) {
+    private void AddNamespace(TreeNodeCollection parentNodes, string ns, bool isSelected) {
+      int dotIndex = ns.IndexOf('.');
+      string prefix = ns;
+      if (dotIndex != -1)
+        prefix = ns.Substring(0, dotIndex);
+      TreeNode node = null;
+      if (parentNodes.ContainsKey(prefix)) {
+        node = parentNodes[prefix];
+      } else {
+        node = parentNodes.Add(prefix, prefix);
+      }
+      if (dotIndex != -1 && dotIndex + 1 < ns.Length) {
+        AddNamespace(node.Nodes, ns.Substring(dotIndex + 1, ns.Length - (dotIndex + 1)), isSelected);
+        if (isSelected)
+          node.Expand();
+      }  else
+        node.Checked = isSelected;
+    }
+
+    private void namespacesTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
       if (initializing)
         return;
-      if (e.NewValue == CheckState.Checked) {
-        ProgrammableOperator.SelectNamespace((string)namespacesListBox.Items[e.Index]);
-      } else if (e.NewValue == CheckState.Unchecked) {
-        ProgrammableOperator.UnselectNamespace((string)namespacesListBox.Items[e.Index]);
+      if (e.Node.Checked) {
+        ProgrammableOperator.SelectNamespace(e.Node.FullPath);
+      } else {
+        ProgrammableOperator.UnselectNamespace(e.Node.FullPath);
       }
       codeEditor.Prefix = GetGeneratedPrefix();
@@ -237,29 +270,5 @@
     }
 
-  }
-
-  public class CheckedListBoxItem : IComparable {
-
-    public object Tag { get; private set; }
-    public string Text { get; private set; }
-
-    public CheckedListBoxItem(string text, object tag) {
-      Text = text;
-      Tag = tag;
-    }
-
-    public override string ToString() {
-      return Text;
-    }
-
-    public int CompareTo(object obj) {
-      if (obj == null)
-        throw new ArgumentException("cannot compare to null");
-      if (!(obj is CheckedListBoxItem))
-        throw new ArgumentException(string.Format(
-          "cannot compare CheckedListBoxItem to {0}",
-          obj.GetType().Name));
-      return Text.CompareTo(((CheckedListBoxItem)obj).Text);
-    }
+
   }
 }
