Index: trunk/sources/HeuristicLab.Operators.Views.GraphVisualization/3.3/OperatorGraphView.cs
===================================================================
--- trunk/sources/HeuristicLab.Operators.Views.GraphVisualization/3.3/OperatorGraphVisualizationView.cs	(revision 2819)
+++ trunk/sources/HeuristicLab.Operators.Views.GraphVisualization/3.3/OperatorGraphView.cs	(revision 2853)
@@ -33,172 +33,244 @@
 using Netron.Diagramming.Core;
 using HeuristicLab.Parameters;
+using HeuristicLab.MainForm.WindowsForms;
 
 namespace HeuristicLab.Operators.Views.GraphVisualization {
-  [Content(typeof(IOperator), false)]
-  public partial class OperatorGraphVisualizationView : ItemView {
-    private Dictionary<IOperator, IShape> operatorShapeMapping;
-    private Dictionary<KeyValuePair<IOperator, IValueParameter<IOperator>>, IConnection> connectionMapping;
-    private HashSet<IValueParameter<IOperator>> parameters;
-    /// <summary>
-    /// Initializes a new instance of <see cref="OperatorGraphVisualizationView"/> with caption "Operator Graph".
-    /// </summary>
-    public OperatorGraphVisualizationView() {
+  [Content(typeof(OperatorGraph), false)]
+  public partial class OperatorGraphView : ContentView {
+    private BidirectionalLookup<IShapeInfo, IShape> shapeMapping;
+    private BidirectionalLookup<IConnectionInfo, IConnection> connectionMapping;
+
+    private bool causedUpdateOfShapeInfo;
+    public OperatorGraphView() {
       InitializeComponent();
+      this.causedUpdateOfShapeInfo = false;
       Caption = "Operator Graph";
-      this.operatorShapeMapping = new Dictionary<IOperator, IShape>();
-      this.connectionMapping = new Dictionary<KeyValuePair<IOperator, IValueParameter<IOperator>>, IConnection>();
-      this.parameters = new HashSet<IValueParameter<IOperator>>();
-
-      this.graphVisualization.Controller.Model.OnEntityRemoved += new EventHandler<EntityEventArgs>(Model_OnEntityRemoved);
-    }
-
-    /// <summary>
-    /// Initializes a new instance of <see cref="OperatorGraphVisualizationView"/> 
-    /// with the given <paramref name="operatorGraph"/>.
-    /// </summary>
-    /// <remarks>Calls <see cref="OperatorGraphView()"/>.</remarks>
-    /// <param name="operatorGraph">The operator graph to represent visually.</param>
-    public OperatorGraphVisualizationView(IOperator content)
+      this.shapeMapping = new BidirectionalLookup<IShapeInfo, IShape>();
+      this.connectionMapping = new BidirectionalLookup<IConnectionInfo, IConnection>();
+    }
+
+    public OperatorGraphView(OperatorGraph content)
       : this() {
       this.Content = content;
     }
 
-    /// <summary>
-    /// Gets or sets the operator graph to represent visually.
-    /// </summary>
-    /// <remarks>Uses property <see cref="ViewBase.Item"/> of base class <see cref="ViewBase"/>.
-    /// No own data storage present.</remarks>
-    public new IOperator Content {
-      get { return (IOperator)base.Content; }
+    public new OperatorGraph Content {
+      get { return (OperatorGraph)base.Content; }
       set { base.Content = value; }
     }
 
-    private IModel GraphModel {
-      get { return this.graphVisualization.Controller.Model; }
-    }
-
-
     protected override void OnContentChanged() {
-      base.OnContentChanged();
-      this.ClearGraph();
-
-      this.CreateGraph(null, new OperatorParameter(string.Empty, this.Content));
-      foreach (IShape shape in this.operatorShapeMapping.Values)
-        this.GraphModel.AddShape(shape);
-
-      foreach (IConnection connection in this.connectionMapping.Values)
-        this.GraphModel.AddConnection(connection);
-
-      if (this.Content == null)
-        this.graphVisualization.Controller.Model.LayoutRoot = null;
-      else
-        this.graphVisualization.Controller.Model.LayoutRoot = this.operatorShapeMapping[this.Content];
-      this.RelayoutOperatorGraph();
-    }
-
-    private void opParam_ValueChanged(object sender, EventArgs e) {
-      if (InvokeRequired)
-        Invoke(new EventHandler(opParam_ValueChanged), sender, e);
-      else {
-        this.OnContentChanged();
+      if (this.VisualizationInfo == null)
+        this.VisualizationInfo = new OperatorGraphVisualizationInfo(this.Content);
+      this.UpdateVisualizationInfo();
+    }
+
+    private OperatorGraphVisualizationInfo VisualizationInfo {
+      get { return Content.VisualizationInfo as OperatorGraphVisualizationInfo; }
+      set { this.Content.VisualizationInfo = value; }
+    }
+
+    private void UpdateVisualizationInfo() {
+      foreach (IShapeInfo shapeInfo in this.shapeMapping.FirstValues)
+        this.RemoveShapeInfo(shapeInfo);
+      this.shapeMapping.Clear();
+
+      foreach (IShapeInfo shapeInfo in this.VisualizationInfo.ShapeInfos)
+        this.AddShapeInfo(shapeInfo);
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      this.VisualizationInfo.ObserveableShapeInfos.ItemsAdded += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsAdded);
+      this.VisualizationInfo.ObserveableShapeInfos.ItemsRemoved += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsRemoved);
+      this.VisualizationInfo.ObserveableShapeInfos.CollectionReset += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_CollectionReset);
+    }
+
+    protected override void DeregisterContentEvents() {
+      base.DeregisterContentEvents();
+      this.VisualizationInfo.ObserveableShapeInfos.ItemsAdded -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsAdded);
+      this.VisualizationInfo.ObserveableShapeInfos.ItemsRemoved -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsRemoved);
+      this.VisualizationInfo.ObserveableShapeInfos.CollectionReset -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_CollectionReset);
+    }
+
+
+    private void ShapeInfos_CollectionReset(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
+      foreach (IShapeInfo shapeInfo in e.OldItems)
+        this.RemoveShapeInfo(shapeInfo);
+      foreach (IShapeInfo shapeInfo in e.Items)
+        this.AddShapeInfo(shapeInfo);
+      this.graphVisualization.Invalidate();
+    }
+
+    private void ShapeInfos_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
+      foreach (IShapeInfo shapeInfo in e.Items)
+        this.AddShapeInfo(shapeInfo);
+      this.graphVisualization.Invalidate();
+    }
+
+    private void ShapeInfos_ItemsRemoved(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
+      foreach (IShapeInfo shapeInfo in e.Items)
+        this.RemoveShapeInfo(shapeInfo);
+      this.graphVisualization.Invalidate();
+    }
+
+    private void AddShapeInfo(IShapeInfo shapeInfo) {
+      IShape shape = shapeInfo.CreateShape();
+      this.graphVisualization.Controller.Model.AddShape(shape);
+      this.shapeMapping.Add(shapeInfo, shape);
+
+      shape.OnEntityChange += new EventHandler<EntityEventArgs>(shape_OnEntityChange);
+      shapeInfo.Changed += new ChangedEventHandler(shapeInfo_Changed);
+    }
+
+    private void RemoveShapeInfo(IShapeInfo shapeInfo) {
+      IShape shape = this.shapeMapping.GetByFirst(shapeInfo);
+      shape.OnEntityChange -= new EventHandler<EntityEventArgs>(shape_OnEntityChange);
+      shapeInfo.Changed -= new ChangedEventHandler(shapeInfo_Changed);
+
+      this.shapeMapping.RemoveByFirst(shapeInfo);
+      if (this.graphVisualization.Controller.Model.Shapes.Contains(shape))
+        this.graphVisualization.Controller.Model.RemoveShape(shape);
+    }
+
+    private void shapeInfo_Changed(object sender, ChangedEventArgs e) {
+      IShapeInfo shapeInfo = (IShapeInfo)sender;
+      this.UpdateShape(shapeInfo);
+    }
+
+    private void shape_OnEntityChange(object sender, EntityEventArgs e) {
+      this.causedUpdateOfShapeInfo = true;
+      IShape shape = e.Entity as IShape;
+      IShapeInfo shapeInfo = this.shapeMapping.GetBySecond(shape);
+
+      shapeInfo.Location = shape.Location;
+      this.graphVisualization.Invalidate();
+      this.causedUpdateOfShapeInfo = false;
+    }
+
+    private void UpdateShape(IShapeInfo shapeInfo) {
+      if (!this.causedUpdateOfShapeInfo) {
+        IShape shape = this.shapeMapping.GetByFirst(shapeInfo);
+        shape.Location = shapeInfo.Location;
       }
     }
 
-    private void ClearGraph() {
-      this.GraphModel.Clear();
-      foreach (IValueParameter<IOperator> opParam in this.parameters)
-        opParam.ValueChanged -= opParam_ValueChanged;
-
-      this.operatorShapeMapping.Clear();
-      this.parameters.Clear();
-      this.connectionMapping.Clear();
-    }
-
-
-
-    private void CreateGraph(IOperator parent, IValueParameter<IOperator> op) {
-      if (op == null || op.Value == null)
-        return;
-
-      IShape shape;
-      if (!this.operatorShapeMapping.ContainsKey(op.Value)) {
-        shape = CreateOperatorShape(op.Value);
-        this.operatorShapeMapping[op.Value] = shape;
-
-        foreach (IParameter param in op.Value.Parameters) {
-          IValueParameter<IOperator> opParam = param as IValueParameter<IOperator>;
-          if (opParam != null) {
-            HandleOperatorParameter(opParam);
-            this.CreateGraph(op.Value, opParam);
-          }
-        }
+    private void graphVisualization_OnEntityRemoved(object sender, EntityEventArgs e) {
+      IShape shape = (IShape)e.Entity;
+      if (this.shapeMapping.ContainsSecond(shape)) {
+        IShapeInfo shapeInfo = this.shapeMapping.GetBySecond(shape);
+        this.VisualizationInfo.RemoveShapeInfo(shapeInfo);
       }
-
-      if (parent != null)
-        ConnectShapes(parent, op);
-    }
-
-    private void HandleOperatorParameter(IValueParameter<IOperator> opParam) {
-      if (opParam == null)
-        return;
-      opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
-      parameters.Add(opParam);
-    }
-
-    private IConnection ConnectShapes(IOperator parent, IValueParameter<IOperator> opParam) {
-      IShape operatorShape = this.operatorShapeMapping[opParam.Value];
-      IShape parentShape = this.operatorShapeMapping[parent];
-      IConnector operatorConnector = parentShape.Connectors.Where(c => c.Name == "Bottom connector").First();
-      IConnector parentConnector = operatorShape.Connectors.Where(c => c.Name == "Top connector").First();
-
-      IConnection connection = new Connection(parentConnector.Point, operatorConnector.Point);
-      parentConnector.AttachConnector(connection.From);
-      operatorConnector.AttachConnector(connection.To);
-
-      this.connectionMapping[new KeyValuePair<IOperator, IValueParameter<IOperator>>(parent, opParam)] = connection;
-      return connection;
-    }
-
-    private IShape CreateOperatorShape(IOperator op) {
-      ClassShape shape = new ClassShape();
-      shape.Name = op.Name;
-      shape.Text = op.Name;
-      shape.Title = op.Name;
-      shape.SubTitle = op.GetType().ToString();
-
-      return shape;
-    }
-
-    private void Model_OnEntityRemoved(object sender, EntityEventArgs e) {
-      IShape shape = e.Entity as IShape;
-      if (shape != null) {
-        IOperator op = operatorShapeMapping.Where(os => os.Value == shape).First().Key;
-        if (op == this.Content)
-          this.Content = null;
-        else {
-          //clear all connections to the removed operator
-          IEnumerable<IValueParameter<IOperator>> parentOperator = this.connectionMapping.Where(cs => cs.Key.Value.Value == op).Select(x => x.Key.Value);
-          foreach(IValueParameter<IOperator> opParam in parentOperator.ToArray())
-            opParam.Value = null;
-
-          //remove connections from graph view
-          IEnumerable<IConnection> connections = this.connectionMapping.Where(cs => cs.Key.Value.Value == op).Select(x => x.Value);
-          foreach (IConnection connection in connections)
-            this.GraphModel.Remove(connection);
-
-          this.graphVisualization.Invalidate();
-        }
-
-
-      }
-    }
+    }
+
+
+
+
+    //protected override void OnContentChanged() {
+    //  base.OnContentChanged();
+    //  this.ClearGraph();
+
+    //  this.CreateGraph(null, new OperatorParameter(string.Empty, this.Content));
+    //  foreach (IShape shape in this.operatorShapeMapping.Values)
+    //    this.GraphModel.AddShape(shape);
+
+    //  foreach (IConnection connection in this.connectionMapping.Values)
+    //    this.GraphModel.AddConnection(connection);
+
+    //  if (this.Content == null)
+    //    this.graphVisualization.Controller.Model.LayoutRoot = null;
+    //  else
+    //    this.graphVisualization.Controller.Model.LayoutRoot = this.operatorShapeMapping[this.Content];
+    //  this.RelayoutOperatorGraph();
+    //}
+
+    //private void opParam_ValueChanged(object sender, EventArgs e) {
+    //  if (InvokeRequired)
+    //    Invoke(new EventHandler(opParam_ValueChanged), sender, e);
+    //  else {
+    //    this.OnContentChanged();
+    //  }
+    //}
+
+    //private void ClearGraph() {
+    //  this.GraphModel.Clear();
+    //  foreach (IValueParameter<IOperator> opParam in this.parameters)
+    //    opParam.ValueChanged -= opParam_ValueChanged;
+
+    //  this.operatorShapeMapping.Clear();
+    //  this.parameters.Clear();
+    //  this.connectionMapping.Clear();
+    //}
+
+
+
+    //private void CreateGraph(IOperator parent, IValueParameter<IOperator> op) {
+    //  if (op == null || op.Value == null)
+    //    return;
+
+    //  IShape shape;
+    //  if (!this.operatorShapeMapping.ContainsKey(op.Value)) {
+    //    //shape = GraphVisualizationInfo.CreateShape(op.Value);
+    //    //this.operatorShapeMapping[op.Value] = shape;
+
+    //    foreach (IParameter param in op.Value.Parameters) {
+    //      IValueParameter<IOperator> opParam = param as IValueParameter<IOperator>;
+    //      if (opParam != null) {
+    //        HandleOperatorParameter(opParam);
+    //        this.CreateGraph(op.Value, opParam);
+    //      }
+    //    }
+    //  }
+
+    //  if (parent != null) {
+    //    IShape from = this.operatorShapeMapping[parent];
+    //    IShape to = this.operatorShapeMapping[op.Value];
+    //    //IConnection connection = GraphVisualizationInfo.CreateConnection(from,to);
+    //    //this.connectionMapping[new KeyValuePair<IOperator, IValueParameter<IOperator>>(parent, op)] = connection;
+    //  }
+    //}
+
+    //private void DeleteGraph(IOperator parent, IValueParameter<IOperator> op) {
+
+    //}
+
+    //private void HandleOperatorParameter(IValueParameter<IOperator> opParam) {
+    //  if (opParam == null)
+    //    return;
+    //  opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
+    //  parameters.Add(opParam);
+    //}
+
+    //private void Model_OnEntityRemoved(object sender, EntityEventArgs e) {
+    //  IShape shape = e.Entity as IShape;
+    //  if (shape != null) {
+    //    IOperator op = operatorShapeMapping.Where(os => os.Value == shape).First().Key;
+    //    if (op == this.Content)
+    //      this.Content = null;
+    //    else {
+    //      //clear all connections to the removed operator
+    //      IEnumerable<IValueParameter<IOperator>> parentOperator = this.connectionMapping.Where(cs => cs.Key.Value.Value == op).Select(x => x.Key.Value);
+    //      foreach (IValueParameter<IOperator> opParam in parentOperator.ToArray())
+    //        opParam.Value = null;
+
+    //      //remove connections from graph view
+    //      IEnumerable<IConnection> connections = this.connectionMapping.Where(cs => cs.Key.Value.Value == op).Select(x => x.Value);
+    //      foreach (IConnection connection in connections)
+    //        this.GraphModel.Remove(connection);
+
+    //      this.graphVisualization.Invalidate();
+    //    }
+
+
+    //  }
+    //}
 
     #region methods for toolbar items
 
     internal void RelayoutOperatorGraph() {
-      if (this.operatorShapeMapping.Count > 0 && this.connectionMapping.Count > 0) { //otherwise the layout does not work
-        this.graphVisualization.Invalidate();
-        this.graphVisualization.Controller.RunActivity("Standard TreeLayout");
-      }
+      //if (this.operatorShapeMapping.Count > 0 && this.connectionMapping.Count > 0) { //otherwise the layout does not work
+      this.graphVisualization.Controller.RunActivity("Standard TreeLayout");
+      this.graphVisualization.Invalidate();
+      //}
     }
 
@@ -221,4 +293,26 @@
     internal void ActivateSelectTool() {
       this.graphVisualization.Controller.ActivateTool(ControllerBase.SelectionToolName);
+    }
+
+    #endregion
+
+    #region drag and drop
+    private void OperatorGraphView_DragEnter(object sender, DragEventArgs e) {
+      e.Effect = DragDropEffects.None;
+      Type type = e.Data.GetData("Type") as Type;
+      if ((type != null) && (typeof(IOperator).IsAssignableFrom(type))) {
+        e.Effect = DragDropEffects.Copy;
+      }
+    }
+
+    private void OperatorGraphView_DragDrop(object sender, DragEventArgs e) {
+      if (e.Effect != DragDropEffects.None) {
+        IOperator op = e.Data.GetData("Value") as IOperator;
+        IShapeInfo shapeInfo = ShapeInfoFactory.CreateShapeInfo(op);
+        Point controlCoordinates = this.PointToClient(new Point(e.X, e.Y));
+        PointF viewCoordinates = this.graphVisualization.Controller.View.DeviceToView(controlCoordinates);
+        shapeInfo.Location = new Point((int)viewCoordinates.X, (int)viewCoordinates.Y);
+        this.VisualizationInfo.AddShapeInfo(op, shapeInfo);
+      }
     }
 
