Changeset 1249


Ignore:
Timestamp:
03/04/09 21:35:43 (12 years ago)
Author:
bspisic
Message:

reimplemented panning and zooming (#424)

Location:
trunk/sources
Files:
1 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Visualization.Test/LegendForm.Designer.cs

    r872 r1249  
    3030      //
    3131      this.canvasUI.Location = new System.Drawing.Point(12, 12);
    32       this.canvasUI.MouseEventListener = null;
    3332      this.canvasUI.Name = "canvasUI";
    3433      this.canvasUI.Size = new System.Drawing.Size(260, 240);
  • trunk/sources/HeuristicLab.Visualization.Test/LineChartTestForm.cs

    r1038 r1249  
    2525      if (view != null) {
    2626        LineChart lineChart = (LineChart)view;
    27         lineChart.ResetView();
     27        lineChart.ZoomToFullView();
    2828      }
    2929    }
  • trunk/sources/HeuristicLab.Visualization.Test/MainForm.Designer.cs

    r1045 r1249  
    3232      //
    3333      this.canvasUI.Location = new System.Drawing.Point(12, 29);
    34       this.canvasUI.MouseEventListener = null;
    3534      this.canvasUI.Name = "canvasUI";
    3635      this.canvasUI.Size = new System.Drawing.Size(800, 571);
  • trunk/sources/HeuristicLab.Visualization/CanvasUI.Designer.cs

    r724 r1249  
    3333          // CanvasUI
    3434          //
    35           this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.CanvasUI_MouseMove);
    36           this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.CanvasUI_MouseUp);
    3735          this.ResumeLayout(false);
    3836
  • trunk/sources/HeuristicLab.Visualization/CanvasUI.cs

    r1240 r1249  
    77  public partial class CanvasUI : Control {
    88    private readonly Canvas canvas = new Canvas();
    9     private IMouseEventListener mouseEventListener;
    109
    1110    public CanvasUI() {
     
    1716    public Canvas Canvas {
    1817      get { return canvas; }
    19     }
    20 
    21     public IMouseEventListener MouseEventListener {
    22       get { return mouseEventListener; }
    23       set { mouseEventListener = value; }
    2418    }
    2519
     
    4438      base.OnResize(e);
    4539    }
    46 
    47     private void CanvasUI_MouseMove(object sender, MouseEventArgs e) {
    48       if (mouseEventListener != null) {
    49         mouseEventListener.MouseMove(sender, e);
    50       }
    51     }
    52 
    53     private void CanvasUI_MouseUp(object sender, MouseEventArgs e) {
    54       if (mouseEventListener != null) {
    55         mouseEventListener.MouseUp(sender, e);
    56       }
    57     }
    5840  }
    5941}
  • trunk/sources/HeuristicLab.Visualization/HeuristicLab.Visualization.csproj

    r1240 r1249  
    120120    <Compile Include="SizeD.cs" />
    121121    <Compile Include="Transform.cs" />
     122    <Compile Include="Translate.cs" />
    122123    <Compile Include="WorldShape.cs" />
    123124    <Compile Include="XAxis.cs" />
  • trunk/sources/HeuristicLab.Visualization/IMouseEventListener.cs

    r1055 r1249  
    66    void MouseMove(object sender, MouseEventArgs e);
    77    void MouseUp(object sender, MouseEventArgs e);
    8 
    9     event MouseEventHandler OnMouseMove;
    10     event MouseEventHandler OnMouseUp;
    118  }
    129
    13   public delegate void SetNewClippingAreaHandler(RectangleD newClippingArea);
    14   public delegate void DrawRectangleHandler(Rectangle rectangle);
     10  public delegate void MoveHandler(Point startPoint, Point endPoint);
     11  public delegate void RectangleHandler(Rectangle rectangle);
    1512}
  • trunk/sources/HeuristicLab.Visualization/LineChart.Designer.cs

    r1240 r1249  
    4242          this.canvasUI.Dock = System.Windows.Forms.DockStyle.Fill;
    4343          this.canvasUI.Location = new System.Drawing.Point(0, 0);
    44           this.canvasUI.MouseEventListener = null;
    4544          this.canvasUI.Name = "canvasUI";
    4645          this.canvasUI.Size = new System.Drawing.Size(551, 373);
     
    4847          this.canvasUI.Text = "canvas";
    4948          this.canvasUI.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.canvasUI1_MouseWheel);
    50           this.canvasUI.MouseMove += new System.Windows.Forms.MouseEventHandler(this.canvas_MouseMove);
     49          this.canvasUI.MouseMove += new System.Windows.Forms.MouseEventHandler(this.canvasUI_MouseMove);
    5150          this.canvasUI.ContextMenuStripChanged += new System.EventHandler(this.optionsToolStripMenuItem_Click);
    5251          this.canvasUI.MouseDown += new System.Windows.Forms.MouseEventHandler(this.canvasUI1_MouseDown);
     52          this.canvasUI.MouseUp += new System.Windows.Forms.MouseEventHandler(this.canvasUI_MouseUp);
    5353          this.canvasUI.KeyDown += new System.Windows.Forms.KeyEventHandler(this.canvasUI1_KeyDown);
    5454          //
  • trunk/sources/HeuristicLab.Visualization/LineChart.cs

    r1244 r1249  
    11using System;
    22using System.Collections.Generic;
    3 using System.Diagnostics;
    43using System.Drawing;
    54using System.Windows.Forms;
     
    109namespace HeuristicLab.Visualization {
    1110  public partial class LineChart : ViewBase {
    12     internal class LinesShape : WorldShape {}
    1311    private readonly IChartDataRowsModel model;
    1412    private readonly Canvas canvas;
    1513
    1614    private int maxDataRowCount;
    17     private Boolean zoomFullView;
    1815    private double minDataValue;
    1916    private double maxDataValue;
    20  
    2117
    2218    private readonly TextShape titleShape;
     
    2824    private readonly Grid grid;
    2925
    30     private readonly WorldShape berni;
    31     private readonly RectangleShape mousePointer;
     26    private readonly Stack<RectangleD> clippingAreaHistory = new Stack<RectangleD>();
     27    private readonly WorldShape userInteractionShape;
     28    private readonly RectangleShape rectangleShape;
     29    private IMouseEventListener mouseEventListener;
     30    private bool zoomToFullView;
    3231
    3332    /// <summary>
     
    4746      }
    4847
    49    
    5048      canvas = canvasUI.Canvas;
    5149
     
    7169      canvas.AddShape(legendShape);
    7270
    73       berni = new WorldShape();
    74       canvas.AddShape(berni);
    75 
    76       mousePointer = new RectangleShape(10, 10, 20, 20, Color.Black);
    77       berni.AddShape(mousePointer);
     71      userInteractionShape = new WorldShape();
     72      canvas.AddShape(userInteractionShape);
     73
     74      rectangleShape = new RectangleShape(0, 0, 0, 0, Color.Blue);
     75      rectangleShape.Opacity = 50;
    7876
    7977      maxDataRowCount = 0;
     
    8583
    8684      //The whole data rows are shown per default
    87       ResetView();
     85      ZoomToFullView();
    8886    }
    8987
     
    103101                                              canvasUI.Height);
    104102
    105       berni.BoundingBox = linesShape.BoundingBox;
    106       berni.ClippingArea = new RectangleD(0, 0, berni.BoundingBox.Width, berni.BoundingBox.Height);
     103      userInteractionShape.BoundingBox = linesShape.BoundingBox;
     104      userInteractionShape.ClippingArea = new RectangleD(0, 0, userInteractionShape.BoundingBox.Width, userInteractionShape.BoundingBox.Height);
    107105
    108106      grid.BoundingBox = linesShape.BoundingBox;
     
    122120      legendShape.ClippingArea = new RectangleD(0, 0, legendShape.BoundingBox.Width,
    123121                                                legendShape.BoundingBox.Height);
    124     }
    125 
    126     public void ResetView() {
    127       zoomFullView = true;
    128       ZoomToFullView();
    129 
    130       canvasUI.Invalidate();
    131122    }
    132123
     
    193184    #endregion
    194185
    195     private void ZoomToFullView() {
    196       if (!zoomFullView) {
    197         return;
    198       }
    199       var newClippingArea = new RectangleD(-0.1,
    200                                            minDataValue - ((maxDataValue - minDataValue)*0.05),
    201                                            maxDataRowCount - 0.9,
    202                                            maxDataValue + ((maxDataValue - minDataValue)*0.05));
    203 
    204       SetLineClippingArea(newClippingArea);
    205       historyStack.Push(newClippingArea);
     186    public void ZoomToFullView() {
     187      RectangleD newClippingArea = new RectangleD(-0.1,
     188                                                  minDataValue - ((maxDataValue - minDataValue)*0.05),
     189                                                  maxDataRowCount - 0.9,
     190                                                  maxDataValue + ((maxDataValue - minDataValue)*0.05));
     191
     192      SetLineClippingArea(newClippingArea, true);
     193
     194      zoomToFullView = true;
    206195    }
    207196
     
    210199    /// </summary>
    211200    /// <param name="clippingArea"></param>
    212     private void SetLineClippingArea(RectangleD clippingArea) {
     201    /// <param name="pushToHistoryStack"></param>
     202    private void SetLineClippingArea(RectangleD clippingArea, bool pushToHistoryStack) {
     203      zoomToFullView = false;
     204
     205      if (pushToHistoryStack) {
     206        int count = clippingAreaHistory.Count;
     207
     208        if (count > 40) {
     209          RectangleD[] clippingAreas = clippingAreaHistory.ToArray();
     210          clippingAreaHistory.Clear();
     211
     212          for (int i = count - 20; i < count; i++) {
     213            clippingAreaHistory.Push(clippingAreas[i]);
     214          }
     215        }
     216
     217        clippingAreaHistory.Push(clippingArea);
     218      }
     219
    213220      linesShape.ClippingArea = clippingArea;
    214221
     
    227234                                          yAxis.BoundingBox.X2,
    228235                                          linesShape.ClippingArea.Y2);
     236
     237      canvasUI.Invalidate();
    229238    }
    230239
     
    247256          linesShape.AddShape(lineShape);
    248257        }
    249       }
    250       else {
     258      } else {
    251259        for (int i = 1; i < row.Count; i++) {
    252260          var lineShape = new LineShape(i - 1, row[i - 1], i, row[i], row.Color, row.Thickness, row.Style);
     
    260268      //horizontalLineShape.YVal = maxDataValue;
    261269      rowToLineShapes[row] = lineShapes;
     270
    262271      ZoomToFullView();
    263 
    264       canvasUI.Invalidate();
    265272    }
    266273
     
    277284          // TODO each DataRow needs its own WorldShape so Y Axes can be zoomed independently.
    278285          linesShape.AddShape(lineShape);
    279         }
    280         else {
     286        } else {
    281287          // lineShapes[0].X2 = maxDataRowCount;
    282288          lineShapes[0].Y1 = value;
    283289          lineShapes[0].Y2 = value;
    284290        }
    285       }
    286       else {
     291      } else {
    287292        //  horizontalLineShape.YVal = maxDataValue;
    288293        if (index > lineShapes.Count + 1) {
     
    315320
    316321      ZoomToFullView();
    317       canvasUI.Invalidate();
    318322    }
    319323
     
    337341    }
    338342
    339  
    340343    #region Begin-/EndUpdate
    341344
     
    362365    #region Zooming / Panning
    363366
    364     private readonly Stack<RectangleD> historyStack = new Stack<RectangleD>();
    365     private RectangleShape rectangleShape;
     367    private void Pan(Point startPoint, Point endPoint) {
     368      RectangleD clippingArea = CalcPanClippingArea(startPoint, endPoint);
     369      SetLineClippingArea(clippingArea, false);
     370    }
     371
     372    private void PanEnd(Point startPoint, Point endPoint) {
     373      RectangleD clippingArea = CalcPanClippingArea(startPoint, endPoint);
     374      SetLineClippingArea(clippingArea, true);
     375    }
     376
     377    private RectangleD CalcPanClippingArea(Point startPoint, Point endPoint) {
     378      return Translate.ClippingArea(startPoint, endPoint, linesShape.ClippingArea, linesShape.Viewport);
     379    }
     380
     381    private void SetClippingArea(Rectangle rectangle) {
     382      RectangleD clippingArea = Transform.ToWorld(rectangle, linesShape.Viewport, linesShape.ClippingArea);
     383
     384      SetLineClippingArea(clippingArea, true);
     385      userInteractionShape.RemoveShape(rectangleShape);
     386    }
     387
     388    private void DrawRectangle(Rectangle rectangle) {
     389      rectangleShape.Rectangle = Transform.ToWorld(rectangle, userInteractionShape.Viewport, userInteractionShape.ClippingArea);
     390      canvasUI.Invalidate();
     391    }
    366392
    367393    private void canvasUI1_KeyDown(object sender, KeyEventArgs e) {
    368       if (e.KeyCode == Keys.Back && historyStack.Count > 1) {
    369         historyStack.Pop();
    370 
    371         RectangleD clippingArea = historyStack.Peek();
    372 
    373         SetNewClippingArea(clippingArea);
    374         canvasUI.Invalidate();
     394      if (e.KeyCode == Keys.Back && clippingAreaHistory.Count > 1) {
     395        clippingAreaHistory.Pop();
     396
     397        RectangleD clippingArea = clippingAreaHistory.Peek();
     398
     399        SetLineClippingArea(clippingArea, false);
    375400      }
    376401    }
     
    378403    private void canvasUI1_MouseDown(object sender, MouseEventArgs e) {
    379404      Focus();
     405
    380406      if (e.Button == MouseButtons.Right) {
    381407        contextMenuStrip1.Show(PointToScreen(e.Location));
    382       }
    383       else {
    384         if (ModifierKeys == Keys.Control) {
    385           CreateZoomListener(e);
    386         }
    387         else {
    388           CreatePanListener(e);
    389         }
    390       }
    391     }
    392 
    393     private Point prevMousePosition = Point.Empty;
    394 
    395     private void canvas_MouseMove(object sender, MouseEventArgs e) {
    396       if (prevMousePosition != e.Location) {
    397         prevMousePosition = e.Location;
    398 
    399         double x = Transform.ToWorldX(e.X, berni.Viewport, berni.ClippingArea);
    400         double y = Transform.ToWorldY(e.Y, berni.Viewport, berni.ClippingArea);
    401 
    402         mousePointer.Rectangle = new RectangleD(x - 1, y - 1, x + 1, y + 1);
    403         canvasUI.Invalidate();
    404       }
     408      } else if (e.Button == MouseButtons.Left) {
     409        if (ModifierKeys == Keys.None) {
     410          PanListener panListener = new PanListener(e.Location);
     411          panListener.Pan += Pan;
     412          panListener.PanEnd += PanEnd;
     413
     414          mouseEventListener = panListener;
     415        } else if (ModifierKeys == Keys.Control) {
     416          ZoomListener zoomListener = new ZoomListener(e.Location);
     417          zoomListener.DrawRectangle += DrawRectangle;
     418          zoomListener.SetClippingArea += SetClippingArea;
     419
     420          rectangleShape.Rectangle = RectangleD.Empty;
     421          userInteractionShape.AddShape(rectangleShape);
     422
     423          mouseEventListener = zoomListener;
     424        }
     425      }
     426    }
     427
     428    private void canvasUI_MouseMove(object sender, MouseEventArgs e) {
     429      if (mouseEventListener != null) {
     430        mouseEventListener.MouseMove(sender, e);
     431      }
     432    }
     433
     434    private void canvasUI_MouseUp(object sender, MouseEventArgs e) {
     435      if (mouseEventListener != null) {
     436        mouseEventListener.MouseUp(sender, e);
     437      }
     438
     439      mouseEventListener = null;
    405440    }
    406441
     
    411446        RectangleD clippingArea = ZoomListener.ZoomClippingArea(linesShape.ClippingArea, zoomFactor);
    412447
    413         SetLineClippingArea(clippingArea);
    414         canvasUI.Invalidate();
    415       }
    416     }
    417 
    418     private void CreateZoomListener(MouseEventArgs e) {
    419       var zoomListener = new ZoomListener(e.Location);
    420       zoomListener.DrawRectangle += DrawRectangle;
    421       zoomListener.OnMouseUp += OnZoom_MouseUp;
    422 
    423       canvasUI.MouseEventListener = zoomListener;
    424 
    425       rectangleShape = new RectangleShape(e.X, e.Y, e.X, e.Y, Color.Blue);
    426       rectangleShape.Opacity = 50;
    427 
    428       linesShape.AddShape(rectangleShape);
    429     }
    430 
    431     private void OnZoom_MouseUp(object sender, MouseEventArgs e) {
    432       canvasUI.MouseEventListener = null;
    433 
    434       RectangleD clippingArea = rectangleShape.Rectangle;
    435 
    436       SetLineClippingArea(clippingArea);
    437       historyStack.Push(clippingArea);
    438 
    439       linesShape.RemoveShape(rectangleShape);
    440 
    441       zoomFullView = false; //user wants to zoom => no full view
    442 
    443       canvasUI.Invalidate();
    444     }
    445 
    446     private void DrawRectangle(Rectangle rectangle) {
    447       rectangleShape.Rectangle = Transform.ToWorld(rectangle, canvasUI.ClientRectangle, linesShape.ClippingArea);
    448       canvasUI.Invalidate();
    449     }
    450 
    451     private void CreatePanListener(MouseEventArgs e) {
    452       PanListener panListener = new PanListener(canvasUI.ClientRectangle, linesShape.ClippingArea, e.Location);
    453 
    454       panListener.SetNewClippingArea += SetNewClippingArea;
    455       panListener.OnMouseUp += delegate {
    456                                  historyStack.Push(linesShape.ClippingArea);
    457                                  canvasUI.MouseEventListener = null;
    458                                };
    459 
    460       canvasUI.MouseEventListener = panListener;
    461     }
    462 
    463     private void SetNewClippingArea(RectangleD newClippingArea) {
    464       SetLineClippingArea(newClippingArea);
    465 
    466       zoomFullView = false;
    467       canvasUI.Invalidate();
     448        SetLineClippingArea(clippingArea, true);
     449      }
    468450    }
    469451
    470452    #endregion
    471453
    472    
     454    #region Nested type: LinesShape
     455
     456    internal class LinesShape : WorldShape {}
     457
     458    #endregion
    473459  }
    474460}
  • trunk/sources/HeuristicLab.Visualization/PanListener.cs

    r1055 r1249  
    44namespace HeuristicLab.Visualization {
    55  public class PanListener : IMouseEventListener {
    6     private readonly Rectangle viewPort;
    7     private readonly RectangleD clippingArea;
    8     private readonly Point startPoint;
     6    private Point startPoint;
    97
    10     public PanListener(Rectangle viewPort, RectangleD clippingArea, Point startPoint) {
    11       this.viewPort = viewPort;
    12       this.clippingArea = clippingArea;
     8    public event MoveHandler Pan;
     9    public event MoveHandler PanEnd;
     10
     11    public PanListener(Point startPoint) {
    1312      this.startPoint = startPoint;
    1413    }
     
    1615    #region IMouseEventListener Members
    1716
    18     public event SetNewClippingAreaHandler SetNewClippingArea;
    19     public event MouseEventHandler OnMouseMove;
    20     public event MouseEventHandler OnMouseUp;
    21 
    2217    public void MouseMove(object sender, MouseEventArgs e) {
    23       PointD worldStartPoint = Transform.ToWorld(startPoint, viewPort, clippingArea);
    24       PointD worldActualPoint = Transform.ToWorld(e.Location, viewPort, clippingArea);
    25 
    26       double xDiff = worldActualPoint.X - worldStartPoint.X;
    27       double yDiff = worldActualPoint.Y - worldStartPoint.Y;
    28 
    29       RectangleD newClippingArea = new RectangleD();
    30       newClippingArea.X1 = clippingArea.X1 - xDiff;
    31       newClippingArea.X2 = clippingArea.X2 - xDiff;
    32       newClippingArea.Y1 = clippingArea.Y1 - yDiff;
    33       newClippingArea.Y2 = clippingArea.Y2 - yDiff;
    34 
    35       if (SetNewClippingArea != null) {
    36         SetNewClippingArea(newClippingArea);
     18      if (Pan != null) {
     19        Pan(startPoint, e.Location);
    3720      }
    3821
    39       if (OnMouseMove != null) {
    40         OnMouseMove(sender, e);
    41       }
     22      startPoint = e.Location; 
    4223    }
    4324
    4425    public void MouseUp(object sender, MouseEventArgs e) {
    45       if (OnMouseUp != null) {
    46         OnMouseUp(sender, e);
     26      if(PanEnd != null) {
     27        PanEnd(startPoint, e.Location);
    4728      }
    4829    }
  • trunk/sources/HeuristicLab.Visualization/ZoomListener.cs

    r1058 r1249  
    66    private readonly Point startPoint;
    77
    8     public event DrawRectangleHandler DrawRectangle;
     8    public event RectangleHandler DrawRectangle;
     9    public event RectangleHandler SetClippingArea;
    910
    1011    public ZoomListener(Point startPoint) {
     
    1415    #region IMouseEventListener Members
    1516
    16     public event MouseEventHandler OnMouseMove;
    17     public event MouseEventHandler OnMouseUp;
    18 
    1917    public void MouseMove(object sender, MouseEventArgs e) {
    20       Rectangle r = new Rectangle();
    21       Point actualPoint = e.Location;
    22 
    23       if (startPoint.X < actualPoint.X) {
    24         r.X = startPoint.X;
    25         r.Width = actualPoint.X - startPoint.X;
    26       } else {
    27         r.X = actualPoint.X;
    28         r.Width = startPoint.X - actualPoint.X;
    29       }
    30 
    31       if (startPoint.Y < actualPoint.Y) {
    32         r.Y = startPoint.Y;
    33         r.Height = actualPoint.Y - startPoint.Y;
    34       } else {
    35         r.Y = actualPoint.Y;
    36         r.Height = startPoint.Y - actualPoint.Y;
    37       }
    38 
    3918      if(DrawRectangle != null) {
    40         DrawRectangle(r);
    41       }
    42 
    43       if (OnMouseMove != null) {
    44         OnMouseMove(sender, e);
     19        DrawRectangle(CalcRectangle(e.Location));
    4520      }
    4621    }
    4722
    4823    public void MouseUp(object sender, MouseEventArgs e) {
    49       if (OnMouseUp != null) {
    50         OnMouseUp(sender, e);
    51       }
     24     if(SetClippingArea != null) {
     25       SetClippingArea(CalcRectangle(e.Location));
     26     }
    5227    }
    5328
    5429    #endregion
     30
     31    private Rectangle CalcRectangle(Point actualPoint) {
     32      Rectangle rectangle = new Rectangle();
     33
     34      if (startPoint.X < actualPoint.X) {
     35        rectangle.X = startPoint.X;
     36        rectangle.Width = actualPoint.X - startPoint.X;
     37      } else {
     38        rectangle.X = actualPoint.X;
     39        rectangle.Width = startPoint.X - actualPoint.X;
     40      }
     41
     42      if (startPoint.Y < actualPoint.Y) {
     43        rectangle.Y = startPoint.Y;
     44        rectangle.Height = actualPoint.Y - startPoint.Y;
     45      } else {
     46        rectangle.Y = actualPoint.Y;
     47        rectangle.Height = startPoint.Y - actualPoint.Y;
     48      }
     49
     50      return rectangle;
     51    }
    5552
    5653    public static RectangleD ZoomClippingArea(RectangleD clippingArea, double zoomFactor) {
Note: See TracChangeset for help on using the changeset viewer.