Moving links

Hi,

I want to know this is possible to move a link with the link itself and not the points of the link.

For instance : One link, 2 points and I draw example of the cursor on the link at different location.

Thanks a lot !

I haven’t really tested this code, but you could try replacing the standard LinkReshapingTool with an instance of this:

[code] public class CustomLinkReshapingTool : LinkReshapingTool {
public const String ToolCategory = “ReshapeLink”;

public override void UpdateAdornments(Part part) {
  Link link = part as Link;
  if (link == null) return;  // no Nodes

  Adornment adornment = null;
  if (link.IsSelected) {
    FrameworkElement selelt = link.Path;
    if (selelt != null && link.CanReshape() && Part.IsVisibleElement(selelt)) {
      adornment = link.GetAdornment(ToolCategory);
      if (adornment == null) {
        Route route = link.Route;
        IEnumerable<Point> pts = route.Points;
        int numpts = route.PointsCount;
        if (numpts < 2) return;
        bool ortho = route.Orthogonal;

        // this Adornment consists of a LinkPanel holding a bunch of ToolHandles
        LinkPanel panel = new LinkPanel();
        int firstindex = route.FirstPickIndex;
        int lastindex = route.LastPickIndex;
        int orthadjust = (ortho ? 1 : 0);
        if (/*route.Resegmentable &&*/ route.Curve != LinkCurve.Bezier) {
          for (int i = firstindex+orthadjust; i < lastindex-orthadjust; i++) {
            Point a = route.GetPoint(i);
            Point b = route.GetPoint(i + 1);
            if (IsApprox(a, b)) continue;
            FrameworkElement mh = null;
            // now the handle at the middle of each segment:
            if (IsApprox(a.X, b.X)) {
              mh = new ToolHandle() {
                Width = 6,
                Height = 16,
                Fill = Brushes.Yellow,
                Stroke = Brushes.Black,
                StrokeThickness = 1
              };
            }
            else {
              mh = new ToolHandle() {
                Width = 16,
                Height = 6,
                Fill = Brushes.Yellow,
                Stroke = Brushes.Black,
                StrokeThickness = 1
              };
            }
            NodePanel.SetFigure(mh, NodeFigure.Rectangle);
            // identify this particular handle within the LinkPanel
            LinkPanel.SetIndex(mh, i);  // the segment
            LinkPanel.SetFraction(mh, 0.5);  // how far along the segment
            if (IsApprox(a.X, b.X)) {
              SetReshapeBehavior(mh, ReshapeBehavior.Horizontal);
              mh.Cursor = Cursors.SizeWE;
            }
            else {
              SetReshapeBehavior(mh, ReshapeBehavior.Vertical);
              mh.Cursor = Cursors.SizeNS;
            }
            panel.Children.Add(mh);
          }
        }
        // don't bother creating handles for firstindex or lastindex
        for (int i = firstindex + 1; i < lastindex; i++) {
          // the handle at each vertex point:
          FrameworkElement h = new ToolHandle() {
            Width = 6,
            Height = 6,
            Fill = Brushes.Yellow,
            Stroke = Brushes.Black,
            StrokeThickness = 1
          };
          NodePanel.SetFigure(h, NodeFigure.Rectangle);
          // identify the segment for this particular handle
          LinkPanel.SetIndex(h, i);
          // now determines its reshape behavior and cursor, depending on whether Orthogonal et al.
          if (i == firstindex + 1 && ortho) {
            Point a = route.GetPoint(firstindex);
            Point b = route.GetPoint(firstindex + 1);
            if (IsApprox(a, b)) {
              b = route.GetPoint(firstindex - 1);
              if (IsApprox(a.X, b.X)) {
                SetReshapeBehavior(h, ReshapeBehavior.Vertical);
                h.Cursor = Cursors.SizeNS;
              } else if (IsApprox(a.Y, b.Y)) {
                SetReshapeBehavior(h, ReshapeBehavior.Horizontal);
                h.Cursor = Cursors.SizeWE;
              }
            } else if (IsApprox(a.X, b.X)) {
              SetReshapeBehavior(h, ReshapeBehavior.Vertical);
              h.Cursor = Cursors.SizeNS;
            } else if (IsApprox(a.Y, b.Y)) {
              SetReshapeBehavior(h, ReshapeBehavior.Horizontal);
              h.Cursor = Cursors.SizeWE;
            }
          } else if (i == lastindex - 1 && ortho) {
            Point a = route.GetPoint(lastindex - 1);
            Point b = route.GetPoint(lastindex);
            if (IsApprox(a, b)) {
              a = route.GetPoint(lastindex + 1);
              if (IsApprox(a.X, b.X)) {
                SetReshapeBehavior(h, ReshapeBehavior.Vertical);
                h.Cursor = Cursors.SizeNS;
              } else if (IsApprox(a.Y, b.Y)) {
                SetReshapeBehavior(h, ReshapeBehavior.Horizontal);
                h.Cursor = Cursors.SizeWE;
              }
            } else if (IsApprox(a.X, b.X)) {
              SetReshapeBehavior(h, ReshapeBehavior.Vertical);
              h.Cursor = Cursors.SizeNS;
            } else if (IsApprox(a.Y, b.Y)) {
              SetReshapeBehavior(h, ReshapeBehavior.Horizontal);
              h.Cursor = Cursors.SizeWE;
            }
          } else {
            SetReshapeBehavior(h, ReshapeBehavior.All);
            h.Cursor = Cursors.SizeAll;
          }
          panel.Children.Add(h);
        }

        adornment = new Adornment();
        adornment.AdornedElement = selelt;
        adornment.Category = ToolCategory;
        adornment.Content = panel;  // just provide the FrameworkElement as the Content and as the Visual Child
        adornment.LocationSpot = Spot.TopLeft;
      }
    }
    if (adornment != null) {
      Point loc = link.GetElementPoint(selelt, Spot.TopLeft);
      adornment.Position = loc;
      //adornment.RotationAngle = link.GetAngle(selelt);
      adornment.Remeasure();
    }
  }
  link.SetAdornment(ToolCategory, adornment);
}

protected override void DoReshape(Point newPoint) {
  Link link = this.AdornedLink;
  Route route = link.Route;
  int index = this.HandleIndex;
  ReshapeBehavior behavior = GetReshapeBehavior(this.Handle);
  if (behavior == ReshapeBehavior.None) return;
  if (route.Orthogonal) {  // need to adjust adjacent points as well
    if (index == route.FirstPickIndex+1) {
      int midfirst = route.FirstPickIndex+1;
      if (behavior == ReshapeBehavior.Vertical) {
        // move segment vertically
        route.SetPoint(midfirst, new Point(route.GetPoint(midfirst-1).X, newPoint.Y));
        route.SetPoint(midfirst+1, new Point(route.GetPoint(midfirst+2).X, newPoint.Y));
      } else if (behavior == ReshapeBehavior.Horizontal) {
        // move segment horizontally
        route.SetPoint(midfirst, new Point(newPoint.X, route.GetPoint(midfirst-1).Y));
        route.SetPoint(midfirst+1, new Point(newPoint.X, route.GetPoint(midfirst+2).Y));
      }
    } else if (index == route.LastPickIndex-1) {
      int midlast = route.LastPickIndex-1;
      if (behavior == ReshapeBehavior.Vertical) {
        // move segment vertically
        route.SetPoint(midlast-1, new Point(route.GetPoint(midlast-2).X, newPoint.Y));
        route.SetPoint(midlast, new Point(route.GetPoint(midlast+1).X, newPoint.Y));
      } else if (behavior == ReshapeBehavior.Horizontal) {
        // move segment horizontally
        route.SetPoint(midlast-1, new Point(newPoint.X, route.GetPoint(midlast-2).Y));
        route.SetPoint(midlast, new Point(newPoint.X, route.GetPoint(midlast+1).Y));
      }
    } else {
      // can move anywhere, but need to keep adjacent segments orthogonal
      int i = index;
      Point oldpt = route.GetPoint(i);
      Point before = route.GetPoint(i-1);
      Point after = route.GetPoint(i+1);
      if (IsApprox(before.X, oldpt.X) && IsApprox(oldpt.Y, after.Y)) {
        if (IsApprox(before.X, route.GetPoint(i-2).X) && !IsApprox(before.Y, route.GetPoint(i-2).Y)) {
          route.InsertPoint(i, new Point(newPoint.X, before.Y));
          index++;
          i++;
        } else route.SetPoint(i-1, new Point(newPoint.X, before.Y));
        if (IsApprox(after.Y, route.GetPoint(i+2).Y) && !IsApprox(after.X, route.GetPoint(i+2).X)) {
          route.InsertPoint(i+1, new Point(after.X, newPoint.Y));
        } else route.SetPoint(i+1, new Point(after.X, newPoint.Y));
      } else if (IsApprox(before.Y, oldpt.Y) && IsApprox(oldpt.X, after.X)) {
        if (IsApprox(before.Y, route.GetPoint(i-2).Y) && !IsApprox(before.X, route.GetPoint(i-2).X)) {
          route.InsertPoint(i, new Point(before.X, newPoint.Y));
          index++;
          i++;
        } else route.SetPoint(i-1, new Point(before.X, newPoint.Y));
        if (IsApprox(after.X, route.GetPoint(i+2).X) && !IsApprox(after.Y, route.GetPoint(i+2).Y)) {
          route.InsertPoint(i+1, new Point(newPoint.X, after.Y));
        } else route.SetPoint(i+1, new Point(newPoint.X, after.Y));
      } else if (IsApprox(before.X, oldpt.X) && IsApprox(oldpt.X, after.X)) {
        if (IsApprox(before.X, route.GetPoint(i-2).X) && !IsApprox(before.Y, route.GetPoint(i-2).Y)) {
          route.InsertPoint(i, new Point(newPoint.X, before.Y));
          index++;
          i++;
        } else route.SetPoint(i-1, new Point(newPoint.X, before.Y));
        if (IsApprox(after.X, route.GetPoint(i+2).X) && !IsApprox(after.Y, route.GetPoint(i+2).Y)) {
          route.InsertPoint(i+1, new Point(newPoint.X, after.Y));
        } else route.SetPoint(i+1, new Point(newPoint.X, after.Y));
      } else if (IsApprox(before.Y, oldpt.Y) && IsApprox(oldpt.Y, after.Y)) {
        if (IsApprox(before.Y, route.GetPoint(i-2).Y) && !IsApprox(before.X, route.GetPoint(i-2).X)) {
          route.InsertPoint(i, new Point(before.X, newPoint.Y));
          index++;
          i++;
        } else route.SetPoint(i-1, new Point(before.X, newPoint.Y));
        if (IsApprox(after.Y, route.GetPoint(i+2).Y) && !IsApprox(after.X, route.GetPoint(i+2).X)) {
          route.InsertPoint(i+1, new Point(after.X, newPoint.Y));
        } else route.SetPoint(i+1, new Point(after.X, newPoint.Y));
      }
      route.SetPoint(index, newPoint);
    }
  } else {  // no Orthogonal constraints, just set the new point
    route.SetPoint(this.HandleIndex, newPoint);
    // also adjust the end point if there is no spot for the port
    var fromNode = link.FromNode;
    var fromPort = link.FromPort;
    var fromSpot = Node.GetFromSpot(fromPort);
    var toNode = link.ToNode;
    var toPort = link.ToPort;
    var toSpot = Node.GetToSpot(toPort);
    if (this.HandleIndex == 1 && fromSpot.IsNoSpot) {
      var endpt = route.GetLinkPoint(fromNode, fromPort, Spot.None, true, false, toNode, toPort);
      route.SetPoint(0, endpt);
    }
    if (this.HandleIndex == route.PointsCount - 2 && toSpot.IsNoSpot) {
      var endpt = route.GetLinkPoint(toNode, toPort, Spot.None, false, false, fromNode, fromPort);
      route.SetPoint(route.PointsCount - 1, endpt);
    }
  }
}

public static bool IsApprox(double x, double y) {
  double d = x - y;
  return d < 0.5 && d > -0.5;
}
public static bool IsApprox(Point a, Point b) {
  return IsApprox(a.X, b.X) && IsApprox(a.Y, b.Y);
}

}[/code]

Thanks, it works !