using System.Collections.Generic; using System.Drawing; using HeuristicLab.Visualization.Drawing; namespace HeuristicLab.Visualization.Legend { public enum LegendPosition { Top, Bottom, Left, Right } public class LegendShape : WorldShape { private readonly IList legendItems = new List(); // legend draw default value: column private Color color = Color.Blue; private Font font = new Font("Arial", 8); public bool Row { get; set; } public bool Top { get; set; } public LegendShape() { CreateLegend(); } private bool ExistsLegendItems() { return legendItems.Count > 0; } /// /// paints the legend on the canvas /// public void CreateLegend() { if (ExistsLegendItems()) { ClearShapes(); double x = ClippingArea.X1; double y = ClippingArea.Y2; if (Row && !Top) { y = GetOptimalBottomHeight(); } int legendItemCounter = 1; foreach (LegendItem item in legendItems) { if (!Row) { CreateColumn(item, y); y -= Font.Height; } else { if (IsNewRow(legendItemCounter)) { x = ClippingArea.X1; y -= Font.Height+15; } CreateRow(item, x, y); x += GetLabelLengthInPixel(item); legendItemCounter++; } } } } /// /// calculates the optimal height, when the legend shall be draw at the bottom /// /// optimal bottom height private double GetOptimalBottomHeight() { int rowsToDraw = 1; for (int i = 0; i < legendItems.Count; i++) { if (IsNewRow(i + 1)) { rowsToDraw++; } } return (Font.Height + 12) * rowsToDraw; } /// /// returns a boolean value, if the new legend item has to be paint in a /// new row /// /// /// true, draw legend item in a new row /// false, draw the legend item in the current row /// private bool IsNewRow(int toCurrentItem) { double sum = 0; double caw = ClippingArea.Width; for (int i = 0; i < toCurrentItem; i++) { sum += GetLabelLengthInPixel(legendItems[i]); if (sum > caw) { return true; } } return false; } /// /// returns the length of the current legenditem in pixel /// /// legend item to calculate the length /// length of the legend item private int GetLabelLengthInPixel(LegendItem item) { int dummy = (int)(item.Label.Length*Font.Size + 20); if (dummy < LegendItem.WIDTH) { return LegendItem.WIDTH; } return dummy; } /// /// draws the legend as a row at the top or bottom of the WorldShape /// /// the legenditem to draw /// x axis to draw the item /// y axis to draw the item private void CreateRow(LegendItem item, double x, double y) { AddShape(new LineShape(x, y - (Font.Height / 2), x + 20, y - (Font.Height / 2), item.Color, item.Thickness, DrawingStyle.Solid)); AddShape(new TextShape(x + 25, y, item.Label, Font, Color)); } /// /// draws the legend as a column on the right or left side of the WorldShape /// /// the legenditem to draw /// y axis to draw the item private void CreateColumn(LegendItem item, double y) { AddShape(new LineShape(10, y - (Font.Height / 2), 30, y - (Font.Height / 2), item.Color, item.Thickness, DrawingStyle.Solid)); AddShape(new TextShape(35, y, item.Label, Font, Color));//Font.Height+12 } /// /// adds a legenditem to the items list /// /// legenditem to add public void AddLegendItem(LegendItem item) { legendItems.Add(item); } /// /// searches the longest label and returns it with factor of the the current font size /// useful to set the width of the legend area on the left or right side /// /// max label length with factor of the current font size public int GetMaxLabelLength() { int maxLabelLength = 0; if (ExistsLegendItems()) { maxLabelLength = legendItems[0].Label.Length; foreach (var item in legendItems) { if (item.Label.Length > maxLabelLength) { maxLabelLength = item.Label.Length; } } maxLabelLength = (int)(maxLabelLength*Font.Size); } return maxLabelLength < LegendItem.WIDTH ? LegendItem.WIDTH : maxLabelLength; } /// /// removes a legenditem from the items list /// /// legenditem to remove public void RemoveLegendItem(LegendItem item) { legendItems.Remove(item); } /// /// deletes the legenditem list /// public void ClearLegendItems() { legendItems.Clear(); } public Color Color { get { return color; } set { color = value; UpdateTextShapes(); } } public Font Font { get { return font; } set { font = value; UpdateTextShapes(); } } /// /// updates the font settings of the legend /// private void UpdateTextShapes() { foreach (IShape shape in shapes) { TextShape textShape = shape as TextShape; if (textShape != null) { textShape.Font = font; textShape.Color = color; } } } } }