123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- using System.Windows;
- using System.Windows.Input;
- using System.Windows.Media;
- using HandyControl.Data;
- namespace HandyControl.Interactivity;
- public class MouseDragElementBehavior : Behavior<FrameworkElement>
- {
- public static readonly DependencyProperty ConstrainToParentBoundsProperty =
- DependencyProperty.Register("ConstrainToParentBounds", typeof(bool), typeof(MouseDragElementBehavior),
- new PropertyMetadata(ValueBoxes.FalseBox, OnConstrainToParentBoundsChanged));
- public static readonly DependencyProperty XProperty = DependencyProperty.Register("X", typeof(double),
- typeof(MouseDragElementBehavior), new PropertyMetadata(double.PositiveInfinity, OnXChanged));
- public static readonly DependencyProperty YProperty = DependencyProperty.Register("Y", typeof(double),
- typeof(MouseDragElementBehavior), new PropertyMetadata(double.PositiveInfinity, OnYChanged));
- // Fields
- private Transform _cachedRenderTransform;
- private Point _relativePosition;
- private bool _settingPosition;
- // Properties
- public bool ConstrainToParentBounds
- {
- get => (bool) GetValue(ConstrainToParentBoundsProperty);
- set => SetValue(ConstrainToParentBoundsProperty, ValueBoxes.BooleanBox(value));
- }
- private Rect ElementBounds
- {
- get
- {
- var layoutRect = ExtendedVisualStateManager.GetLayoutRect(AssociatedObject);
- return new Rect(new Point(0.0, 0.0), new Size(layoutRect.Width, layoutRect.Height));
- }
- }
- private FrameworkElement ParentElement =>
- AssociatedObject.Parent as FrameworkElement;
- private Transform RenderTransform
- {
- get
- {
- if (_cachedRenderTransform == null ||
- !ReferenceEquals(_cachedRenderTransform, AssociatedObject.RenderTransform))
- {
- var transform = CloneTransform(AssociatedObject.RenderTransform);
- RenderTransform = transform;
- }
- return _cachedRenderTransform;
- }
- set
- {
- if (!Equals(_cachedRenderTransform, value))
- {
- _cachedRenderTransform = value;
- AssociatedObject.RenderTransform = value;
- }
- }
- }
- private UIElement RootElement
- {
- get
- {
- DependencyObject associatedObject = AssociatedObject;
- for (var obj3 = associatedObject; obj3 != null; obj3 = VisualTreeHelper.GetParent(associatedObject))
- associatedObject = obj3;
- return associatedObject as UIElement;
- }
- }
- public double X
- {
- get =>
- (double) GetValue(XProperty);
- set => SetValue(XProperty, value);
- }
- public double Y
- {
- get =>
- (double) GetValue(YProperty);
- set => SetValue(YProperty, value);
- }
- // Events
- public event MouseEventHandler DragBegun;
- public event MouseEventHandler DragFinished;
- public event MouseEventHandler Dragging;
- // Methods
- private void ApplyTranslation(double x, double y)
- {
- if (ParentElement != null)
- {
- var point = TransformAsVector(RootElement.TransformToVisual(ParentElement), x, y);
- x = point.X;
- y = point.Y;
- if (ConstrainToParentBounds)
- {
- var parentElement = ParentElement;
- var rect = new Rect(0.0, 0.0, parentElement.ActualWidth, parentElement.ActualHeight);
- var transform2 = AssociatedObject.TransformToVisual(parentElement);
- var elementBounds = ElementBounds;
- var rect3 = transform2.TransformBounds(elementBounds);
- rect3.X += x;
- rect3.Y += y;
- if (!RectContainsRect(rect, rect3))
- {
- if (rect3.X < rect.Left)
- {
- var num = rect3.X - rect.Left;
- x -= num;
- }
- else if (rect3.Right > rect.Right)
- {
- var num2 = rect3.Right - rect.Right;
- x -= num2;
- }
- if (rect3.Y < rect.Top)
- {
- var num3 = rect3.Y - rect.Top;
- y -= num3;
- }
- else if (rect3.Bottom > rect.Bottom)
- {
- var num4 = rect3.Bottom - rect.Bottom;
- y -= num4;
- }
- }
- }
- ApplyTranslationTransform(x, y);
- }
- }
- internal void ApplyTranslationTransform(double x, double y)
- {
- var renderTransform = RenderTransform;
- var transform2 = renderTransform as TranslateTransform;
- if (transform2 == null)
- {
- var group = renderTransform as TransformGroup;
- var transform3 = renderTransform as MatrixTransform;
- if (group != null)
- {
- if (group.Children.Count > 0)
- transform2 = group.Children[group.Children.Count - 1] as TranslateTransform;
- if (transform2 == null)
- {
- transform2 = new TranslateTransform();
- group.Children.Add(transform2);
- }
- }
- else
- {
- if (transform3 != null)
- {
- var matrix = transform3.Matrix;
- matrix.OffsetX += x;
- matrix.OffsetY += y;
- var transform4 = new MatrixTransform
- {
- Matrix = matrix
- };
- RenderTransform = transform4;
- return;
- }
- var group2 = new TransformGroup();
- transform2 = new TranslateTransform();
- if (renderTransform != null)
- group2.Children.Add(renderTransform);
- group2.Children.Add(transform2);
- RenderTransform = group2;
- }
- }
- transform2.X += x;
- transform2.Y += y;
- }
- internal static Transform CloneTransform(Transform transform)
- {
- if (transform == null)
- return null;
- if (transform is ScaleTransform transform2)
- return new ScaleTransform
- {
- CenterX = transform2.CenterX,
- CenterY = transform2.CenterY,
- ScaleX = transform2.ScaleX,
- ScaleY = transform2.ScaleY
- };
- if (transform is RotateTransform transform3)
- return new RotateTransform
- {
- Angle = transform3.Angle,
- CenterX = transform3.CenterX,
- CenterY = transform3.CenterY
- };
- if (transform is SkewTransform transform4)
- return new SkewTransform
- {
- AngleX = transform4.AngleX,
- AngleY = transform4.AngleY,
- CenterX = transform4.CenterX,
- CenterY = transform4.CenterY
- };
- if (transform is TranslateTransform transform5)
- return new TranslateTransform
- {
- X = transform5.X,
- Y = transform5.Y
- };
- if (transform is MatrixTransform transform6)
- return new MatrixTransform { Matrix = transform6.Matrix };
- if (!(transform is TransformGroup group))
- return null;
- var group2 = new TransformGroup();
- foreach (var transform12 in group.Children)
- group2.Children.Add(CloneTransform(transform12));
- return group2;
- }
- internal void EndDrag()
- {
- AssociatedObject.MouseMove -= OnMouseMove;
- AssociatedObject.LostMouseCapture -= OnLostMouseCapture;
- AssociatedObject.RemoveHandler(UIElement.MouseLeftButtonUpEvent,
- new MouseButtonEventHandler(OnMouseLeftButtonUp));
- }
- private static Point GetTransformOffset(GeneralTransform transform)
- {
- return transform.Transform(new Point(0.0, 0.0));
- }
- internal void HandleDrag(Point newPositionInElementCoordinates)
- {
- var x = newPositionInElementCoordinates.X - _relativePosition.X;
- var y = newPositionInElementCoordinates.Y - _relativePosition.Y;
- var point = TransformAsVector(AssociatedObject.TransformToVisual(RootElement), x, y);
- _settingPosition = true;
- ApplyTranslation(point.X, point.Y);
- UpdatePosition();
- _settingPosition = false;
- }
- protected override void OnAttached()
- {
- AssociatedObject.AddHandler(UIElement.MouseLeftButtonDownEvent,
- new MouseButtonEventHandler(OnMouseLeftButtonDown), false);
- }
- private static void OnConstrainToParentBoundsChanged(object sender, DependencyPropertyChangedEventArgs args)
- {
- var behavior = (MouseDragElementBehavior) sender;
- behavior.UpdatePosition(new Point(behavior.X, behavior.Y));
- }
- protected override void OnDetaching()
- {
- AssociatedObject.RemoveHandler(UIElement.MouseLeftButtonDownEvent,
- new MouseButtonEventHandler(OnMouseLeftButtonDown));
- }
- private void OnLostMouseCapture(object sender, MouseEventArgs e)
- {
- EndDrag();
- DragFinished?.Invoke(this, e);
- }
- private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- {
- StartDrag(e.GetPosition(AssociatedObject));
- DragBegun?.Invoke(this, e);
- }
- private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
- {
- AssociatedObject.ReleaseMouseCapture();
- }
- private void OnMouseMove(object sender, MouseEventArgs e)
- {
- HandleDrag(e.GetPosition(AssociatedObject));
- Dragging?.Invoke(this, e);
- }
- private static void OnXChanged(object sender, DependencyPropertyChangedEventArgs args)
- {
- var behavior = (MouseDragElementBehavior) sender;
- behavior.UpdatePosition(new Point((double) args.NewValue, behavior.Y));
- }
- private static void OnYChanged(object sender, DependencyPropertyChangedEventArgs args)
- {
- var behavior = (MouseDragElementBehavior) sender;
- behavior.UpdatePosition(new Point(behavior.X, (double) args.NewValue));
- }
- private static bool RectContainsRect(Rect rect1, Rect rect2)
- {
- if (rect1.IsEmpty || rect2.IsEmpty)
- return false;
- return rect1.X <= rect2.X && rect1.Y <= rect2.Y && rect1.X + rect1.Width >= rect2.X + rect2.Width &&
- rect1.Y + rect1.Height >= rect2.Y + rect2.Height;
- }
- internal void StartDrag(Point positionInElementCoordinates)
- {
- _relativePosition = positionInElementCoordinates;
- AssociatedObject.CaptureMouse();
- AssociatedObject.MouseMove += OnMouseMove;
- AssociatedObject.LostMouseCapture += OnLostMouseCapture;
- AssociatedObject.AddHandler(UIElement.MouseLeftButtonUpEvent,
- new MouseButtonEventHandler(OnMouseLeftButtonUp), false);
- }
- private static Point TransformAsVector(GeneralTransform transform, double x, double y)
- {
- var point = transform.Transform(new Point(0.0, 0.0));
- var point2 = transform.Transform(new Point(x, y));
- return new Point(point2.X - point.X, point2.Y - point.Y);
- }
- private void UpdatePosition()
- {
- var transformOffset = GetTransformOffset(AssociatedObject.TransformToVisual(RootElement));
- X = transformOffset.X;
- Y = transformOffset.Y;
- }
- private void UpdatePosition(Point point)
- {
- if (!_settingPosition && AssociatedObject != null)
- {
- var transformOffset = GetTransformOffset(AssociatedObject.TransformToVisual(RootElement));
- var x = double.IsNaN(point.X) ? 0.0 : point.X - transformOffset.X;
- var y = double.IsNaN(point.Y) ? 0.0 : point.Y - transformOffset.Y;
- ApplyTranslation(x, y);
- }
- }
- }
|