PageRenderTime 20ms CodeModel.GetById 2ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

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

#
C# | 459 lines | 348 code | 99 blank | 12 comment | 5 complexity | dde15f0da9f00583ccb98bc4712c96dd MD5 | raw file
  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}