internal void SetPanel(BaseVisualElementPanel p)
        {
            if (panel == p)
            {
                return;
            }

            //We now gather all Elements in order to dispatch events in an efficient manner
            List <VisualElement> elements = VisualElementListPool.Get();

            try
            {
                elements.Add(this);
                GatherAllChildren(elements);

                EventDispatcher.Gate?pDispatcherGate = null;
                if (p?.dispatcher != null)
                {
                    pDispatcherGate = new EventDispatcher.Gate(p.dispatcher);
                }

                EventDispatcher.Gate?panelDispatcherGate = null;
                if (panel?.dispatcher != null && panel.dispatcher != p?.dispatcher)
                {
                    panelDispatcherGate = new EventDispatcher.Gate(panel.dispatcher);
                }

                using (pDispatcherGate)
                    using (panelDispatcherGate)
                    {
                        foreach (var e in elements)
                        {
                            e.ChangePanel(p);
                        }
                    }
            }
            finally
            {
                VisualElementListPool.Release(elements);
            }
        }
        private static bool DoDispatch(BaseVisualElementPanel panel)
        {
            bool result;

            if (UIElementsUtility.s_EventInstance.type == EventType.Repaint)
            {
                panel.Repaint(UIElementsUtility.s_EventInstance);
                result = (panel.IMGUIContainersCount > 0);
            }
            else
            {
                panel.ValidateLayout();
                EventPropagation eventPropagation = UIElementsUtility.s_EventDispatcher.DispatchEvent(UIElementsUtility.s_EventInstance, panel);
                if (eventPropagation == EventPropagation.Stop)
                {
                    panel.visualTree.Dirty(ChangeType.Repaint);
                }
                result = (eventPropagation == EventPropagation.Stop);
            }
            return(result);
        }
Exemple #3
0
        void ChangePanel(BaseVisualElementPanel p)
        {
            if (panel == p)
            {
                return;
            }

            if (panel != null)
            {
                using (var e = DetachFromPanelEvent.GetPooled(panel, p))
                {
                    e.target = this;
                    elementPanel.SendEvent(e, DispatchMode.Immediate);
                }
            }

            IPanel prevPanel = panel;

            elementPanel = p;

            if (panel != null)
            {
                using (var e = AttachToPanelEvent.GetPooled(prevPanel, p))
                {
                    e.target = this;
                    elementPanel.SendEvent(e, DispatchMode.Immediate);
                }
            }

            // styles are dependent on topology
            IncrementVersion(VersionChangeType.StyleSheet | VersionChangeType.Layout | VersionChangeType.Transform);

            // persistent data key may have changed or needs initialization
            if (!string.IsNullOrEmpty(persistenceKey))
            {
                IncrementVersion(VersionChangeType.PersistentData);
            }
        }
        internal virtual void ChangePanel(BaseVisualElementPanel p)
        {
            if (panel == p)
            {
                return;
            }

            if (panel != null)
            {
                using (var e = DetachFromPanelEvent.GetPooled())
                {
                    e.target = this;
                    UIElementsUtility.eventDispatcher.DispatchEvent(e, panel);
                }
            }

            elementPanel = p;

            if (panel != null)
            {
                using (var e = AttachToPanelEvent.GetPooled())
                {
                    e.target = this;
                    UIElementsUtility.eventDispatcher.DispatchEvent(e, panel);
                }
            }

            Dirty(ChangeType.Styles);

            if (m_Children != null && m_Children.Count > 0)
            {
                for (var index = 0; index < m_Children.Count; index++)
                {
                    var child = m_Children[index];
                    child.ChangePanel(p);
                }
            }
        }
Exemple #5
0
        public EventPropagation DispatchEvent(Event e, BaseVisualElementPanel panel)
        {
            EventPropagation result;

            if (e.type == EventType.Repaint)
            {
                Debug.Log("Repaint should be handled by Panel before Dispatcher");
                result = EventPropagation.Continue;
            }
            else
            {
                bool flag = false;
                if (panel.panelDebug != null && panel.panelDebug.enabled && panel.panelDebug.interceptEvents != null && panel.panelDebug.interceptEvents(e))
                {
                    result = EventPropagation.Stop;
                }
                else
                {
                    if (this.capture != null && this.capture.panel == null)
                    {
                        Debug.Log(string.Format("Capture has no panel, forcing removal (capture={0} eventType={1})", this.capture, e.type));
                        this.RemoveCapture();
                    }
                    if (this.capture != null)
                    {
                        if (this.capture.panel.contextType != panel.contextType)
                        {
                            result = EventPropagation.Continue;
                            return(result);
                        }
                        VisualElement visualElement = this.capture as VisualElement;
                        if (visualElement != null)
                        {
                            e.mousePosition = visualElement.GlobalToBound(e.mousePosition);
                        }
                        else
                        {
                            IManipulator manipulator = this.capture as IManipulator;
                            if (manipulator != null)
                            {
                                e.mousePosition = manipulator.target.GlobalToBound(e.mousePosition);
                            }
                        }
                        flag = true;
                        if (this.capture.HandleEvent(e, this.capture as VisualElement) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                    }
                    if (e.isKey)
                    {
                        flag = true;
                        if (panel.focusedElement != null)
                        {
                            if (this.PropagateEvent(panel.focusedElement, e) == EventPropagation.Stop)
                            {
                                result = EventPropagation.Stop;
                                return(result);
                            }
                        }
                        else if (this.SendEventToIMGUIContainers(panel.visualTree, e, panel.focusedElement) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                    }
                    else if (e.isMouse || e.isScrollWheel || e.type == EventType.DragUpdated || e.type == EventType.DragPerform || e.type == EventType.DragExited)
                    {
                        if (e.type == EventType.MouseLeaveWindow)
                        {
                            this.elementUnderMouse = null;
                        }
                        else
                        {
                            this.elementUnderMouse = panel.Pick(e.mousePosition);
                        }
                        if (e.type == EventType.MouseDown && this.elementUnderMouse != null && this.elementUnderMouse.enabled)
                        {
                            this.SetFocusedElement(panel, this.elementUnderMouse);
                        }
                        if (this.elementUnderMouse != null)
                        {
                            flag = true;
                            if (this.PropagateEvent(this.elementUnderMouse, e) == EventPropagation.Stop)
                            {
                                result = EventPropagation.Stop;
                                return(result);
                            }
                        }
                        if (e.type == EventType.MouseEnterWindow || e.type == EventType.MouseLeaveWindow)
                        {
                            flag = true;
                            if (this.SendEventToIMGUIContainers(panel.visualTree, e, null) == EventPropagation.Stop)
                            {
                                result = EventPropagation.Stop;
                                return(result);
                            }
                        }
                    }
                    if (e.type == EventType.ExecuteCommand || e.type == EventType.ValidateCommand)
                    {
                        flag = true;
                        if (panel.focusedElement != null && this.PropagateEvent(panel.focusedElement, e) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                        if (this.SendEventToIMGUIContainers(panel.visualTree, e, panel.focusedElement) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                    }
                    if (e.type == EventType.Used)
                    {
                        flag = true;
                        if (this.SendEventToIMGUIContainers(panel.visualTree, e, null) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                    }
                    if (!flag)
                    {
                        if (this.SendEventToIMGUIContainers(panel.visualTree, e, null) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                    }
                    result = EventPropagation.Continue;
                }
            }
            return(result);
        }
        void ProcessEvent(EventBase evt, IPanel panel)
        {
            using (new Gate(this))
            {
                evt.PreDispatch();

                var panelDebug = (panel as BaseVisualElementPanel)?.panelDebug;
                if (panelDebug != null && panelDebug.showOverlay)
                {
                    if (panelDebug.InterceptEvents(evt.imguiEvent))
                    {
                        evt.StopPropagation();
                        evt.PostDispatch();
                        return;
                    }
                }

                IMouseEvent         mouseEvent         = evt as IMouseEvent;
                IMouseEventInternal mouseEventInternal = evt as IMouseEventInternal;
                if (mouseEvent != null && mouseEventInternal != null && mouseEventInternal.hasUnderlyingPhysicalEvent)
                {
                    m_LastMousePositionPanel = panel;
                    m_LastMousePosition      = mouseEvent.mousePosition;
                }

                bool eventHandled = false;

                // Release mouse capture if capture element is not in a panel.
                VisualElement captureVE = MouseCaptureController.mouseCapture as VisualElement;
                if (evt.GetEventTypeId() != MouseCaptureOutEvent.TypeId() && captureVE != null && captureVE.panel == null)
                {
                    Event e = evt.imguiEvent;
                    Debug.Log(String.Format("Capture has no panel, forcing removal (capture={0} eventType={1})", MouseCaptureController.mouseCapture, e != null ? e.type.ToString() : "null"));
                    MouseCaptureController.ReleaseMouse();
                }

                // Send all IMGUI events (for backward compatibility) and MouseEvents with null target (because thats what we want to do in the new system)
                // to the capture, if there is one. Note that events coming from IMGUI have their target set to null.
                bool sendEventToMouseCapture = false;
                bool mouseEventWasCaptured   = false;
                if (MouseCaptureController.mouseCapture != null)
                {
                    if (evt.imguiEvent != null && evt.target == null)
                    {
                        // Non exclusive processing by capturing element.
                        sendEventToMouseCapture = true;
                        mouseEventWasCaptured   = false;
                    }

                    if (mouseEvent != null && (evt.target == null || evt.target == MouseCaptureController.mouseCapture))
                    {
                        // Exclusive processing by capturing element.
                        sendEventToMouseCapture = true;
                        mouseEventWasCaptured   = true;
                    }

                    if (panel != null)
                    {
                        if (captureVE != null && captureVE.panel.contextType != panel.contextType)
                        {
                            // Capturing element is not in the right context. Ignore it.
                            sendEventToMouseCapture = false;
                            mouseEventWasCaptured   = false;
                        }
                    }

                    if (evt.GetEventTypeId() == WheelEvent.TypeId())
                    {
                        sendEventToMouseCapture = false;
                        mouseEventWasCaptured   = false;
                    }
                }

                evt.skipElement = null;

                if (sendEventToMouseCapture)
                {
                    BaseVisualElementPanel basePanel = panel as BaseVisualElementPanel;

                    if (mouseEvent != null && basePanel != null)
                    {
                        VisualElement currentTopElementUnderMouse = basePanel.topElementUnderMouse;

                        if (evt.target == null)
                        {
                            basePanel.topElementUnderMouse = basePanel.Pick(mouseEvent.mousePosition);
                        }

                        DispatchEnterLeaveEvents(currentTopElementUnderMouse, basePanel.topElementUnderMouse, evt);
                    }

                    IEventHandler originalCaptureElement = MouseCaptureController.mouseCapture;

                    eventHandled = true;

                    evt.dispatch         = true;
                    evt.target           = MouseCaptureController.mouseCapture;
                    evt.currentTarget    = MouseCaptureController.mouseCapture;
                    evt.propagationPhase = PropagationPhase.AtTarget;
                    MouseCaptureController.mouseCapture.HandleEvent(evt);

                    // Do further processing with a target computed the usual way.
                    // However, if mouseEventWasCaptured, the only thing remaining to do is ExecuteDefaultAction,
                    // which whould be done with mouseCapture as the target.
                    if (!mouseEventWasCaptured)
                    {
                        evt.target = null;
                    }

                    evt.currentTarget    = null;
                    evt.propagationPhase = PropagationPhase.None;
                    evt.dispatch         = false;

                    // Do not call HandleEvent again for this element.
                    evt.skipElement = originalCaptureElement;
                }

                if (!mouseEventWasCaptured && !evt.isPropagationStopped)
                {
                    if (evt is IKeyboardEvent && panel != null)
                    {
                        eventHandled = true;
                        if (panel.focusController.focusedElement != null)
                        {
                            IMGUIContainer imguiContainer = panel.focusController.focusedElement as IMGUIContainer;

                            if (imguiContainer != null)
                            {
                                // THINK ABOUT THIS PF: shoudln't we allow for the TrickleDown dispatch phase?
                                if (imguiContainer != evt.skipElement && imguiContainer.HandleIMGUIEvent(evt.imguiEvent))
                                {
                                    evt.StopPropagation();
                                    evt.PreventDefault();
                                }
                            }
                            else
                            {
                                evt.target = panel.focusController.focusedElement;
                                PropagateEvent(evt);
                            }
                        }
                        else
                        {
                            evt.target = panel.visualTree;
                            PropagateEvent(evt);

                            if (!evt.isPropagationStopped)
                            {
                                PropagateToIMGUIContainer(panel.visualTree, evt);
                            }
                        }
                    }
                    else if (mouseEvent != null)
                    {
                        // FIXME: we should not change hover state when capture is true.
                        // However, when doing drag and drop, drop target should be highlighted.

                        // TODO when EditorWindow is docked MouseLeaveWindow is not always sent
                        // this is a problem in itself but it could leave some elements as "hover"

                        BaseVisualElementPanel basePanel = panel as BaseVisualElementPanel;

                        if (basePanel != null && evt.GetEventTypeId() == MouseLeaveWindowEvent.TypeId())
                        {
                            VisualElement currentTopElementUnderMouse = basePanel.topElementUnderMouse;
                            basePanel.topElementUnderMouse = null;
                            DispatchMouseEnterMouseLeave(currentTopElementUnderMouse, basePanel.topElementUnderMouse, mouseEvent);
                            DispatchMouseOverMouseOut(currentTopElementUnderMouse, basePanel.topElementUnderMouse, mouseEvent);
                        }
                        else if (basePanel != null && evt.GetEventTypeId() == DragExitedEvent.TypeId())
                        {
                            VisualElement currentTopElementUnderMouse = basePanel.topElementUnderMouse;
                            basePanel.topElementUnderMouse = null;
                            DispatchDragEnterDragLeave(currentTopElementUnderMouse, basePanel.topElementUnderMouse, mouseEvent);
                        }
                        // update element under mouse and fire necessary events
                        else
                        {
                            VisualElement currentTopElementUnderMouse = null;
                            if (evt.target == null && basePanel != null)
                            {
                                currentTopElementUnderMouse    = basePanel.topElementUnderMouse;
                                basePanel.topElementUnderMouse = panel.Pick(mouseEvent.mousePosition);
                                evt.target = basePanel.topElementUnderMouse;
                            }

                            if (evt.target != null)
                            {
                                eventHandled = true;
                                PropagateEvent(evt);
                            }

                            if (basePanel != null)
                            {
                                DispatchEnterLeaveEvents(currentTopElementUnderMouse, basePanel.topElementUnderMouse, evt);
                            }
                        }
                    }
                    else if (panel != null && evt is ICommandEvent)
                    {
                        IMGUIContainer imguiContainer = panel.focusController.focusedElement as IMGUIContainer;

                        eventHandled = true;
                        if (imguiContainer != null)
                        {
                            if (imguiContainer != evt.skipElement && imguiContainer.HandleIMGUIEvent(evt.imguiEvent))
                            {
                                evt.StopPropagation();
                                evt.PreventDefault();
                            }
                        }
                        else if (panel.focusController.focusedElement != null)
                        {
                            evt.target = panel.focusController.focusedElement;
                            PropagateEvent(evt);
                        }
                        else
                        {
                            PropagateToIMGUIContainer(panel.visualTree, evt);
                        }
                    }
                    else if (evt is IPropagatableEvent ||
                             evt is IFocusEvent ||
                             evt is IChangeEvent ||
                             evt.GetEventTypeId() == InputEvent.TypeId() ||
                             evt.GetEventTypeId() == GeometryChangedEvent.TypeId())
                    {
                        Debug.Assert(evt.target != null);
                        eventHandled = true;
                        PropagateEvent(evt);
                    }
                }

                if (!mouseEventWasCaptured && !evt.isPropagationStopped && panel != null)
                {
                    Event e = evt.imguiEvent;
                    if (!eventHandled || (e != null && e.type == EventType.Used) ||
                        evt.GetEventTypeId() == MouseEnterWindowEvent.TypeId() ||
                        evt.GetEventTypeId() == MouseLeaveWindowEvent.TypeId())
                    {
                        PropagateToIMGUIContainer(panel.visualTree, evt);
                    }
                }

                if (evt.target == null && panel != null)
                {
                    evt.target = panel.visualTree;
                }

                ExecuteDefaultAction(evt);

                evt.PostDispatch();
            }
        }