[761] | 1 | using System;
|
---|
[860] | 2 | using System.Collections.Generic;
|
---|
[1996] | 3 | using System.Drawing;
|
---|
[1988] | 4 | using System.Globalization;
|
---|
| 5 | using System.Xml;
|
---|
[1996] | 6 | using HeuristicLab.Core;
|
---|
[761] | 7 |
|
---|
| 8 | namespace HeuristicLab.Visualization {
|
---|
[867] | 9 | public enum Action {
|
---|
| 10 | Added,
|
---|
| 11 | Modified,
|
---|
| 12 | Deleted
|
---|
| 13 | }
|
---|
| 14 |
|
---|
[761] | 15 | public delegate void DataRowChangedHandler(IDataRow row);
|
---|
[867] | 16 | public delegate void ValuesChangedHandler(IDataRow row, double[] values, int index, Action action);
|
---|
| 17 | public delegate void ValueChangedHandler(IDataRow row, double value, int index, Action action);
|
---|
[761] | 18 |
|
---|
[1350] | 19 | public class DataRow : DataRowBase {
|
---|
[1233] | 20 | private readonly List<double> dataRow = new List<double>();
|
---|
[761] | 21 |
|
---|
[1285] | 22 | private double minValue = double.MaxValue;
|
---|
| 23 | private double maxValue = double.MinValue;
|
---|
| 24 |
|
---|
[1993] | 25 | public DataRow() {}
|
---|
[1190] | 26 |
|
---|
[867] | 27 | public DataRow(string label) {
|
---|
[1962] | 28 | this.RowSettings.Label = label;
|
---|
[867] | 29 | }
|
---|
| 30 |
|
---|
[1350] | 31 | public override void AddValue(double value) {
|
---|
[1285] | 32 | UpdateMinMaxValue(value);
|
---|
| 33 |
|
---|
[860] | 34 | dataRow.Add(value);
|
---|
[867] | 35 | OnValueChanged(value, dataRow.Count - 1, Action.Added);
|
---|
[761] | 36 | }
|
---|
| 37 |
|
---|
[1350] | 38 | public override void AddValue(double value, int index) {
|
---|
[867] | 39 | //check if index is valid
|
---|
| 40 | if (index >= 0 && index < dataRow.Count) {
|
---|
[1982] | 41 | UpdateMinMaxValue(value);
|
---|
[867] | 42 | dataRow.Insert(index, value);
|
---|
| 43 | OnValueChanged(value, index, Action.Added);
|
---|
| 44 | } else {
|
---|
[1233] | 45 | throw new IndexOutOfRangeException();
|
---|
[867] | 46 | }
|
---|
[761] | 47 | }
|
---|
| 48 |
|
---|
[1350] | 49 | public override void AddValues(double[] values) {
|
---|
[1978] | 50 | int startIndex = dataRow.Count;
|
---|
[860] | 51 |
|
---|
[1978] | 52 | foreach (double value in values) {
|
---|
| 53 | UpdateMinMaxValue(value);
|
---|
| 54 | dataRow.Add(value);
|
---|
[860] | 55 | }
|
---|
[1978] | 56 |
|
---|
| 57 | OnValuesChanged(values, startIndex, Action.Added);
|
---|
[761] | 58 | }
|
---|
| 59 |
|
---|
[1350] | 60 | public override void AddValues(double[] values, int index) {
|
---|
[1983] | 61 | if (index >= 0 && index < dataRow.Count) {
|
---|
| 62 | for (int i = 0; i < values.Length; i++) {
|
---|
| 63 | double value = values[i];
|
---|
| 64 | UpdateMinMaxValue(value);
|
---|
| 65 | dataRow.Insert(index + i, value);
|
---|
[860] | 66 | }
|
---|
[867] | 67 | OnValuesChanged(values, index, Action.Added);
|
---|
[860] | 68 | } else {
|
---|
[1233] | 69 | throw new IndexOutOfRangeException();
|
---|
[860] | 70 | }
|
---|
[761] | 71 | }
|
---|
| 72 |
|
---|
[1350] | 73 | public override void ModifyValue(double value, int index) {
|
---|
[867] | 74 | //check if index is valid
|
---|
| 75 | if (index >= 0 && index < dataRow.Count) {
|
---|
[1983] | 76 | UpdateMinMaxValue(value, index); // bad runtime but works
|
---|
[867] | 77 | dataRow[index] = value;
|
---|
| 78 | OnValueChanged(value, index, Action.Modified);
|
---|
| 79 | } else {
|
---|
[1233] | 80 | throw new IndexOutOfRangeException();
|
---|
[867] | 81 | }
|
---|
[761] | 82 | }
|
---|
| 83 |
|
---|
[1350] | 84 | public override void ModifyValues(double[] values, int index) {
|
---|
[867] | 85 | //check if index to start modification is valid
|
---|
[1983] | 86 | if (index >= 0 && index + values.Length < dataRow.Count) {
|
---|
| 87 | for (int i = 0; i < values.Length; i++) {
|
---|
| 88 | double value = values[i];
|
---|
| 89 | UpdateMinMaxValue(value, index + i); // bad runtime but works
|
---|
| 90 | dataRow[index+i] = value;
|
---|
[867] | 91 | }
|
---|
[1983] | 92 | OnValuesChanged(values, index, Action.Modified);
|
---|
[867] | 93 | } else {
|
---|
[1233] | 94 | throw new IndexOutOfRangeException();
|
---|
[867] | 95 | }
|
---|
[761] | 96 | }
|
---|
| 97 |
|
---|
[1350] | 98 | public override void RemoveValue(int index) {
|
---|
[867] | 99 | if (index >= 0 && index < dataRow.Count) {
|
---|
[1984] | 100 | UpdateMinMaxValueForRemovedValue(index); // bad runtime but works
|
---|
| 101 | double removedValue = dataRow[index];
|
---|
[867] | 102 | dataRow.RemoveAt(index);
|
---|
[1984] | 103 | OnValueChanged(removedValue, index, Action.Deleted);
|
---|
[867] | 104 | } else {
|
---|
[1233] | 105 | throw new IndexOutOfRangeException();
|
---|
[867] | 106 | }
|
---|
[761] | 107 | }
|
---|
| 108 |
|
---|
[1350] | 109 | public override void RemoveValues(int index, int count) {
|
---|
[867] | 110 | if (count > 0) {
|
---|
| 111 | if ((index >= 0) && (index + count <= dataRow.Count)) {
|
---|
[1984] | 112 | double[] removedValues = new double[count];
|
---|
| 113 | for (int i = 0; i < count; i++) {
|
---|
| 114 | removedValues[i] = dataRow[index + i];
|
---|
| 115 | UpdateMinMaxValueForRemovedValue(index); // bad runtime but works
|
---|
| 116 | dataRow.RemoveAt(index);
|
---|
[867] | 117 | }
|
---|
[1984] | 118 | OnValuesChanged(removedValues, index, Action.Deleted);
|
---|
[867] | 119 | } else {
|
---|
[1233] | 120 | throw new IndexOutOfRangeException();
|
---|
[867] | 121 | }
|
---|
| 122 | } else {
|
---|
[1233] | 123 | throw new Exception("parameter count must be > 0!");
|
---|
[867] | 124 | }
|
---|
[761] | 125 | }
|
---|
| 126 |
|
---|
[1350] | 127 | public override int Count {
|
---|
[860] | 128 | get { return dataRow.Count; }
|
---|
[761] | 129 | }
|
---|
| 130 |
|
---|
[1350] | 131 | public override double this[int index] {
|
---|
[860] | 132 | get { return dataRow[index]; }
|
---|
[761] | 133 | set {
|
---|
[860] | 134 | dataRow[index] = value;
|
---|
[867] | 135 | OnValueChanged(value, index, Action.Modified);
|
---|
[761] | 136 | }
|
---|
| 137 | }
|
---|
[1285] | 138 |
|
---|
[1350] | 139 | public override double MinValue {
|
---|
[1285] | 140 | get { return minValue; }
|
---|
| 141 | }
|
---|
| 142 |
|
---|
[1350] | 143 | public override double MaxValue {
|
---|
[1285] | 144 | get { return maxValue; }
|
---|
| 145 | }
|
---|
| 146 |
|
---|
[1984] | 147 | private void UpdateMinMaxValueForRemovedValue(int removedValueIndex) {
|
---|
| 148 | if (minValue == dataRow[removedValueIndex] || maxValue == dataRow[removedValueIndex]) {
|
---|
| 149 | minValue = double.MaxValue;
|
---|
| 150 | maxValue = double.MinValue;
|
---|
| 151 |
|
---|
| 152 | for (int i = 0; i < dataRow.Count; i++) {
|
---|
| 153 | if (i != removedValueIndex) {
|
---|
| 154 | UpdateMinMaxValue(dataRow[i]);
|
---|
| 155 | }
|
---|
| 156 | }
|
---|
| 157 | }
|
---|
| 158 | }
|
---|
| 159 |
|
---|
[1983] | 160 | private void UpdateMinMaxValue(double newValue, int oldValueIndex) {
|
---|
| 161 | if (minValue != dataRow[oldValueIndex] && maxValue != dataRow[oldValueIndex])
|
---|
| 162 | UpdateMinMaxValue(newValue);
|
---|
| 163 | else {
|
---|
| 164 | minValue = double.MaxValue;
|
---|
| 165 | maxValue = double.MinValue;
|
---|
| 166 |
|
---|
| 167 | for (int i = 0; i < dataRow.Count; i++) {
|
---|
| 168 | double value = oldValueIndex != i ? dataRow[i] : newValue;
|
---|
| 169 | UpdateMinMaxValue(value);
|
---|
| 170 | }
|
---|
| 171 | }
|
---|
| 172 | }
|
---|
| 173 |
|
---|
[1285] | 174 | private void UpdateMinMaxValue(double value) {
|
---|
| 175 | maxValue = Math.Max(value, maxValue);
|
---|
| 176 | minValue = Math.Min(value, minValue);
|
---|
| 177 | }
|
---|
[1996] | 178 |
|
---|
| 179 | public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
|
---|
| 180 | XmlNode node = base.GetXmlNode(name, document, persistedObjects);
|
---|
| 181 |
|
---|
| 182 | XmlSupport.SetAttribute("Label", RowSettings.Label, node);
|
---|
| 183 | XmlSupport.SetAttribute("Color", RowSettings.Color.ToArgb().ToString(), node);
|
---|
| 184 | XmlSupport.SetAttribute("LineType", RowSettings.LineType.ToString(), node);
|
---|
| 185 | XmlSupport.SetAttribute("Thickness", RowSettings.Thickness.ToString(), node);
|
---|
| 186 | XmlSupport.SetAttribute("ShowMarkers", RowSettings.ShowMarkers ? "true" : "false", node);
|
---|
| 187 | XmlSupport.SetAttribute("Style", RowSettings.Style.ToString(), node);
|
---|
| 188 |
|
---|
| 189 | node.AppendChild(PersistenceManager.Persist("YAxis", this.YAxis, document, persistedObjects));
|
---|
| 190 |
|
---|
| 191 | List<string> strValues = new List<string>();
|
---|
| 192 | for (int i = 0; i < this.Count; i++) {
|
---|
| 193 | strValues.Add(this[i].ToString(CultureInfo.InvariantCulture));
|
---|
| 194 | }
|
---|
| 195 | XmlElement valuesElement = document.CreateElement("Values");
|
---|
| 196 | valuesElement.InnerText = string.Join(";", strValues.ToArray());
|
---|
| 197 | node.AppendChild(valuesElement);
|
---|
| 198 |
|
---|
| 199 | return node;
|
---|
| 200 | }
|
---|
| 201 |
|
---|
| 202 | public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
|
---|
| 203 | base.Populate(node, restoredObjects);
|
---|
| 204 |
|
---|
| 205 | this.RowSettings.Label = XmlSupport.GetAttribute("Label", "", node);
|
---|
| 206 | this.RowSettings.Color = Color.FromArgb(Int32.Parse(XmlSupport.GetAttribute("Color", Color.Black.ToArgb().ToString(), node)));
|
---|
| 207 | this.RowSettings.LineType = (DataRowType)Enum.Parse(typeof(DataRowType), XmlSupport.GetAttribute("LineType", "Normal", node));
|
---|
| 208 | this.RowSettings.Thickness = Int32.Parse(XmlSupport.GetAttribute("Thickness", "2", node));
|
---|
| 209 | this.RowSettings.ShowMarkers = XmlSupport.GetAttribute("ShowMarkers", "true", node) == "true";
|
---|
| 210 | this.RowSettings.Style = (DrawingStyle)Enum.Parse(typeof(DrawingStyle), XmlSupport.GetAttribute("Style", DrawingStyle.Solid.ToString(), node));
|
---|
| 211 |
|
---|
| 212 | XmlNode yAxisNode = node.SelectSingleNode("YAxis");
|
---|
| 213 | if (yAxisNode != null) {
|
---|
| 214 | this.YAxis = (YAxisDescriptor)PersistenceManager.Restore(yAxisNode, restoredObjects);
|
---|
| 215 | }
|
---|
| 216 |
|
---|
| 217 | XmlNode valuesNode = node.SelectSingleNode("Values");
|
---|
| 218 | if (valuesNode != null) {
|
---|
| 219 | string[] strValues = valuesNode.InnerText.Split(';');
|
---|
| 220 | foreach (string strValue in strValues) {
|
---|
| 221 | double value = double.Parse(strValue, CultureInfo.InvariantCulture);
|
---|
| 222 | this.AddValue(value);
|
---|
| 223 | }
|
---|
| 224 | }
|
---|
| 225 | }
|
---|
[761] | 226 | }
|
---|
| 227 | } |
---|