Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/DynamicDataDisplay/Charts/Navigation/MouseNavigation.cs @ 13398

Last change on this file since 13398 was 12503, checked in by aballeit, 10 years ago

#2283 added GUI and charts; fixed MCTS

File size: 10.2 KB
Line 
1using System;
2using System.Windows;
3using System.Windows.Documents;
4using System.Windows.Input;
5using System.Windows.Media;
6using Microsoft.Research.DynamicDataDisplay.Common;
7using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
8using System.Diagnostics;
9
10
11namespace Microsoft.Research.DynamicDataDisplay.Navigation
12{
13  /// <summary>Provides common methods of mouse navigation around viewport</summary>
14  public class MouseNavigation : NavigationBase
15  {
16    /// <summary>
17    /// Initializes a new instance of the <see cref="MouseNavigation"/> class.
18    /// </summary>
19    public MouseNavigation() { }
20
21    private AdornerLayer adornerLayer;
22    protected AdornerLayer AdornerLayer
23    {
24      get
25      {
26        if (adornerLayer == null)
27        {
28          adornerLayer = AdornerLayer.GetAdornerLayer(this);
29          if (adornerLayer != null)
30          {
31            adornerLayer.IsHitTestVisible = false;
32          }
33        }
34
35        return adornerLayer;
36      }
37    }
38
39    protected override void OnPlotterAttached(Plotter plotter)
40    {
41      base.OnPlotterAttached(plotter);
42
43      Mouse.AddMouseDownHandler(Parent, OnMouseDown);
44      Mouse.AddMouseMoveHandler(Parent, OnMouseMove);
45      Mouse.AddMouseUpHandler(Parent, OnMouseUp);
46      Mouse.AddMouseWheelHandler(Parent, OnMouseWheel);
47
48      plotter.KeyDown += new KeyEventHandler(OnParentKeyDown);
49    }
50
51    protected override void OnPlotterDetaching(Plotter plotter)
52    {
53      plotter.KeyDown -= new KeyEventHandler(OnParentKeyDown);
54
55      Mouse.RemoveMouseDownHandler(Parent, OnMouseDown);
56      Mouse.RemoveMouseMoveHandler(Parent, OnMouseMove);
57      Mouse.RemoveMouseUpHandler(Parent, OnMouseUp);
58      Mouse.RemoveMouseWheelHandler(Parent, OnMouseWheel);
59
60      base.OnPlotterDetaching(plotter);
61    }
62
63    private void OnParentKeyDown(object sender, KeyEventArgs e)
64    {
65      if (e.Key == Key.Escape || e.Key == Key.Back)
66      {
67        if (isZooming)
68        {
69          isZooming = false;
70          zoomRect = null;
71          ReleaseMouseCapture();
72          RemoveSelectionAdorner();
73
74          e.Handled = true;
75        }
76      }
77    }
78
79    private void OnMouseWheel(object sender, MouseWheelEventArgs e)
80    {
81      if (!e.Handled)
82      {
83        Point mousePos = e.GetPosition(this);
84        int delta = -e.Delta;
85        MouseWheelZoom(mousePos, delta);
86
87        e.Handled = true;
88      }
89    }
90
91#if DEBUG
92    public override string ToString()
93    {
94      if (!String.IsNullOrEmpty(Name))
95      {
96        return Name;
97      }
98      return base.ToString();
99    }
100#endif
101
102    bool adornerAdded;
103    RectangleSelectionAdorner selectionAdorner;
104    private void AddSelectionAdorner()
105    {
106      if (!adornerAdded)
107      {
108        AdornerLayer layer = AdornerLayer;
109        if (layer != null)
110        {
111          selectionAdorner = new RectangleSelectionAdorner(this) { Border = zoomRect };
112
113          layer.Add(selectionAdorner);
114          adornerAdded = true;
115        }
116      }
117    }
118
119    private void RemoveSelectionAdorner()
120    {
121      AdornerLayer layer = AdornerLayer;
122      if (layer != null)
123      {
124        layer.Remove(selectionAdorner);
125        adornerAdded = false;
126      }
127    }
128
129    private void UpdateSelectionAdorner()
130    {
131      selectionAdorner.Border = zoomRect;
132      selectionAdorner.InvalidateVisual();
133    }
134
135    Rect? zoomRect = null;
136    private const double wheelZoomSpeed = 1.2;
137    private bool shouldKeepRatioWhileZooming;
138
139    private bool isZooming = false;
140    protected bool IsZooming
141    {
142      get { return isZooming; }
143    }
144
145    private bool isPanning = false;
146    protected bool IsPanning
147    {
148      get { return isPanning; }
149    }
150
151    private Point panningStartPointInViewport;
152    protected Point PanningStartPointInViewport
153    {
154      get { return panningStartPointInViewport; }
155    }
156
157    private Point zoomStartPoint;
158
159    private static bool IsShiftOrCtrl
160    {
161      get
162      {
163        ModifierKeys currKeys = Keyboard.Modifiers;
164        return (currKeys | ModifierKeys.Shift) == currKeys ||
165          (currKeys | ModifierKeys.Control) == currKeys;
166      }
167    }
168
169    protected virtual bool ShouldStartPanning(MouseButtonEventArgs e)
170    {
171      return e.ChangedButton == MouseButton.Left && Keyboard.Modifiers == ModifierKeys.None;
172    }
173
174    protected virtual bool ShouldStartZoom(MouseButtonEventArgs e)
175    {
176      return e.ChangedButton == MouseButton.Left && IsShiftOrCtrl;
177    }
178
179    Point panningStartPointInScreen;
180    protected virtual void StartPanning(MouseButtonEventArgs e)
181    {
182      panningStartPointInScreen = e.GetPosition(this);
183      panningStartPointInViewport = panningStartPointInScreen.ScreenToViewport(Viewport.Transform);
184
185      Plotter2D.UndoProvider.CaptureOldValue(Viewport, Viewport2D.VisibleProperty, Viewport.Visible);
186
187      isPanning = true;
188
189      // not capturing mouse because this made some tools like PointSelector not
190      // receive MouseUp events on markers;
191      // Mouse will be captured later, in the first MouseMove handler call.
192      // CaptureMouse();
193
194      Viewport.PanningState = Viewport2DPanningState.Panning;
195
196      //e.Handled = true;
197    }
198
199    protected virtual void StartZoom(MouseButtonEventArgs e)
200    {
201      zoomStartPoint = e.GetPosition(this);
202      if (Viewport.Output.Contains(zoomStartPoint))
203      {
204        isZooming = true;
205        AddSelectionAdorner();
206        CaptureMouse();
207        shouldKeepRatioWhileZooming = Keyboard.Modifiers == ModifierKeys.Shift;
208
209        e.Handled = true;
210      }
211    }
212
213    private void OnMouseDown(object sender, MouseButtonEventArgs e)
214    {
215      // dragging
216      bool shouldStartDrag = ShouldStartPanning(e);
217      if (shouldStartDrag)
218        StartPanning(e);
219
220      // zooming
221      bool shouldStartZoom = ShouldStartZoom(e);
222      if (shouldStartZoom)
223        StartZoom(e);
224
225      if (!Plotter.IsFocused)
226      {
227        //var window = Window.GetWindow(Plotter);
228        //var focusWithinWindow = FocusManager.GetFocusedElement(window) != null;
229
230        Plotter.Focus();
231
232        //if (!focusWithinWindow)
233        //{
234
235        // this is done to prevent other tools like PointSelector from getting mouse click event when clicking on plotter
236        // to activate window it's contained within
237        e.Handled = true;
238
239        //}
240      }
241    }
242
243    private void OnMouseMove(object sender, MouseEventArgs e)
244    {
245      if (!isPanning && !isZooming) return;
246
247      // dragging
248      if (isPanning && e.LeftButton == MouseButtonState.Pressed)
249      {
250        if (!IsMouseCaptured)
251        {
252          CaptureMouse();
253        }
254
255        Point endPoint = e.GetPosition(this).ScreenToViewport(Viewport.Transform);
256
257        Point loc = Viewport.Visible.Location;
258        Vector shift = panningStartPointInViewport - endPoint;
259        loc += shift;
260
261        // preventing unnecessary changes, if actually visible hasn't change.
262        if (shift.X != 0 || shift.Y != 0)
263        {
264          Cursor = Cursors.ScrollAll;
265
266          DataRect visible = Viewport.Visible;
267
268          visible.Location = loc;
269
270          Viewport.SetChangeType(ChangeType.Pan);
271          Viewport.Visible = visible;
272          Viewport.SetChangeType();
273        }
274
275        e.Handled = true;
276      }
277      // zooming
278      else if (isZooming && e.LeftButton == MouseButtonState.Pressed)
279      {
280        Point zoomEndPoint = e.GetPosition(this);
281        UpdateZoomRect(zoomEndPoint);
282
283        e.Handled = true;
284      }
285    }
286
287    private static bool IsShiftPressed()
288    {
289      return Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
290    }
291
292    private void UpdateZoomRect(Point zoomEndPoint)
293    {
294      Rect output = Viewport.Output;
295      Rect tmpZoomRect = new Rect(zoomStartPoint, zoomEndPoint);
296      tmpZoomRect = Rect.Intersect(tmpZoomRect, output);
297
298      shouldKeepRatioWhileZooming = IsShiftPressed();
299      if (shouldKeepRatioWhileZooming)
300      {
301        double currZoomRatio = tmpZoomRect.Width / tmpZoomRect.Height;
302        double zoomRatio = output.Width / output.Height;
303        if (currZoomRatio < zoomRatio)
304        {
305          double oldHeight = tmpZoomRect.Height;
306          double height = tmpZoomRect.Width / zoomRatio;
307          tmpZoomRect.Height = height;
308          if (!tmpZoomRect.Contains(zoomStartPoint))
309          {
310            tmpZoomRect.Offset(0, oldHeight - height);
311          }
312        }
313        else
314        {
315          double oldWidth = tmpZoomRect.Width;
316          double width = tmpZoomRect.Height * zoomRatio;
317          tmpZoomRect.Width = width;
318          if (!tmpZoomRect.Contains(zoomStartPoint))
319          {
320            tmpZoomRect.Offset(oldWidth - width, 0);
321          }
322        }
323      }
324
325      zoomRect = tmpZoomRect;
326      UpdateSelectionAdorner();
327    }
328
329    private void OnMouseUp(object sender, MouseButtonEventArgs e)
330    {
331      OnParentMouseUp(e);
332    }
333
334    protected virtual void OnParentMouseUp(MouseButtonEventArgs e)
335    {
336      if (isPanning && e.ChangedButton == MouseButton.Left)
337      {
338        isPanning = false;
339        StopPanning(e);
340      }
341      else if (isZooming && e.ChangedButton == MouseButton.Left)
342      {
343        isZooming = false;
344        StopZooming();
345      }
346    }
347
348    protected virtual void StopZooming()
349    {
350      if (zoomRect.HasValue)
351      {
352        Rect output = Viewport.Output;
353
354        Point p1 = zoomRect.Value.TopLeft.ScreenToViewport(Viewport.Transform);
355        Point p2 = zoomRect.Value.BottomRight.ScreenToViewport(Viewport.Transform);
356        DataRect newVisible = new DataRect(p1, p2);
357
358        Viewport.SetChangeType(ChangeType.Zoom);
359        Viewport.Visible = newVisible;
360        Viewport.SetChangeType();
361
362        zoomRect = null;
363        ReleaseMouseCapture();
364        RemoveSelectionAdorner();
365      }
366    }
367
368    protected virtual void StopPanning(MouseButtonEventArgs e)
369    {
370      Plotter2D.UndoProvider.CaptureNewValue(Plotter2D.Viewport, Viewport2D.VisibleProperty, Viewport.Visible);
371
372      if (!Plotter.IsFocused)
373      {
374        Plotter2D.Focus();
375      }
376
377      Plotter2D.Viewport.PanningState = Viewport2DPanningState.NotPanning;
378
379      ReleaseMouseCapture();
380      ClearValue(CursorProperty);
381    }
382
383    protected override void OnLostFocus(RoutedEventArgs e)
384    {
385      if (isZooming)
386      {
387        RemoveSelectionAdorner();
388        isZooming = false;
389      }
390      if (isPanning)
391      {
392        Plotter2D.Viewport.PanningState = Viewport2DPanningState.NotPanning;
393        isPanning = false;
394      }
395      ReleaseMouseCapture();
396      base.OnLostFocus(e);
397    }
398
399    private void MouseWheelZoom(Point mousePos, double wheelRotationDelta)
400    {
401      Point zoomTo = mousePos.ScreenToViewport(Viewport.Transform);
402
403      double zoomSpeed = Math.Abs(wheelRotationDelta / Mouse.MouseWheelDeltaForOneLine);
404      zoomSpeed *= wheelZoomSpeed;
405      if (wheelRotationDelta < 0)
406      {
407        zoomSpeed = 1 / zoomSpeed;
408      }
409
410      Viewport.SetChangeType(ChangeType.Zoom);
411      Viewport.Visible = Viewport.Visible.Zoom(zoomTo, zoomSpeed);
412      Viewport.SetChangeType();
413    }
414  }
415}
Note: See TracBrowser for help on using the repository browser.