Index: /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartControl.cs
===================================================================
--- /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartControl.cs	(revision 13131)
+++ /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartControl.cs	(revision 13132)
@@ -388,5 +388,5 @@
       };
 
-      rb.CheckedChanged += (sender, args) => { if (rb.Checked) Mode = chartMode; };
+      rb.CheckedChanged += (sender, args) => { if (rb.Checked) chartMode.Select(); };
 
       return rb;
@@ -400,5 +400,5 @@
       };
 
-      mi.CheckedChanged += (sender, args) => { if (mi.Checked) Mode = chartMode; };
+      mi.CheckedChanged += (sender, args) => { if (mi.Checked) chartMode.Select(); };
 
       return mi;
Index: /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartMode.cs
===================================================================
--- /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartMode.cs	(revision 13131)
+++ /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartMode.cs	(revision 13132)
@@ -41,10 +41,32 @@
     }
 
+    private bool selected;
+    public bool Selected {
+      get { return selected; }
+      set {
+        if (selected == value) return;
+        selected = value;
+        if (selected) {
+          chartControl.Mode = this;
+          OnSelected();
+        } else {
+          if (chartControl.Mode == this)
+            chartControl.Mode = null;
+          OnDeselected();
+        }
+        OnSelectedChanged();
+      }
+    }
+
     protected ChartMode(ChartControl control) {
       chartControl = control;
+      chartControl.ModeChanged += (sender, args) => Selected = chartControl.Mode == this;
     }
 
-    public void Select() { chartControl.Mode = this; }
-    public void Deselect() { chartControl.Mode = null; }
+    public void Select() { Selected = true; }
+    public void Deselect() { Selected = false; }
+
+    protected virtual void OnSelected() { }
+    protected virtual void OnDeselected() { }
 
     public virtual void HandleOnKeyDown(object sender, KeyEventArgs e) {
@@ -75,4 +97,10 @@
     public virtual void HandleOnMouseLeave(object sender, EventArgs e) { }
     public virtual void HandleOnClick(object sender, EventArgs e) { }
+
+    public event EventHandler SelectedChanged;
+    protected virtual void OnSelectedChanged() {
+      var handler = SelectedChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
   }
 }
Index: /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartModes/RulerChartMode.cs
===================================================================
--- /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartModes/RulerChartMode.cs	(revision 13131)
+++ /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartModes/RulerChartMode.cs	(revision 13132)
@@ -85,4 +85,5 @@
     }
 
+    #region Helpers
     protected virtual void DrawCross(Graphics graphics, Point point) {
       using (var pen = new Pen(Color.Red)) {
@@ -112,6 +113,6 @@
       graphics.DrawRectangle(Pens.Red, location.X, location.Y, width, height);
       graphics.DrawString(text, SystemFonts.DefaultFont, Brushes.Black, location.X, location.Y + 2);
-
     }
+    #endregion
   }
 }
Index: /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartModes/SelectChartMode.cs
===================================================================
--- /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartModes/SelectChartMode.cs	(revision 13131)
+++ /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartModes/SelectChartMode.cs	(revision 13132)
@@ -33,4 +33,15 @@
     public SelectChartMode(ChartControl control) : base(control) { }
 
+    protected override void OnDeselected() {
+      try {
+        chartControl.SuspendRendering();
+        foreach (var p in chartControl.Chart.Group.SelectedPrimitives)
+          p.Selected = false;
+      } finally {
+        chartControl.ResumeRendering();
+        base.OnDeselected();
+      }
+    }
+
     public override void HandleOnKeyDown(object sender, KeyEventArgs e) {
       try {
@@ -39,8 +50,7 @@
             try {
               chartControl.SuspendRendering();
-              foreach (var primitive in chartControl.Chart.Group.SelectedPrimitives)
-                chartControl.Chart.Group.Remove(primitive);
+              foreach (var p in chartControl.Chart.Group.SelectedPrimitives)
+                chartControl.Chart.Group.Remove(p);
             } finally { chartControl.ResumeRendering(); }
-
             break;
         }
@@ -57,8 +67,8 @@
               chartControl.SuspendRendering();
               var worldLocation = chartControl.Chart.TransformPixelToWorld(e.Location);
-              foreach (var sp in chartControl.Chart.Group.SelectedPrimitives.Where(x => !x.ContainsPoint(worldLocation)))
-                sp.Selected = false;
-              var p = chartControl.Chart.GetPrimitive(e.Location);
-              if (p != null) p.Selected = true;
+              foreach (var p in chartControl.Chart.Group.SelectedPrimitives.Where(x => !x.ContainsPoint(worldLocation)))
+                p.Selected = false;
+              var sp = chartControl.Chart.GetPrimitive(e.Location);
+              if (sp != null) sp.Selected = true;
             } finally { chartControl.ResumeRendering(); }
             break;
@@ -80,6 +90,6 @@
             try {
               chartControl.SuspendRendering();
-              foreach (var primitive in chartControl.Chart.Group.SelectedPrimitives.Where(p => p.ContainsPoint(previousWorldLocation)))
-                primitive.Move(previousWorldLocation, offset);
+              foreach (var p in chartControl.Chart.Group.SelectedPrimitives.Where(p => p.ContainsPoint(previousWorldLocation)))
+                p.Move(previousWorldLocation, offset);
             } finally { chartControl.ResumeRendering(); }
             break;
Index: /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/HeuristicLab.Visualization-3.3.csproj
===================================================================
--- /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/HeuristicLab.Visualization-3.3.csproj	(revision 13131)
+++ /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/HeuristicLab.Visualization-3.3.csproj	(revision 13132)
@@ -132,4 +132,5 @@
     <Compile Include="ChartModes\PanChartMode.cs" />
     <Compile Include="ChartModes\RulerChartMode.cs" />
+    <Compile Include="PrimitiveAttribute.cs" />
     <Compile Include="Primitives\Grid.cs" />
     <Compile Include="Properties\Resources.Designer.cs">
Index: /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/PrimitiveAttribute.cs
===================================================================
--- /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/PrimitiveAttribute.cs	(revision 13132)
+++ /branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/PrimitiveAttribute.cs	(revision 13132)
@@ -0,0 +1,121 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Visualization;
+
+namespace HeuristicLab.Networks.Views.NetworkVisualization {
+  [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+  public sealed class PrimitiveAttribute : Attribute {
+    public Type VisualizableType { get; }
+    public bool IsDefaultPrimitive { get; set; }
+
+    private static readonly Dictionary<Type, Type> defaultPrimitives = new Dictionary<Type, Type>();
+
+    static PrimitiveAttribute() {
+      var primitiveTypes = ApplicationManager.Manager.GetTypes(typeof(IPrimitive), true, true)
+                                                     .Where(x => !x.IsAbstract && !x.IsInterface && HasPrimitiveAttribute(x));
+
+      foreach (var primitiveType in primitiveTypes) {
+        foreach (var visualizableType in GetDefaultVisualizableTypes(primitiveType)) {
+          if (defaultPrimitives.ContainsKey(visualizableType))
+            throw new ArgumentException("DefaultPrimitive for type " + visualizableType + " is " + defaultPrimitives[visualizableType] +
+              ". Can't register additional DefaultPrimitive " + primitiveType + ".");
+          defaultPrimitives[visualizableType] = primitiveType;
+        }
+      }
+    }
+
+    public PrimitiveAttribute(Type visualizableType) {
+      VisualizableType = visualizableType;
+    }
+
+    public PrimitiveAttribute(Type visualizableType, bool isDefaultPrimitive)
+      : this(visualizableType) {
+      IsDefaultPrimitive = isDefaultPrimitive;
+    }
+
+    public static bool HasPrimitiveAttribute(MemberInfo primitiveType) {
+      var attributes = primitiveType.GetCustomAttributes(typeof(PrimitiveAttribute), false);
+      return attributes.Any();
+    }
+
+    public static bool CanVisualizeType(MemberInfo primitiveType, Type visualizable) {
+      var attributes = (PrimitiveAttribute[])primitiveType.GetCustomAttributes(typeof(PrimitiveAttribute), false);
+      return attributes.Any(x => visualizable.IsAssignableFrom(x.VisualizableType));
+    }
+
+    public static IEnumerable<Type> GetDefaultVisualizableTypes(Type primitiveType) {
+      var attributes = (PrimitiveAttribute[])primitiveType.GetCustomAttributes(typeof(PrimitiveAttribute), false);
+      return attributes.Where(x => x.IsDefaultPrimitive).Select(x => x.VisualizableType);
+    }
+
+    public static IEnumerable<Type> GetVisualizableTypes(Type primitiveType) {
+      var attributes = (PrimitiveAttribute[])primitiveType.GetCustomAttributes(typeof(PrimitiveAttribute), false);
+      return attributes.Select(x => x.VisualizableType);
+    }
+
+    public static IPrimitive CreateDefaultPrimitive(Type visualizableType, params object[] args) {
+      var t = GetDefaultPrimitiveType(visualizableType);
+      if (t == null) return null;
+
+      return (IPrimitive)Activator.CreateInstance(t, args);
+    }
+
+    // TODO: add support for generic types
+    public static Type GetDefaultPrimitiveType(Type visualizableType) {
+      var type = visualizableType;
+      while (type != null) {
+        Type primitiveType;
+        if (defaultPrimitives.TryGetValue(type, out primitiveType))
+          return primitiveType;
+
+        var nonInheritedInterfaces = type.GetInterfaces().Where(i => !i.IsAssignableFrom(type.BaseType));
+        var interfaces = new HashSet<Type>(nonInheritedInterfaces);
+
+        while (interfaces.Any()) {
+          interfaces.RemoveWhere(i => interfaces.Any(x => x.GetInterfaces().Contains(i)));
+
+          var defaultViewList = defaultPrimitives.Keys.Where(interfaces.Contains).Select(x => defaultPrimitives[x]).ToList();
+
+          foreach (Type viewType in defaultViewList)
+            if (defaultViewList.Any(t => t.IsSubclassOf(viewType)))
+              defaultViewList.Remove(viewType);
+
+          if (defaultViewList.Count == 1) return defaultViewList[0];
+          if (defaultViewList.Count > 1)
+            throw new InvalidOperationException("Could not determine which is the default primitive for type " + visualizableType +
+              " because more than one implemented interfaces have a default primitive.");
+
+          interfaces = new HashSet<Type>(interfaces.SelectMany(i => i.GetInterfaces()));
+        }
+
+        type = type.BaseType;
+      }
+
+      return null;
+    }
+  }
+}
