Ah, I understand you now. OK, it is true that the default behavior of Part.GetAngle and Part.SetAngle deal with the RenderTransform and not the LayoutTransform. I haven’t tried this, but I believe you can override those two methods on your Nodes.
Here’s how they are currently implemented. Pardon me if there are some internal dependencies in this code:
public virtual double GetAngle(UIElement elt) {
if (elt == null) elt = this.VisualElement;
if (elt == null) return 0;
Transform transform = elt.RenderTransform;
RotateTransform rt = transform as RotateTransform;
TransformGroup tg = transform as TransformGroup;
if (rt == null && tg != null) {
foreach (Transform t in tg.Children) {
rt = t as RotateTransform;
if (rt != null) break;
}
}
if (rt != null) return rt.Angle;
return 0;
}
public virtual void SetAngle(UIElement elt, double angle, Spot focus) {
SetAngleAndScale(elt, angle, focus, new Size(1, 1));
}
internal void SetAngleAndScale(UIElement elt, double angle, Spot focus, Size scale) {
if (elt == null) elt = this.VisualElement;
if (elt == null) return;
if (Double.IsNaN(angle) || Double.IsInfinity(angle)) angle = 0;
double scaleX = scale.Width;
if (Double.IsNaN(scaleX) || Double.IsInfinity(scaleX)) scaleX = 1;
double scaleY = scale.Height;
if (Double.IsNaN(scaleY) || Double.IsInfinity(scaleY)) scaleY = 1;
// handle most common case, especially for speed in Get[Relative]Element(Point/Bounds)
if (angle == 0 && scaleX == 1 && scaleY == 1) {
elt.RenderTransform = null;
elt.RenderTransformOrigin = new Point(0, 0);
} else {
if (!(this is Adornment)) {
if (focus.IsNoSpot) focus = Spot.Center;
elt.RenderTransformOrigin = new Point(focus.X, focus.Y);
}
// try to find an existing transforms
Transform transform = elt.RenderTransform;
TransformGroup tg = transform as TransformGroup;
// try to find an existing RotateTransform
RotateTransform rt = transform as RotateTransform;
if (rt == null && tg != null) {
foreach (Transform t in tg.Children) {
rt = t as RotateTransform;
if (rt != null) break;
}
}
// try to find an existing ScaleTransform
ScaleTransform st = transform as ScaleTransform;
if (st == null && tg != null) {
foreach (Transform t in tg.Children) {
st = t as ScaleTransform;
if (st != null) break;
}
}
RotateTransform rt2 = null;
ScaleTransform st2 = null;
if (rt != null && !rt.IsFrozen) {
rt.Angle = angle;
} else if (angle != 0) {
rt2 = new RotateTransform();
rt2.Angle = angle;
}
if (st != null && !st.IsFrozen) {
st.ScaleX = scaleX;
st.ScaleY = scaleY;
} else if (scaleX != 1 || scaleY != 1) {
st2 = new ScaleTransform();
st2.ScaleX = scaleX;
st2.ScaleY = scaleY;
}
TransformGroup newtg = null;
if (rt2 != null && st2 != null) {
newtg = new TransformGroup();
newtg.Children.Add(st2);
newtg.Children.Add(rt2);
elt.RenderTransform = newtg;
} else if (rt2 != null) {
newtg = new TransformGroup();
newtg.Children.Add(rt2);
if (st != null)
newtg.Children.Add(st);
elt.RenderTransform = newtg;
} else if (st2 != null) {
newtg = new TransformGroup();
if (rt != null)
newtg.Children.Add(rt);
newtg.Children.Add(st2);
elt.RenderTransform = newtg;
}
}
Node node = this as Node;
if (node != null) {
if (elt == node.SelectionElement) {
// save the angle as the RotationAngle attached property
Node.SetRotationAngle(node.VisualElement, angle);
// (not saving scale as an attached dependency property)
}
InvalidateRelationships();
}
}
Presumably you can adapt this code to work with the LayoutTransform.
To make use of your custom Node subclass, you’ll need to use a custom PartManager. Override this method, replacing the Node constructor with your own constructor:
protected virtual Node MakeNodeForData(Object nodedata, IDiagramModel model, bool isgroup, bool islinklabel, String category, DataTemplate templ) {
Node node = (isgroup ? new Group() : new Node()); // for PartManager.MakeNodeForData
PartBinding data = new PartBinding(node, nodedata);
node.Content = data;
node.DataContext = data;
node.ContentTemplate = templ; // for PartManager.MakeNodeForData
node.IsLinkLabel = islinklabel;
if (category != null && category != "") {
if (node.Category != category) node.Category = category;
}
return node;
}
I hope this is enough information for you to accomplish what you want.