Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Visualization/3.2/LineChart.cs @ 1879

Last change on this file since 1879 was 1879, checked in by mstoeger, 15 years ago

Layout is only updated when necessary (before painting) #498

File size: 23.8 KB
RevLine 
[683]1using System;
[861]2using System.Collections.Generic;
[928]3using System.Drawing;
[1559]4using System.Drawing.Drawing2D;
[928]5using System.Windows.Forms;
[697]6using HeuristicLab.Core;
[1781]7using HeuristicLab.Visualization.DataExport;
[1233]8using HeuristicLab.Visualization.Legend;
[1195]9using HeuristicLab.Visualization.Options;
[1457]10using HeuristicLab.Visualization.Test;
[683]11
[861]12namespace HeuristicLab.Visualization {
[1187]13  public partial class LineChart : ViewBase {
[697]14    private readonly IChartDataRowsModel model;
[1240]15    private readonly Canvas canvas;
16
[1285]17    private readonly TextShape titleShape = new TextShape("Title");
18    private readonly LegendShape legendShape = new LegendShape();
19    private readonly XAxis xAxis = new XAxis();
[1876]20    private readonly XAxisGrid xAxisGrid = new XAxisGrid();
[1285]21    private readonly List<RowEntry> rowEntries = new List<RowEntry>();
[684]22
[1285]23    private readonly Dictionary<IDataRow, RowEntry> rowToRowEntry = new Dictionary<IDataRow, RowEntry>();
[1038]24
[1341]25    private readonly ViewSettings viewSettings;
26
[1285]27    private readonly WorldShape userInteractionShape = new WorldShape();
28    private readonly RectangleShape rectangleShape = new RectangleShape(0, 0, 0, 0, Color.FromArgb(50, 0, 0, 255));
29    private IMouseEventListener mouseEventListener;
[983]30
[1285]31    private const int YAxisWidth = 100;
[1462]32    private const int XAxisHeight = 40;
[1285]33
[697]34    /// <summary>
35    /// This constructor shouldn't be called. Only required for the designer.
36    /// </summary>
[861]37    public LineChart() {
[684]38      InitializeComponent();
39    }
40
[697]41    /// <summary>
42    /// Initializes the chart.
43    /// </summary>
[754]44    /// <param name="model">Referenz to the model, for data</param>
[861]45    public LineChart(IChartDataRowsModel model) : this() {
[1045]46      if (model == null) {
[697]47        throw new NullReferenceException("Model cannot be null.");
[1045]48      }
[684]49
[1240]50      canvas = canvasUI.Canvas;
[983]51
[1285]52      this.model = model;
[1341]53      viewSettings = model.ViewSettings;
[1342]54      viewSettings.OnUpdateSettings += UpdateViewSettings;
[1038]55
[983]56      Item = model;
[1038]57
[1879]58      this.ResizeRedraw = true;
59
[1240]60      UpdateLayout();
[1285]61      ZoomToFullView();
[697]62    }
[684]63
[1346]64    /// <summary>
65    /// updates the view settings
66    /// </summary>
[1342]67    private void UpdateViewSettings() {
[1341]68      titleShape.Font = viewSettings.TitleFont;
69      titleShape.Color = viewSettings.TitleColor;
[1839]70      titleShape.Text = model.Title;
[1337]71
[1341]72      legendShape.Font = viewSettings.LegendFont;
73      legendShape.Color = viewSettings.LegendColor;
[1337]74
[1341]75      xAxis.Font = viewSettings.XAxisFont;
76      xAxis.Color = viewSettings.XAxisColor;
[1337]77
[1345]78      SetLegendPosition();
[1342]79
[1879]80      this.Invalidate(true);
[1337]81    }
82
[1038]83    /// <summary>
84    /// Layout management - arranges the inner shapes.
85    /// </summary>
86    private void UpdateLayout() {
[1285]87      canvas.ClearShapes();
88
[1608]89      titleShape.Text = model.Title;
90
[1876]91      if (model.ShowXAxisGrid) {
92        canvas.AddShape(xAxisGrid);
93      }
94
[1350]95      foreach (YAxisDescriptor yAxisDescriptor in model.YAxes) {
96        YAxisInfo info = GetYAxisInfo(yAxisDescriptor);
[1458]97        if (yAxisDescriptor.ShowGrid) {
98          info.Grid.Color = yAxisDescriptor.GridColor;
99          canvas.AddShape(info.Grid);
100        }
[1285]101      }
102
103      foreach (RowEntry rowEntry in rowEntries) {
104        canvas.AddShape(rowEntry.LinesShape);
105      }
106
[1462]107      xAxis.ShowLabel = model.ShowXAxisLabel;
108      xAxis.Label = model.XAxisLabel;
109
[1285]110      canvas.AddShape(xAxis);
111
[1457]112      int yAxesWidthLeft = 0;
113      int yAxesWidthRight = 0;
[1343]114
[1350]115      foreach (YAxisDescriptor yAxisDescriptor in model.YAxes) {
116        YAxisInfo info = GetYAxisInfo(yAxisDescriptor);
117        if (yAxisDescriptor.ShowYAxis) {
118          canvas.AddShape(info.YAxis);
[1462]119          info.YAxis.ShowLabel = yAxisDescriptor.ShowYAxisLabel;
120          info.YAxis.Label = yAxisDescriptor.Label;
[1457]121          info.YAxis.Position = yAxisDescriptor.Position;
122          switch (yAxisDescriptor.Position) {
123            case AxisPosition.Left:
124              yAxesWidthLeft += YAxisWidth;
125              break;
126            case AxisPosition.Right:
127              yAxesWidthRight += YAxisWidth;
128              break;
129            default:
130              throw new NotImplementedException();
131          }
[1343]132        }
[1285]133      }
134
135      canvas.AddShape(titleShape);
136      canvas.AddShape(legendShape);
137
138      canvas.AddShape(userInteractionShape);
139
[1038]140      titleShape.X = 10;
[1240]141      titleShape.Y = canvasUI.Height - 10;
[1038]142
[1457]143      RectangleD linesAreaBoundingBox = new RectangleD(yAxesWidthLeft,
[1285]144                                                       XAxisHeight,
[1457]145                                                       canvasUI.Width - yAxesWidthRight,
[1285]146                                                       canvasUI.Height);
[1240]147
[1285]148      foreach (RowEntry rowEntry in rowEntries) {
149        rowEntry.LinesShape.BoundingBox = linesAreaBoundingBox;
150      }
[1182]151
[1876]152      xAxisGrid.BoundingBox = linesAreaBoundingBox;
153
[1350]154      foreach (YAxisDescriptor yAxisDescriptor in model.YAxes) {
155        YAxisInfo info = GetYAxisInfo(yAxisDescriptor);
156        info.Grid.BoundingBox = linesAreaBoundingBox;
157      }
158
[1285]159      int yAxisLeft = 0;
[1457]160      int yAxisRight = (int)linesAreaBoundingBox.X2;
161
[1350]162      foreach (YAxisDescriptor yAxisDescriptor in model.YAxes) {
163        YAxisInfo info = GetYAxisInfo(yAxisDescriptor);
164        if (yAxisDescriptor.ShowYAxis) {
[1457]165          switch (yAxisDescriptor.Position) {
166            case AxisPosition.Left:
167              info.YAxis.BoundingBox = new RectangleD(yAxisLeft,
168                                                      linesAreaBoundingBox.Y1,
169                                                      yAxisLeft + YAxisWidth,
170                                                      linesAreaBoundingBox.Y2);
171              yAxisLeft += YAxisWidth;
172              break;
173            case AxisPosition.Right:
174              info.YAxis.BoundingBox = new RectangleD(yAxisRight,
175                                                      linesAreaBoundingBox.Y1,
176                                                      yAxisRight + YAxisWidth,
177                                                      linesAreaBoundingBox.Y2);
178              yAxisRight += YAxisWidth;
179              break;
180            default:
181              throw new NotImplementedException();
182          }
[1343]183        }
[1285]184      }
[1187]185
[1285]186      userInteractionShape.BoundingBox = linesAreaBoundingBox;
187      userInteractionShape.ClippingArea = new RectangleD(0, 0, userInteractionShape.BoundingBox.Width, userInteractionShape.BoundingBox.Height);
[1182]188
[1285]189      xAxis.BoundingBox = new RectangleD(linesAreaBoundingBox.X1,
[1038]190                                         0,
[1285]191                                         linesAreaBoundingBox.X2,
192                                         linesAreaBoundingBox.Y1);
[1049]193
[1345]194      SetLegendPosition();
[1342]195    }
196
[1350]197    private readonly Dictionary<YAxisDescriptor, YAxisInfo> yAxisInfos = new Dictionary<YAxisDescriptor, YAxisInfo>();
198
199    private YAxisInfo GetYAxisInfo(YAxisDescriptor yAxisDescriptor) {
200      YAxisInfo info;
201
202      if (!yAxisInfos.TryGetValue(yAxisDescriptor, out info)) {
203        info = new YAxisInfo();
204        yAxisInfos[yAxisDescriptor] = info;
205      }
206
207      return info;
208    }
209
[1346]210    /// <summary>
211    /// sets the legend position
212    /// </summary>
[1345]213    private void SetLegendPosition() {
214      switch (viewSettings.LegendPosition) {
215        case LegendPosition.Bottom:
216          setLegendBottom();
217          break;
218
219        case LegendPosition.Top:
220          setLegendTop();
221          break;
222
223        case LegendPosition.Left:
224          setLegendLeft();
225          break;
226
227        case LegendPosition.Right:
228          setLegendRight();
229          break;
230      }
231    }
232
[1342]233    public void setLegendRight() {
234      // legend right
[1388]235      legendShape.BoundingBox = new RectangleD(canvasUI.Width - legendShape.GetMaxLabelLength(), 10, canvasUI.Width, canvasUI.Height - 50);
[1342]236      legendShape.ClippingArea = new RectangleD(0, 0, legendShape.BoundingBox.Width, legendShape.BoundingBox.Height);
237      legendShape.Row = false;
238      legendShape.CreateLegend();
239    }
240
241    public void setLegendLeft() {
242      // legend left
[1388]243      legendShape.BoundingBox = new RectangleD(10, 10, canvasUI.Width, canvasUI.Height - 50);
[1342]244      legendShape.ClippingArea = new RectangleD(0, 0, legendShape.BoundingBox.Width, legendShape.BoundingBox.Height);
245      legendShape.Row = false;
246      legendShape.CreateLegend();
[1285]247
[1879]248      this.Invalidate(true);
[1038]249    }
250
[1342]251    public void setLegendTop() {
252      // legend top
253      legendShape.BoundingBox = new RectangleD(100, canvasUI.Height - canvasUI.Height, canvasUI.Width, canvasUI.Height - 10);
254      legendShape.ClippingArea = new RectangleD(0, 0, legendShape.BoundingBox.Width, legendShape.BoundingBox.Height);
255      legendShape.Row = true;
256      legendShape.Top = true;
257      legendShape.CreateLegend();
258    }
259
260    public void setLegendBottom() {
261      // legend bottom
[1878]262      legendShape.BoundingBox = new RectangleD(100, 2, canvasUI.Width, canvasUI.Height);
[1342]263      legendShape.ClippingArea = new RectangleD(0, 0, legendShape.BoundingBox.Width, legendShape.BoundingBox.Height);
264      legendShape.Row = true;
265      legendShape.Top = false;
266      legendShape.CreateLegend();
267    }
268
[1242]269    private void optionsToolStripMenuItem_Click(object sender, EventArgs e) {
[1341]270      OptionsDialog optionsdlg = new OptionsDialog(model);
[1459]271      optionsdlg.Show();
[1242]272    }
273
[1781]274    private void exportToolStripMenuItem_Click(object sender, EventArgs e) {
275      ExportDialog exportdlg = new ExportDialog();
276      exportdlg.ShowDialog(this);
277
278      IExporter exporter = exportdlg.SelectedExporter;
279
280      if (exporter != null)
281        exporter.Export(model);
282    }
283
[1242]284    public void OnDataRowChanged(IDataRow row) {
[1285]285      RowEntry rowEntry = rowToRowEntry[row];
286
287      rowEntry.LinesShape.UpdateStyle(row);
288
[1879]289      this.Invalidate(true);
[1242]290    }
291
[861]292    #region Add-/RemoveItemEvents
293
294    protected override void AddItemEvents() {
295      base.AddItemEvents();
296
297      model.DataRowAdded += OnDataRowAdded;
298      model.DataRowRemoved += OnDataRowRemoved;
299      model.ModelChanged += OnModelChanged;
[869]300
[1045]301      foreach (IDataRow row in model.Rows) {
[869]302        OnDataRowAdded(row);
[1045]303      }
[683]304    }
[684]305
[861]306    protected override void RemoveItemEvents() {
307      base.RemoveItemEvents();
308
309      model.DataRowAdded -= OnDataRowAdded;
310      model.DataRowRemoved -= OnDataRowRemoved;
311      model.ModelChanged -= OnModelChanged;
[697]312    }
313
[861]314    private void OnDataRowAdded(IDataRow row) {
315      row.ValueChanged += OnRowValueChanged;
316      row.ValuesChanged += OnRowValuesChanged;
[1237]317      row.DataRowChanged += OnDataRowChanged;
318
[1049]319      legendShape.AddLegendItem(new LegendItem(row.Label, row.Color, row.Thickness));
320      legendShape.CreateLegend();
[1285]321
[987]322      InitLineShapes(row);
[1285]323
[1879]324      this.Invalidate(true);
[684]325    }
[697]326
[1240]327    private void OnDataRowRemoved(IDataRow row) {
328      row.ValueChanged -= OnRowValueChanged;
329      row.ValuesChanged -= OnRowValuesChanged;
330      row.DataRowChanged -= OnDataRowChanged;
[1285]331
332      rowToRowEntry.Remove(row);
333      rowEntries.RemoveAll(delegate(RowEntry rowEntry) { return rowEntry.DataRow == row; });
334
[1879]335      this.Invalidate(true);
[1240]336    }
337
338    #endregion
339
[1249]340    public void ZoomToFullView() {
[1285]341      SetClipX(-0.1, model.MaxDataRowValues - 0.9);
[987]342
[1285]343      foreach (RowEntry rowEntry in rowEntries) {
[1350]344        YAxisDescriptor yAxisDescriptor = rowEntry.DataRow.YAxis;
[1249]345
[1285]346        SetClipY(rowEntry,
[1350]347                 yAxisDescriptor.MinValue - ((yAxisDescriptor.MaxValue - yAxisDescriptor.MinValue)*0.05),
348                 yAxisDescriptor.MaxValue + ((yAxisDescriptor.MaxValue - yAxisDescriptor.MinValue)*0.05));
[1285]349      }
350
[1879]351      this.Invalidate(true);
[987]352    }
353
[1285]354    private void SetClipX(double x1, double x2) {
[1876]355      xAxisGrid.ClippingArea = new RectangleD(x1,
356                                              xAxisGrid.ClippingArea.Y1,
357                                              x2,
358                                              xAxisGrid.ClippingArea.Y2);
359
[1285]360      xAxis.ClippingArea = new RectangleD(x1,
361                                          0,
362                                          x2,
363                                          XAxisHeight);
[1249]364
[1285]365      foreach (RowEntry rowEntry in rowEntries) {
366        rowEntry.LinesShape.ClippingArea = new RectangleD(x1,
367                                                          rowEntry.LinesShape.ClippingArea.Y1,
368                                                          x2,
369                                                          rowEntry.LinesShape.ClippingArea.Y2);
[1249]370      }
[1350]371
372      foreach (YAxisDescriptor yAxisDescriptor in model.YAxes) {
373        YAxisInfo info = GetYAxisInfo(yAxisDescriptor);
374        info.Grid.ClippingArea = new RectangleD(x1,
375                                                info.Grid.ClippingArea.Y1,
376                                                x2,
377                                                info.Grid.ClippingArea.Y2);
378        info.YAxis.ClippingArea = new RectangleD(0,
379                                                 info.YAxis.ClippingArea.Y1,
380                                                 YAxisWidth,
381                                                 info.YAxis.ClippingArea.Y2);
382      }
[1285]383    }
[1249]384
[1350]385    private void SetClipY(RowEntry rowEntry, double y1, double y2) {
[1876]386      xAxisGrid.ClippingArea = new RectangleD(xAxisGrid.ClippingArea.X1,
387                                              y1,
388                                              xAxisGrid.ClippingArea.X2,
389                                              y2);
390
[1285]391      rowEntry.LinesShape.ClippingArea = new RectangleD(rowEntry.LinesShape.ClippingArea.X1,
392                                                        y1,
393                                                        rowEntry.LinesShape.ClippingArea.X2,
394                                                        y2);
[1350]395
396      YAxisInfo info = GetYAxisInfo(rowEntry.DataRow.YAxis);
397
398      info.Grid.ClippingArea = new RectangleD(info.Grid.ClippingArea.X1,
399                                              y1,
400                                              info.Grid.ClippingArea.X2,
401                                              y2);
402      info.YAxis.ClippingArea = new RectangleD(info.YAxis.ClippingArea.X1,
403                                               y1,
404                                               info.YAxis.ClippingArea.X2,
405                                               y2);
[981]406    }
407
[987]408    private void InitLineShapes(IDataRow row) {
[1285]409      RowEntry rowEntry = new RowEntry(row);
410      rowEntries.Add(rowEntry);
411      rowToRowEntry[row] = rowEntry;
412
[1242]413      if ((row.LineType == DataRowType.SingleValue)) {
414        if (row.Count > 0) {
415          LineShape lineShape = new HorizontalLineShape(0, row[0], double.MaxValue, row[0], row.Color, row.Thickness,
416                                                        row.Style);
[1285]417          rowEntry.LinesShape.AddShape(lineShape);
[1242]418        }
[1249]419      } else {
[1561]420        rowEntry.showMarkers(row.ShowMarkers);
[1242]421        for (int i = 1; i < row.Count; i++) {
[1283]422          LineShape lineShape = new LineShape(i - 1, row[i - 1], i, row[i], row.Color, row.Thickness, row.Style);
[1285]423          rowEntry.LinesShape.AddShape(lineShape);
[1608]424          rowEntry.LinesShape.AddMarkerShape(new MarkerShape(i - 1, row[i - 1], 8, row.Color));
[1242]425        }
[1608]426        if (row.Count > 0) {
[1559]427          rowEntry.LinesShape.AddMarkerShape(new MarkerShape((row.Count - 1), row[(row.Count - 1)], 8, row.Color));
[1608]428        }
[1242]429      }
[1249]430
[981]431      ZoomToFullView();
[697]432    }
433
[869]434    private void OnRowValueChanged(IDataRow row, double value, int index, Action action) {
[1285]435      RowEntry rowEntry = rowToRowEntry[row];
436
[1242]437      if (row.LineType == DataRowType.SingleValue) {
438        if (action == Action.Added) {
439          LineShape lineShape = new HorizontalLineShape(0, row[0], double.MaxValue, row[0], row.Color, row.Thickness,
440                                                        row.Style);
[1285]441          rowEntry.LinesShape.AddShape(lineShape);
[1249]442        } else {
[1285]443          LineShape lineShape = rowEntry.LinesShape.GetShape(0);
444          lineShape.Y1 = value;
445          lineShape.Y2 = value;
[1242]446        }
[1249]447      } else {
[1608]448        if (index > rowEntry.LinesShape.Count + 1) {
449          //MarkersShape is on position zero
[1242]450          throw new NotImplementedException();
451        }
[861]452
[1603]453        if (action == Action.Added) {
454          // new value was added
455          if (index > 0 && index == rowEntry.LinesShape.Count + 1) {
456            LineShape lineShape = new LineShape(index - 1, row[index - 1], index, row[index], row.Color, row.Thickness,
457                                                row.Style);
458            rowEntry.LinesShape.AddShape(lineShape);
459            rowEntry.LinesShape.AddMarkerShape(new MarkerShape(index, row[index], 8, row.Color));
460          }
[1608]461        } else if (action == Action.Modified) {
[1603]462          // not the first value
463          if (index > 0) {
464            rowEntry.LinesShape.GetShape(index - 1).Y2 = value;
[1608]465            ((MarkerShape)rowEntry.LinesShape.markersShape.GetShape(index - 1)).Y = value;
[1603]466          }
[861]467
[1603]468          // not the last value
469          if (index > 0 && index < row.Count - 1) {
470            rowEntry.LinesShape.GetShape(index).Y1 = value;
[1608]471            ((MarkerShape)rowEntry.LinesShape.markersShape.GetShape(index)).Y = value;
[1603]472          }
[1242]473        }
[1045]474      }
[861]475
[981]476      ZoomToFullView();
[697]477    }
478
[869]479    private void OnRowValuesChanged(IDataRow row, double[] values, int index, Action action) {
[1045]480      foreach (double value in values) {
[869]481        OnRowValueChanged(row, value, index++, action);
[1045]482      }
[861]483    }
[761]484
[1182]485    private void OnModelChanged() {
[1879]486      this.Invalidate(true);
[1182]487    }
488
[697]489    #region Begin-/EndUpdate
490
[1242]491    private int beginUpdateCount;
[697]492
[861]493    public void BeginUpdate() {
[697]494      beginUpdateCount++;
495    }
496
[861]497    public void EndUpdate() {
[1045]498      if (beginUpdateCount == 0) {
[697]499        throw new InvalidOperationException("Too many EndUpdates.");
[1045]500      }
[697]501
502      beginUpdateCount--;
503
[1045]504      if (beginUpdateCount == 0) {
[1879]505        this.Invalidate(true);
[1045]506      }
[697]507    }
508
509    #endregion
[928]510
[1059]511    #region Zooming / Panning
512
[1249]513    private void Pan(Point startPoint, Point endPoint) {
[1351]514      RectangleD clippingArea = Translate.ClippingArea(startPoint, endPoint, xAxis.ClippingArea, xAxis.Viewport);
[1285]515
[1351]516      SetClipX(clippingArea.X1, clippingArea.X2);
[1285]517
518      foreach (RowEntry rowEntry in rowEntries) {
[1390]519        if (rowEntry.DataRow.YAxis.ClipChangeable) {
520          clippingArea = Translate.ClippingArea(startPoint, endPoint, rowEntry.LinesShape.ClippingArea, rowEntry.LinesShape.Viewport);
521          SetClipY(rowEntry, clippingArea.Y1, clippingArea.Y2);
522        }
[1285]523      }
524
[1879]525      this.Invalidate(true);
[1249]526    }
527
[1351]528    private void PanEnd(Point startPoint, Point endPoint) {
529      Pan(startPoint, endPoint);
[1249]530    }
531
532    private void SetClippingArea(Rectangle rectangle) {
[1351]533      RectangleD clippingArea = Transform.ToWorld(rectangle, xAxis.Viewport, xAxis.ClippingArea);
534
535      SetClipX(clippingArea.X1, clippingArea.X2);
536
[1285]537      foreach (RowEntry rowEntry in rowEntries) {
[1390]538        if (rowEntry.DataRow.YAxis.ClipChangeable) {
539          clippingArea = Transform.ToWorld(rectangle, rowEntry.LinesShape.Viewport, rowEntry.LinesShape.ClippingArea);
[1249]540
[1390]541          SetClipY(rowEntry, clippingArea.Y1, clippingArea.Y2);
542        }
[1285]543      }
544
[1249]545      userInteractionShape.RemoveShape(rectangleShape);
[1879]546      this.Invalidate(true);
[1249]547    }
548
549    private void DrawRectangle(Rectangle rectangle) {
550      rectangleShape.Rectangle = Transform.ToWorld(rectangle, userInteractionShape.Viewport, userInteractionShape.ClippingArea);
[1879]551      this.Invalidate(true);
[1249]552    }
553
[1608]554    private void canvasUI1_KeyDown(object sender, KeyEventArgs e) {}
[1059]555
[928]556    private void canvasUI1_MouseDown(object sender, MouseEventArgs e) {
[1058]557      Focus();
[1249]558
[1237]559      if (e.Button == MouseButtons.Right) {
[1781]560        contextMenu.Show(PointToScreen(e.Location));
[1249]561      } else if (e.Button == MouseButtons.Left) {
562        if (ModifierKeys == Keys.None) {
563          PanListener panListener = new PanListener(e.Location);
564          panListener.Pan += Pan;
565          panListener.PanEnd += PanEnd;
566
567          mouseEventListener = panListener;
568        } else if (ModifierKeys == Keys.Control) {
569          ZoomListener zoomListener = new ZoomListener(e.Location);
570          zoomListener.DrawRectangle += DrawRectangle;
571          zoomListener.SetClippingArea += SetClippingArea;
572
573          rectangleShape.Rectangle = RectangleD.Empty;
574          userInteractionShape.AddShape(rectangleShape);
575
576          mouseEventListener = zoomListener;
[1187]577        }
578      }
[928]579    }
580
[1249]581    private void canvasUI_MouseMove(object sender, MouseEventArgs e) {
582      if (mouseEventListener != null) {
583        mouseEventListener.MouseMove(sender, e);
584      }
585    }
[1244]586
[1249]587    private void canvasUI_MouseUp(object sender, MouseEventArgs e) {
588      if (mouseEventListener != null) {
589        mouseEventListener.MouseUp(sender, e);
590      }
[1240]591
[1249]592      mouseEventListener = null;
[1240]593    }
594
[1058]595    private void canvasUI1_MouseWheel(object sender, MouseEventArgs e) {
596      if (ModifierKeys == Keys.Control) {
[1351]597        double zoomFactor = (e.Delta > 0) ? 0.7 : 1.3;
[1058]598
[1351]599        PointD world;
600
601        world = Transform.ToWorld(e.Location, xAxis.Viewport, xAxis.ClippingArea);
602
603        double x1 = world.X - (world.X - xAxis.ClippingArea.X1)*zoomFactor;
604        double x2 = world.X + (xAxis.ClippingArea.X2 - world.X)*zoomFactor;
605
606        SetClipX(x1, x2);
607
[1285]608        foreach (RowEntry rowEntry in rowEntries) {
[1351]609          world = Transform.ToWorld(e.Location, rowEntry.LinesShape.Viewport, rowEntry.LinesShape.ClippingArea);
610
[1608]611          double y1 = world.Y - (world.Y - rowEntry.LinesShape.ClippingArea.Y1)*zoomFactor;
[1351]612          double y2 = world.Y + (rowEntry.LinesShape.ClippingArea.Y2 - world.Y)*zoomFactor;
613
614          SetClipY(rowEntry, y1, y2);
[1285]615        }
[1351]616
[1879]617        this.Invalidate(true);
[1058]618      }
619    }
620
[1249]621    #endregion
[928]622
[1879]623    protected override void OnPaint(PaintEventArgs e) {
624      UpdateLayout();
625      base.OnPaint(e);
626    }
627
[1285]628    private class LinesShape : WorldShape {
[1559]629      public readonly CompositeShape markersShape = new CompositeShape();
630
[1285]631      public void UpdateStyle(IDataRow row) {
632        foreach (IShape shape in shapes) {
633          LineShape lineShape = shape as LineShape;
634          if (lineShape != null) {
635            lineShape.LSColor = row.Color;
636            lineShape.LSDrawingStyle = row.Style;
637            lineShape.LSThickness = row.Thickness;
638          }
639        }
[1561]640        this.markersShape.ShowChildShapes = row.ShowMarkers;
[1285]641      }
[928]642
[1559]643      public override void Draw(Graphics graphics) {
644        GraphicsState gstate = graphics.Save();
645
646        graphics.SetClip(Viewport);
647        foreach (IShape shape in shapes) {
648          // draw child shapes using our own clipping area
649          shape.Draw(graphics);
650        }
651        markersShape.Draw(graphics);
652        graphics.Restore(gstate);
653      }
654
655      public void AddMarkerShape(IShape shape) {
656        shape.Parent = this;
657        markersShape.AddShape(shape);
658      }
659
[1285]660      public int Count {
661        get { return shapes.Count; }
662      }
[928]663
[1285]664      public LineShape GetShape(int index) {
[1608]665        return (LineShape)shapes[index]; //shapes[0] is markersShape!!
[1285]666      }
667    }
668
669    private class RowEntry {
670      private readonly IDataRow dataRow;
671
672      private readonly LinesShape linesShape = new LinesShape();
673
674      public RowEntry(IDataRow dataRow) {
675        this.dataRow = dataRow;
[1559]676        linesShape.markersShape.Parent = linesShape;
[1285]677      }
678
679      public IDataRow DataRow {
680        get { return dataRow; }
681      }
682
[1350]683      public LinesShape LinesShape {
684        get { return linesShape; }
685      }
[1559]686
[1561]687      public void showMarkers(bool flag) {
688        linesShape.markersShape.ShowChildShapes = flag;
[1559]689      }
[1350]690    }
691
[1608]692    private class YAxisInfo {
[1876]693      private readonly YAxisGrid grid = new YAxisGrid();
[1350]694      private readonly YAxis yAxis = new YAxis();
695
[1876]696      public YAxisGrid Grid {
[1285]697        get { return grid; }
698      }
699
700      public YAxis YAxis {
701        get { return yAxis; }
702      }
703    }
[684]704  }
[1608]705}
Note: See TracBrowser for help on using the repository browser.