Emulating "container - child" relations in NShape :: demo-project.

Mar 14, 2013 at 5:42 PM
Edited Mar 14, 2013 at 5:48 PM

In my application, shapes of certain types must be placed "into" shapes of other certain types. The former can be called "child" shapes, the latter - "container" shapes. After "child" is placed into "container", the following things must happen:
  • movement/resizing of child shape must be restricted by boundaries of its container shape,
  • resizing of container shape must be restricted by the overall rectangle of all its child shapes (i.e. the smallest axis-aligned rectangle covering all child shapes),
  • container shape must be moved together with all its child shapes.
Seems it's not too complex to implement... but only at the first glance!

Yes, NShape's Shape type exposes property Children (of type IShapeCollection), but if we execute the following code
Shape containerShape = ...;
Shape childShape = ...;
-- we will see that several side effects occur:
  • child shape cannot be moved inside the container shape,
  • child shape cannot be resized,
  • child shape cannot establish new connections with other shapes (fortunately, existing connections - if any - are preserved).
In fact, containerShape and childShape become a monolithic junction :( and this makes it impossible to implement the desired functionality described in the beginning.

In this topic, I want to share a solution for this problem. It is possible to achieve the desired functionality via controlling the following:
  • keyboard keys (particularily the "arrow" ones) - to control movement of shapes (via key suppression),
  • mouse position and state - to control movement and resizing of the child shapes (via "cursor clipping"),
  • Selection Tool - to control movement of container shapes (and ensure that all child shapes get moved along with their container).
You may download the solution from this link. It's a WinRar archive containing a Visual Studio 2010 solution (consisting of one Windows Forms Application project). The archive does not contain referenced [NShape] assemblies, so you'll need to recreate project references before building the solution for the first time.

Hope this solution will be helpful for other developers facing the same problem.

It will be nice to hear NShape Team opinion on this solution, and it will be also great if future releases of NShape Framework contain this functionality out of the box.

[UPDATE] This topic is related to this one.