- Timestamp:
- 01/13/17 12:55:06 (7 years ago)
- Location:
- branches/MemPRAlgorithm
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/MemPRAlgorithm
-
branches/MemPRAlgorithm/HeuristicLab.Analysis.Views
- Property svn:mergeinfo changed
/trunk/sources/HeuristicLab.Analysis.Views (added) merged: 14435-14439,14457-14458,14493,14508,14516,14519
- Property svn:mergeinfo changed
-
branches/MemPRAlgorithm/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.cs
r14185 r14562 21 21 22 22 using System; 23 using System.Collections.Generic;24 using System.Drawing;25 using System.Linq;26 23 using System.Windows.Forms; 27 using System.Windows.Forms.DataVisualization.Charting;28 using HeuristicLab.Collections;29 using HeuristicLab.Common;30 24 using HeuristicLab.Core.Views; 31 25 using HeuristicLab.MainForm; … … 35 29 [Content(typeof(ScatterPlot), true)] 36 30 public partial class ScatterPlotView : NamedItemView, IConfigureableView { 37 protected List<Series> invisibleSeries;38 protected Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow> pointsRowsTable;39 private double xMin, xMax, yMin, yMax;40 31 41 32 public new ScatterPlot Content { … … 46 37 public ScatterPlotView() { 47 38 InitializeComponent(); 48 pointsRowsTable = new Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow>();49 invisibleSeries = new List<Series>();50 chart.CustomizeAllChartAreas();51 chart.ChartAreas[0].CursorX.Interval = 1;52 39 } 53 54 #region Event Handler Registration55 protected override void DeregisterContentEvents() {56 foreach (ScatterPlotDataRow row in Content.Rows)57 DeregisterScatterPlotDataRowEvents(row);58 Content.VisualPropertiesChanged -= new EventHandler(Content_VisualPropertiesChanged);59 Content.Rows.ItemsAdded -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded);60 Content.Rows.ItemsRemoved -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved);61 Content.Rows.ItemsReplaced -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced);62 Content.Rows.CollectionReset -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset);63 base.DeregisterContentEvents();64 }65 protected override void RegisterContentEvents() {66 base.RegisterContentEvents();67 Content.VisualPropertiesChanged += new EventHandler(Content_VisualPropertiesChanged);68 Content.Rows.ItemsAdded += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded);69 Content.Rows.ItemsRemoved += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved);70 Content.Rows.ItemsReplaced += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced);71 Content.Rows.CollectionReset += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset);72 }73 74 protected virtual void RegisterScatterPlotDataRowEvents(ScatterPlotDataRow row) {75 row.NameChanged += new EventHandler(Row_NameChanged);76 row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged);77 pointsRowsTable.Add(row.Points, row);78 row.Points.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded);79 row.Points.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved);80 row.Points.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced);81 row.Points.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset);82 }83 protected virtual void DeregisterScatterPlotDataRowEvents(ScatterPlotDataRow row) {84 row.Points.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded);85 row.Points.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved);86 row.Points.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced);87 row.Points.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset);88 pointsRowsTable.Remove(row.Points);89 row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged);90 row.NameChanged -= new EventHandler(Row_NameChanged);91 }92 #endregion93 40 94 41 protected override void OnContentChanged() { 95 42 base.OnContentChanged(); 96 invisibleSeries.Clear(); 97 chart.Titles[0].Text = string.Empty; 98 chart.ChartAreas[0].AxisX.Title = string.Empty; 99 chart.ChartAreas[0].AxisY.Title = string.Empty; 100 chart.Series.Clear(); 101 if (Content != null) { 102 chart.Titles[0].Text = Content.Name; 103 AddScatterPlotDataRows(Content.Rows); 104 ConfigureChartArea(chart.ChartAreas[0]); 105 RecalculateMinMaxPointValues(); 106 RecalculateAxesScale(chart.ChartAreas[0]); 107 } 43 chart.Content = Content; 108 44 } 109 45 … … 114 50 115 51 public void ShowConfiguration() { 116 if (Content != null) { 117 using (ScatterPlotVisualPropertiesDialog dialog = new ScatterPlotVisualPropertiesDialog(Content)) { 118 dialog.ShowDialog(this); 119 } 120 } else MessageBox.Show("Nothing to configure."); 52 chart.ShowConfiguration(); 121 53 } 122 54 123 protected virtual void AddScatterPlotDataRows(IEnumerable<ScatterPlotDataRow> rows) {124 foreach (var row in rows) {125 RegisterScatterPlotDataRowEvents(row);126 Series series = new Series(row.Name);127 if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;128 else series.LegendText = row.Name;129 ConfigureSeries(series, row);130 FillSeriesWithRowValues(series, row);131 chart.Series.Add(series);132 }133 ConfigureChartArea(chart.ChartAreas[0]);134 RecalculateMinMaxPointValues();135 RecalculateAxesScale(chart.ChartAreas[0]);136 UpdateYCursorInterval();137 }138 139 protected virtual void RemoveScatterPlotDataRows(IEnumerable<ScatterPlotDataRow> rows) {140 foreach (var row in rows) {141 DeregisterScatterPlotDataRowEvents(row);142 Series series = chart.Series[row.Name];143 chart.Series.Remove(series);144 if (invisibleSeries.Contains(series))145 invisibleSeries.Remove(series);146 }147 RecalculateMinMaxPointValues();148 RecalculateAxesScale(chart.ChartAreas[0]);149 }150 151 private void ConfigureSeries(Series series, ScatterPlotDataRow row) {152 series.BorderWidth = 1;153 series.BorderDashStyle = ChartDashStyle.Solid;154 series.BorderColor = Color.Empty;155 156 if (row.VisualProperties.Color != Color.Empty)157 series.Color = row.VisualProperties.Color;158 else series.Color = Color.Empty;159 series.IsVisibleInLegend = row.VisualProperties.IsVisibleInLegend;160 series.ChartType = SeriesChartType.FastPoint;161 series.MarkerSize = row.VisualProperties.PointSize;162 series.MarkerStyle = ConvertPointStyle(row.VisualProperties.PointStyle);163 series.XAxisType = AxisType.Primary;164 series.YAxisType = AxisType.Primary;165 166 if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;167 else series.LegendText = row.Name;168 169 string xAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.XAxisTitle)170 ? "X"171 : Content.VisualProperties.XAxisTitle;172 string yAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.YAxisTitle)173 ? "Y"174 : Content.VisualProperties.YAxisTitle;175 series.ToolTip =176 series.LegendText + Environment.NewLine +177 xAxisTitle + " = " + "#VALX," + Environment.NewLine +178 yAxisTitle + " = " + "#VAL";179 }180 181 private void ConfigureChartArea(ChartArea area) {182 if (Content.VisualProperties.TitleFont != null) chart.Titles[0].Font = Content.VisualProperties.TitleFont;183 if (!Content.VisualProperties.TitleColor.IsEmpty) chart.Titles[0].ForeColor = Content.VisualProperties.TitleColor;184 chart.Titles[0].Text = Content.VisualProperties.Title;185 186 if (Content.VisualProperties.AxisTitleFont != null) area.AxisX.TitleFont = Content.VisualProperties.AxisTitleFont;187 if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX.TitleForeColor = Content.VisualProperties.AxisTitleColor;188 area.AxisX.Title = Content.VisualProperties.XAxisTitle;189 area.AxisX.MajorGrid.Enabled = Content.VisualProperties.XAxisGrid;190 191 if (Content.VisualProperties.AxisTitleFont != null) area.AxisY.TitleFont = Content.VisualProperties.AxisTitleFont;192 if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY.TitleForeColor = Content.VisualProperties.AxisTitleColor;193 area.AxisY.Title = Content.VisualProperties.YAxisTitle;194 area.AxisY.MajorGrid.Enabled = Content.VisualProperties.YAxisGrid;195 }196 197 private void RecalculateAxesScale(ChartArea area) {198 area.AxisX.Minimum = CalculateMinBound(xMin);199 area.AxisX.Maximum = CalculateMaxBound(xMax);200 if (area.AxisX.Minimum == area.AxisX.Maximum) {201 area.AxisX.Minimum = xMin - 0.5;202 area.AxisX.Maximum = xMax + 0.5;203 }204 area.AxisY.Minimum = CalculateMinBound(yMin);205 area.AxisY.Maximum = CalculateMaxBound(yMax);206 if (area.AxisY.Minimum == area.AxisY.Maximum) {207 area.AxisY.Minimum = yMin - 0.5;208 area.AxisY.Maximum = yMax + 0.5;209 }210 if (xMax - xMin > 0) area.CursorX.Interval = Math.Pow(10, Math.Floor(Math.Log10(area.AxisX.Maximum - area.AxisX.Minimum) - 3));211 else area.CursorX.Interval = 1;212 area.AxisX.IsMarginVisible = false;213 214 if (!Content.VisualProperties.XAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue)) area.AxisX.Minimum = Content.VisualProperties.XAxisMinimumFixedValue;215 if (!Content.VisualProperties.XAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue)) area.AxisX.Maximum = Content.VisualProperties.XAxisMaximumFixedValue;216 if (!Content.VisualProperties.YAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.YAxisMinimumFixedValue)) area.AxisY.Minimum = Content.VisualProperties.YAxisMinimumFixedValue;217 if (!Content.VisualProperties.YAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.YAxisMaximumFixedValue)) area.AxisY.Maximum = Content.VisualProperties.YAxisMaximumFixedValue;218 }219 220 private static double CalculateMinBound(double min) {221 if (min == 0) return 0;222 var scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(min))));223 return scale * (Math.Floor(min / scale));224 }225 226 private static double CalculateMaxBound(double max) {227 if (max == 0) return 0;228 var scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(max))));229 return scale * (Math.Ceiling(max / scale));230 }231 232 protected virtual void UpdateYCursorInterval() {233 double interestingValuesRange = (234 from series in chart.Series235 where series.Enabled236 let values = (from point in series.Points237 where !point.IsEmpty238 select point.YValues[0]).DefaultIfEmpty(1.0)239 let range = values.Max() - values.Min()240 where range > 0.0241 select range242 ).DefaultIfEmpty(1.0).Min();243 244 double digits = (int)Math.Log10(interestingValuesRange) - 3;245 double yZoomInterval = Math.Pow(10, digits);246 this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;247 }248 249 #region Event Handlers250 55 #region Content Event Handlers 251 56 protected override void Content_NameChanged(object sender, EventArgs e) { … … 253 58 Invoke(new EventHandler(Content_NameChanged), sender, e); 254 59 else { 255 chart.Titles[0].Text= Content.Name;60 Content.VisualProperties.Title = Content.Name; 256 61 base.Content_NameChanged(sender, e); 257 62 } 258 }259 private void Content_VisualPropertiesChanged(object sender, EventArgs e) {260 if (InvokeRequired)261 Invoke(new EventHandler(Content_VisualPropertiesChanged), sender, e);262 else {263 ConfigureChartArea(chart.ChartAreas[0]);264 RecalculateAxesScale(chart.ChartAreas[0]); // axes min/max could have changed265 }266 }267 #endregion268 #region Rows Event Handlers269 private void Rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {270 if (InvokeRequired)271 Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded), sender, e);272 else {273 AddScatterPlotDataRows(e.Items);274 }275 }276 private void Rows_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {277 if (InvokeRequired)278 Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved), sender, e);279 else {280 RemoveScatterPlotDataRows(e.Items);281 }282 }283 private void Rows_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {284 if (InvokeRequired)285 Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced), sender, e);286 else {287 RemoveScatterPlotDataRows(e.OldItems);288 AddScatterPlotDataRows(e.Items);289 }290 }291 private void Rows_CollectionReset(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {292 if (InvokeRequired)293 Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset), sender, e);294 else {295 RemoveScatterPlotDataRows(e.OldItems);296 AddScatterPlotDataRows(e.Items);297 }298 }299 #endregion300 #region Row Event Handlers301 private void Row_VisualPropertiesChanged(object sender, EventArgs e) {302 if (InvokeRequired)303 Invoke(new EventHandler(Row_VisualPropertiesChanged), sender, e);304 else {305 ScatterPlotDataRow row = (ScatterPlotDataRow)sender;306 Series series = chart.Series[row.Name];307 series.Points.Clear();308 ConfigureSeries(series, row);309 FillSeriesWithRowValues(series, row);310 RecalculateMinMaxPointValues();311 RecalculateAxesScale(chart.ChartAreas[0]);312 }313 }314 private void Row_NameChanged(object sender, EventArgs e) {315 if (InvokeRequired)316 Invoke(new EventHandler(Row_NameChanged), sender, e);317 else {318 ScatterPlotDataRow row = (ScatterPlotDataRow)sender;319 chart.Series[row.Name].Name = row.Name;320 }321 }322 #endregion323 #region Points Event Handlers324 private void Points_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {325 if (InvokeRequired)326 Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded), sender, e);327 else {328 ScatterPlotDataRow row = null;329 pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);330 if (row != null) {331 Series rowSeries = chart.Series[row.Name];332 if (!invisibleSeries.Contains(rowSeries)) {333 rowSeries.Points.Clear();334 FillSeriesWithRowValues(rowSeries, row);335 RecalculateMinMaxPointValues();336 RecalculateAxesScale(chart.ChartAreas[0]);337 UpdateYCursorInterval();338 }339 }340 }341 }342 private void Points_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {343 if (InvokeRequired)344 Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved), sender, e);345 else {346 ScatterPlotDataRow row = null;347 pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);348 if (row != null) {349 Series rowSeries = chart.Series[row.Name];350 if (!invisibleSeries.Contains(rowSeries)) {351 rowSeries.Points.Clear();352 FillSeriesWithRowValues(rowSeries, row);353 RecalculateMinMaxPointValues();354 RecalculateAxesScale(chart.ChartAreas[0]);355 UpdateYCursorInterval();356 }357 }358 }359 }360 private void Points_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {361 if (InvokeRequired)362 Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced), sender, e);363 else {364 ScatterPlotDataRow row = null;365 pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);366 if (row != null) {367 Series rowSeries = chart.Series[row.Name];368 if (!invisibleSeries.Contains(rowSeries)) {369 rowSeries.Points.Clear();370 FillSeriesWithRowValues(rowSeries, row);371 RecalculateMinMaxPointValues();372 RecalculateAxesScale(chart.ChartAreas[0]);373 UpdateYCursorInterval();374 }375 }376 }377 }378 private void Points_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {379 if (InvokeRequired)380 Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset), sender, e);381 else {382 ScatterPlotDataRow row = null;383 pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);384 if (row != null) {385 Series rowSeries = chart.Series[row.Name];386 if (!invisibleSeries.Contains(rowSeries)) {387 rowSeries.Points.Clear();388 FillSeriesWithRowValues(rowSeries, row);389 RecalculateMinMaxPointValues();390 RecalculateAxesScale(chart.ChartAreas[0]);391 UpdateYCursorInterval();392 }393 }394 }395 }396 #endregion397 #endregion398 399 #region Chart Event Handlers400 private void chart_MouseDown(object sender, MouseEventArgs e) {401 HitTestResult result = chart.HitTest(e.X, e.Y);402 if (result.ChartElementType == ChartElementType.LegendItem) {403 ToggleSeriesVisible(result.Series);404 }405 }406 private void chart_MouseMove(object sender, MouseEventArgs e) {407 HitTestResult result = chart.HitTest(e.X, e.Y);408 if (result.ChartElementType == ChartElementType.LegendItem)409 this.Cursor = Cursors.Hand;410 else411 this.Cursor = Cursors.Default;412 }413 private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {414 foreach (LegendItem legendItem in e.LegendItems) {415 var series = chart.Series[legendItem.SeriesName];416 if (series != null) {417 bool seriesIsInvisible = invisibleSeries.Contains(series);418 foreach (LegendCell cell in legendItem.Cells) {419 cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;420 }421 }422 }423 }424 #endregion425 426 private void ToggleSeriesVisible(Series series) {427 if (!invisibleSeries.Contains(series)) {428 series.Points.Clear();429 invisibleSeries.Add(series);430 RecalculateMinMaxPointValues();431 } else {432 invisibleSeries.Remove(series);433 if (Content != null) {434 435 var row = (from r in Content.Rows436 where r.Name == series.Name437 select r).Single();438 FillSeriesWithRowValues(series, row);439 RecalculateMinMaxPointValues();440 this.chart.Legends[series.Legend].ForeColor = Color.Black;441 RecalculateAxesScale(chart.ChartAreas[0]);442 UpdateYCursorInterval();443 }444 }445 }446 447 private void RecalculateMinMaxPointValues() {448 yMin = xMin = double.MaxValue;449 yMax = xMax = double.MinValue;450 foreach (var s in chart.Series.Where(x => x.Enabled)) {451 foreach (var p in s.Points) {452 double x = p.XValue, y = p.YValues[0];453 if (xMin > x) xMin = x;454 if (xMax < x) xMax = x;455 if (yMin > y) yMin = y;456 if (yMax < y) yMax = y;457 }458 }459 }460 461 private void FillSeriesWithRowValues(Series series, ScatterPlotDataRow row) {462 for (int i = 0; i < row.Points.Count; i++) {463 var value = row.Points[i];464 DataPoint point = new DataPoint();465 if (IsInvalidValue(value.X) || IsInvalidValue(value.Y))466 point.IsEmpty = true;467 else {468 point.XValue = value.X;469 point.YValues = new double[] { value.Y };470 }471 series.Points.Add(point);472 }473 }474 475 #region Helpers476 private MarkerStyle ConvertPointStyle(ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle pointStyle) {477 switch (pointStyle) {478 case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Circle:479 return MarkerStyle.Circle;480 case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Cross:481 return MarkerStyle.Cross;482 case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Diamond:483 return MarkerStyle.Diamond;484 case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Square:485 return MarkerStyle.Square;486 case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star4:487 return MarkerStyle.Star4;488 case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star5:489 return MarkerStyle.Star5;490 case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star6:491 return MarkerStyle.Star6;492 case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star10:493 return MarkerStyle.Star10;494 case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Triangle:495 return MarkerStyle.Triangle;496 default:497 return MarkerStyle.None;498 }499 }500 501 protected static bool IsInvalidValue(double x) {502 return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue;503 63 } 504 64 #endregion
Note: See TracChangeset
for help on using the changeset viewer.