ResizingTool and MultiSelect

Hi,
is it possible to implement a ResizingTool, where we get an additional surrounding Adorner, so that we control the resize of all selected nodes relativ to their OriginalLocation and OriginalBounds?
Something like in the image below.

Yes, that is quite possible, but I’m afraid that I do not have such a sample for you.

I might be able to give you some code that resizes a Group by resizing its member nodes, which you might adapt to your Group-less situation. But it will take a while to clean up the code.

That would be nice.

Thank you Walter.

OK, here is some code to allow resizing a Group just by its right, bottom-right, and bottom resize handles so as to proportionally resize and relocate the Part.ResizeElementName elements of the group’s member nodes:

  public class CustomResizingTool : ResizingTool {
    private Dictionary<Node, Rect> originalLocSizes = null;

    public override void DoActivate() {
      base.DoActivate();
      var node = this.AdornedNode;
      if (node is Group) {
        var sizes = new Dictionary<Node, Rect>();
        foreach (var m in ((Group)node).MemberNodes) {
          var ele = m.FindNamedDescendant(m.ResizeElementName);
          var tl = m.GetElementPoint(ele, Spot.TopLeft);
          var br = m.GetElementPoint(ele, Spot.BottomRight);
          var bnds = new Rect(tl, br);
          var sw = 0.0;
          if (ele is Shape) sw = ((Shape)ele).StrokeThickness/2;
          sizes[m] = new Rect(m.Location.X, m.Location.Y, bnds.Width-sw, bnds.Height-sw);
        }
        this.originalLocSizes = sizes;
      }
    }

    public override void DoDeactivate() {
      base.DoDeactivate();
      this.originalLocSizes = null;
    }

    protected override void DoResize(Rect newr) {
      var node = this.AdornedNode;  // the resized element's Part
      // proportionally scale all member parts' by both size and location relative to the top-left corner of the group
      if (node is Group && this.originalLocSizes != null) {
        //if (!this.diagram.lastInput.up) return;
        var group = node;
        var oldsize = this.OriginalBounds;
        if (oldsize.Width == 0 || oldsize.Height == 0) return;
        var oldloc = this.OriginalLocation;
        var grpelt = group.FindNamedDescendant(group.ResizeElementName);
        var newsize = newr.Size;  // assume desiredSize was set by resizing
        var factorx = newsize.Width / oldsize.Width;
        var factory = newsize.Height / oldsize.Height;
        var newloc = group.GetElementPoint(grpelt, new Spot(0, 0, newr.X, newr.Y));
        grpelt.Width = newsize.Width;
        grpelt.Height = newsize.Height;
        foreach (var kvp in this.originalLocSizes) {
          var m = kvp.Key;
          var bounds = kvp.Value;
          // set desiredSize based on old size * factor
          var mele = m.FindNamedDescendant(m.ResizeElementName); 
          mele.Width = bounds.Width * factorx;
          mele.Height = bounds.Height * factory;
          // also need to move member Parts -- assume Group.locationSpot == Spot.TopLeft,
          // so set location based on old location + offset * factor
          m.Location = new Point(oldloc.X + (bounds.X - oldloc.X) * factorx,
                                 oldloc.Y + (bounds.Y - oldloc.Y) * factory);
        }
      } else {
        base.DoResize(newr);
      }
    }
  }
    <DataTemplate x:Key="GroupResizeAdornmentTemplate">
      <go:SpotPanel>
        <go:ToolHandle go:SpotPanel.Spot="1.0 0.5"
                       go:NodePanel.Figure="Rectangle" Width="6" Height="6"
                       Fill="Fuchsia" Stroke="Black" StrokeThickness="1" />
        <go:ToolHandle go:SpotPanel.Spot="0.5 1.0"
                       go:NodePanel.Figure="Rectangle" Width="6" Height="6"
                       Fill="Fuchsia" Stroke="Black" StrokeThickness="1" />
        <go:ToolHandle go:SpotPanel.Spot="1.0 1.0"
                       go:NodePanel.Figure="Rectangle" Width="6" Height="6"
                       Fill="Fuchsia" Stroke="Black" StrokeThickness="1" />
      </go:SpotPanel>
    </DataTemplate>

    <DataTemplate x:Key="GroupTemplate">
      <Border BorderBrush="Blue" BorderThickness="2" Background="AliceBlue"
              go:Node.LocationElementName="myGroupPanel"
              go:Part.Resizable="True" go:Part.ResizeElementName="myGroupPanel"
              go:Part.ResizeAdornmentTemplate="{StaticResource GroupResizeAdornmentTemplate}">
        <go:GroupPanel x:Name="myGroupPanel" Padding="5" />
      </Border>
    </DataTemplate>

Install the new CustomResizingTool either in XAML or in code by assigning Diagram.ResizingTool.

Hi Walter,
first I have to thank you for the code.
My problem is, that I don’t have a group. I just have a multi select.
Sure I can make a new group after the multiselect, but I use grouping of nodes already - to move them as a group for example.
Is it possible to make two sorts of group? One for the resize and the other for simple grouping of nodes?

I think for you it would be better to adapt the code not to use a Group at all.