#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();
}
}
}