private bool AcceptsElementInternal(GraphElement element, ref int proposedIndex, int maxIndex)
 {
     return(element != null && !(element is Scope) &&
            !(element is StackNode) && !(element is TokenNode) &&
            (element.GetContainingScope() as Group) == null &&
            AcceptsElement(element, ref proposedIndex, maxIndex));
 }
Exemple #2
0
        private void AddElementInternal(GraphElement element)
        {
            if (element == null)
            {
                throw new ArgumentException("Cannot add null element");
            }

            if (containedElements.Contains(element))
            {
                throw new ArgumentException("The specified element is already contained in this scope.");
            }

            string reasonWhyNotAccepted = "Cannot add the specified element to this scope.";

            if (!AcceptsElement(element, ref reasonWhyNotAccepted))
            {
                throw new ArgumentException(reasonWhyNotAccepted);
            }

            // Removes the element from its current scope
            Scope currentScope = element.GetContainingScope();

            if (currentScope != null)
            {
                currentScope.RemoveElement(element);
            }

            m_ContainedElements.Add(element);

            element.SetContainingScope(this);

            // To update the scope geometry whenever the added element's geometry changes
            element.RegisterCallback <GeometryChangedEvent>(OnSubElementGeometryChanged);
            ScheduleUpdateGeometryFromContent();
        }
Exemple #3
0
 private bool AcceptsElementInternal(GraphElement element, ref int proposedIndex, int maxIndex)
 {
     // TODO: we probably need a "Stackable" capability
     return(element != null && !(element is Scope) &&
            !(element is StackNode) && !(element is TokenNode) &&
            !(element is Placemat) &&
            (element.GetContainingScope() as Group) == null &&
            AcceptsElement(element, ref proposedIndex, maxIndex));
 }
Exemple #4
0
        protected new void OnMouseMove(MouseMoveEvent e)
        {
            if (!m_Active)
            {
                return;
            }

            if (m_GraphView == null)
            {
                return;
            }

            var     ve         = (VisualElement)e.target;
            Vector2 gvMousePos = ve.ChangeCoordinatesTo(m_GraphView.contentContainer, e.localMousePosition);

            m_PanDiff = GetEffectivePanSpeed(gvMousePos);


            if (m_PanDiff != Vector3.zero)
            {
                m_PanSchedule.Resume();
            }
            else
            {
                m_PanSchedule.Pause();
            }

            // We need to monitor the mouse diff "by hand" because we stop positioning the graph elements once the
            // mouse has gone out.
            m_MouseDiff = m_originalMouse - e.mousePosition;

            var groupElementsDraggedOut = e.shiftKey ? new Dictionary <Group, List <GraphElement> >() : null;

            // Handle the selected element
            Rect selectedElementGeom = GetSelectedElementGeom();

            m_ShiftClicked = e.shiftKey;

            if (snapEnabled && !m_ShiftClicked)
            {
                ComputeSnappedRect(ref selectedElementGeom, m_XScale);
            }

            if (snapEnabled && m_ShiftClicked)
            {
                m_Snapper.ClearSnapLines();
            }

            foreach (KeyValuePair <GraphElement, OriginalPos> v in m_OriginalPos)
            {
                GraphElement ce = v.Key;

                // Protect against stale visual elements that have been deparented since the start of the manipulation
                if (ce.hierarchy.parent == null)
                {
                    continue;
                }

                if (!v.Value.dragStarted)
                {
                    // TODO Would probably be a good idea to batch stack items as we do for group ones.
                    var stackParent = ce.GetFirstAncestorOfType <StackNode>();
                    if (stackParent != null)
                    {
                        stackParent.OnStartDragging(ce);
                    }

                    if (groupElementsDraggedOut != null)
                    {
                        var groupParent = ce.GetContainingScope() as Group;
                        if (groupParent != null)
                        {
                            if (!groupElementsDraggedOut.ContainsKey(groupParent))
                            {
                                groupElementsDraggedOut[groupParent] = new List <GraphElement>();
                            }
                            groupElementsDraggedOut[groupParent].Add(ce);
                        }
                    }
                    v.Value.dragStarted = true;
                }

                SnapOrMoveElement(v, selectedElementGeom);
            }

            // Needed to ensure nodes can be dragged out of multiple groups all at once.
            if (groupElementsDraggedOut != null)
            {
                foreach (KeyValuePair <Group, List <GraphElement> > kvp in groupElementsDraggedOut)
                {
                    kvp.Key.OnStartDragging(e, kvp.Value);
                }
            }

            List <ISelectable> selection = m_GraphView.selection;

            // TODO: Replace with a temp drawing or something...maybe manipulator could fake position
            // all this to let operation know which element sits under cursor...or is there another way to draw stuff that is being dragged?

            IDropTarget dropTarget = GetDropTargetAt(e.mousePosition, selection.OfType <VisualElement>());

            if (m_PrevDropTarget != dropTarget)
            {
                if (m_PrevDropTarget != null)
                {
                    using (DragLeaveEvent eexit = DragLeaveEvent.GetPooled(e))
                    {
                        SendDragAndDropEvent(eexit, selection, m_PrevDropTarget, m_GraphView);
                    }
                }

                using (DragEnterEvent eenter = DragEnterEvent.GetPooled(e))
                {
                    SendDragAndDropEvent(eenter, selection, dropTarget, m_GraphView);
                }
            }

            using (DragUpdatedEvent eupdated = DragUpdatedEvent.GetPooled(e))
            {
                SendDragAndDropEvent(eupdated, selection, dropTarget, m_GraphView);
            }

            m_PrevDropTarget = dropTarget;

            m_Dragging = true;
            e.StopPropagation();
        }
        protected new void OnMouseDown(MouseDownEvent e)
        {
            if (m_Active)
            {
                e.StopImmediatePropagation();
                return;
            }

            if (CanStartManipulation(e))
            {
                m_GraphView = target as GraphView;

                if (m_GraphView == null)
                {
                    return;
                }

                selectedElement = null;

                // avoid starting a manipulation on a non movable object
                clickedElement = e.target as GraphElement;
                if (clickedElement == null)
                {
                    var ve = e.target as VisualElement;
                    clickedElement = ve.GetFirstAncestorOfType <GraphElement>();
                    if (clickedElement == null)
                    {
                        return;
                    }
                }

                // Only start manipulating if the clicked element is movable, selected and that the mouse is in its clickable region (it must be deselected otherwise).
                if (!clickedElement.IsMovable() || !clickedElement.HitTest(clickedElement.WorldToLocal(e.mousePosition)))
                {
                    return;
                }

                // If we hit this, this likely because the element has just been unselected
                // It is important for this manipulator to receive the event so the previous one did not stop it
                // but we shouldn't let it propagate to other manipulators to avoid a re-selection
                if (!m_GraphView.selection.Contains(clickedElement))
                {
                    e.StopImmediatePropagation();
                    return;
                }

                selectedElement = clickedElement;

                m_OriginalPos = new Dictionary <GraphElement, OriginalPos>();

                foreach (ISelectable s in m_GraphView.selection)
                {
                    GraphElement ce = s as GraphElement;
                    if (ce == null || !ce.IsMovable())
                    {
                        continue;
                    }

                    StackNode stackNode = null;
                    if (ce.parent is StackNode)
                    {
                        stackNode = ce.parent as StackNode;

                        if (stackNode.IsSelected(m_GraphView))
                        {
                            continue;
                        }
                    }

                    Rect geometry = ce.GetPosition();
                    Rect geometryInContentViewSpace = ce.hierarchy.parent.ChangeCoordinatesTo(m_GraphView.contentViewContainer, geometry);
                    m_OriginalPos[ce] = new OriginalPos
                    {
                        pos        = geometryInContentViewSpace,
                        scope      = ce.GetContainingScope(),
                        stack      = stackNode,
                        stackIndex = stackNode != null?stackNode.IndexOf(ce) : -1
                    };
                }

                m_originalMouse = e.mousePosition;
                m_ItemPanDiff   = Vector3.zero;

                if (m_PanSchedule == null)
                {
                    m_PanSchedule = m_GraphView.schedule.Execute(Pan).Every(k_PanInterval).StartingIn(k_PanInterval);
                    m_PanSchedule.Pause();
                }

                m_Active = true;
                target.CaptureMouse(); // We want to receive events even when mouse is not over ourself.
                e.StopImmediatePropagation();
            }
        }