PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Main/src/DynamicDataDisplay/Charts/Navigation/Navigation/MouseNavigation.cs

#
C# | 235 lines | 188 code | 37 blank | 10 comment | 53 complexity | 9c674772dc6b969ddaa5c98d5655f011 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. using System;
  2. using System.Windows;
  3. using System.Windows.Documents;
  4. using System.Windows.Input;
  5. namespace Microsoft.Research.DynamicDataDisplay.Navigation
  6. {
  7. /// <summary>Provides common methods of mouse navigation around viewport</summary>
  8. public class MouseNavigation : NavigationBase {
  9. private AdornerLayer adornerLayer;
  10. protected AdornerLayer AdornerLayer {
  11. get {
  12. if (adornerLayer == null) {
  13. adornerLayer = AdornerLayer.GetAdornerLayer(this);
  14. if (adornerLayer != null) {
  15. adornerLayer.IsHitTestVisible = false;
  16. }
  17. }
  18. return adornerLayer;
  19. }
  20. }
  21. protected override void OnViewportChanged() {
  22. base.OnViewportChanged();
  23. //Mouse.AddPreviewMouseDownHandler(Parent, (MouseButtonEventHandler)OnMouseDown);
  24. //Mouse.AddPreviewMouseMoveHandler(Parent, (MouseEventHandler)OnMouseMove);
  25. //Mouse.AddPreviewMouseUpHandler(Parent, (MouseButtonEventHandler)OnMouseUp);
  26. Mouse.AddMouseDownHandler(Parent, OnMouseDown);
  27. Mouse.AddMouseMoveHandler(Parent, OnMouseMove);
  28. Mouse.AddMouseUpHandler(Parent, OnMouseUp);
  29. Mouse.AddMouseWheelHandler(Parent, OnMouseWheel);
  30. }
  31. private void OnMouseWheel(object sender, MouseWheelEventArgs e) {
  32. if (!e.Handled) {
  33. Point mousePos = e.GetPosition(this);
  34. int delta = -e.Delta;
  35. MouseWheelZoom(mousePos, delta);
  36. }
  37. }
  38. #if DEBUG
  39. public override string ToString()
  40. {
  41. if (!String.IsNullOrEmpty(Name)) {
  42. return Name;
  43. }
  44. return base.ToString();
  45. }
  46. #endif
  47. bool adornerAdded;
  48. RectangleSelectionAdorner selectionAdorner;
  49. private void AddSelectionAdorner() {
  50. if (!adornerAdded) {
  51. AdornerLayer layer = AdornerLayer;
  52. if (layer != null) {
  53. selectionAdorner = new RectangleSelectionAdorner(this) { Border = zoomRect };
  54. layer.Add(selectionAdorner);
  55. adornerAdded = true;
  56. }
  57. }
  58. }
  59. private void RemoveSelectionAdorner() {
  60. AdornerLayer layer = AdornerLayer;
  61. if (layer != null) {
  62. layer.Remove(selectionAdorner);
  63. adornerAdded = false;
  64. }
  65. }
  66. private void UpdateSelectionAdorner() {
  67. selectionAdorner.Border = zoomRect;
  68. selectionAdorner.InvalidateVisual();
  69. }
  70. Rect? zoomRect = null;
  71. private const double wheelZoomSpeed = 1.2;
  72. private bool shouldKeepRatioWhileZooming;
  73. private bool isZooming;
  74. private bool isDragging;
  75. private Point dragStartPointInVisible;
  76. private Point zoomStartPoint;
  77. private static bool IsShiftOrCtrl {
  78. get {
  79. ModifierKeys currKeys = Keyboard.Modifiers;
  80. return (currKeys | ModifierKeys.Shift) == currKeys ||
  81. (currKeys | ModifierKeys.Control) == currKeys;
  82. }
  83. }
  84. private void OnMouseDown(object sender, MouseButtonEventArgs e) {
  85. // dragging
  86. bool shouldStartDrag = e.ChangedButton == MouseButton.Left && Keyboard.Modifiers == ModifierKeys.None;
  87. if (shouldStartDrag) {
  88. Point dragStartPointInOutput = e.GetPosition(this);
  89. dragStartPointInVisible = dragStartPointInOutput.Transform(Viewport.Output, Viewport.Visible);
  90. isDragging = true;
  91. CaptureMouse();
  92. }
  93. bool shouldStartZoom = e.ChangedButton == MouseButton.Left && IsShiftOrCtrl;
  94. if (shouldStartZoom) {
  95. // zooming
  96. zoomStartPoint = e.GetPosition(this);
  97. if (Viewport.Output.Contains(zoomStartPoint)) {
  98. isZooming = true;
  99. AddSelectionAdorner();
  100. CaptureMouse();
  101. shouldKeepRatioWhileZooming = Keyboard.Modifiers == ModifierKeys.Shift;
  102. }
  103. }
  104. ((IInputElement) Parent).Focus();
  105. }
  106. private void OnMouseMove(object sender, MouseEventArgs e) {
  107. if (!isDragging && !isZooming) return;
  108. // dragging
  109. if (isDragging && e.LeftButton == MouseButtonState.Pressed) {
  110. Point endPoint = e.GetPosition(this).Transform(Viewport.Output, Viewport.Visible);
  111. Point loc = Viewport.Visible.Location;
  112. Vector shift = dragStartPointInVisible - endPoint;
  113. loc += shift;
  114. if (shift.X != 0 || shift.Y != 0) {
  115. Rect visible = Viewport.Visible;
  116. visible.Location = loc;
  117. Viewport.Visible = visible;
  118. }
  119. }
  120. // zooming
  121. else if (isZooming && e.LeftButton == MouseButtonState.Pressed) {
  122. Point zoomEndPoint = e.GetPosition(this);
  123. UpdateZoomRect(zoomEndPoint);
  124. }
  125. }
  126. private static bool IsShiftPressed() {
  127. return Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
  128. }
  129. private void UpdateZoomRect(Point zoomEndPoint) {
  130. Rect output = Viewport.Output;
  131. Rect tmpZoomRect = new Rect(zoomStartPoint, zoomEndPoint);
  132. tmpZoomRect = Rect.Intersect(tmpZoomRect, output);
  133. shouldKeepRatioWhileZooming = IsShiftPressed();
  134. if (shouldKeepRatioWhileZooming) {
  135. double currZoomRatio = tmpZoomRect.Width / tmpZoomRect.Height;
  136. double zoomRatio = output.Width / output.Height;
  137. if (currZoomRatio < zoomRatio) {
  138. double oldHeight = tmpZoomRect.Height;
  139. double height = tmpZoomRect.Width / zoomRatio;
  140. tmpZoomRect.Height = height;
  141. if (!tmpZoomRect.Contains(zoomStartPoint)) {
  142. tmpZoomRect.Offset(0, oldHeight - height);
  143. }
  144. }
  145. else {
  146. double oldWidth = tmpZoomRect.Width;
  147. double width = tmpZoomRect.Height * zoomRatio;
  148. tmpZoomRect.Width = width;
  149. if (!tmpZoomRect.Contains(zoomStartPoint)) {
  150. tmpZoomRect.Offset(oldWidth - width, 0);
  151. }
  152. }
  153. }
  154. zoomRect = tmpZoomRect;
  155. UpdateSelectionAdorner();
  156. }
  157. private void OnMouseUp(object sender, MouseButtonEventArgs e) {
  158. if (isDragging && e.ChangedButton == MouseButton.Left) {
  159. isDragging = false;
  160. ReleaseMouseCapture();
  161. Point endPoint = e.GetPosition(this).Transform(Viewport.Output, Viewport.Visible);
  162. // focusing on LMB click
  163. if (endPoint == dragStartPointInVisible) {
  164. //Keyboard.Focus(Parent as IInputElement);
  165. }
  166. }
  167. else if (isZooming && e.ChangedButton == MouseButton.Left) {
  168. isZooming = false;
  169. if (zoomRect.HasValue) {
  170. Rect output = Viewport.Output;
  171. Point p1 = zoomRect.Value.TopLeft.Transform(output, Viewport.Visible);
  172. Point p2 = zoomRect.Value.BottomRight.Transform(output, Viewport.Visible);
  173. Rect newVisible = new Rect(p1, p2);
  174. Viewport.Visible = newVisible;
  175. zoomRect = null;
  176. ReleaseMouseCapture();
  177. RemoveSelectionAdorner();
  178. }
  179. }
  180. }
  181. protected override void OnLostFocus(RoutedEventArgs e) {
  182. if (isZooming) {
  183. RemoveSelectionAdorner();
  184. }
  185. ReleaseMouseCapture();
  186. base.OnLostFocus(e);
  187. }
  188. private void MouseWheelZoom(Point mousePos, int wheelRotationDelta) {
  189. Point zoomTo = mousePos.Transform(Viewport.Output, Viewport.Visible);
  190. double zoomSpeed = Math.Abs(wheelRotationDelta / Mouse.MouseWheelDeltaForOneLine);
  191. zoomSpeed *= wheelZoomSpeed;
  192. if (wheelRotationDelta < 0) {
  193. zoomSpeed = 1 / zoomSpeed;
  194. }
  195. Viewport.Visible = Viewport.Visible.Zoom(zoomTo, zoomSpeed);
  196. }
  197. }
  198. }