You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1217 lines
44 KiB
1217 lines
44 KiB
using System;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Animation;
|
|
|
|
namespace HMIControl
|
|
{
|
|
public class ZoomBoxPanel : Panel
|
|
{
|
|
// Fields
|
|
private bool animations;
|
|
private Size childSize = new Size(1.0, 1.0);
|
|
private static DependencyProperty ClickZoomDeltaProperty;
|
|
private bool lockContent;
|
|
private static DependencyProperty MaxZoomProperty = DependencyProperty.Register("MaxZoom", typeof(double), typeof(ZoomBoxPanel), new FrameworkPropertyMetadata(1000.0, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(ZoomBoxPanel.PropertyChanged_Zoom), new CoerceValueCallback(ZoomBoxPanel.CoerceMaxZoom)), new ValidateValueCallback(ZoomBoxPanel.ValidateIsPositiveNonZero));
|
|
private static DependencyProperty MaxZoomTickProperty = DependencyProperty.Register("MaxZoomTick", typeof(double), typeof(ZoomBoxPanel), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(ZoomBoxPanel.PropertyChanged_Zoom), new CoerceValueCallback(ZoomBoxPanel.CoerceMaxZoomTick)), null);
|
|
private int minMouseDelta = 0xf4240;
|
|
private const double MINZOOM = 1E-07;
|
|
private static DependencyProperty MinZoomProperty = DependencyProperty.Register("MinZoom", typeof(double), typeof(ZoomBoxPanel), new FrameworkPropertyMetadata(1.0, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(ZoomBoxPanel.PropertyChanged_Zoom), new CoerceValueCallback(ZoomBoxPanel.CoerceMinZoom)), new ValidateValueCallback(ZoomBoxPanel.ValidateIsPositiveNonZero));
|
|
private static DependencyProperty MinZoomTickProperty = DependencyProperty.Register("MinZoomTick", typeof(double), typeof(ZoomBoxPanel), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(ZoomBoxPanel.PropertyChanged_Zoom), new CoerceValueCallback(ZoomBoxPanel.CoerceMinZoomTick)), null);
|
|
public static readonly RoutedEvent ModeChangeEvent;
|
|
private static DependencyProperty MouseModeProperty;
|
|
private double panX;
|
|
private double panY;
|
|
private Cursor prevCursor;
|
|
private double rotateAngle;
|
|
private double rotateCenterX;
|
|
private double rotateCenterY;
|
|
public static RoutedUICommand rotateClockwiseCommand;
|
|
public static RoutedUICommand rotateCounterclockwiseCommand;
|
|
private static DependencyProperty RotateDeltaProperty;
|
|
public static RoutedUICommand rotateHomeCommand;
|
|
public static RoutedUICommand rotateReverseCommand;
|
|
private RotateTransform rotateTransform = new RotateTransform();
|
|
private double scrollDelta = 25.0;
|
|
private Point startMouseCapturePanel = new Point(0.0, 0.0);
|
|
private TransformGroup transformGroup = new TransformGroup();
|
|
private TranslateTransform translateTransform = new TranslateTransform();
|
|
private static DependencyProperty WheelModeProperty;
|
|
private static DependencyProperty WheelZoomDeltaProperty;
|
|
private bool zoomCircularReference;
|
|
private static DependencyProperty ZoomModeProperty;
|
|
private static DependencyProperty ZoomProperty = DependencyProperty.Register("Zoom", typeof(double), typeof(ZoomBoxPanel), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(ZoomBoxPanel.PropertyChanged_Zoom), new CoerceValueCallback(ZoomBoxPanel.CoerceZoom)), new ValidateValueCallback(ZoomBoxPanel.ValidateIsPositiveNonZero));
|
|
private static DependencyProperty ZoomTickProperty = DependencyProperty.Register("ZoomTick", typeof(double), typeof(ZoomBoxPanel), new FrameworkPropertyMetadata(50.0, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(ZoomBoxPanel.PropertyChanged_Zoom), new CoerceValueCallback(ZoomBoxPanel.CoerceZoomTick)), null);
|
|
private ScaleTransform zoomTransform = new ScaleTransform();
|
|
|
|
// Events
|
|
public event RoutedEventHandler ModeChange
|
|
{
|
|
add
|
|
{
|
|
base.AddHandler(ModeChangeEvent, value);
|
|
}
|
|
remove
|
|
{
|
|
base.RemoveHandler(ModeChangeEvent, value);
|
|
}
|
|
}
|
|
|
|
// Methods
|
|
static ZoomBoxPanel()
|
|
{
|
|
FrameworkPropertyMetadata typeMetadata = new FrameworkPropertyMetadata
|
|
{
|
|
DefaultValue = 20.0
|
|
};
|
|
ClickZoomDeltaProperty = DependencyProperty.Register("ClickZoomDelta", typeof(double), typeof(ZoomBoxPanel), typeMetadata, new ValidateValueCallback(ZoomBoxPanel.ValidateIsPositiveNonZero));
|
|
WheelZoomDeltaProperty = DependencyProperty.Register("WheelZoomDelta", typeof(double), typeof(ZoomBoxPanel), new FrameworkPropertyMetadata(10.0), new ValidateValueCallback(ZoomBoxPanel.ValidateIsPositiveNonZero));
|
|
RotateDeltaProperty = DependencyProperty.Register("RotateDelta", typeof(double), typeof(ZoomBoxPanel), new FrameworkPropertyMetadata(15.0, null, new CoerceValueCallback(ZoomBoxPanel.CoerceRotateDelta)), new ValidateValueCallback(ZoomBoxPanel.ValidateIsPositiveNonZero));
|
|
typeMetadata = new FrameworkPropertyMetadata
|
|
{
|
|
DefaultValue = eWheelMode.Zoom,
|
|
PropertyChangedCallback = new PropertyChangedCallback(ZoomBoxPanel.PropertyChanged_AMode)
|
|
};
|
|
WheelModeProperty = DependencyProperty.Register("WheelMode", typeof(eWheelMode), typeof(ZoomBoxPanel), typeMetadata, null);
|
|
typeMetadata = new FrameworkPropertyMetadata
|
|
{
|
|
DefaultValue = eZoomMode.FitPage,
|
|
AffectsRender = true,
|
|
Journal = true,
|
|
PropertyChangedCallback = new PropertyChangedCallback(ZoomBoxPanel.PropertyChanged_AMode)
|
|
};
|
|
ZoomModeProperty = DependencyProperty.Register("ZoomMode", typeof(eZoomMode), typeof(ZoomBoxPanel), typeMetadata, null);
|
|
typeMetadata = new FrameworkPropertyMetadata
|
|
{
|
|
DefaultValue = eMouseMode.Zoom,
|
|
PropertyChangedCallback = new PropertyChangedCallback(ZoomBoxPanel.PropertyChanged_AMode)
|
|
};
|
|
MouseModeProperty = DependencyProperty.Register("MouseMode", typeof(eMouseMode), typeof(ZoomBoxPanel), typeMetadata, null);
|
|
CommandManager.RegisterClassCommandBinding(typeof(ZoomBoxPanel), new CommandBinding(NavigationCommands.IncreaseZoom, new ExecutedRoutedEventHandler(ZoomBoxPanel.ExecutedEventHandler_IncreaseZoom), new CanExecuteRoutedEventHandler(ZoomBoxPanel.CanExecuteEventHandler_IfHasContent)));
|
|
CommandManager.RegisterClassCommandBinding(typeof(ZoomBoxPanel), new CommandBinding(NavigationCommands.DecreaseZoom, new ExecutedRoutedEventHandler(ZoomBoxPanel.ExecutedEventHandler_DecreaseZoom), new CanExecuteRoutedEventHandler(ZoomBoxPanel.CanExecuteEventHandler_IfHasContent)));
|
|
InputGestureCollection inputGestures = new InputGestureCollection();
|
|
inputGestures.Add(new KeyGesture(Key.R, ModifierKeys.Control));
|
|
rotateClockwiseCommand = new RoutedUICommand("Rotate Clockwise", "RotateClockwise", typeof(ZoomBoxPanel), inputGestures);
|
|
CommandManager.RegisterClassCommandBinding(typeof(ZoomBoxPanel), new CommandBinding(rotateClockwiseCommand, new ExecutedRoutedEventHandler(ZoomBoxPanel.ExecutedEventHandler_RotateClockwise), new CanExecuteRoutedEventHandler(ZoomBoxPanel.CanExecuteEventHandler_IfHasContent)));
|
|
InputGestureCollection gestures2 = new InputGestureCollection();
|
|
gestures2.Add(new KeyGesture(Key.R, ModifierKeys.Alt));
|
|
rotateCounterclockwiseCommand = new RoutedUICommand("Rotate Counterclockwise", "RotateCounterclockwise", typeof(ZoomBoxPanel), gestures2);
|
|
CommandManager.RegisterClassCommandBinding(typeof(ZoomBoxPanel), new CommandBinding(rotateCounterclockwiseCommand, new ExecutedRoutedEventHandler(ZoomBoxPanel.ExecutedEventHandler_RotateCounterclockwise), new CanExecuteRoutedEventHandler(ZoomBoxPanel.CanExecuteEventHandler_IfHasContent)));
|
|
InputGestureCollection gestures3 = new InputGestureCollection();
|
|
gestures3.Add(new KeyGesture(Key.Home, ModifierKeys.None));
|
|
rotateHomeCommand = new RoutedUICommand("Rotate Home", "RotateHome", typeof(ZoomBoxPanel), gestures3);
|
|
CommandManager.RegisterClassCommandBinding(typeof(ZoomBoxPanel), new CommandBinding(rotateHomeCommand, new ExecutedRoutedEventHandler(ZoomBoxPanel.ExecutedEventHandler_RotateHome), new CanExecuteRoutedEventHandler(ZoomBoxPanel.CanExecuteEventHandler_IfHasContent)));
|
|
InputGestureCollection gestures4 = new InputGestureCollection();
|
|
gestures4.Add(new KeyGesture(Key.End, ModifierKeys.None));
|
|
rotateReverseCommand = new RoutedUICommand("Rotate Reverse", "RotateReverse", typeof(ZoomBoxPanel), gestures4);
|
|
CommandManager.RegisterClassCommandBinding(typeof(ZoomBoxPanel), new CommandBinding(rotateReverseCommand, new ExecutedRoutedEventHandler(ZoomBoxPanel.ExecutedEventHandler_RotateReverse), new CanExecuteRoutedEventHandler(ZoomBoxPanel.CanExecuteEventHandler_IfHasContent)));
|
|
ModeChangeEvent = EventManager.RegisterRoutedEvent("ModeChange", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ZoomBoxPanel));
|
|
}
|
|
|
|
public ZoomBoxPanel()
|
|
{
|
|
this.transformGroup.Children.Add(this.rotateTransform);
|
|
this.transformGroup.Children.Add(this.zoomTransform);
|
|
this.transformGroup.Children.Add(this.translateTransform);
|
|
this.panX = 0.0;
|
|
this.panY = 0.0;
|
|
this.rotateAngle = 0.0;
|
|
this.rotateCenterX = 0.0;
|
|
this.rotateCenterY = 0.0;
|
|
base.ClipToBounds = true;
|
|
}
|
|
|
|
private bool ApplyPanAbs(double deltaX, double deltaY)
|
|
{
|
|
double panX = deltaX;
|
|
double panY = deltaY;
|
|
switch (this.ZoomMode)
|
|
{
|
|
case eZoomMode.FitWidth:
|
|
panX = this.panX;
|
|
break;
|
|
|
|
case eZoomMode.FitHeight:
|
|
panY = this.panY;
|
|
break;
|
|
|
|
case eZoomMode.FitPage:
|
|
panX = this.panX;
|
|
panY = this.panY;
|
|
break;
|
|
}
|
|
if ((panX == this.panX) && (panY == this.panY))
|
|
{
|
|
return false;
|
|
}
|
|
this.panX = panX;
|
|
this.panY = panY;
|
|
return true;
|
|
}
|
|
|
|
private bool ApplyPanDelta(double deltaX, double deltaY)
|
|
{
|
|
double panX = this.panX + deltaX;
|
|
double panY = this.panY + deltaY;
|
|
switch (this.ZoomMode)
|
|
{
|
|
case eZoomMode.FitWidth:
|
|
panX = this.panX;
|
|
break;
|
|
|
|
case eZoomMode.FitHeight:
|
|
panY = this.panY;
|
|
break;
|
|
|
|
case eZoomMode.FitPage:
|
|
panX = this.panX;
|
|
panY = this.panY;
|
|
break;
|
|
}
|
|
if ((panX == this.panX) && (panY == this.panY))
|
|
{
|
|
return false;
|
|
}
|
|
this.panX = panX;
|
|
this.panY = panY;
|
|
return true;
|
|
}
|
|
|
|
public void MoveTo(UIElement element)
|
|
{
|
|
Point position = element.TranslatePoint(new Point(0, 0), this);
|
|
Point centerPoint = new Point(this.ActualWidth / (2* this.zoomTransform.ScaleX), this.ActualHeight / (2* this.zoomTransform.ScaleY));
|
|
|
|
double x = centerPoint.X -position.X;
|
|
double y = centerPoint.Y -position.Y;
|
|
|
|
x *= this.zoomTransform.ScaleX;
|
|
y *= this.zoomTransform.ScaleY;
|
|
|
|
this.translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(x), HandoffBehavior.Compose);
|
|
this.translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(y), HandoffBehavior.Compose);
|
|
}
|
|
|
|
private DoubleAnimation CreatePanAnimation(double toValue)
|
|
{
|
|
var da = new DoubleAnimation(toValue, new Duration(TimeSpan.FromMilliseconds(100)));
|
|
da.AccelerationRatio = 0.1;
|
|
da.DecelerationRatio = 0.9;
|
|
da.FillBehavior = FillBehavior.HoldEnd;
|
|
da.Freeze();
|
|
return da;
|
|
}
|
|
|
|
protected void ApplyRotateCommand(double delta, int factor, Point panelPoint)
|
|
{
|
|
if (factor > 0)
|
|
{
|
|
this.rotateAngle = (this.rotateAngle + (delta * factor)) % 360.0;
|
|
if (this.rotateAngle < 0.0)
|
|
{
|
|
this.rotateAngle += 360.0;
|
|
}
|
|
this.ZoomMode = eZoomMode.CustomSize;
|
|
this.rotateCenterX = this.childSize.Width / 2.0;
|
|
this.rotateCenterY = this.childSize.Height / 2.0;
|
|
this.ApplyZoom(true);
|
|
}
|
|
}
|
|
|
|
protected void ApplyScrollCommand(double delta, int factor, Point panelPoint)
|
|
{
|
|
if (factor > 0)
|
|
{
|
|
double deltaY = delta * factor;
|
|
if (this.ApplyPanDelta(0.0, deltaY))
|
|
{
|
|
this.ApplyZoom(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void ApplyZoom(bool animate)
|
|
{
|
|
if (!animate || !this.animations)
|
|
{
|
|
this.translateTransform.BeginAnimation(TranslateTransform.XProperty, null);
|
|
this.translateTransform.BeginAnimation(TranslateTransform.YProperty, null);
|
|
this.zoomTransform.BeginAnimation(ScaleTransform.ScaleXProperty, null);
|
|
this.zoomTransform.BeginAnimation(ScaleTransform.ScaleYProperty, null);
|
|
this.rotateTransform.Angle = this.rotateAngle;
|
|
this.rotateTransform.CenterX = this.rotateCenterX;
|
|
this.rotateTransform.CenterY = this.rotateCenterY;
|
|
this.translateTransform.X = this.panX;
|
|
this.translateTransform.Y = this.panY;
|
|
this.zoomTransform.ScaleX = this.ZoomFactor;
|
|
this.zoomTransform.ScaleY = this.ZoomFactor;
|
|
}
|
|
else
|
|
{
|
|
DoubleAnimation animation = this.MakeZoomAnimation(this.panX);
|
|
DoubleAnimation animation2 = this.MakeZoomAnimation(this.panY);
|
|
DoubleAnimation animation3 = this.MakeZoomAnimation(this.ZoomFactor);
|
|
DoubleAnimation animation4 = this.MakeZoomAnimation(this.ZoomFactor);
|
|
this.translateTransform.BeginAnimation(TranslateTransform.XProperty, animation);
|
|
this.translateTransform.BeginAnimation(TranslateTransform.YProperty, animation2);
|
|
this.zoomTransform.BeginAnimation(ScaleTransform.ScaleXProperty, animation3);
|
|
this.zoomTransform.BeginAnimation(ScaleTransform.ScaleYProperty, animation4);
|
|
}
|
|
}
|
|
|
|
protected void ApplyZoomCommand(Point panelPoint)
|
|
{
|
|
Point point = this.transformGroup.Inverse.Transform(panelPoint);
|
|
this.ZoomMode = eZoomMode.CustomSize;
|
|
this.panX = -1.0 * ((point.X * this.ZoomFactor) - panelPoint.X);
|
|
this.panY = -1.0 * ((point.Y * this.ZoomFactor) - panelPoint.Y);
|
|
this.ApplyZoom(true);
|
|
}
|
|
|
|
protected void ApplyZoomCommand(double delta, int factor, Point panelPoint)
|
|
{
|
|
if (factor > 0)
|
|
{
|
|
double zoomFactor = this.ZoomFactor;
|
|
for (int i = 1; i <= factor; i++)
|
|
{
|
|
zoomFactor *= delta;
|
|
}
|
|
this.ZoomFactor = zoomFactor;
|
|
this.ApplyZoomCommand(panelPoint);
|
|
}
|
|
}
|
|
|
|
protected override Size ArrangeOverride(Size panelRect)
|
|
{
|
|
foreach (UIElement element in base.InternalChildren)
|
|
{
|
|
element.Arrange(new Rect(0.0, 0.0, element.DesiredSize.Width, element.DesiredSize.Height));
|
|
}
|
|
this.RecalcPage(panelRect);
|
|
return panelRect;
|
|
}
|
|
|
|
protected double CalcFloatingOffset(double zoom, double parent, double child, bool blockOnMargin, double margin)
|
|
{
|
|
double num = 0.0;
|
|
double num2 = child * zoom;
|
|
num = (parent - num2) / 2.0;
|
|
if (blockOnMargin && (num < margin))
|
|
{
|
|
num = margin;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
private void calcZoomFromTick()
|
|
{
|
|
double num = Math.Log10(this.MinZoom);
|
|
double num2 = Math.Log10(this.MaxZoom);
|
|
if (num2 <= num)
|
|
{
|
|
num2 = num + 0.01;
|
|
}
|
|
double num3 = (this.ZoomTick - this.MinZoomTick) / (this.MaxZoomTick - this.MinZoomTick);
|
|
double y = (num3 * (num2 - num)) + num;
|
|
this.Zoom = Math.Pow(10.0, y);
|
|
Point panelPoint = new Point(base.ActualWidth / 2.0, base.ActualHeight / 2.0);
|
|
this.ApplyZoomCommand(panelPoint);
|
|
}
|
|
|
|
private void calcZoomTick()
|
|
{
|
|
double num = Math.Log10(this.MinZoom);
|
|
double num2 = Math.Log10(this.MaxZoom);
|
|
double num3 = Math.Log10(this.Zoom);
|
|
if (num2 <= num)
|
|
{
|
|
num2 = num + 0.01;
|
|
}
|
|
double num4 = (num3 - num) / (num2 - num);
|
|
this.ZoomTick = (num4 * (this.MaxZoomTick - this.MinZoomTick)) + this.MinZoomTick;
|
|
}
|
|
|
|
private static void CanExecuteEventHandler_IfHasContent(object sender, CanExecuteRoutedEventArgs e)
|
|
{
|
|
ZoomBoxPanel panel = sender as ZoomBoxPanel;
|
|
e.CanExecute = (panel != null) && (panel.Children.Count > 0);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private static object CoerceMaxZoom(DependencyObject d, object value)
|
|
{
|
|
double num = (double)value;
|
|
ZoomBoxPanel panel = d as ZoomBoxPanel;
|
|
if (panel != null)
|
|
{
|
|
if (num < panel.MinZoom)
|
|
{
|
|
panel.MinZoom = num;
|
|
}
|
|
if (panel.Zoom > num)
|
|
{
|
|
panel.Zoom = num;
|
|
}
|
|
}
|
|
return num;
|
|
}
|
|
|
|
private static object CoerceMaxZoomTick(DependencyObject d, object value)
|
|
{
|
|
double num = (double)value;
|
|
ZoomBoxPanel panel = d as ZoomBoxPanel;
|
|
if ((panel != null) && (num <= panel.MinZoomTick))
|
|
{
|
|
panel.MinZoomTick = num - 1.0;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
private static object CoerceMinZoom(DependencyObject d, object value)
|
|
{
|
|
double num = (double)value;
|
|
ZoomBoxPanel panel = d as ZoomBoxPanel;
|
|
if (panel != null)
|
|
{
|
|
if (num <= 1E-07)
|
|
{
|
|
num = 1E-07;
|
|
}
|
|
if (num > panel.MaxZoom)
|
|
{
|
|
panel.MaxZoom = num;
|
|
}
|
|
if (panel.Zoom < num)
|
|
{
|
|
panel.Zoom = num;
|
|
}
|
|
}
|
|
return num;
|
|
}
|
|
|
|
private static object CoerceMinZoomTick(DependencyObject d, object value)
|
|
{
|
|
double num = (double)value;
|
|
ZoomBoxPanel panel = d as ZoomBoxPanel;
|
|
if ((panel != null) && (num >= panel.MaxZoomTick))
|
|
{
|
|
panel.MaxZoomTick = num + 1.0;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
private static object CoerceRotateDelta(DependencyObject d, object value)
|
|
{
|
|
double num = (double)value;
|
|
if (num <= 0.0)
|
|
{
|
|
return 1.0;
|
|
}
|
|
if (num > 359.0)
|
|
{
|
|
num = 359.0;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
private static object CoerceZoom(DependencyObject d, object value)
|
|
{
|
|
double minZoom = (double)value;
|
|
ZoomBoxPanel panel = d as ZoomBoxPanel;
|
|
if (panel != null)
|
|
{
|
|
if (minZoom > panel.MaxZoom)
|
|
{
|
|
return panel.MaxZoom;
|
|
}
|
|
if (minZoom < panel.MinZoom)
|
|
{
|
|
minZoom = panel.MinZoom;
|
|
}
|
|
}
|
|
return minZoom;
|
|
}
|
|
|
|
private static object CoerceZoomTick(DependencyObject d, object value)
|
|
{
|
|
double minZoomTick = (double)value;
|
|
ZoomBoxPanel panel = d as ZoomBoxPanel;
|
|
if (panel != null)
|
|
{
|
|
if (minZoomTick > panel.MaxZoomTick)
|
|
{
|
|
return panel.MaxZoomTick;
|
|
}
|
|
if (minZoomTick < panel.MinZoomTick)
|
|
{
|
|
minZoomTick = panel.MinZoomTick;
|
|
}
|
|
}
|
|
return minZoomTick;
|
|
}
|
|
|
|
public static void ExecutedEventHandler_DecreaseZoom(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
ZoomBoxPanel panel = sender as ZoomBoxPanel;
|
|
if (panel != null)
|
|
{
|
|
panel.process_ZoomCommand(false);
|
|
}
|
|
}
|
|
|
|
public static void ExecutedEventHandler_IncreaseZoom(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
ZoomBoxPanel panel = sender as ZoomBoxPanel;
|
|
if (panel != null)
|
|
{
|
|
panel.process_ZoomCommand(true);
|
|
}
|
|
}
|
|
|
|
public static void ExecutedEventHandler_RotateClockwise(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
ZoomBoxPanel panel = sender as ZoomBoxPanel;
|
|
double? angle = null;
|
|
string parameter = e.Parameter as string;
|
|
if ((parameter != null) && (parameter.Length > 0))
|
|
{
|
|
angle = new double?(double.Parse(parameter));
|
|
}
|
|
if (panel != null)
|
|
{
|
|
panel.process_RotateCommand(true, angle);
|
|
}
|
|
}
|
|
|
|
public static void ExecutedEventHandler_RotateCounterclockwise(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
ZoomBoxPanel panel = sender as ZoomBoxPanel;
|
|
double? angle = null;
|
|
string parameter = e.Parameter as string;
|
|
if ((parameter != null) && (parameter.Length > 0))
|
|
{
|
|
angle = new double?(double.Parse(parameter));
|
|
}
|
|
if (panel != null)
|
|
{
|
|
panel.process_RotateCommand(false, angle);
|
|
}
|
|
}
|
|
|
|
public static void ExecutedEventHandler_RotateHome(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
ZoomBoxPanel panel = sender as ZoomBoxPanel;
|
|
if (panel != null)
|
|
{
|
|
panel.process_RotateHomeReverse(true);
|
|
}
|
|
}
|
|
|
|
public static void ExecutedEventHandler_RotateReverse(object sender, ExecutedRoutedEventArgs e)
|
|
{
|
|
ZoomBoxPanel panel = sender as ZoomBoxPanel;
|
|
if (panel != null)
|
|
{
|
|
panel.process_RotateHomeReverse(false);
|
|
}
|
|
}
|
|
|
|
public Point LogicalCentrePoint()
|
|
{
|
|
Point point = new Point(base.ActualWidth / 2.0, base.ActualHeight / 2.0);
|
|
return this.transformGroup.Inverse.Transform(point);
|
|
}
|
|
|
|
protected DoubleAnimation MakeZoomAnimation(double value)
|
|
{
|
|
return new DoubleAnimation(value, new Duration(TimeSpan.FromMilliseconds(300.0))) { FillBehavior = FillBehavior.HoldEnd };
|
|
}
|
|
|
|
protected override Size MeasureOverride(Size constraint)
|
|
{
|
|
Size size = new Size(150.0, 150.0);
|
|
if (!double.IsNaN(constraint.Width) && !double.IsInfinity(constraint.Width))
|
|
{
|
|
size.Width = constraint.Width;
|
|
}
|
|
if (!double.IsNaN(constraint.Height) && !double.IsInfinity(constraint.Height))
|
|
{
|
|
size.Height = constraint.Height;
|
|
}
|
|
this.childSize = new Size(1.0, 1.0);
|
|
Size availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
|
|
foreach (UIElement element in base.InternalChildren)
|
|
{
|
|
element.Measure(availableSize);
|
|
if (element.DesiredSize.Width > this.childSize.Width)
|
|
{
|
|
this.childSize.Width = element.DesiredSize.Width;
|
|
}
|
|
if (element.DesiredSize.Height > this.childSize.Height)
|
|
{
|
|
this.childSize.Height = element.DesiredSize.Height;
|
|
}
|
|
}
|
|
return size;
|
|
}
|
|
|
|
public override void OnApplyTemplate()
|
|
{
|
|
base.OnApplyTemplate();
|
|
base.Focusable = true;
|
|
}
|
|
|
|
protected override void OnInitialized(EventArgs e)
|
|
{
|
|
base.OnInitialized(e);
|
|
base.MouseWheel += new MouseWheelEventHandler(this.process_MouseWheel);
|
|
base.MouseDown += new MouseButtonEventHandler(this.process_MouseDown);
|
|
base.MouseUp += new MouseButtonEventHandler(this.process_MouseUp);
|
|
base.MouseMove += new MouseEventHandler(this.process_MouseMove);
|
|
base.PreviewMouseDown += new MouseButtonEventHandler(this.process_PreviewMouseDown);
|
|
base.PreviewMouseUp += new MouseButtonEventHandler(this.process_PreviewMouseUp);
|
|
base.PreviewMouseMove += new MouseEventHandler(this.process_PreviewMouseMove);
|
|
this.ApplyZoom(false);
|
|
foreach (UIElement element in base.InternalChildren)
|
|
{
|
|
element.RenderTransform = this.transformGroup;
|
|
}
|
|
}
|
|
|
|
private void process_MouseDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
e.GetPosition(this);
|
|
if ((this.MouseMode == eMouseMode.Pan) && (((e.ChangedButton == MouseButton.Left) && (((byte)(Keyboard.GetKeyStates(Key.LeftAlt) & KeyStates.Down)) == 0)) && (((byte)(Keyboard.GetKeyStates(Key.RightAlt) & KeyStates.Down)) == 0)))
|
|
{
|
|
this.prevCursor = base.Cursor;
|
|
this.StartMouseCapture(e.GetPosition(this));
|
|
base.Cursor = Cursors.ScrollAll;
|
|
}
|
|
}
|
|
|
|
private void process_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
//e.GetPosition(this);
|
|
switch (this.MouseMode)
|
|
{
|
|
case eMouseMode.Zoom:
|
|
break;
|
|
|
|
case eMouseMode.Pan:
|
|
if (base.IsMouseCaptured)
|
|
{
|
|
Point position = e.GetPosition(this);
|
|
double deltaX = position.X - this.startMouseCapturePanel.X;
|
|
double deltaY = position.Y - this.startMouseCapturePanel.Y;
|
|
if ((deltaX != 0.0) || (deltaY != 0.0))
|
|
{
|
|
this.startMouseCapturePanel.X = position.X;
|
|
this.startMouseCapturePanel.Y = position.Y;
|
|
if (this.ApplyPanDelta(deltaX, deltaY))
|
|
{
|
|
this.ApplyZoom(false);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void process_MouseUp(object sender, MouseButtonEventArgs e)
|
|
{
|
|
Point position;
|
|
int num;
|
|
double num2;
|
|
e.GetPosition(this);
|
|
switch (this.MouseMode)
|
|
{
|
|
case eMouseMode.Zoom:
|
|
position = e.GetPosition(this);
|
|
num = 0;
|
|
num2 = 1.0 + (this.ClickZoomDelta / 100.0);
|
|
switch (e.ChangedButton)
|
|
{
|
|
case MouseButton.Left:
|
|
num = 1;
|
|
break;
|
|
|
|
case MouseButton.Right:
|
|
num = 1;
|
|
num2 = 1.0 / num2;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
goto lab1;
|
|
}
|
|
this.ApplyZoomCommand(num2, num, position);
|
|
lab1:
|
|
if (base.IsMouseCaptured)
|
|
{
|
|
base.ReleaseMouseCapture();
|
|
base.Cursor = this.prevCursor;
|
|
this.prevCursor = null;
|
|
}
|
|
}
|
|
|
|
private void process_MouseWheel(object sender, MouseWheelEventArgs e)
|
|
{
|
|
Point position = e.GetPosition(this);
|
|
double delta = 0.0;
|
|
int num2 = Math.Abs(e.Delta);
|
|
if ((this.minMouseDelta > num2) && (num2 > 0))
|
|
{
|
|
this.minMouseDelta = num2;
|
|
}
|
|
int factor = num2 / this.minMouseDelta;
|
|
if (factor < 1)
|
|
{
|
|
factor = 1;
|
|
}
|
|
switch (this.WheelMode)
|
|
{
|
|
case eWheelMode.Zoom:
|
|
delta = 1.0 + (this.WheelZoomDelta / 100.0);
|
|
if ((e.Delta <= 0) && (delta != 0.0))
|
|
{
|
|
delta = 1.0 / delta;
|
|
}
|
|
this.ApplyZoomCommand(delta, factor, position);
|
|
return;
|
|
|
|
case eWheelMode.Scroll:
|
|
delta = this.scrollDelta;
|
|
if (e.Delta <= 0)
|
|
{
|
|
delta *= -1.0;
|
|
}
|
|
this.ApplyScrollCommand(delta, factor, position);
|
|
return;
|
|
|
|
case eWheelMode.Rotate:
|
|
delta = this.RotateDelta;
|
|
if (e.Delta <= 0)
|
|
{
|
|
delta *= -1.0;
|
|
}
|
|
this.ApplyRotateCommand(delta, factor, position);
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void process_PreviewMouseDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
if (this.lockContent)
|
|
{
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void process_PreviewMouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
if (this.lockContent)
|
|
{
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void process_PreviewMouseUp(object sender, MouseButtonEventArgs e)
|
|
{
|
|
if (this.lockContent)
|
|
{
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void process_PropertyChanged_Zoom(DependencyPropertyChangedEventArgs e)
|
|
{
|
|
if (!this.zoomCircularReference)
|
|
{
|
|
this.zoomCircularReference = true;
|
|
if (e.Property == ZoomProperty)
|
|
{
|
|
this.calcZoomTick();
|
|
}
|
|
else if (e.Property == ZoomTickProperty)
|
|
{
|
|
this.calcZoomFromTick();
|
|
}
|
|
this.zoomCircularReference = false;
|
|
}
|
|
}
|
|
|
|
private void process_RotateCommand(bool clockWise, double? angle)
|
|
{
|
|
Point panelPoint = new Point(base.ActualWidth / 2.0, base.ActualHeight / 2.0);
|
|
double rotateDelta = this.RotateDelta;
|
|
if (angle.HasValue)
|
|
{
|
|
rotateDelta = angle.Value;
|
|
}
|
|
if (!clockWise)
|
|
{
|
|
rotateDelta *= -1.0;
|
|
}
|
|
this.ApplyRotateCommand(rotateDelta, 1, panelPoint);
|
|
}
|
|
|
|
private void process_RotateHomeReverse(bool isHome)
|
|
{
|
|
new Point(base.ActualWidth / 2.0, base.ActualHeight / 2.0);
|
|
this.rotateAngle = isHome ? ((double)0) : ((double)180);
|
|
this.rotateCenterX = this.childSize.Width / 2.0;
|
|
this.rotateCenterY = this.childSize.Height / 2.0;
|
|
this.ApplyZoom(true);
|
|
}
|
|
|
|
private void process_ZoomCommand(bool increase)
|
|
{
|
|
Point panelPoint = new Point(base.ActualWidth / 2.0, base.ActualHeight / 2.0);
|
|
double delta = 1.0 + (this.ClickZoomDelta / 100.0);
|
|
if (!increase)
|
|
{
|
|
delta = 1.0 / delta;
|
|
}
|
|
this.ApplyZoomCommand(delta, 1, panelPoint);
|
|
}
|
|
|
|
private static void PropertyChanged_AMode(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
ZoomBoxPanel panel = d as ZoomBoxPanel;
|
|
if (panel != null)
|
|
{
|
|
panel.RaiseModeChangeEvent();
|
|
}
|
|
}
|
|
|
|
private static void PropertyChanged_Zoom(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
ZoomBoxPanel panel = d as ZoomBoxPanel;
|
|
if (panel != null)
|
|
{
|
|
panel.process_PropertyChanged_Zoom(e);
|
|
}
|
|
}
|
|
|
|
private void RaiseModeChangeEvent()
|
|
{
|
|
RoutedEventArgs e = new RoutedEventArgs(ModeChangeEvent);
|
|
base.RaiseEvent(e);
|
|
}
|
|
|
|
protected void RecalcPage(Size panelRect)
|
|
{
|
|
double margin = 4.0;
|
|
double num2 = 4.0;
|
|
double num3 = 3.0;
|
|
double num4 = 3.0;
|
|
double width = 0.0;
|
|
double height = 0.0;
|
|
double num7 = 0.0;
|
|
double num8 = 0.0;
|
|
double num9 = 5.0;
|
|
switch (this.ZoomMode)
|
|
{
|
|
case eZoomMode.CustomSize:
|
|
break;
|
|
|
|
case eZoomMode.FitWidth:
|
|
width = (panelRect.Width - margin) - num2;
|
|
if (width < num9)
|
|
{
|
|
width = num9;
|
|
}
|
|
num7 = width / this.childSize.Width;
|
|
this.ZoomFactor = num7;
|
|
this.panX = margin;
|
|
this.panY = this.CalcFloatingOffset(this.ZoomFactor, panelRect.Height, this.childSize.Height, true, num3);
|
|
this.ApplyZoom(false);
|
|
return;
|
|
|
|
case eZoomMode.FitHeight:
|
|
height = (panelRect.Height - num3) - num4;
|
|
if (height < num9)
|
|
{
|
|
height = num9;
|
|
}
|
|
num8 = height / this.childSize.Height;
|
|
this.ZoomFactor = num8;
|
|
this.panX = this.CalcFloatingOffset(this.ZoomFactor, panelRect.Width, this.childSize.Width, true, margin);
|
|
this.panY = num3;
|
|
this.ApplyZoom(false);
|
|
return;
|
|
|
|
case eZoomMode.FitPage:
|
|
width = (panelRect.Width - margin) - num2;
|
|
if (width < num9)
|
|
{
|
|
width = num9;
|
|
}
|
|
num7 = width / this.childSize.Width;
|
|
height = (panelRect.Height - num3) - num4;
|
|
if (height < num9)
|
|
{
|
|
height = num9;
|
|
}
|
|
num8 = height / this.childSize.Height;
|
|
if (num7 <= num8)
|
|
{
|
|
this.ZoomFactor = num7;
|
|
this.panX = margin;
|
|
this.panY = this.CalcFloatingOffset(this.ZoomFactor, panelRect.Height, this.childSize.Height, true, num3);
|
|
}
|
|
else
|
|
{
|
|
this.ZoomFactor = num8;
|
|
this.panX = this.CalcFloatingOffset(this.ZoomFactor, panelRect.Width, this.childSize.Width, true, margin);
|
|
this.panY = num3;
|
|
}
|
|
this.ApplyZoom(false);
|
|
return;
|
|
|
|
case eZoomMode.FitVisible:
|
|
width = panelRect.Width;
|
|
if (width < num9)
|
|
{
|
|
width = num9;
|
|
}
|
|
num7 = width / this.childSize.Width;
|
|
height = panelRect.Height;
|
|
if (height < num9)
|
|
{
|
|
height = num9;
|
|
}
|
|
num8 = height / this.childSize.Height;
|
|
if (num7 >= num8)
|
|
{
|
|
this.ZoomFactor = num7;
|
|
this.panX = 0.0;
|
|
this.panY = this.CalcFloatingOffset(this.ZoomFactor, panelRect.Height, this.childSize.Height, true, 0.0);
|
|
}
|
|
else
|
|
{
|
|
this.ZoomFactor = num8;
|
|
this.panX = this.CalcFloatingOffset(this.ZoomFactor, panelRect.Width, this.childSize.Width, true, 0.0);
|
|
this.panY = 0.0;
|
|
}
|
|
this.ApplyZoom(false);
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void setMouseCursorFromMode()
|
|
{
|
|
switch (this.MouseMode)
|
|
{
|
|
case eMouseMode.Zoom:
|
|
base.Cursor = Cursors.ScrollAll;
|
|
return;
|
|
|
|
case eMouseMode.Pan:
|
|
base.Cursor = Cursors.Hand;
|
|
return;
|
|
}
|
|
base.Cursor = Cursors.Arrow;
|
|
}
|
|
|
|
public void SetPan(double x, double y)
|
|
{
|
|
if (this.ApplyPanAbs(x, y))
|
|
{
|
|
this.ApplyZoom(false);
|
|
}
|
|
}
|
|
|
|
public void SetZoomForVirtualWidth(int value)
|
|
{
|
|
this.ZoomMode = eZoomMode.CustomSize;
|
|
if (this.childSize.Width > 0.0)
|
|
{
|
|
this.ZoomFactor = ((double)value) / this.childSize.Width;
|
|
}
|
|
this.panX = 0.0;
|
|
this.panY = 0.0;
|
|
this.rotateAngle = 0.0;
|
|
this.rotateCenterX = 0.0;
|
|
this.rotateCenterY = 0.0;
|
|
this.ApplyZoom(false);
|
|
}
|
|
|
|
private void StartMouseCapture(Point startPoint)
|
|
{
|
|
this.startMouseCapturePanel = startPoint;
|
|
base.CaptureMouse();
|
|
}
|
|
|
|
private static bool ValidateIsNonZero(object value)
|
|
{
|
|
double num = (double)value;
|
|
if (num == 0.0)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static bool ValidateIsPositiveNonZero(object value)
|
|
{
|
|
double num = (double)value;
|
|
if (num <= 0.0)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Properties
|
|
public bool Animations
|
|
{
|
|
get
|
|
{
|
|
return this.animations;
|
|
}
|
|
set
|
|
{
|
|
this.animations = value;
|
|
}
|
|
}
|
|
|
|
public double ClickZoomDelta
|
|
{
|
|
get
|
|
{
|
|
return (double)base.GetValue(ClickZoomDeltaProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(ClickZoomDeltaProperty, value);
|
|
}
|
|
}
|
|
|
|
public bool LockContent
|
|
{
|
|
get
|
|
{
|
|
return this.lockContent;
|
|
}
|
|
set
|
|
{
|
|
this.lockContent = value;
|
|
}
|
|
}
|
|
|
|
public double MaxZoom
|
|
{
|
|
get
|
|
{
|
|
return (double)base.GetValue(MaxZoomProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(MaxZoomProperty, value);
|
|
}
|
|
}
|
|
|
|
public double MaxZoomTick
|
|
{
|
|
get
|
|
{
|
|
return (double)base.GetValue(MaxZoomTickProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(MaxZoomTickProperty, value);
|
|
}
|
|
}
|
|
|
|
public double MinZoom
|
|
{
|
|
get
|
|
{
|
|
return (double)base.GetValue(MinZoomProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(MinZoomProperty, value);
|
|
}
|
|
}
|
|
|
|
public double MinZoomTick
|
|
{
|
|
get
|
|
{
|
|
return (double)base.GetValue(MinZoomTickProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(MinZoomTickProperty, value);
|
|
}
|
|
}
|
|
|
|
public eMouseMode MouseMode
|
|
{
|
|
get
|
|
{
|
|
return (eMouseMode)base.GetValue(MouseModeProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(MouseModeProperty, value);
|
|
}
|
|
}
|
|
|
|
public static RoutedUICommand RotateClockwise
|
|
{
|
|
get
|
|
{
|
|
return rotateClockwiseCommand;
|
|
}
|
|
}
|
|
|
|
public static RoutedUICommand RotateCounterclockwise
|
|
{
|
|
get
|
|
{
|
|
return rotateCounterclockwiseCommand;
|
|
}
|
|
}
|
|
|
|
public double RotateDelta
|
|
{
|
|
get
|
|
{
|
|
return (double)base.GetValue(RotateDeltaProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(RotateDeltaProperty, value);
|
|
}
|
|
}
|
|
|
|
public static RoutedUICommand RotateHome
|
|
{
|
|
get
|
|
{
|
|
return rotateHomeCommand;
|
|
}
|
|
}
|
|
|
|
public static RoutedUICommand RotateReverse
|
|
{
|
|
get
|
|
{
|
|
return rotateReverseCommand;
|
|
}
|
|
}
|
|
|
|
public eWheelMode WheelMode
|
|
{
|
|
get
|
|
{
|
|
return (eWheelMode)base.GetValue(WheelModeProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(WheelModeProperty, value);
|
|
}
|
|
}
|
|
|
|
public double WheelZoomDelta
|
|
{
|
|
get
|
|
{
|
|
return (double)base.GetValue(WheelZoomDeltaProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(WheelZoomDeltaProperty, value);
|
|
}
|
|
}
|
|
|
|
public double Zoom
|
|
{
|
|
get
|
|
{
|
|
return (double)base.GetValue(ZoomProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(ZoomProperty, value);
|
|
}
|
|
}
|
|
|
|
protected double ZoomFactor
|
|
{
|
|
get
|
|
{
|
|
return (this.Zoom / 100.0);
|
|
}
|
|
set
|
|
{
|
|
this.Zoom = value * 100.0;
|
|
}
|
|
}
|
|
|
|
public eZoomMode ZoomMode
|
|
{
|
|
get
|
|
{
|
|
return (eZoomMode)base.GetValue(ZoomModeProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(ZoomModeProperty, value);
|
|
}
|
|
}
|
|
|
|
public double ZoomTick
|
|
{
|
|
get
|
|
{
|
|
return (double)base.GetValue(ZoomTickProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(ZoomTickProperty, value);
|
|
}
|
|
}
|
|
|
|
// Nested Types
|
|
public enum eMouseMode
|
|
{
|
|
None,
|
|
Pointer,
|
|
Zoom,
|
|
Pan
|
|
}
|
|
|
|
public enum eWheelMode
|
|
{
|
|
None,
|
|
Zoom,
|
|
Scroll,
|
|
Rotate
|
|
}
|
|
|
|
public enum eZoomMode
|
|
{
|
|
CustomSize,
|
|
FitWidth,
|
|
FitHeight,
|
|
FitPage,
|
|
FitVisible
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|