#region License Information /* HeuristicLab * Copyright (C) 2002-2016 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; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; namespace HeuristicLab.Visualization { public class Group : PrimitiveBase, IGroup { private readonly LinkedList primitives; private readonly HashSet primitivesLookup; public virtual IEnumerable Primitives { get { return primitives.ToArray(); } } public virtual IEnumerable SelectedPrimitives { get { return primitives.Where(x => x.Selected).ToArray(); } } public override bool Selected { get { return base.Selected; } set { SuppressEvents = true; try { foreach (var primitive in primitives) primitive.Selected = value; base.Selected = value; } finally { SuppressEvents = false; OnRedrawRequired(); } } } public Group(IChart chart) : base(chart) { primitives = new LinkedList(); primitivesLookup = new HashSet(); } public virtual void Add(IPrimitive primitive) { if (Contains(primitive)) throw new ArgumentException("Primitive already added"); primitives.AddFirst(primitive); primitivesLookup.Add(primitive); primitive.RedrawRequired += PrimitiveOnRedrawRequired; OnRedrawRequired(); } public virtual void AddRange(IEnumerable primitives) { foreach (var primitive in this.primitives) { if (Contains(primitive)) throw new ArgumentException("Primitive already added"); this.primitives.AddFirst(primitive); primitivesLookup.Add(primitive); primitive.RedrawRequired += PrimitiveOnRedrawRequired; } OnRedrawRequired(); } public virtual bool Contains(IPrimitive primitive) { return primitivesLookup.Contains(primitive); } public virtual bool Remove(IPrimitive primitive) { if (!primitives.Remove(primitive)) return false; primitivesLookup.Remove(primitive); primitive.RedrawRequired -= PrimitiveOnRedrawRequired; OnRedrawRequired(); return true; } public virtual void Clear() { foreach (var primitive in primitives) { primitive.RedrawRequired -= PrimitiveOnRedrawRequired; } primitives.Clear(); primitivesLookup.Clear(); OnRedrawRequired(); } public virtual IPrimitive GetPrimitive(PointD point) { return primitives.FirstOrDefault(primitive => primitive.ContainsPoint(point)); } public virtual IEnumerable GetAllPrimitives(PointD point) { var result = new List(); foreach (var primitive in primitives.Where(primitive => primitive.ContainsPoint(point))) { result.Add(primitive); var group = primitive as IGroup; if (group != null) result.AddRange(group.GetAllPrimitives(point)); } return result; } public override void Move(Offset delta) { SuppressEvents = true; try { foreach (var primitive in primitives) primitive.Move(delta); } finally { SuppressEvents = false; OnRedrawRequired(); } } public override void Move(PointD point, Offset delta) { SuppressEvents = true; try { foreach (var primitive in primitives) primitive.Move(point, delta); } finally { SuppressEvents = false; OnRedrawRequired(); } } public override void SnapToGrid(IGrid grid) { SuppressEvents = true; try { foreach (var primitive in primitives) primitive.SnapToGrid(grid); } finally { SuppressEvents = false; OnRedrawRequired(); } } public override void SnapToGrid(PointD point, IGrid grid) { SuppressEvents = true; try { foreach (var primitive in primitives) primitive.SnapToGrid(point, grid); } finally { SuppressEvents = false; OnRedrawRequired(); } } public override bool ContainsPoint(PointD point) { return GetPrimitive(point) != null; } public override Cursor GetCursor(PointD point) { var primitive = GetPrimitive(point); return primitive != null ? primitive.GetCursor(point) : base.GetCursor(point); } public override string GetToolTipText(PointD point) { var primitive = GetPrimitive(point); return primitive != null ? primitive.GetToolTipText(point) : base.GetToolTipText(point); } public void OneLayerUp(IPrimitive primitive) { if (!Contains(primitive)) throw new ArgumentException("Primitive not found"); var curr = primitives.Find(primitive); if (curr == null) return; var prev = curr.Previous; var temp = curr.Value; curr.Value = prev.Value; prev.Value = temp; OnRedrawRequired(); } public void OneLayerDown(IPrimitive primitive) { if (!Contains(primitive)) throw new ArgumentException("Primitive not found"); var curr = primitives.Find(primitive); if (curr == null) return; var next = curr.Next; var temp = curr.Value; curr.Value = next.Value; next.Value = temp; } public void IntoForeground(IPrimitive primitive) { if (!Contains(primitive)) throw new ArgumentException("Primitive not found"); primitives.Remove(primitive); primitives.AddFirst(primitive); OnRedrawRequired(); } public void IntoBackground(IPrimitive primitive) { if (!Contains(primitive)) throw new ArgumentException("Primitive not found"); primitives.Remove(primitive); primitives.AddLast(primitive); OnRedrawRequired(); } public override void Draw(Graphics graphics) { var current = primitives.Last; while (current != null) { var primitive = current.Value; primitive.PreDraw(graphics); primitive.Draw(graphics); primitive.PostDraw(graphics); current = current.Previous; } } private void PrimitiveOnRedrawRequired(object sender, EventArgs e) { if (SuppressEvents) return; OnRedrawRequired(); } public IEnumerator GetEnumerator() { return primitives.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }