- Timestamp:
- 09/14/11 13:59:25 (13 years ago)
- Location:
- branches/PersistenceSpeedUp
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/PersistenceSpeedUp
- Property svn:ignore
-
old new 12 12 *.psess 13 13 *.vsp 14 *.docstates
-
- Property svn:mergeinfo changed
- Property svn:ignore
-
branches/PersistenceSpeedUp/HeuristicLab.Analysis.Views/3.3/DataTableView.cs
r5445 r6760 36 36 [View("DataTable View")] 37 37 [Content(typeof(DataTable), true)] 38 public partial class DataTableView : NamedItemView {38 public partial class DataTableView : NamedItemView, IConfigureableView { 39 39 protected List<Series> invisibleSeries; 40 40 protected Dictionary<IObservableList<double>, DataRow> valuesRowsTable; … … 60 60 } 61 61 62 #region Event Handler Registration 62 63 /// <summary> 63 64 /// Removes the eventhandlers from the underlying <see cref="Variable"/>. … … 89 90 RegisterDataRowEvents(row); 90 91 } 92 93 /// <summary> 94 /// Automatically called for every existing data row and whenever a data row is added 95 /// to the data table. Do not call this method directly. 96 /// </summary> 97 /// <param name="row">The DataRow that was added.</param> 98 protected virtual void RegisterDataRowEvents(DataRow row) { 99 row.NameChanged += new EventHandler(Row_NameChanged); 100 row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged); 101 valuesRowsTable.Add(row.Values, row); 102 row.Values.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded); 103 row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved); 104 row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced); 105 row.Values.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved); 106 row.Values.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset); 107 } 108 109 /// <summary> 110 /// Automatically called for every data row that is removed from the DataTable. Do 111 /// not directly call this method. 112 /// </summary> 113 /// <param name="row">The DataRow that was removed.</param> 114 protected virtual void DeregisterDataRowEvents(DataRow row) { 115 row.Values.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded); 116 row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved); 117 row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced); 118 row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved); 119 row.Values.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset); 120 valuesRowsTable.Remove(row.Values); 121 row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged); 122 row.NameChanged -= new EventHandler(Row_NameChanged); 123 } 124 #endregion 91 125 92 126 protected override void OnContentChanged() { … … 102 136 foreach (DataRow row in Content.Rows) 103 137 AddDataRow(row); 104 chart.ChartAreas[0].AxisX.Title = Content.VisualProperties.XAxisTitle; 105 chart.ChartAreas[0].AxisY.Title = Content.VisualProperties.YAxisTitle; 106 chart.ChartAreas[0].AxisY2.Title = Content.VisualProperties.SecondYAxisTitle; 138 ConfigureChartArea(chart.ChartAreas[0]); 139 RecalculateAxesScale(chart.ChartAreas[0]); 107 140 } 108 141 } … … 113 146 } 114 147 148 public void ShowConfiguration() { 149 if (Content != null) { 150 DataTableVisualPropertiesDialog dialog = new DataTableVisualPropertiesDialog(Content); 151 dialog.ShowDialog(); 152 } else MessageBox.Show("Nothing to configure."); 153 } 115 154 116 155 /// <summary> … … 120 159 protected virtual void AddDataRow(DataRow row) { 121 160 Series series = new Series(row.Name); 161 if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName; 162 else series.LegendText = row.Name; 163 ConfigureSeries(series, row); 164 FillSeriesWithRowValues(series, row); 165 166 chart.Series.Add(series); 167 ConfigureChartArea(chart.ChartAreas[0]); 168 RecalculateAxesScale(chart.ChartAreas[0]); 169 UpdateYCursorInterval(); 170 } 171 172 private void ConfigureSeries(Series series, DataRow row) { 173 RemoveCustomPropertyIfExists(series, "PointWidth"); 174 series.BorderWidth = 1; 175 series.BorderDashStyle = ChartDashStyle.Solid; 176 series.BorderColor = Color.Empty; 177 178 if (row.VisualProperties.Color != Color.Empty) 179 series.Color = row.VisualProperties.Color; 180 else series.Color = Color.Empty; 181 122 182 switch (row.VisualProperties.ChartType) { 123 183 case DataRowVisualProperties.DataRowChartType.Line: 124 184 series.ChartType = SeriesChartType.FastLine; 185 series.BorderWidth = row.VisualProperties.LineWidth; 186 series.BorderDashStyle = ConvertLineStyle(row.VisualProperties.LineStyle); 125 187 break; 126 188 case DataRowVisualProperties.DataRowChartType.Bars: 127 series.ChartType = SeriesChartType.Bar; 189 // Bar is incompatible with anything but Bar and StackedBar* 190 if (!chart.Series.Any(x => x.ChartType != SeriesChartType.Bar && x.ChartType != SeriesChartType.StackedBar && x.ChartType != SeriesChartType.StackedBar100)) 191 series.ChartType = SeriesChartType.Bar; 192 else { 193 series.ChartType = SeriesChartType.FastPoint; //default 194 row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points; 195 } 128 196 break; 129 197 case DataRowVisualProperties.DataRowChartType.Columns: … … 133 201 series.ChartType = SeriesChartType.FastPoint; 134 202 break; 203 case DataRowVisualProperties.DataRowChartType.Histogram: 204 series.ChartType = SeriesChartType.Column; 205 series.SetCustomProperty("PointWidth", "1"); 206 if (!series.Color.IsEmpty && series.Color.GetBrightness() < 0.25) 207 series.BorderColor = Color.White; 208 else series.BorderColor = Color.Black; 209 break; 135 210 default: 136 211 series.ChartType = SeriesChartType.FastPoint; … … 138 213 } 139 214 series.YAxisType = row.VisualProperties.SecondYAxis ? AxisType.Secondary : AxisType.Primary; 140 if (row.VisualProperties.Color != Color.Empty) series.Color = row.VisualProperties.Color; 141 series.ToolTip = row.Name + " X = #INDEX, Y = #VAL"; 142 FillSeriesWithRowValues(series, row); 143 chart.Series.Add(series); 144 chart.ChartAreas[0].RecalculateAxesScale(); 145 UpdateYCursorInterval(); 146 } 147 215 series.XAxisType = row.VisualProperties.SecondXAxis ? AxisType.Secondary : AxisType.Primary; 216 if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName; 217 else series.LegendText = row.Name; 218 series.ToolTip = series.LegendText + " X = #INDEX, Y = #VAL"; 219 } 220 221 private void ConfigureChartArea(ChartArea area) { 222 if (Content.VisualProperties.TitleFont != null) chart.Titles[0].Font = Content.VisualProperties.TitleFont; 223 if (!Content.VisualProperties.TitleColor.IsEmpty) chart.Titles[0].ForeColor = Content.VisualProperties.TitleColor; 224 225 if (Content.VisualProperties.AxisTitleFont != null) area.AxisX.TitleFont = Content.VisualProperties.AxisTitleFont; 226 if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX.TitleForeColor = Content.VisualProperties.AxisTitleColor; 227 area.AxisX.Title = Content.VisualProperties.XAxisTitle; 228 229 if (Content.VisualProperties.AxisTitleFont != null) area.AxisX2.TitleFont = Content.VisualProperties.AxisTitleFont; 230 if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX2.TitleForeColor = Content.VisualProperties.AxisTitleColor; 231 area.AxisX2.Title = Content.VisualProperties.SecondXAxisTitle; 232 233 if (Content.VisualProperties.AxisTitleFont != null) area.AxisY.TitleFont = Content.VisualProperties.AxisTitleFont; 234 if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY.TitleForeColor = Content.VisualProperties.AxisTitleColor; 235 area.AxisY.Title = Content.VisualProperties.YAxisTitle; 236 237 if (Content.VisualProperties.AxisTitleFont != null) area.AxisY2.TitleFont = Content.VisualProperties.AxisTitleFont; 238 if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY2.TitleForeColor = Content.VisualProperties.AxisTitleColor; 239 area.AxisY2.Title = Content.VisualProperties.SecondYAxisTitle; 240 } 241 242 private void RecalculateAxesScale(ChartArea area) { 243 // Reset the axes bounds so that RecalculateAxesScale() will assign new bounds 244 foreach (Axis a in area.Axes) { 245 a.Minimum = double.NaN; 246 a.Maximum = double.NaN; 247 } 248 area.RecalculateAxesScale(); 249 area.AxisX.IsMarginVisible = false; 250 area.AxisX2.IsMarginVisible = false; 251 252 if (!Content.VisualProperties.XAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue)) area.AxisX.Minimum = Content.VisualProperties.XAxisMinimumFixedValue; 253 if (!Content.VisualProperties.XAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue)) area.AxisX.Maximum = Content.VisualProperties.XAxisMaximumFixedValue; 254 if (!Content.VisualProperties.SecondXAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMinimumFixedValue)) area.AxisX2.Minimum = Content.VisualProperties.SecondXAxisMinimumFixedValue; 255 if (!Content.VisualProperties.SecondXAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMaximumFixedValue)) area.AxisX2.Maximum = Content.VisualProperties.SecondXAxisMaximumFixedValue; 256 if (!Content.VisualProperties.YAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.YAxisMinimumFixedValue)) area.AxisY.Minimum = Content.VisualProperties.YAxisMinimumFixedValue; 257 if (!Content.VisualProperties.YAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.YAxisMaximumFixedValue)) area.AxisY.Maximum = Content.VisualProperties.YAxisMaximumFixedValue; 258 if (!Content.VisualProperties.SecondYAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMinimumFixedValue)) area.AxisY2.Minimum = Content.VisualProperties.SecondYAxisMinimumFixedValue; 259 if (!Content.VisualProperties.SecondYAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMaximumFixedValue)) area.AxisY2.Maximum = Content.VisualProperties.SecondYAxisMaximumFixedValue; 260 if (area.AxisX.Minimum >= area.AxisX.Maximum) area.AxisX.Maximum = area.AxisX.Minimum + 1; 261 if (area.AxisX2.Minimum >= area.AxisX2.Maximum) area.AxisX2.Maximum = area.AxisX2.Minimum + 1; 262 if (area.AxisY.Minimum >= area.AxisY.Maximum) area.AxisY.Maximum = area.AxisY.Minimum + 1; 263 if (area.AxisY2.Minimum >= area.AxisY2.Maximum) area.AxisY2.Maximum = area.AxisY2.Minimum + 1; 264 } 148 265 149 266 /// <summary> … … 151 268 /// </summary> 152 269 protected virtual void UpdateYCursorInterval() { 153 double interestingValuesRange = (from series in chart.Series 154 where series.Enabled 155 let values = (from point in series.Points 156 where !point.IsEmpty 157 select point.YValues[0]) 158 .DefaultIfEmpty(1.0) 159 let range = values.Max() - values.Min() 160 where range > 0.0 161 select range) 162 .DefaultIfEmpty(1.0) 163 .Min(); 270 double interestingValuesRange = ( 271 from series in chart.Series 272 where series.Enabled 273 let values = (from point in series.Points 274 where !point.IsEmpty 275 select point.YValues[0]).DefaultIfEmpty(1.0) 276 let range = values.Max() - values.Min() 277 where range > 0.0 278 select range 279 ).DefaultIfEmpty(1.0).Min(); 164 280 165 281 double digits = (int)Math.Log10(interestingValuesRange) - 3; … … 178 294 if (invisibleSeries.Contains(series)) 179 295 invisibleSeries.Remove(series); 180 chart.ChartAreas[0].RecalculateAxesScale(); 181 } 182 183 #region Content Events 184 /// <summary> 185 /// Automatically called for every existing data row and whenever a data row is added 186 /// to the data table. Do not call this method directly. 187 /// </summary> 188 /// <param name="row">The DataRow that was added.</param> 189 protected virtual void RegisterDataRowEvents(DataRow row) { 190 row.NameChanged += new EventHandler(Row_NameChanged); 191 row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged); 192 valuesRowsTable.Add(row.Values, row); 193 row.Values.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded); 194 row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved); 195 row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced); 196 row.Values.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved); 197 row.Values.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset); 198 } 199 200 /// <summary> 201 /// Automatically called for every data row that is removed from the DataTable. Do 202 /// not directly call this method. 203 /// </summary> 204 /// <param name="row">The DataRow that was removed.</param> 205 protected virtual void DeregisterDataRowEvents(DataRow row) { 206 row.Values.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded); 207 row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved); 208 row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced); 209 row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved); 210 row.Values.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset); 211 valuesRowsTable.Remove(row.Values); 212 row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged); 213 row.NameChanged -= new EventHandler(Row_NameChanged); 214 } 296 RecalculateAxesScale(chart.ChartAreas[0]); 297 } 298 299 #region Event Handlers 300 #region Content Event Handlers 215 301 protected override void Content_NameChanged(object sender, EventArgs e) { 216 302 if (InvokeRequired) … … 225 311 Invoke(new EventHandler(Content_VisualPropertiesChanged), sender, e); 226 312 else { 227 chart.ChartAreas[0].AxisX.Title = Content.VisualProperties.XAxisTitle; 228 chart.ChartAreas[0].AxisY.Title = Content.VisualProperties.YAxisTitle; 229 chart.ChartAreas[0].AxisY2.Title = Content.VisualProperties.SecondYAxisTitle; 230 } 231 } 313 ConfigureChartArea(chart.ChartAreas[0]); 314 RecalculateAxesScale(chart.ChartAreas[0]); // axes min/max could have changed 315 } 316 } 317 #endregion 318 #region Rows Event Handlers 232 319 private void Rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<DataRow> e) { 233 320 if (InvokeRequired) … … 278 365 } 279 366 } 367 #endregion 368 #region Row Event Handlers 280 369 private void Row_VisualPropertiesChanged(object sender, EventArgs e) { 281 370 if (InvokeRequired) … … 283 372 else { 284 373 DataRow row = (DataRow)sender; 285 switch (row.VisualProperties.ChartType) { 286 case DataRowVisualProperties.DataRowChartType.Line: 287 chart.Series[row.Name].ChartType = SeriesChartType.FastLine; 288 break; 289 case DataRowVisualProperties.DataRowChartType.Bars: 290 chart.Series[row.Name].ChartType = SeriesChartType.Bar; 291 break; 292 case DataRowVisualProperties.DataRowChartType.Columns: 293 chart.Series[row.Name].ChartType = SeriesChartType.Column; 294 break; 295 case DataRowVisualProperties.DataRowChartType.Points: 296 chart.Series[row.Name].ChartType = SeriesChartType.FastPoint; 297 break; 298 default: 299 chart.Series[row.Name].ChartType = SeriesChartType.FastPoint; 300 break; 301 } 302 chart.Series[row.Name].YAxisType = row.VisualProperties.SecondYAxis ? AxisType.Secondary : AxisType.Primary; 303 if (row.VisualProperties.Color != Color.Empty) chart.Series[row.Name].Color = row.VisualProperties.Color; 304 chart.ChartAreas[0].RecalculateAxesScale(); 374 Series series = chart.Series[row.Name]; 375 series.Points.Clear(); 376 ConfigureSeries(series, row); 377 FillSeriesWithRowValues(series, row); 378 RecalculateAxesScale(chart.ChartAreas[0]); 305 379 } 306 380 } … … 313 387 } 314 388 } 389 #endregion 390 #region Values Event Handlers 315 391 private void Values_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) { 316 392 if (InvokeRequired) … … 324 400 rowSeries.Points.Clear(); 325 401 FillSeriesWithRowValues(rowSeries, row); 402 RecalculateAxesScale(chart.ChartAreas[0]); 326 403 UpdateYCursorInterval(); 327 404 } … … 340 417 rowSeries.Points.Clear(); 341 418 FillSeriesWithRowValues(rowSeries, row); 419 RecalculateAxesScale(chart.ChartAreas[0]); 342 420 UpdateYCursorInterval(); 343 421 } … … 354 432 Series rowSeries = chart.Series[row.Name]; 355 433 if (!invisibleSeries.Contains(rowSeries)) { 356 foreach (IndexedItem<double> item in e.Items) { 357 if (IsInvalidValue(item.Value)) 358 rowSeries.Points[item.Index].IsEmpty = true; 359 else { 360 rowSeries.Points[item.Index].YValues = new double[] { item.Value }; 361 rowSeries.Points[item.Index].IsEmpty = false; 434 if (row.VisualProperties.ChartType == DataRowVisualProperties.DataRowChartType.Histogram) { 435 rowSeries.Points.Clear(); 436 FillSeriesWithRowValues(rowSeries, row); 437 } else { 438 foreach (IndexedItem<double> item in e.Items) { 439 if (IsInvalidValue(item.Value)) 440 rowSeries.Points[item.Index].IsEmpty = true; 441 else { 442 rowSeries.Points[item.Index].YValues = new double[] { item.Value }; 443 rowSeries.Points[item.Index].IsEmpty = false; 444 } 362 445 } 363 446 } 447 RecalculateAxesScale(chart.ChartAreas[0]); 364 448 UpdateYCursorInterval(); 365 449 } … … 378 462 rowSeries.Points.Clear(); 379 463 FillSeriesWithRowValues(rowSeries, row); 464 RecalculateAxesScale(chart.ChartAreas[0]); 380 465 UpdateYCursorInterval(); 381 466 } … … 395 480 rowSeries.Points.Clear(); 396 481 FillSeriesWithRowValues(rowSeries, row); 482 RecalculateAxesScale(chart.ChartAreas[0]); 397 483 UpdateYCursorInterval(); 398 484 } … … 401 487 } 402 488 #endregion 403 404 #region Chart Events 489 #endregion 490 491 #region Chart Event Handlers 405 492 private void chart_MouseDown(object sender, MouseEventArgs e) { 406 493 HitTestResult result = chart.HitTest(e.X, e.Y); … … 409 496 } 410 497 } 498 private void chart_MouseMove(object sender, MouseEventArgs e) { 499 HitTestResult result = chart.HitTest(e.X, e.Y); 500 if (result.ChartElementType == ChartElementType.LegendItem) 501 this.Cursor = Cursors.Hand; 502 else 503 this.Cursor = Cursors.Default; 504 } 505 private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) { 506 foreach (LegendItem legendItem in e.LegendItems) { 507 var series = chart.Series[legendItem.SeriesName]; 508 if (series != null) { 509 bool seriesIsInvisible = invisibleSeries.Contains(series); 510 foreach (LegendCell cell in legendItem.Cells) { 511 cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black; 512 } 513 } 514 } 515 } 516 #endregion 411 517 412 518 private void ToggleSeriesVisible(Series series) { … … 423 529 FillSeriesWithRowValues(series, row); 424 530 this.chart.Legends[series.Legend].ForeColor = Color.Black; 531 RecalculateAxesScale(chart.ChartAreas[0]); 425 532 UpdateYCursorInterval(); 426 533 } … … 429 536 430 537 private void FillSeriesWithRowValues(Series series, DataRow row) { 431 for (int i = 0; i < row.Values.Count; i++) { 432 var value = row.Values[i]; 433 DataPoint point = new DataPoint(); 434 point.XValue = row.VisualProperties.StartIndexZero ? i : i + 1; 435 if (IsInvalidValue(value)) 436 point.IsEmpty = true; 437 else 438 point.YValues = new double[] { value }; 439 series.Points.Add(point); 440 } 441 } 442 443 private void chart_MouseMove(object sender, MouseEventArgs e) { 444 HitTestResult result = chart.HitTest(e.X, e.Y); 445 if (result.ChartElementType == ChartElementType.LegendItem) 446 this.Cursor = Cursors.Hand; 447 else 448 this.Cursor = Cursors.Default; 449 } 450 private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) { 451 foreach (LegendItem legendItem in e.LegendItems) { 452 var series = chart.Series[legendItem.SeriesName]; 453 if (series != null) { 454 bool seriesIsInvisible = invisibleSeries.Contains(series); 455 foreach (LegendCell cell in legendItem.Cells) { 456 cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black; 457 } 458 } 459 } 460 } 461 #endregion 462 538 switch (row.VisualProperties.ChartType) { 539 case DataRowVisualProperties.DataRowChartType.Histogram: 540 CalculateHistogram(series, row); 541 break; 542 default: { 543 for (int i = 0; i < row.Values.Count; i++) { 544 var value = row.Values[i]; 545 DataPoint point = new DataPoint(); 546 point.XValue = row.VisualProperties.StartIndexZero ? i : i + 1; 547 if (IsInvalidValue(value)) 548 point.IsEmpty = true; 549 else 550 point.YValues = new double[] { value }; 551 series.Points.Add(point); 552 } 553 } 554 break; 555 } 556 } 557 558 protected virtual void CalculateHistogram(Series series, DataRow row) { 559 series.Points.Clear(); 560 if (!row.Values.Any()) return; 561 int bins = row.VisualProperties.Bins; 562 563 double minValue = row.Values.Min(); 564 double maxValue = row.Values.Max(); 565 double intervalWidth = (maxValue - minValue) / bins; 566 if (intervalWidth < 0) return; 567 if (intervalWidth == 0) { 568 series.Points.AddXY(minValue, row.Values.Count); 569 return; 570 } 571 572 if (!row.VisualProperties.ExactBins) { 573 intervalWidth = HumanRoundRange(intervalWidth); 574 minValue = Math.Floor(minValue / intervalWidth) * intervalWidth; 575 maxValue = Math.Ceiling(maxValue / intervalWidth) * intervalWidth; 576 } 577 578 double current = minValue, intervalCenter = intervalWidth / 2.0; 579 int frequency = 0; 580 series.Points.AddXY(current - intervalCenter, 0); // so that the first column is not visually truncated 581 foreach (double v in row.Values.Where(x => !IsInvalidValue(x)).OrderBy(x => x)) { 582 while (v > current + intervalWidth) { 583 series.Points.AddXY(current + intervalCenter, frequency); 584 current += intervalWidth; 585 frequency = 0; 586 } 587 frequency++; 588 } 589 series.Points.AddXY(current + intervalCenter, frequency); 590 series.Points.AddXY(current + 3 * intervalCenter, 0); // so that the last column is not visually truncated 591 } 592 593 #region Helpers 594 protected void RemoveCustomPropertyIfExists(Series series, string property) { 595 if (series.IsCustomPropertySet(property)) series.DeleteCustomProperty(property); 596 } 597 598 private double HumanRoundRange(double range) { 599 double base10 = Math.Pow(10.0, Math.Floor(Math.Log10(range))); 600 double rounding = range / base10; 601 if (rounding <= 1.5) rounding = 1; 602 else if (rounding <= 2.25) rounding = 2; 603 else if (rounding <= 3.75) rounding = 2.5; 604 else if (rounding <= 7.5) rounding = 5; 605 else rounding = 10; 606 return rounding * base10; 607 } 608 609 private double HumanRoundMax(double max) { 610 double base10; 611 if (max > 0) base10 = Math.Pow(10.0, Math.Floor(Math.Log10(max))); 612 else base10 = Math.Pow(10.0, Math.Ceiling(Math.Log10(-max))); 613 double rounding = (max > 0) ? base10 : -base10; 614 while (rounding < max) rounding += base10; 615 return rounding; 616 } 617 618 private ChartDashStyle ConvertLineStyle(DataRowVisualProperties.DataRowLineStyle dataRowLineStyle) { 619 switch (dataRowLineStyle) { 620 case DataRowVisualProperties.DataRowLineStyle.Dash: 621 return ChartDashStyle.Dash; 622 case DataRowVisualProperties.DataRowLineStyle.DashDot: 623 return ChartDashStyle.DashDot; 624 case DataRowVisualProperties.DataRowLineStyle.DashDotDot: 625 return ChartDashStyle.DashDotDot; 626 case DataRowVisualProperties.DataRowLineStyle.Dot: 627 return ChartDashStyle.Dot; 628 case DataRowVisualProperties.DataRowLineStyle.NotSet: 629 return ChartDashStyle.NotSet; 630 case DataRowVisualProperties.DataRowLineStyle.Solid: 631 return ChartDashStyle.Solid; 632 default: 633 return ChartDashStyle.NotSet; 634 } 635 } 463 636 464 637 /// <summary> … … 471 644 return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue; 472 645 } 646 #endregion 473 647 } 474 648 }
Note: See TracChangeset
for help on using the changeset viewer.