using System; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace Bro.Common.ImageCanvas { public class ZoomAndPanScrollViewer : ScrollViewer { public Action OnMousePositionChanged { get; set; } // private ZoomAndPanControl _zoomAndPanControl; #region constructor and overrides /// /// Static constructor to define metadata for the control (and link it to the style in Generic.xaml). /// static ZoomAndPanScrollViewer() { DefaultStyleKeyProperty.OverrideMetadata(typeof(ZoomAndPanScrollViewer), new FrameworkPropertyMetadata(typeof(ZoomAndPanScrollViewer))); } public override void OnApplyTemplate() { base.OnApplyTemplate(); ZoomAndPanContent = Template.FindName("PART_ZoomAndPanControl", this) as ZoomAndPanControl; OnPropertyChanged(new DependencyPropertyChangedEventArgs(ZoomAndPanContentProperty, null, ZoomAndPanContent)); RefreshProperties(); } #endregion /// /// Get/set the maximum value for 'ViewportZoom'. /// public ZoomAndPanControl ZoomAndPanContent { get { return (ZoomAndPanControl)GetValue(ZoomAndPanContentProperty); } set { SetValue(ZoomAndPanContentProperty, value); } } public static readonly DependencyProperty ZoomAndPanContentProperty = DependencyProperty.Register("ZoomAndPanContent", typeof(ZoomAndPanControl), typeof(ZoomAndPanScrollViewer), new FrameworkPropertyMetadata(null)); #region DependencyProperties /// /// Get/set the maximum value for 'ViewportZoom'. /// public MinimumZoomTypeEnum MinimumZoomType { get { return (MinimumZoomTypeEnum)GetValue(MinimumZoomTypeProperty); } set { SetValue(MinimumZoomTypeProperty, value); } } public static readonly DependencyProperty MinimumZoomTypeProperty = DependencyProperty.Register("MinimumZoomType", typeof(MinimumZoomTypeEnum), typeof(ZoomAndPanScrollViewer), new FrameworkPropertyMetadata(MinimumZoomTypeEnum.MinimumZoom)); /// /// Get/set the MinimumZoom value for 'ViewportZoom'. /// public Point? MousePosition { get { return (Point?)GetValue(MousePositionProperty); } set { SetValue(MousePositionProperty, value); } } public static readonly DependencyProperty MousePositionProperty = DependencyProperty.Register("MousePosition", typeof(Point?), typeof(ZoomAndPanScrollViewer), new PropertyMetadata(null, OnMousePointPropertyChanged)); private static void OnMousePointPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ZoomAndPanScrollViewer ctrl = d as ZoomAndPanScrollViewer; if (ctrl != null) { Point? p = (Point?)e.NewValue; if (p != null) { ctrl.OnMousePositionChanged?.BeginInvoke(p.Value, null, null); } } } /// /// Disables animations if set to false /// public bool UseAnimations { get { return (bool)GetValue(UseAnimationsProperty); } set { SetValue(UseAnimationsProperty, value); } } public static readonly DependencyProperty UseAnimationsProperty = DependencyProperty.Register("UseAnimations", typeof(bool), typeof(ZoomAndPanScrollViewer), new FrameworkPropertyMetadata(true)); /// /// Get/set the current scale (or zoom factor) of the content. /// public double ViewportZoom { get { return (double)GetValue(ViewportZoomProperty); } set { SetValue(ViewportZoomProperty, value); } } public static readonly DependencyProperty ViewportZoomProperty = DependencyProperty.Register("ViewportZoom", typeof(double), typeof(ZoomAndPanScrollViewer), new FrameworkPropertyMetadata(1.0)); /// /// The duration of the animations (in seconds) started by calling AnimatedZoomTo and the other animation methods. /// public ZoomAndPanInitialPositionEnum ZoomAndPanInitialPosition { get { return (ZoomAndPanInitialPositionEnum)GetValue(ZoomAndPanInitialPositionProperty); } set { SetValue(ZoomAndPanInitialPositionProperty, value); } } public static readonly DependencyProperty ZoomAndPanInitialPositionProperty = DependencyProperty.Register("ZoomAndPanInitialPosition", typeof(ZoomAndPanInitialPositionEnum), typeof(ZoomAndPanScrollViewer), new FrameworkPropertyMetadata(ZoomAndPanInitialPositionEnum.Default)); #endregion #region Commands /// /// Command to implement the zoom to fill /// public ICommand FillCommand => _fillCommand ?? (_fillCommand = new RelayCommand( () => ZoomAndPanContent.FillCommand.Execute(null), () => ZoomAndPanContent?.FillCommand.CanExecute(null) ?? true)); private RelayCommand _fillCommand; /// /// Command to implement the zoom to fit /// public ICommand FitCommand => _fitCommand ?? (_fitCommand = new RelayCommand( () => ZoomAndPanContent.FitCommand.Execute(null), () => ZoomAndPanContent?.FitCommand.CanExecute(null) ?? true)); private RelayCommand _fitCommand; /// /// Command to implement the zoom to 100% /// public ICommand ZoomPercentCommand => _zoomPercentCommand ?? (_zoomPercentCommand = new RelayCommand( value => ZoomAndPanContent.ZoomPercentCommand.Execute(value), value => ZoomAndPanContent?.ZoomPercentCommand.CanExecute(value) ?? true)); private RelayCommand _zoomPercentCommand; /// /// Command to implement the zoom to 100% /// public ICommand ZoomRatioFromMinimumCommand => _zoomRatioFromMinimumCommand ?? (_zoomRatioFromMinimumCommand = new RelayCommand( value => ZoomAndPanContent.ZoomRatioFromMinimumCommand.Execute(value), value => ZoomAndPanContent?.ZoomRatioFromMinimumCommand.CanExecute(value) ?? true)); private RelayCommand _zoomRatioFromMinimumCommand; /// /// Command to implement the zoom out by 110% /// public ICommand ZoomOutCommand => _zoomOutCommand ?? (_zoomOutCommand = new RelayCommand( () => ZoomAndPanContent.ZoomOutCommand.Execute(null), () => ZoomAndPanContent?.ZoomOutCommand.CanExecute(null) ?? true)); private RelayCommand _zoomOutCommand; /// /// Command to implement the zoom in by 91% /// public ICommand ZoomInCommand => _zoomInCommand ?? (_zoomInCommand = new RelayCommand( () => ZoomAndPanContent.ZoomInCommand.Execute(null), () => ZoomAndPanContent?.ZoomInCommand.CanExecute(null) ?? true)); private RelayCommand _zoomInCommand; /// /// Command to implement Undo /// public ICommand UndoZoomCommand => _undoZoomCommand ?? (_undoZoomCommand = new RelayCommand( () => ZoomAndPanContent.UndoZoomCommand.Execute(null), () => ZoomAndPanContent?.UndoZoomCommand.CanExecute(null) ?? true)); private RelayCommand _undoZoomCommand; /// /// Command to implement Redo /// public ICommand RedoZoomCommand => _redoZoomCommand ?? (_redoZoomCommand = new RelayCommand( () => ZoomAndPanContent.RedoZoomCommand.Execute(null), () => ZoomAndPanContent?.RedoZoomCommand.CanExecute(null) ?? true)); private RelayCommand _redoZoomCommand; #endregion private void RefreshProperties() { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FillCommand))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FitCommand))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ZoomPercentCommand))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ZoomRatioFromMinimumCommand))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ZoomInCommand))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ZoomOutCommand))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(UndoZoomCommand))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(RedoZoomCommand))); } public event PropertyChangedEventHandler PropertyChanged; } }