Пример #1
0
        /// <summary>
        /// Global handler for pointer pressed events.
        /// </summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event args.</param>
        private static void OnPreviewPointerPressed(object?sender, RoutedEventArgs e)
        {
            if (sender is null)
            {
                return;
            }

            var ev     = (PointerPressedEventArgs)e;
            var visual = (IVisual)sender;

            if (sender == e.Source && ev.GetCurrentPoint(visual).Properties.IsLeftButtonPressed)
            {
                IVisual?element = ev.Pointer?.Captured ?? e.Source as IInputElement;

                while (element != null)
                {
                    if (element is IInputElement inputElement && CanFocus(inputElement))
                    {
                        Instance?.Focus(inputElement, NavigationMethod.Pointer, ev.KeyModifiers);

                        break;
                    }

                    element = element.VisualParent;
                }
            }
        }
Пример #2
0
 public void End()
 {
     DragControl       = null;
     DropControl       = null;
     DragStartPoint    = default;
     PointerPressed    = false;
     DoDragDrop        = false;
     TargetPoint       = default;
     TargetDockControl = null;
 }
Пример #3
0
 public void Start(IControl dragControl, Point point)
 {
     DragControl       = dragControl;
     DropControl       = null;
     DragStartPoint    = point;
     PointerPressed    = true;
     DoDragDrop        = false;
     TargetPoint       = default;
     TargetDockControl = null;
 }
Пример #4
0
 public void Dispose()
 {
     if (_visual == null)
     {
         return;
     }
     UnsubscribeFromParents();
     _visual.AttachedToVisualTree   -= OnAttachedToVisualTree;
     _visual.DetachedFromVisualTree -= OnDetachedFromVisualTree;
     _visual = null;
 }
Пример #5
0
            public HitTestEnumerator(IVisualNode root, Func <IVisual, bool>?filter, Point point, IVisualNode sceneRoot)
            {
                _nodeStack = new PooledStack <Entry>();
                _nodeStack.Push(new Entry(root, false, null, true));

                _filter    = filter;
                _point     = point;
                _sceneRoot = sceneRoot;

                _current = null;
            }
Пример #6
0
        /// <summary>
        /// Tries to get the first common ancestor of two visuals.
        /// </summary>
        /// <param name="visual">The first visual.</param>
        /// <param name="target">The second visual.</param>
        /// <returns>The common ancestor, or null if not found.</returns>
        public static IVisual?FindCommonVisualAncestor(this IVisual visual, IVisual target)
        {
            IVisual?v = visual ?? throw new ArgumentNullException(nameof(visual));

            if (target is null)
            {
                return(null);
            }

            IVisual?t = target;

            void GoUpwards(ref IVisual?node, int count)
            {
                for (int i = 0; i < count; ++i)
                {
                    node = node?.VisualParent;
                }
            }

            // We want to find lowest node first, then make sure that both nodes are at the same height.
            // By doing that we can sometimes find out that other node is our lowest common ancestor.
            var firstHeight  = CalculateDistanceFromRoot(v);
            var secondHeight = CalculateDistanceFromRoot(t);

            if (firstHeight > secondHeight)
            {
                GoUpwards(ref v, firstHeight - secondHeight);
            }
            else
            {
                GoUpwards(ref t, secondHeight - firstHeight);
            }

            if (v == t)
            {
                return(v);
            }

            while (v != null && t != null)
            {
                IVisual?firstParent  = v.VisualParent;
                IVisual?secondParent = t.VisualParent;

                if (firstParent == secondParent)
                {
                    return(firstParent);
                }

                v = v.VisualParent;
                t = t.VisualParent;
            }

            return(null);
        }
Пример #7
0
        /// <summary>
        /// Gets the common visual parent of the two control.
        /// </summary>
        /// <param name="from">The from control.</param>
        /// <param name="to">The to control.</param>
        /// <returns>The common parent.</returns>
        /// <exception cref="ArgumentException">
        /// The two controls do not share a common parent.
        /// </exception>
        /// <remarks>
        /// Any one of the parameters may be null, but not both.
        /// </remarks>
        private static IVisual GetVisualParent(IVisual?from, IVisual?to)
        {
            var p1 = (from ?? to) !.VisualParent;
            var p2 = (to ?? from) !.VisualParent;

            if (p1 != null && p2 != null && p1 != p2)
            {
                throw new ArgumentException("Controls for PageSlide must have same parent.");
            }

            return(p1 ?? throw new InvalidOperationException("Cannot determine visual parent."));
        }
Пример #8
0
 public PointerEventArgs(RoutedEvent routedEvent,
                         IInteractive?source,
                         IPointer pointer,
                         IVisual?rootVisual, Point rootVisualPosition,
                         ulong timestamp,
                         PointerPointProperties properties,
                         KeyModifiers modifiers,
                         Lazy <IReadOnlyList <RawPointerPoint>?>?previousPoints)
     : this(routedEvent, source, pointer, rootVisual, rootVisualPosition, timestamp, properties, modifiers)
 {
     _previousPoints = previousPoints;
 }
Пример #9
0
        /// <summary>
        /// Calculates the distance from a visual's ancestor.
        /// </summary>
        /// <param name="visual">The visual.</param>
        /// <param name="ancestor">The ancestor visual.</param>
        /// <returns>
        /// The number of steps from the visual to the ancestor or -1 if
        /// <paramref name="visual"/> is not a descendent of <paramref name="ancestor"/>.
        /// </returns>
        public static int CalculateDistanceFromAncestor(this IVisual visual, IVisual?ancestor)
        {
            IVisual?v      = visual ?? throw new ArgumentNullException(nameof(visual));
            var     result = 0;

            while (v != null && v != ancestor)
            {
                v = v.VisualParent;

                result++;
            }

            return(v != null ? result : -1);
        }
Пример #10
0
 public void SetVisual(IVisual?visual)
 {
     Dispose();
     _visual = visual;
     if (visual != null)
     {
         visual.AttachedToVisualTree   += OnAttachedToVisualTree;
         visual.DetachedFromVisualTree -= OnDetachedFromVisualTree;
         if (visual.IsAttachedToVisualTree)
         {
             SubscribeToParents();
         }
         UpdateMatrix();
     }
 }
Пример #11
0
        /// <summary>
        /// Tests whether an <see cref="IVisual"/> is an ancestor of another visual.
        /// </summary>
        /// <param name="visual">The visual.</param>
        /// <param name="target">The potential descendant.</param>
        /// <returns>
        /// True if <paramref name="visual"/> is an ancestor of <paramref name="target"/>;
        /// otherwise false.
        /// </returns>
        public static bool IsVisualAncestorOf(this IVisual visual, IVisual target)
        {
            IVisual?current = target?.VisualParent;

            while (current != null)
            {
                if (current == visual)
                {
                    return(true);
                }

                current = current.VisualParent;
            }

            return(false);
        }
Пример #12
0
 public PointerEventArgs(RoutedEvent routedEvent,
                         IInteractive?source,
                         IPointer pointer,
                         IVisual?rootVisual, Point rootVisualPosition,
                         ulong timestamp,
                         PointerPointProperties properties,
                         KeyModifiers modifiers)
     : base(routedEvent)
 {
     Source              = source;
     _rootVisual         = rootVisual;
     _rootVisualPosition = rootVisualPosition;
     _properties         = properties;
     Pointer             = pointer;
     Timestamp           = timestamp;
     KeyModifiers        = modifiers;
 }
Пример #13
0
        /// <summary>
        /// Finds first ancestor of given type.
        /// </summary>
        /// <typeparam name="T">Ancestor type.</typeparam>
        /// <param name="visual">The visual.</param>
        /// <param name="includeSelf">If given visual should be included in search.</param>
        /// <returns>First ancestor of given type.</returns>
        public static T?FindAncestorOfType <T>(this IVisual visual, bool includeSelf = false) where T : class
        {
            if (visual is null)
            {
                return(null);
            }

            IVisual?parent = includeSelf ? visual : visual.VisualParent;

            while (parent != null)
            {
                if (parent is T result)
                {
                    return(result);
                }

                parent = parent.VisualParent;
            }

            return(null);
        }
        /// <summary>
        /// Gets a transform from an ancestor to a descendent.
        /// </summary>
        /// <param name="ancestor">The ancestor visual.</param>
        /// <param name="visual">The visual.</param>
        /// <returns>The transform.</returns>
        private static Matrix GetOffsetFrom(IVisual ancestor, IVisual visual)
        {
            var     result = Matrix.Identity;
            IVisual?v      = visual;

            while (v != ancestor)
            {
                // this should be calculated BEFORE renderTransform
                if (v.HasMirrorTransform)
                {
                    var mirrorMatrix = new Matrix(-1.0, 0.0, 0.0, 1.0, v.Bounds.Width, 0);
                    result *= mirrorMatrix;
                }

                if (v.RenderTransform?.Value != null)
                {
                    var origin          = v.RenderTransformOrigin.ToPixels(v.Bounds.Size);
                    var offset          = Matrix.CreateTranslation(origin);
                    var renderTransform = (-offset) * v.RenderTransform.Value * (offset);

                    result *= renderTransform;
                }

                var topLeft = v.Bounds.TopLeft;

                if (topLeft != default)
                {
                    result *= Matrix.CreateTranslation(topLeft);
                }

                v = v.VisualParent;

                if (v == null)
                {
                    throw new ArgumentException("'visual' is not a descendant of 'ancestor'.");
                }
            }

            return(result);
        }
Пример #15
0
            public bool MoveNext()
            {
                while (_nodeStack.Count > 0)
                {
                    (var wasVisited, var isRoot, IVisualNode node, Rect? clip) = _nodeStack.Pop();

                    if (wasVisited && isRoot)
                    {
                        break;
                    }

                    var children   = node.Children;
                    int childCount = children.Count;

                    if (childCount == 0 || wasVisited)
                    {
                        if ((wasVisited || FilterAndClip(node, ref clip)) &&
                            (node.Visual is ICustomHitTest custom ? custom.HitTest(_point) : node.HitTest(_point)))
                        {
                            _current = node.Visual;

                            return(true);
                        }
                    }
                    else if (FilterAndClip(node, ref clip))
                    {
                        _nodeStack.Push(new Entry(node, true, null));

                        for (var i = 0; i < childCount; i++)
                        {
                            _nodeStack.Push(new Entry(children[i], false, clip));
                        }
                    }
                }

                return(false);
            }
Пример #16
0
        public void ProcessRawEvent(RawInputEventArgs e)
        {
            if (e.Handled)
            {
                return;
            }

            var element = FocusedElement ?? e.Root;

            if (e is RawKeyEventArgs keyInput)
            {
                switch (keyInput.Type)
                {
                case RawKeyEventType.KeyDown:
                case RawKeyEventType.KeyUp:
                    var routedEvent = keyInput.Type == RawKeyEventType.KeyDown
                            ? InputElement.KeyDownEvent
                            : InputElement.KeyUpEvent;

                    KeyEventArgs ev = new KeyEventArgs
                    {
                        RoutedEvent  = routedEvent,
                        Device       = this,
                        Key          = keyInput.Key,
                        KeyModifiers = KeyModifiersUtils.ConvertToKey(keyInput.Modifiers),
                        Source       = element,
                    };

                    IVisual?currentHandler = element;
                    while (currentHandler != null && !ev.Handled && keyInput.Type == RawKeyEventType.KeyDown)
                    {
                        var bindings = (currentHandler as IInputElement)?.KeyBindings;
                        if (bindings != null)
                        {
                            KeyBinding[]? bindingsCopy = null;

                            // Create a copy of the KeyBindings list if there's a binding which matches the event.
                            // If we don't do this the foreach loop will throw an InvalidOperationException when the KeyBindings list is changed.
                            // This can happen when a new view is loaded which adds its own KeyBindings to the handler.
                            foreach (var binding in bindings)
                            {
                                if (binding.Gesture?.Matches(ev) == true)
                                {
                                    bindingsCopy = bindings.ToArray();
                                    break;
                                }
                            }

                            if (bindingsCopy is object)
                            {
                                foreach (var binding in bindingsCopy)
                                {
                                    if (ev.Handled)
                                    {
                                        break;
                                    }
                                    binding.TryHandle(ev);
                                }
                            }
                        }
                        currentHandler = currentHandler.VisualParent;
                    }

                    element.RaiseEvent(ev);
                    e.Handled = ev.Handled;
                    break;
                }
            }

            if (e is RawTextInputEventArgs text)
            {
                var ev = new TextInputEventArgs()
                {
                    Device      = this,
                    Text        = text.Text,
                    Source      = element,
                    RoutedEvent = InputElement.TextInputEvent
                };

                element.RaiseEvent(ev);
                e.Handled = ev.Handled;
            }
        }
Пример #17
0
        public void ProcessRawEvent(RawInputEventArgs e)
        {
            if (e.Handled)
            {
                return;
            }

            var element = FocusedElement ?? e.Root;

            if (e is RawKeyEventArgs keyInput)
            {
                switch (keyInput.Type)
                {
                case RawKeyEventType.KeyDown:
                case RawKeyEventType.KeyUp:
                    var routedEvent = keyInput.Type == RawKeyEventType.KeyDown
                            ? InputElement.KeyDownEvent
                            : InputElement.KeyUpEvent;

                    KeyEventArgs ev = new KeyEventArgs
                    {
                        RoutedEvent  = routedEvent,
                        Device       = this,
                        Key          = keyInput.Key,
                        KeyModifiers = KeyModifiersUtils.ConvertToKey(keyInput.Modifiers),
                        Source       = element,
                    };

                    IVisual?currentHandler = element;
                    while (currentHandler != null && !ev.Handled && keyInput.Type == RawKeyEventType.KeyDown)
                    {
                        var bindings = (currentHandler as IInputElement)?.KeyBindings;
                        if (bindings != null)
                        {
                            foreach (var binding in bindings)
                            {
                                if (ev.Handled)
                                {
                                    break;
                                }
                                binding.TryHandle(ev);
                            }
                        }
                        currentHandler = currentHandler.VisualParent;
                    }

                    element.RaiseEvent(ev);
                    e.Handled = ev.Handled;
                    break;
                }
            }

            if (e is RawTextInputEventArgs text)
            {
                var ev = new TextInputEventArgs()
                {
                    Device      = this,
                    Text        = text.Text,
                    Source      = element,
                    RoutedEvent = InputElement.TextInputEvent
                };

                element.RaiseEvent(ev);
                e.Handled = ev.Handled;
            }
        }
Пример #18
0
        /// <summary>
        /// Process pointer event.
        /// </summary>
        /// <param name="point">The pointer position.</param>
        /// <param name="delta">The mouse wheel delta.</param>
        /// <param name="eventType">The pointer event type.</param>
        /// <param name="dragAction">The input drag action.</param>
        /// <param name="activeDockControl">The active dock control.</param>
        /// <param name="dockControls">The dock controls.</param>
        public void Process(Point point, Vector delta, EventType eventType, DragAction dragAction, IVisual activeDockControl, IList <IDockControl> dockControls)
        {
            if (!(activeDockControl is IInputElement inputActiveDockControl))
            {
                return;
            }

            switch (eventType)
            {
            case EventType.Pressed:
            {
                var dragControl = DockHelpers.GetControl(inputActiveDockControl, point, DockProperties.IsDragAreaProperty);
                if (dragControl != null)
                {
                    bool isDragEnabled = dragControl.GetValue(DockProperties.IsDragEnabledProperty);
                    if (isDragEnabled != true)
                    {
                        break;
                    }
                    Debug.WriteLine($"Drag : {point} : {eventType} : {dragControl.Name} : {dragControl.GetType().Name} : {dragControl.DataContext?.GetType().Name}");
                    _dragControl       = dragControl;
                    _dropControl       = null;
                    _dragStartPoint    = point;
                    _pointerPressed    = true;
                    _doDragDrop        = false;
                    _targetPoint       = default;
                    _targetDockControl = null;
                    break;
                }
            }
            break;

            case EventType.Released:
            {
                if (_doDragDrop == true)
                {
                    if (_dropControl != null && _targetDockControl != null)
                    {
                        bool isDropEnabled = true;

                        if (_targetDockControl is IControl targetControl)
                        {
                            isDropEnabled = targetControl.GetValue(DockProperties.IsDropEnabledProperty);
                        }

                        if (isDropEnabled == true)
                        {
                            Drop(_targetPoint, dragAction, _targetDockControl);
                        }
                    }
                    else
                    {
                        // TODO: Create window.
                    }
                }
                Leave();
                _dragControl       = null;
                _dropControl       = null;
                _dragStartPoint    = default;
                _pointerPressed    = false;
                _doDragDrop        = false;
                _targetPoint       = default;
                _targetDockControl = null;
            }
            break;

            case EventType.Moved:
            {
                if (_pointerPressed == false)
                {
                    break;
                }

                if (_doDragDrop == false)
                {
                    Vector diff = _dragStartPoint - point;
                    bool   haveMinimumDragDistance = IsMinimumDragDistance(diff);
                    if (haveMinimumDragDistance == true)
                    {
                        if (_dragControl?.DataContext is IDockable targetDockable)
                        {
                            DockHelpers.ShowWindows(targetDockable);
                        }
                        _doDragDrop = true;
                    }
                }

                if (_doDragDrop == true)
                {
                    Point    targetPoint       = default;
                    IVisual? targetDockControl = null;
                    IControl?dropControl       = null;

                    foreach (var dockControl in dockControls)
                    {
                        if (dockControl is IInputElement inputDockControl && inputDockControl != inputActiveDockControl)
                        {
                            var screenPoint      = inputActiveDockControl.PointToScreen(point);
                            var dockControlPoint = (dockControl as IVisual)?.PointToClient(screenPoint);
                            if (dockControlPoint == null)
                            {
                                continue;
                            }
                            dropControl = DockHelpers.GetControl(inputDockControl, dockControlPoint.Value, DockProperties.IsDropAreaProperty);
                            if (dropControl != null)
                            {
                                targetPoint       = dockControlPoint.Value;
                                targetDockControl = inputDockControl;
                                break;
                            }
                        }
                    }

                    if (dropControl == null)
                    {
                        dropControl = DockHelpers.GetControl(inputActiveDockControl, point, DockProperties.IsDropAreaProperty);
                        if (dropControl != null)
                        {
                            targetPoint       = point;
                            targetDockControl = inputActiveDockControl;
                        }
                    }

                    if (dropControl != null && targetDockControl != null)
                    {
                        bool isDropEnabled = true;

                        if (targetDockControl is IControl targetControl)
                        {
                            isDropEnabled = targetControl.GetValue(DockProperties.IsDropEnabledProperty);
                        }

                        Debug.WriteLine($"Drop : {targetPoint} : {eventType} : {dropControl.Name} : {dropControl.GetType().Name} : {dropControl.DataContext?.GetType().Name}");

                        if (isDropEnabled)
                        {
                            if (_dropControl == dropControl)
                            {
                                _targetPoint       = targetPoint;
                                _targetDockControl = targetDockControl;
                                Over(targetPoint, dragAction, targetDockControl);
                            }
                            else
                            {
                                if (_dropControl != null)
                                {
                                    Leave();
                                    _dropControl = null;
                                }

                                _dropControl       = dropControl;
                                _targetPoint       = targetPoint;
                                _targetDockControl = targetDockControl;

                                Enter(targetPoint, dragAction, targetDockControl);
                            }
                        }
                        else
                        {
                            if (_dropControl != null)
                            {
                                Leave();
                                _dropControl       = null;
                                _targetPoint       = default;
                                _targetDockControl = null;
                            }
                        }
                    }
                    else
                    {
                        Leave();
                        _dropControl       = null;
                        _targetPoint       = default;
                        _targetDockControl = null;
                    }
                }
            }
            break;

            case EventType.Enter:
            {
            }
            break;

            case EventType.Leave:
            {
            }
            break;

            case EventType.CaptureLost:
            {
                Leave();
                _dragControl       = null;
                _dropControl       = null;
                _dragStartPoint    = default;
                _pointerPressed    = false;
                _doDragDrop        = false;
                _targetPoint       = default;
                _targetDockControl = null;
            }
            break;

            case EventType.WheelChanged:
            {
            }
            break;
            }
        }
Пример #19
0
 public Point GetPosition(IVisual?relativeTo) => lastPointerEventArgs.GetPosition(relativeTo);
Пример #20
0
 public int Compare(IVisual?x, IVisual?y) => (x?.ZIndex ?? 0).CompareTo(y?.ZIndex ?? 0);
Пример #21
0
 private Point GetPosition(Point pt, IVisual?relativeTo)
 {
     if (_rootVisual == null)
     {
         return(default);
Пример #22
0
 public Point GetPosition(IVisual?relativeTo)
 {
     if (_rootVisual == null)
     {
         return(default);
Пример #23
0
        protected sealed override void OnVisualParentChanged(IVisual?oldParent, IVisual?newParent)
        {
            LayoutHelper.InvalidateSelfAndChildrenMeasure(this);

            base.OnVisualParentChanged(oldParent, newParent);
        }