Changeset 9421 for branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionBubbleChartView.cs
- Timestamp:
- 05/02/13 13:34:32 (11 years ago)
- Location:
- branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Optimization.Views
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Optimization.Views
- Property svn:mergeinfo changed
/trunk/sources/HeuristicLab.Optimization.Views merged: 9229,9235-9236,9267,9276-9277,9312-9313,9315,9332,9340,9404
- Property svn:mergeinfo changed
-
branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionBubbleChartView.cs
r9240 r9421 20 20 #endregion 21 21 22 using HeuristicLab.Common;23 using HeuristicLab.Core;24 using HeuristicLab.Data;25 using HeuristicLab.MainForm;26 using HeuristicLab.MainForm.WindowsForms;27 22 using System; 28 23 using System.Collections.Generic; … … 31 26 using System.Windows.Forms; 32 27 using System.Windows.Forms.DataVisualization.Charting; 28 using HeuristicLab.Common; 29 using HeuristicLab.Core; 30 using HeuristicLab.Data; 31 using HeuristicLab.MainForm; 32 using HeuristicLab.MainForm.WindowsForms; 33 33 34 34 namespace HeuristicLab.Optimization.Views { … … 43 43 private string sizeAxisValue; 44 44 45 private Dictionary<IRun, List<DataPoint>> runToDataPointMapping; 46 private Dictionary<int, Dictionary<object, double>> categoricalMapping; 47 private Dictionary<IRun, double> xJitter; 48 private Dictionary<IRun, double> yJitter; 45 private readonly Dictionary<IRun, List<DataPoint>> runToDataPointMapping = new Dictionary<IRun, List<DataPoint>>(); 46 private readonly Dictionary<IRun, int> runToIndexMapping = new Dictionary<IRun, int>(); 47 private readonly Dictionary<int, Dictionary<object, double>> categoricalMapping = new Dictionary<int, Dictionary<object, double>>(); 48 private readonly Dictionary<IRun, double> xJitter = new Dictionary<IRun, double>(); 49 private readonly Dictionary<IRun, double> yJitter = new Dictionary<IRun, double>(); 50 51 private readonly HashSet<IRun> selectedRuns = new HashSet<IRun>(); 52 private readonly Random random = new Random(); 49 53 private double xJitterFactor = 0.0; 50 54 private double yJitterFactor = 0.0; 51 private Random random;52 55 private bool isSelecting = false; 53 56 private bool suppressUpdates = false; 57 54 58 55 59 public RunCollectionBubbleChartView() { … … 61 65 chart.ContextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(ContextMenuStrip_Opening); 62 66 63 runToDataPointMapping = new Dictionary<IRun, List<DataPoint>>();64 categoricalMapping = new Dictionary<int, Dictionary<object, double>>();65 xJitter = new Dictionary<IRun, double>();66 yJitter = new Dictionary<IRun, double>();67 random = new Random();68 69 67 colorDialog.Color = Color.Black; 70 color Button.Image = this.GenerateImage(16, 16, this.colorDialog.Color);68 colorDialogButton.Image = this.GenerateImage(16, 16, this.colorDialog.Color); 71 69 isSelecting = false; 72 70 … … 84 82 public IStringConvertibleMatrix Matrix { 85 83 get { return this.Content; } 84 } 85 public IEnumerable<IRun> SelectedRuns { 86 get { return selectedRuns; } 86 87 } 87 88 … … 93 94 Content.ItemsRemoved += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved); 94 95 Content.CollectionReset += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset); 96 Content.OptimizerNameChanged += new EventHandler(Content_AlgorithmNameChanged); 95 97 Content.UpdateOfRunsInProgressChanged += new EventHandler(Content_UpdateOfRunsInProgressChanged); 96 Content.OptimizerNameChanged += new EventHandler(Content_AlgorithmNameChanged);97 98 RegisterRunEvents(Content); 98 99 } … … 104 105 Content.ItemsRemoved -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved); 105 106 Content.CollectionReset -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset); 107 Content.OptimizerNameChanged -= new EventHandler(Content_AlgorithmNameChanged); 106 108 Content.UpdateOfRunsInProgressChanged -= new EventHandler(Content_UpdateOfRunsInProgressChanged); 107 Content.OptimizerNameChanged -= new EventHandler(Content_AlgorithmNameChanged);108 109 DeregisterRunEvents(Content); 109 110 } … … 128 129 } 129 130 private void run_Changed(object sender, EventArgs e) { 131 if (suppressUpdates) return; 130 132 if (InvokeRequired) 131 133 this.Invoke(new EventHandler(run_Changed), sender, e); … … 133 135 IRun run = (IRun)sender; 134 136 UpdateRun(run); 137 UpdateCursorInterval(); 138 chart.ChartAreas[0].RecalculateAxesScale(); 139 UpdateAxisLabels(); 140 } 141 } 142 143 private void Content_UpdateOfRunsInProgressChanged(object sender, EventArgs e) { 144 if (InvokeRequired) 145 this.Invoke(new EventHandler(Content_UpdateOfRunsInProgressChanged), sender, e); 146 else { 147 suppressUpdates = Content.UpdateOfRunsInProgress; 148 if (suppressUpdates) return; 149 150 foreach (var run in Content) UpdateRun(run); 151 UpdateMarkerSizes(); 152 UpdateCursorInterval(); 153 chart.ChartAreas[0].RecalculateAxesScale(); 154 UpdateAxisLabels(); 135 155 } 136 156 } 137 157 138 158 private void UpdateRun(IRun run) { 139 if (!suppressUpdates) { 140 if (runToDataPointMapping.ContainsKey(run)) { 141 foreach (DataPoint point in runToDataPointMapping[run]) { 142 point.Color = run.Color; 143 if (!run.Visible) { 144 this.chart.Series[0].Points.Remove(point); 145 UpdateCursorInterval(); 146 chart.ChartAreas[0].RecalculateAxesScale(); 147 } 159 if (runToDataPointMapping.ContainsKey(run)) { 160 foreach (DataPoint point in runToDataPointMapping[run]) { 161 if (!run.Visible) { 162 this.chart.Series[0].Points.Remove(point); 163 continue; 148 164 } 149 if (!run.Visible) runToDataPointMapping.Remove(run); 150 } else { 151 AddDataPoint(run); 152 UpdateCursorInterval(); 153 chart.ChartAreas[0].RecalculateAxesScale(); 154 } 155 156 if (this.chart.Series[0].Points.Count == 0) 157 noRunsLabel.Visible = true; 158 else 159 noRunsLabel.Visible = false; 160 } 165 if (selectedRuns.Contains(run)) { 166 point.Color = Color.Red; 167 point.MarkerStyle = MarkerStyle.Cross; 168 } else { 169 point.Color = Color.FromArgb(255 - transparencyTrackBar.Value, ((IRun)point.Tag).Color); 170 point.MarkerStyle = MarkerStyle.Circle; 171 } 172 173 } 174 if (!run.Visible) runToDataPointMapping.Remove(run); 175 } else { 176 AddDataPoint(run); 177 } 178 179 if (this.chart.Series[0].Points.Count == 0) 180 noRunsLabel.Visible = true; 181 else 182 noRunsLabel.Visible = false; 161 183 } 162 184 … … 167 189 UpdateDataPoints(); 168 190 UpdateCaption(); 169 } 191 RebuildInverseIndex(); 192 } 193 194 private void RebuildInverseIndex() { 195 if (Content != null) { 196 runToIndexMapping.Clear(); 197 int i = 0; 198 foreach (var run in Content) { 199 runToIndexMapping.Add(run, i); 200 i++; 201 } 202 } 203 } 204 170 205 private void Content_ColumnNamesChanged(object sender, EventArgs e) { 171 206 if (InvokeRequired) … … 210 245 changed = true; 211 246 } 212 if (changed) 247 if (changed) { 213 248 UpdateDataPoints(); 214 } 215 } 216 217 218 private void Content_UpdateOfRunsInProgressChanged(object sender, EventArgs e) { 219 if (InvokeRequired) 220 Invoke(new EventHandler(Content_UpdateOfRunsInProgressChanged), sender, e); 221 else { 222 suppressUpdates = Content.UpdateOfRunsInProgress; 223 if (!suppressUpdates) UpdateDataPoints(); 249 UpdateAxisLabels(); 250 } 224 251 } 225 252 } … … 236 263 else { 237 264 this.categoricalMapping.Clear(); 265 RebuildInverseIndex(); 238 266 UpdateDataPoints(); 267 UpdateAxisLabels(); 239 268 } 240 269 } … … 244 273 series.Points.Clear(); 245 274 runToDataPointMapping.Clear(); 275 selectedRuns.Clear(); 246 276 247 277 chart.ChartAreas[0].AxisX.IsMarginVisible = xAxisValue != AxisDimension.Index.ToString(); … … 272 302 273 303 private void UpdateMarkerSizes() { 274 double[] sizeValues = this.chart.Series[0].Points.Select(p => p.YValues[1]).ToArray(); 304 var series = chart.Series[0]; 305 if (series.Points.Count <= 0) return; 306 307 var sizeValues = series.Points.Select(p => p.YValues[1]); 275 308 double minSizeValue = sizeValues.Min(); 276 309 double maxSizeValue = sizeValues.Max(); 277 278 for (int i = 0; i < sizeValues.Length; i++) { 279 DataPoint point = this.chart.Series[0].Points[i]; 280 double sizeRange = maxSizeValue - minSizeValue; 310 double sizeRange = maxSizeValue - minSizeValue; 311 312 const int smallestBubbleSize = 5; 313 314 foreach (DataPoint point in series.Points) { 315 //calculates the relative size of the data point 0 <= relativeSize <= 1 281 316 double relativeSize = (point.YValues[1] - minSizeValue); 282 283 if (sizeRange > double.Epsilon) relativeSize /= sizeRange; 284 else relativeSize = 1; 285 286 point.MarkerSize = (int)Math.Round((sizeTrackBar.Value - sizeTrackBar.Minimum) * relativeSize + sizeTrackBar.Minimum); 317 if (sizeRange > double.Epsilon) { 318 relativeSize /= sizeRange; 319 320 //invert bubble sizes if the value of the trackbar is negative 321 if (sizeTrackBar.Value < 0) relativeSize = Math.Abs(relativeSize - 1); 322 } else relativeSize = 1; 323 324 double sizeChange = Math.Abs(sizeTrackBar.Value) * relativeSize; 325 point.MarkerSize = (int)Math.Round(sizeChange + smallestBubbleSize); 287 326 } 288 327 } … … 344 383 if (xValue.HasValue && yValue.HasValue && sizeValue.HasValue) { 345 384 xValue = xValue.Value; 346 347 385 yValue = yValue.Value; 348 386 … … 350 388 DataPoint point = new DataPoint(xValue.Value, new double[] { yValue.Value, sizeValue.Value }); 351 389 point.Tag = run; 352 point.Color = run.Color;353 390 series.Points.Add(point); 354 391 if (!runToDataPointMapping.ContainsKey(run)) runToDataPointMapping.Add(run, new List<DataPoint>()); 355 392 runToDataPointMapping[run].Add(point); 393 UpdateRun(run); 356 394 } 357 395 } … … 391 429 } 392 430 private double GetCategoricalValue(int dimension, string value) { 393 if (!this.categoricalMapping.ContainsKey(dimension)) 431 if (!this.categoricalMapping.ContainsKey(dimension)) { 394 432 this.categoricalMapping[dimension] = new Dictionary<object, double>(); 395 if (!this.categoricalMapping[dimension].ContainsKey(value)) { 396 if (this.categoricalMapping[dimension].Values.Count == 0) 397 this.categoricalMapping[dimension][value] = 1.0; 398 else 399 this.categoricalMapping[dimension][value] = this.categoricalMapping[dimension].Values.Max() + 1.0; 433 var orderedCategories = Content.Where(r => r.Visible).Select(r => Content.GetValue(r, dimension).ToString()) 434 .Distinct() 435 .OrderBy(x => x, new NaturalStringComparer()); 436 int count = 1; 437 foreach (var category in orderedCategories) { 438 this.categoricalMapping[dimension].Add(category, count); 439 count++; 440 } 400 441 } 401 442 return this.categoricalMapping[dimension][value]; 402 443 } 444 403 445 private double GetValue(IRun run, AxisDimension axisDimension) { 404 446 double value = double.NaN; 405 447 switch (axisDimension) { 406 448 case AxisDimension.Index: { 407 value = Content.ToList().IndexOf(run);449 value = runToIndexMapping[run]; 408 450 break; 409 451 } … … 428 470 } 429 471 private void UpdateCursorInterval() { 430 Series series = chart.Series[0]; 431 double[] xValues = (from point in series.Points 432 where !point.IsEmpty 433 select point.XValue) 434 .DefaultIfEmpty(1.0) 435 .ToArray(); 436 double[] yValues = (from point in series.Points 437 where !point.IsEmpty 438 select point.YValues[0]) 439 .DefaultIfEmpty(1.0) 440 .ToArray(); 441 442 double xRange = xValues.Max() - xValues.Min(); 443 double yRange = yValues.Max() - yValues.Min(); 472 double xMin = double.MaxValue; 473 double xMax = double.MinValue; 474 double yMin = double.MaxValue; 475 double yMax = double.MinValue; 476 477 foreach (var point in chart.Series[0].Points) { 478 if (point.IsEmpty) continue; 479 if (point.XValue < xMin) xMin = point.XValue; 480 if (point.XValue > xMax) xMax = point.XValue; 481 if (point.YValues[0] < yMin) yMin = point.YValues[0]; 482 if (point.YValues[0] > yMax) yMax = point.YValues[0]; 483 } 484 485 double xRange = 0.0; 486 double yRange = 0.0; 487 if (xMin != double.MaxValue && xMax != double.MinValue) xRange = xMax - xMin; 488 if (yMin != double.MaxValue && yMax != double.MinValue) yRange = yMax - yMin; 489 444 490 if (xRange.IsAlmost(0.0)) xRange = 1.0; 445 491 if (yRange.IsAlmost(0.0)) yRange = 1.0; … … 479 525 480 526 private void chart_MouseUp(object sender, MouseEventArgs e) { 481 if (isSelecting) { 482 System.Windows.Forms.DataVisualization.Charting.Cursor xCursor = chart.ChartAreas[0].CursorX; 483 System.Windows.Forms.DataVisualization.Charting.Cursor yCursor = chart.ChartAreas[0].CursorY; 484 485 double minX = Math.Min(xCursor.SelectionStart, xCursor.SelectionEnd); 486 double maxX = Math.Max(xCursor.SelectionStart, xCursor.SelectionEnd); 487 double minY = Math.Min(yCursor.SelectionStart, yCursor.SelectionEnd); 488 double maxY = Math.Max(yCursor.SelectionStart, yCursor.SelectionEnd); 489 490 //check for click to select model 491 if (minX == maxX && minY == maxY) { 492 HitTestResult hitTest = chart.HitTest(e.X, e.Y); 493 if (hitTest.ChartElementType == ChartElementType.DataPoint) { 494 int pointIndex = hitTest.PointIndex; 495 IRun run = (IRun)this.chart.Series[0].Points[pointIndex].Tag; 496 run.Color = colorDialog.Color; 497 } 498 } else { 499 List<DataPoint> selectedPoints = new List<DataPoint>(); 500 foreach (DataPoint p in this.chart.Series[0].Points) { 501 if (p.XValue >= minX && p.XValue < maxX && 502 p.YValues[0] >= minY && p.YValues[0] < maxY) { 503 selectedPoints.Add(p); 504 } 505 } 506 foreach (DataPoint p in selectedPoints) { 507 IRun run = (IRun)p.Tag; 508 run.Color = colorDialog.Color; 509 } 510 } 511 this.chart.ChartAreas[0].CursorX.SelectionStart = this.chart.ChartAreas[0].CursorX.SelectionEnd; 512 this.chart.ChartAreas[0].CursorY.SelectionStart = this.chart.ChartAreas[0].CursorY.SelectionEnd; 513 } 527 if (!isSelecting) return; 528 529 System.Windows.Forms.DataVisualization.Charting.Cursor xCursor = chart.ChartAreas[0].CursorX; 530 System.Windows.Forms.DataVisualization.Charting.Cursor yCursor = chart.ChartAreas[0].CursorY; 531 532 double minX = Math.Min(xCursor.SelectionStart, xCursor.SelectionEnd); 533 double maxX = Math.Max(xCursor.SelectionStart, xCursor.SelectionEnd); 534 double minY = Math.Min(yCursor.SelectionStart, yCursor.SelectionEnd); 535 double maxY = Math.Max(yCursor.SelectionStart, yCursor.SelectionEnd); 536 537 //check for click to select a single model 538 if (minX == maxX && minY == maxY) { 539 HitTestResult hitTest = chart.HitTest(e.X, e.Y, ChartElementType.DataPoint); 540 if (hitTest.ChartElementType == ChartElementType.DataPoint) { 541 int pointIndex = hitTest.PointIndex; 542 var point = chart.Series[0].Points[pointIndex]; 543 IRun run = (IRun)point.Tag; 544 point.Color = Color.Red; 545 point.MarkerStyle = MarkerStyle.Cross; 546 selectedRuns.Add(run); 547 548 } else ClearSelectedRuns(); 549 } else { 550 foreach (DataPoint point in this.chart.Series[0].Points) { 551 if (point.XValue < minX || point.XValue >= maxX) continue; 552 if (point.YValues[0] < minY || point.YValues[0] >= maxY) continue; 553 point.MarkerStyle = MarkerStyle.Cross; 554 point.Color = Color.Red; 555 IRun run = (IRun)point.Tag; 556 selectedRuns.Add(run); 557 } 558 } 559 560 this.chart.ChartAreas[0].CursorX.SelectionStart = this.chart.ChartAreas[0].CursorX.SelectionEnd; 561 this.chart.ChartAreas[0].CursorY.SelectionStart = this.chart.ChartAreas[0].CursorY.SelectionEnd; 562 this.OnChanged(); 514 563 } 515 564 516 565 private void chart_MouseMove(object sender, MouseEventArgs e) { 566 if (Control.MouseButtons != MouseButtons.None) return; 517 567 HitTestResult h = this.chart.HitTest(e.X, e.Y); 518 568 string newTooltipText = string.Empty; … … 638 688 private void zoomButton_CheckedChanged(object sender, EventArgs e) { 639 689 this.isSelecting = selectButton.Checked; 640 this.colorButton.Enabled = this.isSelecting; 690 this.colorDialogButton.Enabled = this.isSelecting; 691 this.colorRunsButton.Enabled = this.isSelecting; 692 this.hideRunsButton.Enabled = this.isSelecting; 641 693 this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = !isSelecting; 642 694 this.chart.ChartAreas[0].AxisY.ScaleView.Zoomable = !isSelecting; 643 } 644 private void colorButton_Click(object sender, EventArgs e) { 645 if (colorDialog.ShowDialog(this) == DialogResult.OK) { 646 this.colorButton.Image = this.GenerateImage(16, 16, this.colorDialog.Color); 647 } 648 } 649 private Image GenerateImage(int width, int height, Color fillColor) { 650 Image colorImage = new Bitmap(width, height); 651 using (Graphics gfx = Graphics.FromImage(colorImage)) { 652 using (SolidBrush brush = new SolidBrush(fillColor)) { 653 gfx.FillRectangle(brush, 0, 0, width, height); 654 } 655 } 656 return colorImage; 695 ClearSelectedRuns(); 657 696 } 658 697 … … 673 712 } 674 713 private void hideRunToolStripMenuItem_Click(object sender, EventArgs e) { 675 var constraint = Content.Constraints.OfType<RunCollectionContentConstraint>(). Where(c => c.Active).FirstOrDefault();714 var constraint = Content.Constraints.OfType<RunCollectionContentConstraint>().FirstOrDefault(c => c.Active); 676 715 if (constraint == null) { 677 716 constraint = new RunCollectionContentConstraint(); … … 680 719 } 681 720 constraint.ConstraintData.Add(runToHide); 721 } 722 private void hideRunsButton_Click(object sender, EventArgs e) { 723 if (!selectedRuns.Any()) return; 724 var constraint = new RunCollectionContentConstraint(); 725 constraint.ConstraintData = new ItemSet<IRun>(selectedRuns); 726 Content.Constraints.Add(constraint); 727 ClearSelectedRuns(); 728 constraint.Active = true; 729 } 730 731 private void ClearSelectedRuns() { 732 foreach (var run in selectedRuns) { 733 foreach (var point in runToDataPointMapping[run]) { 734 point.MarkerStyle = MarkerStyle.Circle; 735 point.Color = Color.FromArgb(255 - LogTransform(transparencyTrackBar.Value), run.Color); 736 } 737 } 738 selectedRuns.Clear(); 739 } 740 741 // returns a value in [0..255] 742 private int LogTransform(int x) { 743 double min = transparencyTrackBar.Minimum; 744 double max = transparencyTrackBar.Maximum; 745 double r = (x - min) / (max - min); // r \in [0..1] 746 double l = Math.Log(r + 1) / Math.Log(2.0); // l \in [0..1] 747 return (int)Math.Round(255.0 * l); 682 748 } 683 749 … … 692 758 private void getDataAsMatrixToolStripMenuItem_Click(object sender, EventArgs e) { 693 759 int xCol = Matrix.ColumnNames.ToList().IndexOf(xAxisValue); 760 int yCol = Matrix.ColumnNames.ToList().IndexOf(yAxisValue); 761 694 762 var grouped = new Dictionary<string, List<string>>(); 695 763 Dictionary<double, string> reverseMapping = null; … … 698 766 foreach (var run in Content.Where(r => r.Visible)) { 699 767 var x = GetValue(run, xAxisValue); 700 var y = GetValue(run, yAxisValue); 701 if (!(x.HasValue && y.HasValue)) continue; 768 object y; 769 if (categoricalMapping.ContainsKey(yCol)) 770 y = Content.GetValue(run, yAxisValue); 771 else y = GetValue(run, yAxisValue); 772 if (!(x.HasValue && y != null)) continue; 702 773 703 774 var category = reverseMapping == null ? x.Value.ToString() : reverseMapping[x.Value]; 704 775 if (!grouped.ContainsKey(category)) grouped[category] = new List<string>(); 705 grouped[category].Add(y. Value.ToString());776 grouped[category].Add(y.ToString()); 706 777 } 707 778 … … 717 788 i++; 718 789 } 719 720 MainFormManager.MainForm.ShowContent(matrix); 790 matrix.SortableView = false; 791 var view = MainFormManager.MainForm.ShowContent(matrix); 792 view.ReadOnly = true; 793 } 794 795 private void transparencyTrackBar_ValueChanged(object sender, EventArgs e) { 796 foreach (var run in Content) 797 UpdateRun(run); 721 798 } 722 799 #endregion 723 800 724 #region Automatic coloring 801 #region coloring 802 private void colorDialogButton_Click(object sender, EventArgs e) { 803 if (colorDialog.ShowDialog(this) == DialogResult.OK) { 804 this.colorDialogButton.Image = this.GenerateImage(16, 16, this.colorDialog.Color); 805 } 806 } 807 private Image GenerateImage(int width, int height, Color fillColor) { 808 Image colorImage = new Bitmap(width, height); 809 using (Graphics gfx = Graphics.FromImage(colorImage)) { 810 using (SolidBrush brush = new SolidBrush(fillColor)) { 811 gfx.FillRectangle(brush, 0, 0, width, height); 812 } 813 } 814 return colorImage; 815 } 816 817 private void colorRunsButton_Click(object sender, EventArgs e) { 818 if (!selectedRuns.Any()) return; 819 Content.UpdateOfRunsInProgress = true; 820 foreach (var run in selectedRuns) 821 run.Color = colorDialog.Color; 822 823 ClearSelectedRuns(); 824 Content.UpdateOfRunsInProgress = false; 825 } 826 725 827 private void colorXAxisButton_Click(object sender, EventArgs e) { 726 828 ColorRuns(xAxisValue); 727 829 } 728 729 830 private void colorYAxisButton_Click(object sender, EventArgs e) { 730 831 ColorRuns(yAxisValue); 731 832 } 732 733 833 private void ColorRuns(string axisValue) { 734 var runs = Content.Where(r => r.Visible).Select(r => new { Run = r, Value = GetValue(r, axisValue) }).Where(r => r.Value.HasValue) ;834 var runs = Content.Where(r => r.Visible).Select(r => new { Run = r, Value = GetValue(r, axisValue) }).Where(r => r.Value.HasValue).ToList(); 735 835 double minValue = runs.Min(r => r.Value.Value); 736 836 double maxValue = runs.Max(r => r.Value.Value); 737 837 double range = maxValue - minValue; 738 739 foreach (var r in runs) { 740 int colorIndex = 0; 741 if (!range.IsAlmost(0)) colorIndex = (int)((ColorGradient.Colors.Count - 1) * (r.Value.Value - minValue) / (range)); 742 r.Run.Color = ColorGradient.Colors[colorIndex]; 743 } 838 // UpdateOfRunsInProgress has to be set to true, otherwise run_Changed is called all the time (also in other views) 839 Content.UpdateOfRunsInProgress = true; 840 if (range.IsAlmost(0)) { 841 Color c = ColorGradient.Colors[0]; 842 runs.ForEach(r => r.Run.Color = c); 843 } else { 844 int maxColorIndex = ColorGradient.Colors.Count - 1; 845 foreach (var r in runs) { 846 int colorIndex = (int)(maxColorIndex * (r.Value - minValue) / (range)); 847 r.Run.Color = ColorGradient.Colors[colorIndex]; 848 } 849 } 850 Content.UpdateOfRunsInProgress = false; 744 851 } 745 852 #endregion
Note: See TracChangeset
for help on using the changeset viewer.