#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 . */ #endregion using System; using System.Collections.Generic; using System.Drawing; using HeuristicLab.Common; using HeuristicLab.Core.Networks; using HeuristicLab.Visualization; namespace HeuristicLab.Networks.Views.NetworkVisualization { [Primitive(typeof(INode), true)] public class NodeRectangle : Visualization.Rectangle, INetworkItemPrimitive { protected readonly Dictionary port2primitive = new Dictionary(); protected readonly IGroup portRectangles; protected bool IgnoreVisualPropertiesChanges { get; set; } protected INode networkItem; public INode NetworkItem { get { return networkItem; } set { if (networkItem == value) return; if (networkItem != null) DeregisterNetworkItemEvents(); networkItem = value; if (networkItem != null) RegisterNetworkItemEvents(); LoadVisualProperties(); OnNetworkItemChanged(); } } public NodeRectangle(IChart chart, INode node) : base(chart, PointD.Empty, PointD.Empty) { NetworkItem = node; portRectangles = new Group(chart); foreach (var port in node.Ports) { var portPrimitive = PrimitiveAttribute.CreateDefaultPrimitive(port.GetType(), chart, port, node); // TODO: port.Parent != node port2primitive.Add(port, portPrimitive); portRectangles.Add(portPrimitive); } portRectangles.RedrawRequired += (sender, args) => OnRedrawRequired(); } protected virtual void RegisterNetworkItemEvents() { networkItem.NameChanged += NetworkItem_NameChanged; if (networkItem.VisualProperties != null) { networkItem.VisualProperties.Changed += VisualProperties_Changed; } if (networkItem.Ports != null) { networkItem.Ports.ItemsAdded += Ports_ItemsAdded; networkItem.Ports.ItemsRemoved += Ports_ItemsRemoved; } } protected virtual void DeregisterNetworkItemEvents() { networkItem.NameChanged -= NetworkItem_NameChanged; if (networkItem.VisualProperties != null) { networkItem.VisualProperties.Changed -= VisualProperties_Changed; } if (networkItem.Ports != null) { networkItem.Ports.ItemsAdded -= Ports_ItemsAdded; networkItem.Ports.ItemsRemoved -= Ports_ItemsRemoved; } } #region Overrides public override void SetPosition(PointD lowerLeft, PointD upperRight) { base.SetPosition(lowerLeft, upperRight); SaveVisualProperties(); } public override void Draw(Graphics graphics) { base.Draw(graphics); var p = Chart.TransformWorldToPixel(new PointD(LowerLeft.X, LowerLeft.Y + Size.Height)); if (networkItem != null) { using (var font = new Font(FontFamily.GenericSansSerif, (float)Math.Round(8.25 * Chart.WorldToPixelRatio.Width))) { graphics.DrawString(networkItem.Name, font, Brushes.Black, p.X + 5, p.Y + 5); } } portRectangles.Draw(graphics); } #endregion public IPrimitive GetPortPrimitive(IPort name) { IPrimitive portPrimitive; port2primitive.TryGetValue(name, out portPrimitive); return portPrimitive; } #region Events public event EventHandler NetworkItemChanged; protected virtual void OnNetworkItemChanged() { var handler = NetworkItemChanged; if (handler != null) handler(this, EventArgs.Empty); } #endregion #region Event Handlers private void VisualProperties_Changed(object sender, EventArgs e) { if (IgnoreVisualPropertiesChanges) return; LoadVisualProperties(); } private void NetworkItem_NameChanged(object sender, EventArgs e) { OnRedrawRequired(); } private void Ports_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs e) { foreach (var port in e.Items) { var portRectangle = PrimitiveAttribute.CreateDefaultPrimitive(port.GetType(), Chart, port, networkItem); port2primitive.Add(port, portRectangle); portRectangles.Add(portRectangle); } OnRedrawRequired(); } private void Ports_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs e) { foreach (var port in e.Items) { var portRectangle = port2primitive[port]; port2primitive.Remove(port); portRectangles.Remove(portRectangle); } OnRedrawRequired(); } #endregion #region Helpers private INodeVisualProperties CreateDefaultVisualProperties() { var offset = Chart.UpperRight - Chart.LowerLeft; var center = new PointD(Chart.LowerLeft.X + offset.DX * 0.5, Chart.LowerLeft.Y + offset.DY * 0.5); var size = Chart.TransformPixelToWorld(new Size(200, 100)); var lowerLeft = center - new Offset(size.Width * 0.5, size.Height * 0.5); var upperRight = center + new Offset(size.Width * 0.5, size.Height * 0.5); return new NodeVisualProperties(new Point2D(lowerLeft.X, lowerLeft.Y), new Point2D(upperRight.X, upperRight.Y)); } private void LoadVisualProperties() { if (networkItem.VisualProperties == null) networkItem.VisualProperties = CreateDefaultVisualProperties(); var vp = (INodeVisualProperties)networkItem.VisualProperties; SetPosition(new PointD(vp.LowerLeft.X, vp.LowerLeft.Y), new PointD(vp.UpperRight.X, vp.UpperRight.Y)); } private void SaveVisualProperties() { if (networkItem == null) return; var vp = (INodeVisualProperties)networkItem.VisualProperties; IgnoreVisualPropertiesChanges = true; try { vp.LowerLeft = new Point2D(LowerLeft.X, LowerLeft.Y); vp.UpperRight = new Point2D(UpperRight.X, UpperRight.Y); } finally { IgnoreVisualPropertiesChanges = false; } } #endregion } }