Drawing your own link route

Hi everyone - just wondering if it was possible to draw your own ‘link’ route between ports instead of using one of the ‘Routing’ types (Ortogonal for example). I was thinking I could just set all the points manually after the link is added to the diagram, but it doesnt seem to work.

so basically... I am getting my links
Link lnk = (from p in myDiagram.Links ....
then I am trying to set the routing manually
lnk.Route.SetPoint(0, new Point(300, 300));
etc etc...
But my changes arent showing up on the screen, and instead Ortogonal is just overriding anything I do. Any ideas why? I'm getting desparate.

My guess is that you are setting the points too soon in the initialization/loading of your diagram.

I suggest you try moving your Route points-setting code to a Diagram.LayoutCompleted event handler, or perhaps to a Diagram.InitialLayoutCompleted event handler.

Here’s an example of what I’m talking about, taken from an updated version of the StateChart sample:

First, we’ll add a Points property to the Transition link data class:

[code] public List Points {
get { return _Points; }
set {
List old = _Points;
List val = value ?? new List();
if (old != val && !old.SequenceEqual(val)) {
_Points = val;
RaisePropertyChanged(“Points”, old, val);
}
}
}
private List _Points = new List();

// read and write the extra property on the link data

public override XElement MakeXElement(XName n) {
  XElement e = base.MakeXElement(n);
  e.Add(XHelper.Attribute("Curviness", this.Curviness, Double.NaN));
  e.Add(XHelper.Attribute("Points", this.Points, new List<Point>()));
  return e;
}

public override void LoadFromXElement(XElement e) {
  base.LoadFromXElement(e);
  this.Curviness = XHelper.Read("Curviness", e, Double.NaN);
  this.Points = new List<Point>(XHelper.Read("Points", e, new List<Point>()));
}[/code]

Then we can augment the behavior of “Save” and “Load”:

[code] private void Save_Click(object sender, RoutedEventArgs e) {
var model = myDiagram.Model as GraphLinksModel<State, String, String, Transition>;
if (model == null) return;
// copy the Route.Points into each Transition data
foreach (Link link in myDiagram.Links) {
Transition transition = (Transition)link.Data;
if (transition == null) continue;
transition.Points = new List(link.Route.Points);
}
XElement root = model.Save<State, Transition>(“StateChart”, “State”, “Transition”);
Demo.MainPage.Instance.SavedXML = root.ToString();
LoadButton.IsEnabled = true;
model.IsModified = false;
}

private void Load_Click(object sender, RoutedEventArgs e) {
  var model = myDiagram.Model as GraphLinksModel<State, String, String, Transition>;
  if (model == null) return;
  try {
    XElement root = XElement.Parse(Demo.MainPage.Instance.SavedXML);
    // set the Route.Points after nodes have been built and the layout has finished
    myDiagram.LayoutCompleted += UpdateRoutes;
    model.Load<State, Transition>(root, "State", "Transition");
  } catch (Exception ex) {
    MessageBox.Show(ex.ToString());
  }
  model.IsModified = false;
}

// only use the saved route points until after the layout has completed,
// because links will get the default routing
private void UpdateRoutes(object sender, DiagramEventArgs e) {
  // just set the Route points once per Load
  myDiagram.LayoutCompleted -= UpdateRoutes;
  foreach (Link link in myDiagram.Links) {
    Transition transition = link.Data as Transition;
    if (transition != null && transition.Points.Count > 1) {
      link.Route.Points = transition.Points;
    }
  }
}[/code]

Awsome, that was it! It works great now!

By the way, for version 1.2 we’re adding a Points property to GraphLinksModelLinkData, so you won’t need to add that code to the Transition class representing link data.