Dragging in and out of a GoSubGraph

Hello,
I am trying to extend the capabilites of the GoSubGraph, so that nodes can be dragged into it and out of it.
The documentation mentions that some customization is needed. Could the steps/logic to handle this task, be specified please?
How is it possible to resize the sub graph without stretching the inner nodes?
Also, how can I add scrolling to the GoSubGraph? Suppose the sub graph contains many nodes and I would like to show just a portion of the nodes. Is it possible?
Thanks
Yuval Naveh
Actimized Ltd.

Basically you’ll need to set up a GoView.SelectionMoved event handler that notices whether the moved object is now positioned inside a GoSubGraph that you care to move it into. The OrgCharter sample does something similar, although with the purpose of creating a link between a node and another node that it is dropped onto.
The same is true for moving a child of a GoSubGraph out.
The tedious part is that you’ll need to manually disconnect all the links on the node that you are moving into or out of the subgraph, and reconnect them after reparenting. That’s currently a restriction of GoDiagram’s GoGroup and GoLayer classes.
What does it mean to resize a GoSubGraph without changing the size and/or position of the children?
If you are thinking that a subgraph is just another object with its own resizable bounds, then it’s probably easiest to add a GoObject such as a GoRectangle as a child of the subgraph, and override the subgraph’s SelectionObject property to refer to that child rectangle. You’ll probably want to define your own subclass of GoRectangle so that you can override the resizing behavior, GoObject.DoResize, so that the user can’t resize the rectangle (and therefore implicitly the subgraph itself) to leave any subgraph children “outside” the rectangle.
Hmmm, but maybe that would be one way for users to remove (or add) nodes to a subgraph–you’d need to work that out. A caution: dealing with subgraphs can be rather complicated, because there are a lot of cases to have to consider what policy you want to implement.
As far as showing only some of the nodes in a subgraph, and allowing the user to scroll them–I suppose that’s possible. You could add some buttons to do the scrolling, and their effect would be to move all of the children up to a minimum or a maximum point, at which time you would need to make them not Visible (rather than moving them beyond the current Bounds of the GoSubGraph).
If you want to implement clipping, I would guess this would require an override of GoSubGraph.Paint and some other notion of determining the Bounds of the subgraph. I suppose using a separate child object such as the rectangle described above would help.

I am now able to drag in. However, drag out is no so obvious.
The default dragging of objects inside the sub graph is still wanted - the sub graph auto stretching it self while dragging. But another type of dragging is needed - A drag out.
How can that be done? Through a tool? I thought maybe to write a tool that is a DraggingOutTool. It might be activated only when the shift key is pressed down. Am I right?
I took your approach of an inner rectangle. Now the selected object is the inner rectangle which eliminates the stretching of other inner objects. good. I also made it invisible so it does not cause a picking problem (Isn’t there a Z order in a layer?!?).
But There are problems matching the size of the sub graph ( parent ) to the inner rect. I want to implement kind of a “Dock Fill” behaviour where the rectangle always fills the inner area. I tried to override the DoResize method of the inner rectangle, but it does not work.
Another problem: When I drag an object inside the SubGraph and move it out of the existing bounds, it moves correctly and the subgraph stretches but the inner rectangle’s size is not stretching. How do I do that? I tried to override ComputeBounds of the SubGraph but it causes problems.
Thanks
Yuval

Yes, you might be able to implement the special drag-out behavior by creating your own subclass of GoToolDragging. Override GoToolDragging.DoDragging to call the base method, and then to check the input state, such as .LastInput.Shift but not .LastInput.Control and that the argument InputState is InputState.Finish, that you care to treat as the special behavior.
Install your new tool in your GoView by calling:
aView.ReplaceMouseTool(typeof(GoToolDragging), new MySpecialTool(aView));

Regarding the inner rectangle, you can make sure it’s the object behind all other children by moving it to the start of the list of the group’s children.
aGroup.InsertBefore(null, aBackgroundObject);
To size it correctly, override LayoutChildren to call the base method to set the rectangle’s Bounds. The following is untested:
public override void LayoutChildren(GoObject childchanged) {
if (this.Initializing) return;
base.LayoutChildren(childchanged);
if (childchanged != theInnerRectangle) {
theInnerRectangle.Bounds = ComputeBounds();
}
}

I have managed to perform drag out but it does not work well.
A custom dragging tool was written and it works by removing the SelectedObject from the subgraph and adding it to the document.
The selected object is in fact dragged out. The problem is that when I release the mouse button (finish the action) the SelectedObject for some unknown reason relocates it self to a position inside the original subgraph although it is not really a child. Also, the view’s OnSelectionMoved is not called, therefore not allowing me to drag it in into another potential SubGraph at the end of the action.
BTW: I could not seem to use the InputSate.Finish constant you recommended. It is never finished, and I want a drag copy (Ctrl) like behavior, that is change the behavior immedialtely.
Any ideas?
Here is an excerpt of the custom dragging tool’s code:
public override void DoDragging( GoInputState evttype )
{
base.DoDragging( evttype ) ;
m_isDragOut = false ;
// Handle Drag out
if ( LastInput.Shift )
{
// Allow drag out only if the current object is a child of sub graph
if ( m_dragOutStarted )
{
m_isDragOut = true ;
}
else if ( this.CurrentObject != null &&
this.CurrentObject.Parent is ExtendedSubGraph )
{
ExtendedSubGraph extendedSubGraph = this.CurrentObject.Parent as ExtendedSubGraph ;
m_origSubGraph = extendedSubGraph ;
extendedSubGraph.Remove( this.CurrentObject ) ;
this.View.Document.Add( this.CurrentObject ) ;
m_dragOutStarted = true ;
m_isDragOut = true ;
}
}
else
{
if ( m_dragOutStarted )
{
this.View.Document.Remove( this.CurrentObject ) ;
m_origSubGraph.Add( this.CurrentObject ) ;
m_origSubGraph = null ;
m_dragOutStarted = false ;
}
}
}

Few more questions regarding sub graphs:

  1. When a subgraph is collapsed and has links to objects outside of it, the links are drawn in new positions & angles (It seems that all inner objects are centered at the top). How is it possible to control the positions of collapsed objects and the angle of entry of their links?
  2. We are evaluting the product and it seems we need to make serious customizations to the subgraph. Is it possible to somehow get just the sources of GoSubGraph without paying for all full source code? (Of course once we purchase the product).
    Yuval

I haven’t had a chance to look at your code.
I’m not sure you can customize the positioning of objects during a Collapse. I suppose you could modify them afterwards, though.
You can look at, and potentially modify, the saved relative positions and sizes of the children in the hashtable that it maintains: GoSubGraph.SavedBounds. But any modifications would only affect the results of a call to Expand.
I think we need a new sample that is just focused on using subgraphs. GoSubGraph is OK for what it was designed for, but there are a lot of things imaginative programmers want to do that it can’t handle (yet).
Sure, if you have purchased a license with updates you’re welcome to parts of the source code if you need it to solve particular problems, as you seem to here. Of course, I’m sure you will understand that the onus of figuring out how the code works and how it could be modified for your purposes will then fall on you.

Walter, thanks for all the quick and informative responses.
I have managed to create a fully operational drag in and drag out sub graphs with links management (the default as you know is to kill the links) - it looks really cool. Needed some tricks to override some GoDiagram built in behaviours but it works …
IMO GoSubGraph is a very special component that should deserve much more attention. Visio for example can do many tasks that GoDiagram cannot yet, but nesting is something innovative which is a killer feature (again IMO).
Yuval

See also:
http://www.nwoods.com/forum/forum_posts.asp?TID=130&PN=3