/Main/src/DynamicDataDisplay/Charts/Navigation/KeyboardNavigation.cs
C# | 459 lines | 348 code | 99 blank | 12 comment | 5 complexity | dde15f0da9f00583ccb98bc4712c96dd MD5 | raw file
Possible License(s): CC-BY-SA-3.0
1using System.Windows; 2using System.Windows.Input; 3using System.Windows.Media; 4using Microsoft.Win32; 5using System; 6using Microsoft.Research.DynamicDataDisplay.Common.UndoSystem; 7using System.Collections.Generic; 8using Microsoft.Research.DynamicDataDisplay.Charts.Navigation; 9 10namespace Microsoft.Research.DynamicDataDisplay.Navigation 11{ 12 /// <summary>Provides keyboard navigation around viewport of ChartPlotter.</summary> 13 public class KeyboardNavigation : IPlotterElement 14 { 15 /// <summary> 16 /// Initializes a new instance of the <see cref="KeyboardNavigation"/> class. 17 /// </summary> 18 public KeyboardNavigation() { } 19 20 private bool isReversed = true; 21 /// <summary> 22 /// Gets or sets a value indicating whether panning directions are reversed. 23 /// </summary> 24 /// <value> 25 /// <c>true</c> if panning directions are reversed; otherwise, <c>false</c>. 26 /// </value> 27 public bool IsReversed 28 { 29 get { return isReversed; } 30 set { isReversed = value; } 31 } 32 33 private readonly List<CommandBinding> addedBindings = new List<CommandBinding>(); 34 private void AddBinding(CommandBinding binding) 35 { 36 plotter2D.CommandBindings.Add(binding); 37 addedBindings.Add(binding); 38 } 39 40 private void InitCommands() 41 { 42 if (plotter2D == null) 43 return; 44 45 var zoomOutToMouseCommandBinding = new CommandBinding( 46 ChartCommands.ZoomOutToMouse, 47 ZoomOutToMouseExecute, 48 ZoomOutToMouseCanExecute); 49 AddBinding(zoomOutToMouseCommandBinding); 50 51 var zoomInToMouseCommandBinding = new CommandBinding( 52 ChartCommands.ZoomInToMouse, 53 ZoomInToMouseExecute, 54 ZoomInToMouseCanExecute); 55 AddBinding(zoomInToMouseCommandBinding); 56 57 var zoomWithParamCommandBinding = new CommandBinding( 58 ChartCommands.ZoomWithParameter, 59 ZoomWithParamExecute, 60 ZoomWithParamCanExecute); 61 AddBinding(zoomWithParamCommandBinding); 62 63 var zoomInCommandBinding = new CommandBinding( 64 ChartCommands.ZoomIn, 65 ZoomInExecute, 66 ZoomInCanExecute); 67 AddBinding(zoomInCommandBinding); 68 69 var zoomOutCommandBinding = new CommandBinding( 70 ChartCommands.ZoomOut, 71 ZoomOutExecute, 72 ZoomOutCanExecute); 73 AddBinding(zoomOutCommandBinding); 74 75 var fitToViewCommandBinding = new CommandBinding( 76 ChartCommands.FitToView, 77 FitToViewExecute, 78 FitToViewCanExecute); 79 AddBinding(fitToViewCommandBinding); 80 81 var ScrollLeftCommandBinding = new CommandBinding( 82 ChartCommands.ScrollLeft, 83 ScrollLeftExecute, 84 ScrollLeftCanExecute); 85 AddBinding(ScrollLeftCommandBinding); 86 87 var ScrollRightCommandBinding = new CommandBinding( 88 ChartCommands.ScrollRight, 89 ScrollRightExecute, 90 ScrollRightCanExecute); 91 AddBinding(ScrollRightCommandBinding); 92 93 var ScrollUpCommandBinding = new CommandBinding( 94 ChartCommands.ScrollUp, 95 ScrollUpExecute, 96 ScrollUpCanExecute); 97 AddBinding(ScrollUpCommandBinding); 98 99 var ScrollDownCommandBinding = new CommandBinding( 100 ChartCommands.ScrollDown, 101 ScrollDownExecute, 102 ScrollDownCanExecute); 103 AddBinding(ScrollDownCommandBinding); 104 105 var SaveScreenshotCommandBinding = new CommandBinding( 106 ChartCommands.SaveScreenshot, 107 SaveScreenshotExecute, 108 SaveScreenshotCanExecute); 109 AddBinding(SaveScreenshotCommandBinding); 110 111 var CopyScreenshotCommandBinding = new CommandBinding( 112 ChartCommands.CopyScreenshot, 113 CopyScreenshotExecute, 114 CopyScreenshotCanExecute); 115 AddBinding(CopyScreenshotCommandBinding); 116 117 var ShowHelpCommandBinding = new CommandBinding( 118 ChartCommands.ShowHelp, 119 ShowHelpExecute, 120 ShowHelpCanExecute); 121 AddBinding(ShowHelpCommandBinding); 122 123 var UndoCommandBinding = new CommandBinding( 124 ApplicationCommands.Undo, 125 UndoExecute, 126 UndoCanExecute); 127 AddBinding(UndoCommandBinding); 128 129 var RedoCommandBinding = new CommandBinding( 130 ApplicationCommands.Redo, 131 RedoExecute, 132 RedoCanExecute); 133 AddBinding(RedoCommandBinding); 134 } 135 136 #region Zoom Out To Mouse 137 138 private void ZoomToPoint(double coeff) 139 { 140 Point pt = Mouse.GetPosition(plotter2D.CentralGrid); 141 Point dataPoint = Viewport.Transform.ScreenToData(pt); 142 DataRect visible = Viewport.Visible; 143 144 Viewport.SetChangeType(ChangeType.Zoom); 145 Viewport.Visible = visible.Zoom(dataPoint, coeff); 146 Viewport.SetChangeType(); 147 } 148 149 private void ZoomOutToMouseExecute(object target, ExecutedRoutedEventArgs e) 150 { 151 ZoomToPoint(zoomOutCoeff); 152 e.Handled = true; 153 } 154 155 private void ZoomOutToMouseCanExecute(object target, CanExecuteRoutedEventArgs e) 156 { 157 e.CanExecute = true; 158 } 159 160 #endregion 161 162 #region Zoom In To Mouse 163 164 private void ZoomInToMouseExecute(object target, ExecutedRoutedEventArgs e) 165 { 166 ZoomToPoint(zoomInCoeff); 167 e.Handled = true; 168 } 169 170 private void ZoomInToMouseCanExecute(object target, CanExecuteRoutedEventArgs e) 171 { 172 e.CanExecute = true; 173 } 174 175 #endregion 176 177 #region Zoom With param 178 179 private void ZoomWithParamExecute(object target, ExecutedRoutedEventArgs e) 180 { 181 double zoomParam = (double)e.Parameter; 182 plotter2D.Viewport.Zoom(zoomParam); 183 e.Handled = true; 184 } 185 186 private void ZoomWithParamCanExecute(object target, CanExecuteRoutedEventArgs e) 187 { 188 e.CanExecute = true; 189 } 190 191 #endregion 192 193 #region Zoom in 194 195 private const double zoomInCoeff = 0.9; 196 private void ZoomInExecute(object target, ExecutedRoutedEventArgs e) 197 { 198 Viewport.Zoom(zoomInCoeff); 199 e.Handled = true; 200 } 201 202 private void ZoomInCanExecute(object target, CanExecuteRoutedEventArgs e) 203 { 204 e.CanExecute = true; 205 } 206 207 #endregion 208 209 #region Zoom out 210 211 private const double zoomOutCoeff = 1 / zoomInCoeff; 212 private void ZoomOutExecute(object target, ExecutedRoutedEventArgs e) 213 { 214 Viewport.Zoom(zoomOutCoeff); 215 e.Handled = true; 216 } 217 218 private void ZoomOutCanExecute(object target, CanExecuteRoutedEventArgs e) 219 { 220 e.CanExecute = true; 221 } 222 223 #endregion 224 225 #region Fit to view 226 227 private void FitToViewExecute(object target, ExecutedRoutedEventArgs e) 228 { 229 // todo сделать нормально. 230 (Viewport as Viewport2D).FitToView(); 231 e.Handled = true; 232 } 233 234 private void FitToViewCanExecute(object target, CanExecuteRoutedEventArgs e) 235 { 236 // todo add a check if viewport is already fitted to view. 237 e.CanExecute = true; 238 } 239 240 #endregion 241 242 #region Scroll 243 244 private double scrollCoeff = 0.05; 245 private void ScrollVisibleProportionally(double xShiftCoeff, double yShiftCoeff) 246 { 247 DataRect visible = Viewport.Visible; 248 DataRect oldVisible = visible; 249 double width = visible.Width; 250 double height = visible.Height; 251 252 double reverseCoeff = isReversed ? -1 : 1; 253 visible.Offset(reverseCoeff * xShiftCoeff * width, reverseCoeff * yShiftCoeff * height); 254 255 Viewport.SetChangeType(xShiftCoeff == 0 ? ChangeType.PanY : ChangeType.PanX); 256 Viewport.Visible = visible; 257 Viewport.SetChangeType(); 258 259 plotter2D.UndoProvider.AddAction(new DependencyPropertyChangedUndoAction(Viewport, Viewport2D.VisibleProperty, oldVisible, visible)); 260 } 261 262 #region ScrollLeft 263 264 private void ScrollLeftExecute(object target, ExecutedRoutedEventArgs e) 265 { 266 ScrollVisibleProportionally(scrollCoeff, 0); 267 e.Handled = true; 268 } 269 270 private void ScrollLeftCanExecute(object target, CanExecuteRoutedEventArgs e) 271 { 272 e.CanExecute = true; 273 } 274 275 #endregion 276 277 #region ScrollRight 278 279 private void ScrollRightExecute(object target, ExecutedRoutedEventArgs e) 280 { 281 ScrollVisibleProportionally(-scrollCoeff, 0); 282 e.Handled = true; 283 } 284 285 private void ScrollRightCanExecute(object target, CanExecuteRoutedEventArgs e) 286 { 287 e.CanExecute = true; 288 } 289 290 #endregion 291 292 #region ScrollUp 293 294 private void ScrollUpExecute(object target, ExecutedRoutedEventArgs e) 295 { 296 ScrollVisibleProportionally(0, -scrollCoeff); 297 e.Handled = true; 298 } 299 300 private void ScrollUpCanExecute(object target, CanExecuteRoutedEventArgs e) 301 { 302 e.CanExecute = true; 303 } 304 305 #endregion 306 307 #region ScrollDown 308 309 private void ScrollDownExecute(object target, ExecutedRoutedEventArgs e) 310 { 311 ScrollVisibleProportionally(0, scrollCoeff); 312 e.Handled = true; 313 } 314 315 private void ScrollDownCanExecute(object target, CanExecuteRoutedEventArgs e) 316 { 317 e.CanExecute = true; 318 } 319 320 #endregion 321 322 #endregion 323 324 #region SaveScreenshot 325 326 private void SaveScreenshotExecute(object target, ExecutedRoutedEventArgs e) 327 { 328 SaveFileDialog dlg = new SaveFileDialog(); 329 dlg.Filter = "PNG (*.png)|*.png|JPEG (*.jpg)|*.jpg|BMP (*.bmp)|*.bmp|GIF (*.gif)|*.gif"; 330 dlg.FilterIndex = 1; 331 dlg.AddExtension = true; 332 if (dlg.ShowDialog().GetValueOrDefault(false)) 333 { 334 string filePath = dlg.FileName; 335 plotter2D.SaveScreenshot(filePath); 336 e.Handled = true; 337 } 338 } 339 340 private void SaveScreenshotCanExecute(object target, CanExecuteRoutedEventArgs e) 341 { 342 e.CanExecute = true; 343 } 344 345 #endregion 346 347 #region CopyScreenshot 348 349 private void CopyScreenshotExecute(object target, ExecutedRoutedEventArgs e) 350 { 351 plotter2D.CopyScreenshotToClipboard(); 352 e.Handled = true; 353 } 354 355 private void CopyScreenshotCanExecute(object target, CanExecuteRoutedEventArgs e) 356 { 357 e.CanExecute = true; 358 } 359 360 #endregion 361 362 #region ShowHelp 363 364 private bool aboutWindowOpened = false; 365 private void ShowHelpExecute(object target, ExecutedRoutedEventArgs e) 366 { 367 if (!aboutWindowOpened) 368 { 369 AboutWindow window = new AboutWindow(); 370 window.Closed += new EventHandler(aboutWindow_Closed); 371 window.DataContext = plotter2D; 372 373 window.Owner = Window.GetWindow(plotter2D); 374 375 aboutWindowOpened = true; 376 window.Show(); 377 378 e.Handled = true; 379 } 380 } 381 382 void aboutWindow_Closed(object sender, EventArgs e) 383 { 384 Window window = (Window)sender; 385 window.Closed -= aboutWindow_Closed; 386 aboutWindowOpened = false; 387 } 388 389 private void ShowHelpCanExecute(object target, CanExecuteRoutedEventArgs e) 390 { 391 e.CanExecute = !aboutWindowOpened; 392 } 393 394 #endregion 395 396 #region Undo 397 398 private void UndoExecute(object target, ExecutedRoutedEventArgs e) 399 { 400 plotter2D.UndoProvider.Undo(); 401 e.Handled = true; 402 } 403 404 private void UndoCanExecute(object target, CanExecuteRoutedEventArgs e) 405 { 406 e.CanExecute = plotter2D.UndoProvider.CanUndo; 407 } 408 409 #endregion 410 411 #region Redo 412 413 private void RedoExecute(object target, ExecutedRoutedEventArgs e) 414 { 415 plotter2D.UndoProvider.Redo(); 416 e.Handled = true; 417 } 418 419 private void RedoCanExecute(object target, CanExecuteRoutedEventArgs e) 420 { 421 e.CanExecute = plotter2D.UndoProvider.CanRedo; 422 } 423 424 #endregion 425 426 #region IPlotterElement Members 427 428 private Viewport2D Viewport 429 { 430 get { return plotter2D.Viewport; } 431 } 432 433 private Plotter2D plotter2D; 434 void IPlotterElement.OnPlotterAttached(Plotter plotter) 435 { 436 plotter2D = (Plotter2D)plotter; 437 438 InitCommands(); 439 } 440 441 void IPlotterElement.OnPlotterDetaching(Plotter plotter) 442 { 443 foreach (var commandBinding in addedBindings) 444 { 445 plotter.CommandBindings.Remove(commandBinding); 446 } 447 addedBindings.Clear(); 448 449 this.plotter2D = null; 450 } 451 452 Plotter IPlotterElement.Plotter 453 { 454 get { return plotter2D; } 455 } 456 457 #endregion 458 } 459}