/// <summary> /// Overridden. After the direct children of the camera have been given a chance /// to be picked objects viewed by the camera are given a chance to be picked. /// </summary> /// <param name="pickPath">The pick path used for the pick operation.</param> /// <returns> /// True if an object viewed by the camera was picked; else false. /// </returns> protected override bool PickAfterChildren(PPickPath pickPath) { if (Intersects(pickPath.PickBounds)) { pickPath.PushMatrix(viewMatrix); if (PickCameraView(pickPath)) { return true; } pickPath.PopMatrix(viewMatrix); return true; } return false; }
/// <summary> /// Pick all the layers that the camera is looking at. /// </summary> /// <param name="pickPath">The pick path to use for the pick operation.</param> /// <returns> /// True if an object viewed by the camera was picked; else false. /// </returns> /// <remarks> /// This method is only called when the camera's view matrix and clip are /// applied to the pickPath. /// </remarks> protected virtual bool PickCameraView(PPickPath pickPath) { int count = LayerCount; for (int i = count - 1; i >= 0; i--) { PLayer each = layers[i]; if (each.FullPick(pickPath)) return true; } return false; }
/// <summary> /// Try to pick this node after its children have had a chance to be picked. /// </summary> /// <param name="pickPath">The pick path used for the pick operation.</param> /// <returns>True if this node was picked; else false.</returns> /// <remarks> /// <b>Notes to Inheritors:</b> Most subclasses that define a different geometry will /// need to override this method. /// </remarks> protected virtual bool PickAfterChildren(PPickPath pickPath) { if (Intersects(pickPath.PickBounds)) { return true; } return false; }
//**************************************************************** // Picking - Methods for picking the camera and it's view. //**************************************************************** /// <summary> /// Generate and return a PPickPath for the point x,y specified in the local /// coordinate system of this camera. /// </summary> /// <param name="x">The x coordinate of the pick point.</param> /// <param name="y">The y coordinate of the pick point.</param> /// <param name="halo"> /// The value to use for the width and height of the rectangle used for picking. /// </param> /// <returns>A PPickPath for the given point.</returns> /// <remarks> /// Picking is done with a rectangle, halo specifies how large that rectangle /// will be. /// </remarks> public virtual PPickPath Pick(float x, float y, float halo) { RectangleF b = PUtil.InflatedRectangle(new PointF(x, y), halo, halo); PPickPath result = new PPickPath(this, b); FullPick(result); // make sure this camera is pushed. if (result.NodeStackReference.Count == 0) { result.PushNode(this); result.PushMatrix(MatrixReference); } return result; }
/// <summary> /// Creates a pick path with the given Camera and pickbounds and adds this node. /// </summary> /// <param name="aCamera">The camera to use when creating the pick path.</param> /// <param name="pickBounds">The pick bounds to use when creating the pick path.</param> /// <returns> /// A pick path with the given camera and pickbounds that contains this node /// </returns> public virtual PPickPath ToPickPath(PCamera aCamera, RectangleF pickBounds) { PPickPath pickPath = new PPickPath(aCamera, pickBounds); pickPath.PushNode(this); return pickPath; }
/// <summary> /// Try to pick this node before its children have had a chance to be picked. /// </summary> /// <param name="pickPath">The pick path used for the pick operation.</param> /// <returns>True if this node was picked; else false.</returns> /// <remarks> /// Nodes that paint on top of their children may want to override this method to see /// if the pick path intersects that paint. /// </remarks> protected virtual bool Pick(PPickPath pickPath) { return false; }
//**************************************************************** // Event Handling - Methods for handling events // // The dispatch manager updates the focus nodes based on the // incoming events, and dispatches those events to the appropriate // focus nodes. //**************************************************************** /// <summary> /// Create a new PInputEvent based on the next windows event and dispatch it to Piccolo. /// </summary> public virtual void ProcessInput() { if (nextInput == null) return; PInputEventArgs e = new PInputEventArgs(this, nextInput, nextType); //The EventArgs object for a Click event does not provide the position, so //we just ignore it here. //if (e.IsMouseEvent || e.IsDragDropEvent) { if (e.IsMouseEvent) { lastCanvasPosition = currentCanvasPosition; //if (e.IsMouseEvent) { currentCanvasPosition = new PointF(((MouseEventArgs)nextInput).X, ((MouseEventArgs)nextInput).Y); //} else { // Point pt = new Point((int)((DragEventArgs)nextInput).X, (int)((DragEventArgs)nextInput).Y); // currentCanvasPosition = nextWindowsSource.PointToClient(pt); //} //if (e.Type == PInputType.MouseMove || e.Type == PInputType.MouseDrag || e.Type == PInputType.DragOver){ PPickPath pickPath = nextInputSource.Pick(currentCanvasPosition.X, currentCanvasPosition.Y, 1); MouseOver = pickPath; //} } nextInput = null; nextInputSource = null; Dispatch(e); }
/// <summary> /// Try to pick this node and all of its descendents. /// </summary> /// <param name="pickPath">The pick path to add the node to if its picked.</param> /// <returns>True if this node or one of its descendents was picked; else false.</returns> /// <remarks> /// <b>Notes to Inheritors:</b> Most subclasses should not need to override this /// method. Instead they should override <c>Pick</c> or <c>PickAfterChildren</c>. /// </remarks> public virtual bool FullPick(PPickPath pickPath) { if ((Pickable || ChildrenPickable) && FullIntersects(pickPath.PickBounds)) { pickPath.PushNode(this); pickPath.PushMatrix(matrix); bool thisPickable = Pickable && pickPath.AcceptsNode(this); if (thisPickable && Pick(pickPath)) { return true; } if (ChildrenPickable) { int count = ChildrenCount; for (int i = count - 1; i >= 0; i--) { if (children[i].FullPick(pickPath)) { return true; } } } if (thisPickable && PickAfterChildren(pickPath)) { return true; } pickPath.PopMatrix(matrix); pickPath.PopNode(this); } return false; }
/// <summary> /// Dispatch the given event to the appropriate focus node. /// </summary> /// <param name="e">An PInputEventArgs that contains the event data.</param> public virtual void Dispatch(PInputEventArgs e) { switch (e.Type) { case PInputType.KeyDown: DispatchToPath(e, PInputType.KeyDown, KeyboardFocus); break; case PInputType.KeyPress: DispatchToPath(e, PInputType.KeyPress, KeyboardFocus); break; case PInputType.KeyUp: DispatchToPath(e, PInputType.KeyUp, KeyboardFocus); break; case PInputType.Click: //The click event occurs before the MouseRelease so we can //dispatch to the current focused node as opposed to the //previously focused node DispatchToPath(e, PInputType.Click, MouseFocus); break; case PInputType.DoubleClick: //The double click event occurs before the MouseRelease so we can //dispatch to the current focused node as opposed to the //previously focused node DispatchToPath(e, PInputType.DoubleClick, MouseFocus); break; case PInputType.MouseDown: MouseFocus = MouseOver; DispatchToPath(e, PInputType.MouseDown, MouseFocus); break; case PInputType.MouseUp: CheckForMouseEnteredAndExited(e); DispatchToPath(e, PInputType.MouseUp, MouseFocus); mouseFocus = null; break; case PInputType.MouseDrag: CheckForMouseEnteredAndExited(e); DispatchToPath(e, PInputType.MouseDrag, MouseFocus); break; case PInputType.MouseMove: CheckForMouseEnteredAndExited(e); DispatchToPath(e, PInputType.MouseMove, MouseOver); break; case PInputType.MouseWheel: MouseFocus = MouseOver; DispatchToPath(e, PInputType.MouseWheel, MouseOver); break; case PInputType.DragOver: CheckForMouseDragEnteredAndExited(e); DispatchToPath(e, PInputType.DragOver, MouseOver); break; case PInputType.DragDrop: CheckForMouseDragEnteredAndExited(e); DispatchToPath(e, PInputType.DragDrop, MouseOver); break; } }
/// <summary> /// Dispatch the given PInputEvent to the given pick path. /// </summary> /// <param name="e">A PInputEventArgs that contains the event data.</param> /// <param name="type">The type of PInputEvent being dispatched.</param> /// <param name="path">The pick path to which the PInputEvent will be dispatched.</param> public virtual void DispatchToPath(PInputEventArgs e, PInputType type, PPickPath path) { if (path != null) { //set the type and clear the handled bit since the same event object is //used to send multiple events such as mouseEntered/mouseExited and mouseMove. e.Type = type; e.Handled = false; path.ProcessEvent(e); } }
/// <summary> /// Check if the mouse has entered or exited a node during a mouse move or drag /// operation and, if so, dispatch the appropriate event. /// </summary> /// <param name="e">A PInputEventArgs that contains the event data.</param> public virtual void CheckForMouseEnteredAndExited(PInputEventArgs e) { PNode c = (mouseOver != null) ? mouseOver.PickedNode : null; PNode p = (previousMouseOver != null) ? previousMouseOver.PickedNode : null; if (c != p) { DispatchToPath(e, PInputType.MouseLeave, previousMouseOver); DispatchToPath(e, PInputType.MouseEnter, mouseOver); previousMouseOver = mouseOver; } }
/// <summary> /// Overridden. Return false since this node should never be picked. /// </summary> /// <param name="pickPath">The pick path used for the pick operation.</param> /// <returns>False since this node should never be picked.</returns> protected override bool PickAfterChildren(PPickPath pickPath) { return(false); }
/// <summary> /// Dispatch the given event to the appropriate focus node. /// </summary> /// <param name="e">An PInputEventArgs that contains the event data.</param> public virtual void Dispatch(PInputEventArgs e) { switch (e.Type) { case PInputType.KeyDown: DispatchToPath(e, PInputType.KeyDown, KeyboardFocus); break; case PInputType.KeyPress: DispatchToPath(e, PInputType.KeyPress, KeyboardFocus); break; case PInputType.KeyUp: DispatchToPath(e, PInputType.KeyUp, KeyboardFocus); break; case PInputType.Click: //The click event occurs before the MouseRelease so we can //dispatch to the current focused node as opposed to the //previously focused node if (MouseFocus.PickedNode == MouseOver.PickedNode) { DispatchToPath(e, PInputType.Click, MouseFocus); } break; case PInputType.DoubleClick: //The double click event occurs before the MouseRelease so we can //dispatch to the current focused node as opposed to the //previously focused node if (MouseFocus.PickedNode == MouseOver.PickedNode) { DispatchToPath(e, PInputType.DoubleClick, MouseFocus); } break; case PInputType.MouseDown: MouseFocus = MouseOver; DispatchToPath(e, PInputType.MouseDown, MouseFocus); break; case PInputType.MouseUp: CheckForMouseEnteredAndExited(e); DispatchToPath(e, PInputType.MouseUp, MouseFocus); mouseFocus = null; break; case PInputType.MouseDrag: CheckForMouseEnteredAndExited(e); DispatchToPath(e, PInputType.MouseDrag, MouseFocus); break; case PInputType.MouseMove: CheckForMouseEnteredAndExited(e); DispatchToPath(e, PInputType.MouseMove, MouseOver); break; case PInputType.MouseWheel: MouseFocus = MouseOver; DispatchToPath(e, PInputType.MouseWheel, MouseOver); break; case PInputType.DragOver: CheckForMouseDragEnteredAndExited(e); DispatchToPath(e, PInputType.DragOver, MouseOver); break; case PInputType.DragDrop: CheckForMouseDragEnteredAndExited(e); DispatchToPath(e, PInputType.DragDrop, MouseOver); break; } }
/// <summary> /// Animates the camera's view to keep the control node on the screen and at 100 /// percent scale with minimal view movement. /// </summary> /// <param name="aCamera">The camera whose view will be animated.</param> /// <param name="aControlNode">The control node to animate to.</param> /// <param name="path">The pick path through which the control node was picked.</param> /// <param name="duration">The length of the animation.</param> /// <returns> /// The activity that animates the camera's view to the control node. /// </returns> public virtual PActivity DirectCameraViewToControl(PCamera aCamera, PControl aControlNode, PPickPath path, int duration) { PMatrix originalViewMatrix = aCamera.ViewMatrix; // Scale the canvas to include SizeF s = new SizeF(1, 0); s = aControlNode.GlobalToLocal(s); float scaleFactor = s.Width / aCamera.ViewScale; PointF scalePoint = PUtil.CenterOfRectangle(aControlNode.GlobalFullBounds); if (scaleFactor != 1) { aCamera.ScaleViewBy(scaleFactor, scalePoint.X, scalePoint.Y); } // Pan the canvas to include the view bounds with minimal canvas // movement. aCamera.AnimateViewToPanToBounds(aControlNode.GlobalFullBounds, 0); // Get rid of any white space. The canvas may be panned and // zoomed in to do this. But make sure not stay constrained by max // magnification. //FillViewWhiteSpace(aCamera); PMatrix resultingMatrix = aCamera.ViewMatrix; aCamera.ViewMatrix = originalViewMatrix; PControl controlNode = (PControl)aControlNode; // Animate the canvas so that it ends up with the given // view transform. PActivity animateCameraViewActivity = AnimateCameraViewMatrixTo(aCamera, resultingMatrix, duration); aCamera.Root.WaitForActivities(); PointF pf = path.GetPathTransformTo(controlNode).Transform(new PointF(controlNode.X, controlNode.Y)); controlNode.ControlLocation = new Point((int)pf.X, (int)pf.Y); controlNode.CurrentCanvas = path.TopCamera.Canvas; controlNode.Editing = true; return(animateCameraViewActivity); }
/// <summary> /// Overridden. Only picks this node's children if the pick bounds intersects the /// clip. /// </summary> /// <param name="pickPath">The pick path to add the node to if its picked.</param> /// <returns> /// True if this node or one of its descendents was picked; else false. /// </returns> public override bool FullPick(PPickPath pickPath) { if (Pickable && FullIntersects(pickPath.PickBounds)) { pickPath.PushNode(this); pickPath.PushMatrix(MatrixReference); if (Pick(pickPath)) { return true; } if (ChildrenPickable && PUtil.RectanglesIntersect(Bounds, pickPath.PickBounds)) { int count = ChildrenCount; for (int i = count - 1; i >= 0; i--) { PNode each = this.GetChild(i); if (each.FullPick(pickPath)) return true; } } if (PickAfterChildren(pickPath)) { return true; } pickPath.PopMatrix(MatrixReference); pickPath.PopNode(this); } return false; }