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; } }
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); } }
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; }); } } }); }