Esempio n. 1
0
    /// <summary>
    /// Compute the new location for a node, given another node that is controlling its movement.
    /// </summary>
    /// <param name="moving">the <see cref="Northwoods.GoXam.Node"/> being dragged</param>
    /// <param name="pt">the <c>Point</c> in model coordinates to which the node is being dragged</param>
    /// <param name="snapper">the <see cref="Northwoods.GoXam.Node"/>, typically a grid, which is controlling the drag snapping</param>
    /// <param name="draggedparts">a <c>Dictionary</c> of <see cref="Part"/>s being dragged</param>
    /// <returns>a new node location, in model coordinates</returns>
    /// <remarks>
    /// <para>
    /// This is called by <see cref="ComputeMove"/>.
    /// </para>
    /// <para>
    /// When there is a <paramref name="snapper"/>, 
    /// if the <paramref name="snapper"/>'s <see cref="Part.DragOverSnapEnabled"/> property is false,
    /// this method just returns the unmodified <paramref name="pt"/> value.
    /// Otherwise this uses the <see cref="Part.DragOverSnapCellSize"/> and
    /// <see cref="Part.DragOverSnapCellSpot"/>
    /// to compute the nearest grid point that should be the location of the
    /// <paramref name="moving"/> node.
    /// </para>
    /// <para>
    /// If there is no <paramref name="snapper"/>, this uses the <see cref="Northwoods.GoXam.Diagram"/>'s
    /// <see cref="Northwoods.GoXam.Diagram.GridSnapCellSize"/>,
    /// <see cref="Northwoods.GoXam.Diagram.GridSnapCellSpot"/>, and
    /// <see cref="Northwoods.GoXam.Diagram.GridSnapOrigin"/>
    /// properties to calculate and return the nearest grid point.
    /// </para>
    /// </remarks>
    protected virtual Point SnapTo(Node moving, Point pt, Node snapper, Dictionary<Part, Info> draggedparts) {
      if (moving == null) return pt;
      if (snapper == null) {
        Diagram diagram = this.Diagram;
        if (diagram == null || !diagram.GridSnapEnabled) return pt;
        Size cell = diagram.GridSnapCellSize;
        Point origin = diagram.GridSnapOrigin;
        Point s = diagram.GridSnapCellSpot.PointInRect(new Rect(0, 0, cell.Width, cell.Height));
        Point q = FindNearestInfiniteGridPoint(pt, s, origin, cell);
        return q;
      } else {
        if (!snapper.DragOverSnapEnabled) return pt;

        Rect r = snapper.GetElementBounds(snapper.LocationElement);
        if (Double.IsNaN(r.X) || Double.IsNaN(r.Y)) return pt;

        Rect mb = moving.Bounds;
        Point oldloc = moving.Location;
        //if (ds.KeepsOutside) {  //???
        //  Point p = oldloc;
        //  if (oldloc.X <= r.Left) {
        //    p.X = r.Left - mb.Width + (oldloc.X-mb.X);
        //  } else if (oldloc.X >= r.Right) {
        //    p.X = r.Right + (oldloc.X-mb.X);
        //  }
        //  if (oldloc.Y <= r.Top) {
        //    p.Y = r.Top - mb.Height + (oldloc.Y-mb.Y);
        //  } else if (oldloc.Y >= r.Bottom) {
        //    p.Y = r.Bottom + (oldloc.Y-mb.Y);
        //  }
        //  return p;
        //}

        double left = Math.Max(0, oldloc.X - mb.Left);
        double right = Math.Max(0, mb.Right - oldloc.X);
        double top = Math.Max(0, oldloc.Y - mb.Top);
        double bottom = Math.Max(0, mb.Bottom - oldloc.Y);

        Size cell = snapper.DragOverSnapCellSize;
        Point origin = snapper.DragOverSnapOrigin;
        r.X += origin.X;
        r.Y += origin.Y;
        Point s = snapper.DragOverSnapCellSpot.PointInRect(new Rect(0, 0, cell.Width, cell.Height));
        Point q = FindNearestInfiniteGridPoint(pt, s, new Point(r.X, r.Y), cell);

        if (q.X - left < r.Left) {
          q.X += cell.Width * (int)Math.Ceiling((r.Left-(q.X-left))/cell.Width);
        }
        if (q.X + right > r.Right) {
          q.X -= cell.Width * (int)Math.Ceiling(((q.X+right)-r.Right)/cell.Width);
        }
        if (right > 0 && q.X - left < r.Left) {
          q.X += cell.Width * (int)Math.Ceiling((r.Left-(q.X-left))/cell.Width);
        }

        if (q.Y - top < r.Top) {
          q.Y += cell.Height * (int)Math.Ceiling((r.Top-(q.Y-top))/cell.Height);
        }
        if (q.Y + bottom > r.Bottom) {
          q.Y -= cell.Height * (int)Math.Ceiling(((q.Y+bottom)-r.Bottom)/cell.Height);
        }
        if (bottom > 0 && q.Y - top < r.Top) {
          q.Y += cell.Height * (int)Math.Ceiling((r.Top-(q.Y-top))/cell.Height);
        }
        return q;
      }
    }