예제 #1
0
        protected void SetAnchorCursor()
        {
            BaseController controller = serviceManager.Get <IFlowSharpCanvasService>().ActiveController;
            ShapeAnchor    anchor     = HoverShape.GetAnchors().FirstOrDefault(a => a.Near(CurrentMousePosition));

            // Hover shape could have changed as we move from a shape to a connector's anchor.
            if (anchor != null)
            {
                controller.Canvas.Cursor = anchor.Cursor;
            }
        }
예제 #2
0
        protected void DragAnchor()
        {
            BaseController controller     = serviceManager.Get <IFlowSharpCanvasService>().ActiveController;
            Point          delta          = CurrentMousePosition.Delta(LastMousePosition);
            GraphicElement hoverShape     = HoverShape;
            ShapeAnchor    selectedAnchor = SelectedAnchor;

            if (!controller.SnapController.SnapCheck(selectedAnchor.Type, delta, (snapDelta) => hoverShape.UpdateSize(selectedAnchor, snapDelta)))
            {
                hoverShape.UpdateSize(selectedAnchor, delta);
                controller.SnapController.UpdateRunningDelta(delta);
            }
        }
예제 #3
0
        public virtual void InitializeBehavior()
        {
            // Any mouse down fires the MouseClick event for external handling.
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.FireMouseClickEvent,
                MouseEvent = MouseEvent.MouseDown,
                Condition  = () => true,
                Action     = (mouseEventArgs) =>
                {
                    // So Ctrl+V paste works, as keystroke is intercepted only when canvas panel has focus.
                    MouseClick.Fire(this, mouseEventArgs);
                }
            });

            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.CanvasFocus,
                MouseEvent = MouseEvent.MouseDown,
                // Condition = () => true,
                Condition = () => !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition) &&
                            !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsChildShapeSelectable(CurrentMousePosition) &&
                            !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsMultiSelect(),
                Action = (_) =>
                {
                    // So Ctrl+V paste works, as keystroke is intercepted only when canvas panel has focus.
                    BaseController canvasController = serviceManager.Get <IFlowSharpCanvasService>().ActiveController;
                    canvasController.Canvas.Focus();
                    serviceManager.Get <IFlowSharpPropertyGridService>().ShowProperties(new CanvasProperties(canvasController.Canvas));
                },
                Else = () =>
                {
                    // So Ctrl+V paste works, as keystroke is intercepted only when canvas panel has focus.
                    BaseController canvasController = serviceManager.Get <IFlowSharpCanvasService>().ActiveController;
                    canvasController.Canvas.Focus();
                }
            });

            // DRAG SURFACE ROUTES:

            // Start drag surface:
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.StartDragSurface,
                MouseEvent = MouseEvent.MouseDown,
                Condition  = () => !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition) && CurrentButtons == MouseButtons.Left,
                Action     = (_) =>
                {
                    DraggingSurface         = true;
                    DraggingSurfaceOccurred = false;
                }
            });

            // End drag surface with no dragging, which deselects all selected shapes
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.EndDragSurfaceWithDeselect,
                MouseEvent = MouseEvent.MouseUp,
                Condition  = () => DraggingSurface && !DraggingSurfaceOccurred,
                Action     = (_) =>
                {
                    DraggingSurface                      = false;
                    BaseController controller            = serviceManager.Get <IFlowSharpCanvasService>().ActiveController;
                    controller.Canvas.Cursor             = Cursors.Arrow;
                    List <GraphicElement> selectedShapes = controller.SelectedElements.ToList();

                    if (selectedShapes.Count != 0)
                    {
                        controller.UndoStack.UndoRedo("Canvas",
                                                      () =>
                        {
                            controller.DeselectCurrentSelectedElements();
                        },
                                                      () =>
                        {
                            controller.DeselectCurrentSelectedElements();
                            controller.SelectElements(selectedShapes);
                        });
                    }
                }
            });

            // End drag surface when dragging occurred, selected shapes stay selected.
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.EndDragSurface,
                MouseEvent = MouseEvent.MouseUp,
                Condition  = () => DraggingSurface && DraggingSurfaceOccurred,
                Action     = (_) =>
                {
                    DraggingSurface           = false;
                    DraggingSurfaceOccurred   = false;
                    BaseController controller = serviceManager.Get <IFlowSharpCanvasService>().ActiveController;
                    controller.Canvas.Cursor  = Cursors.Arrow;
                }
            });

            // Drag surface:
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.DragSurface,
                MouseEvent = MouseEvent.MouseMove,
                Condition  = () => DraggingSurface,
                Action     = (_) =>
                {
                    DraggingSurfaceOccurred = true;
                    DragCanvas();
                }
            });

            // SHAPE DRAGGING ROUTES:

            // Start shape drag:
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.StartShapeDrag,
                MouseEvent = MouseEvent.MouseDown,
                Condition  = () => serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition) &&
                             CurrentButtons == MouseButtons.Left &&
                             serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition).GetAnchors().FirstOrDefault(a => a.Near(CurrentMousePosition)) == null &&
                             !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsChildShapeSelectable(CurrentMousePosition), // can't drag a grouped shape
                Action = (_) =>
                {
                    BaseController controller = serviceManager.Get <IFlowSharpCanvasService>().ActiveController;
                    controller.SnapController.Reset();
                    controller.DeselectGroupedElements();
                    DraggingShapes          = true;
                    startedDraggingShapesAt = CurrentMousePosition;
                },
            });

            // Start anchor drag:
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.StartAnchorDrag,
                MouseEvent = MouseEvent.MouseDown,
                Condition  = () => serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition) &&
                             CurrentButtons == MouseButtons.Left &&
                             serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition).GetAnchors().FirstOrDefault(a => a.Near(CurrentMousePosition)) != null,
                Action = (_) =>
                {
                    BaseController controller = serviceManager.Get <IFlowSharpCanvasService>().ActiveController;
                    controller.SnapController.Reset();
                    DraggingAnchor = true;
                    HoverShape     = serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition);
                    SelectedAnchor = HoverShape.GetAnchors().First(a => a.Near(CurrentMousePosition));
                },
            });

            // End shape dragging:
            router.Add(new MouseRouter()
            {
                // TODO: Similar to EndAnchorDrag and Toolbox.OnMouseUp
                RouteName  = RouteName.EndShapeDrag,
                MouseEvent = MouseEvent.MouseUp,
                Condition  = () => DraggingShapes,
                Action     = (_) =>
                {
                    BaseController controller = serviceManager.Get <IFlowSharpCanvasService>().ActiveController;
                    controller.SnapController.DoUndoSnapActions(controller.UndoStack);

                    if (controller.SnapController.RunningDelta != Point.Empty)
                    {
                        Point delta = controller.SnapController.RunningDelta;     // for closure

                        controller.UndoStack.UndoRedo("ShapeMove",
                                                      () => { }, // Our "do" action is actually nothing, since all the "doing" has been done.
                                                      () =>      // Undo
                        {
                            controller.DragSelectedElements(delta.ReverseDirection());
                        },
                                                      true, // We finish the move.
                                                      () => // Redo
                        {
                            controller.DragSelectedElements(delta);
                        });
                    }

                    controller.SnapController.HideConnectionPoints();
                    controller.SnapController.Reset();
                    DraggingShapes = false;
                    // DraggingOccurred = false;        / Will be cleared by RemoveSelectedShape but this is order dependent!  TODO: Fix this somehow! :)
                    DraggingAnchor           = false;
                    SelectedAnchor           = null;
                    controller.Canvas.Cursor = Cursors.Arrow;
                }
            });

            // End anchor dragging:
            router.Add(new MouseRouter()
            {
                // TODO: Similar to EndShapeDrag and Toolbox.OnMouseUp
                RouteName  = RouteName.EndAnchorDrag,
                MouseEvent = MouseEvent.MouseUp,
                Condition  = () => DraggingAnchor,
                Action     = (_) =>
                {
                    BaseController controller = serviceManager.Get <IFlowSharpCanvasService>().ActiveController;
                    controller.SnapController.DoUndoSnapActions(controller.UndoStack);

                    if (controller.SnapController.RunningDelta != Point.Empty)
                    {
                        Point delta = controller.SnapController.RunningDelta;     // for closure
                        GraphicElement hoverShape  = HoverShape;
                        ShapeAnchor selectedAnchor = SelectedAnchor;

                        controller.UndoStack.UndoRedo("AnchorMove",
                                                      () => { }, // Our "do" action is actually nothing, since all the "doing" has been done.
                                                      () =>      // Undo
                        {
                            hoverShape.UpdateSize(selectedAnchor, delta.ReverseDirection());
                        },
                                                      true, // We finish the anchor drag.
                                                      () => // Redo
                        {
                            hoverShape.UpdateSize(selectedAnchor, delta);
                        });
                    }

                    controller.SnapController.HideConnectionPoints();
                    controller.SnapController.Reset();
                    DraggingShapes = false;
                    // DraggingOccurred = false;        / Will be cleared by RemoveSelectedShape but this is order dependent!  TODO: Fix this somehow! :)
                    DraggingAnchor           = false;
                    SelectedAnchor           = null;
                    controller.Canvas.Cursor = Cursors.Arrow;
                }
            });

            // Drag shapes:
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.DragShapes,
                MouseEvent = MouseEvent.MouseMove,
                Condition  = () => DraggingShapes &&
                             HoverShape != null &&
                             HoverShape.GetAnchors().FirstOrDefault(a => a.Near(CurrentMousePosition)) == null,
                Action = (_) =>
                {
                    DragShapes();
                    DraggingOccurred = true;
                },
            });

            // Drag anchor:
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.DragAnchor,
                MouseEvent = MouseEvent.MouseMove,
                Condition  = () => HoverShape != null && DraggingAnchor,
                Action     = (_) =>
                {
                    DragAnchor();
                },
            });

            // HOVER ROUTES

            // Show anchors when hovering over a shape
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.HoverOverShape,
                MouseEvent = MouseEvent.MouseMove,
                Condition  = () => !DraggingSurface && !DraggingShapes && !SelectingShapes && HoverShape == null &&
                             CurrentButtons == MouseButtons.None &&
                             serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition) &&
                             serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition).Parent == null, // no anchors for grouped children.
                Action = (_) => ShowAnchors(),
            });

            // Change anchors when hover shape changes
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.ShowAnchors,
                MouseEvent = MouseEvent.MouseMove,
                Condition  = () => !DraggingSurface && !DraggingShapes && !SelectingShapes && HoverShape != null &&
                             CurrentButtons == MouseButtons.None &&
                             serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition) &&
                             HoverShape != serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition) &&
                             serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition).Parent == null, // no anchors for grouped children.
                Action = (_) => ChangeAnchors(),
            });

            // Hide anchors when not hovering over a shape
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.HideAnchors,
                MouseEvent = MouseEvent.MouseMove,
                Condition  = () => !DraggingSurface && !DraggingShapes && !SelectingShapes && HoverShape != null &&
                             CurrentButtons == MouseButtons.None &&
                             !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition),
                Action = (_) => HideAnchors(),
            });

            // Show cursor when hovering over an anchor
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.ShowAnchorCursor,
                MouseEvent = MouseEvent.MouseMove,
                Condition  = () => !DraggingSurface && !DraggingShapes && !SelectingShapes && !DraggingAnchor && HoverShape != null &&
                             HoverShape.GetAnchors().FirstOrDefault(a => a.Near(CurrentMousePosition)) != null,
                Action = (_) => SetAnchorCursor(),
            });

            // Clear cursor when hovering over an anchor
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.ClearAnchorCursor,
                MouseEvent = MouseEvent.MouseMove,
                Condition  = () => !DraggingSurface && !DraggingShapes && !SelectingShapes && HoverShape != null &&
                             HoverShape.GetAnchors().FirstOrDefault(a => a.Near(CurrentMousePosition)) == null,
                Action = (_) => ClearAnchorCursor(),
            });

            // SHAPE SELECTION

            // Select a shape
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.SelectSingleShapeMouseDown,
                MouseEvent = MouseEvent.MouseDown,
                Condition  = () => serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition) &&
                             !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsChildShapeSelectable(CurrentMousePosition) &&
                             !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsMultiSelect() &&
                             !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.SelectedElements.Contains(serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition)),
                Action = (_) => SelectSingleRootShape()
            });

            // Select a single grouped shape:
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.SelectSingleGroupedShape,
                MouseEvent = MouseEvent.MouseDown,
                Condition  = () => serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsChildShapeSelectable(CurrentMousePosition) &&
                             !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsMultiSelect() &&
                             !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.SelectedElements.Contains(serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetChildShapeAt(CurrentMousePosition)),
                Action = (_) => SelectSingleChildShape()
            });

            // Select a single shape
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.SelectSingleShapeMouseUp,
                MouseEvent = MouseEvent.MouseUp,
                Condition  = () => serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition) &&
                             !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsChildShapeSelectable(CurrentMousePosition) && // Don't deselect grouped shape on mouse up (as in, don't select groupbox)
                             !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsMultiSelect() &&
                             !DraggingOccurred && !DraggingSelectionBox,
                Action = (_) => SelectSingleRootShape()
            });

            // Add another shape to selection list
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.AddSelectedShape,
                MouseEvent = MouseEvent.MouseUp,
                Condition  = () => serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition) &&
                             serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsMultiSelect() && !DraggingSelectionBox &&
                             !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.SelectedElements.Contains(serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition)),
                Action = (_) => AddShapeToSelectionList(),
            });

            // Remove shape from selection list
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.RemoveSelectedShape,
                MouseEvent = MouseEvent.MouseUp,
                Condition  = () => serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition) &&
                             serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsMultiSelect() && !DraggingSelectionBox &&
                             // TODO: Would nice to avoid multiple GetShapeAt calls when processing conditions.  And not just here.
                             serviceManager.Get <IFlowSharpCanvasService>().ActiveController.SelectedElements.Contains(serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition)) &&
                             !justAddedShape.Contains(serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition)) &&
                             !DraggingOccurred,
                Action = (_) => RemoveShapeFromSelectionList(),
                Else   = () =>
                {
                    justAddedShape.Clear();
                    DraggingOccurred = false;
                },
                Debug = () =>
                {
                    Trace.WriteLine("Route:IsRootShapeSelectable: " + serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition));
                    Trace.WriteLine("Route:IsMultiSelect: " + serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsMultiSelect());
                    Trace.WriteLine("Route:!DraggingSelectionBox: " + !DraggingSelectionBox);
                    Trace.WriteLine("Route:SelectedElements.ContainsShape: " + serviceManager.Get <IFlowSharpCanvasService>().ActiveController.SelectedElements.Contains(serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition)));
                    Trace.WriteLine("Route:!justShapeAdded: " + !justAddedShape.Contains(serviceManager.Get <IFlowSharpCanvasService>().ActiveController.GetRootShapeAt(CurrentMousePosition)));
                    Trace.WriteLine("Route:!DraggingOccurred: " + !DraggingOccurred);
                }
            });

            // SELECTION BOX

            // Start selection box
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.StartDragSelectionBox,
                MouseEvent = MouseEvent.MouseDown,
                Condition  = () => !serviceManager.Get <IFlowSharpCanvasService>().ActiveController.IsRootShapeSelectable(CurrentMousePosition) && CurrentButtons == MouseButtons.Right,
                Action     = (_) =>
                {
                    DraggingSelectionBox   = true;
                    StartSelectionPosition = CurrentMousePosition;
                    CreateSelectionBox();
                },
            });

            // End selection box
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.EndDragSelectionBox,
                MouseEvent = MouseEvent.MouseUp,
                Condition  = () => DraggingSelectionBox,
                Action     = (_) =>
                {
                    DraggingSelectionBox = false;
                    SelectShapesInSelectionBox();
                }
            });

            // Drag selection box
            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.DragSelectionBox,
                MouseEvent = MouseEvent.MouseMove,
                Condition  = () => DraggingSelectionBox,
                Action     = (_) => DragSelectionBox(),
            });

            // Edit Text

            router.Add(new MouseRouter()
            {
                RouteName  = RouteName.EditShapeText,
                MouseEvent = MouseEvent.MouseDoubleClick,
                Condition  = () => true,
                Action     = (_) =>
                {
                    if (doubleClickCounter == 0)
                    {
                        ++doubleClickCounter;
                        serviceManager.Get <IFlowSharpEditService>().EditText();

                        // Reset counter after 1/2 second, so the second double click is ignored.
                        Task.Run(() =>
                        {
                            Thread.Sleep(500);
                            doubleClickCounter = 0;
                        });
                    }
                }
            });
        }