Custom rotation adornment

Hello,

Despite documentation, forum search and the GoXamIntro I have not been able to find out how to get a custom rotation adornment to work. Where do I have to place the template? How do I get the diagram to use my template? How can I place the adornment atop a node instead of right of it?

Also, why does my RotatingTool not rotate the ports with the node? This is what my node template looks like:

<DataTemplate x:Key="ComponentNodeTemplate">
    <go:SpotPanel Style="{StaticResource ComponentStyle}"
                  go:Node.Location="{Binding Path=Data.Location, Mode=TwoWay}"
                  go:Part.SelectionElementName="VisualComponent"
                  go:Part.SelectionAdorned="False"
                  go:Part.LayerName="{Binding Path=Data.Layer.Id}"
                  go:Part.Visible="{Binding Path=Data.IsVisible}"
                  go:Part.Selectable="{Binding Path=Data.IsSelectable}"
                  go:Part.Rotatable="True"
                  MouseLeftButtonDown="Node_MouseLeftButtonDown"
                  MouseEnter="Node_MouseEnterComponent"
                  MouseLeave="Node_MouseLeaveComponent"
                  Width="{Binding Path=Data.NodeSize.Width}"
                  Height="{Binding Path=Data.NodeSize.Height}">
        <go:NodePanel Sizing="Auto"
                      go:Node.PortId="Component"
                      go:SpotPanel.Main="True"
                      Name="VisualComponent">
            <StackPanel>
                <Grid Width="{Binding Path=Data.IconSize.Width}"
                      Height="{Binding Path=Data.IconSize.Height}">
                    <Image Source="{Binding Path=Data.Icon}"
                           Stretch="UniformToFill"
                           HorizontalAlignment="Center"
                           VerticalAlignment="Center"></Image>
                </Grid>
            </StackPanel>
        </go:NodePanel>
        <Ellipse Style="{StaticResource PortStyle}"
                 Stroke="{Binding Path=Node.Tag, Converter={StaticResource ComponentHoverConverter}}"
                 go:Node.PortId="1"
                 go:Node.FromSpot="MiddleBottom"
                 go:Node.ToSpot="MiddleBottom"
                 go:SpotPanel.Spot="MiddleTop"
                 go:SpotPanel.Alignment="MiddleTop" />
        <Ellipse Style="{StaticResource PortStyle}"
                 Stroke="{Binding Path=Node.Tag, Converter={StaticResource ComponentHoverConverter}}"
                 go:Node.PortId="2"
                 go:Node.FromSpot="MiddleLeft"
                 go:Node.ToSpot="MiddleLeft"
                 go:SpotPanel.Spot="MiddleRight"
                 go:SpotPanel.Alignment="MiddleRight" />
        <Ellipse Style="{StaticResource PortStyle}"
                 Stroke="{Binding Path=Node.Tag, Converter={StaticResource ComponentHoverConverter}}"
                 go:Node.PortId="3"
                 go:Node.FromSpot="MiddleTop"
                 go:Node.ToSpot="MiddleTop"
                 go:SpotPanel.Spot="MiddleBottom"
                 go:SpotPanel.Alignment="MiddleBottom" />
        <Ellipse Style="{StaticResource PortStyle}"
                 Stroke="{Binding Path=Node.Tag, Converter={StaticResource ComponentHoverConverter}}"
                 go:Node.PortId="4"
                 go:Node.FromSpot="MiddleRight"
                 go:Node.ToSpot="MiddleRight"
                 go:SpotPanel.Spot="MiddleLeft"
                 go:SpotPanel.Alignment="MiddleLeft" />
    </go:SpotPanel>
</DataTemplate>

The rotation adornment template that is supposed to be used is actually just an icon:

<DataTemplate x:Key="RotationAdornmentTemplate">
    <Image Source="../Images/rotate.png"></Image>
</DataTemplate>

The DraggableLink sample demonstrates the use of the Part.RotateAdornmentTemplate, along with other tool customizations.

The RotatingTool rotates the Part.SelectionElement, which is named by the Part.SelectionElementName. Because you set the SelectionElementName, you named the NodePanel inside the SpotPanel as the SelectionElement, so the user only rotates that NodePanel.

That sample does neither tell me how to place the adornment in the desired position, nor how to use an image as adornment. I tried putting an <image> into the DataTemplate and that draws the image but leaves the adornment unusable. Using <go:ToolHandle> gives a usable adornment but I can’t figure out how to add an image to it, as it doesn’t support direct content. So, how may I get this to work?

If you want to use an Image instead of a ToolHandle, you just need to set the attached property go:NodePanel.Figure="Rectangle" on the Image. (Actually, any non-“None” value will do. This is documented with DiagramTool.FindToolHandleAt.)

    <DataTemplate x:Key="NodeRotateAdornmentTemplate">
      <Image Source="rocking_horse.jpg" Width="16" Height="16" Cursor="Hand"
             go:NodePanel.Figure="Rectangle" />
    </DataTemplate>

And use this on the root visual element of your Node DataTemplate:

          go:Node.RotationAngle="{Binding Path=Data.Angle, Mode=TwoWay}"
          go:Part.Rotatable="True"
          go:Part.RotateAdornmentTemplate="{StaticResource NodeRotateAdornmentTemplate}"

For example, after only changing the NodeRotateAdornmentTemplate as above in the Draggable Link sample, I get this result:

This line did it, now I can use the angle, thanks.

There are but two more things. The adornment is placed right of the node and too far away. Also the node rotates around the point, the cursor points to in the following picture:

How can I get the adornment above the node and the rotation point in its center? Just like in your sample

Try setting go:Node.RotationSpot="Center".

And replace the standard RotatingTool with the custom one defined in the Draggable Link sample. You can adapt the code there too, if you like.

Your solution did not work. However I found out that the SpotPanel of my node was actually larger than the NodePanel within, which contained my Image, which was responsible for the incorrect rotation center. This is fixed now. When I find the time, I’ll take a look into the RotationTool to get the adornment actually on top of the node, instead of the right side. Thank you for your help.