Ctrl+drag; what's copied + customization?

When copying a subtree using ctrl+drag in the treeapp demo, I would
like to also create an extra link so that the newly created copy is
linked to the same parent as the original subtree.

If I add the original parent link to the effective selection it is
copied during the drag but the links FromPort is not assigned to the
parent, and when the selection is dropped the link disappears.

Does this make sense? Any suggestions on a fix?

Also, my nodes contain extra data that isn’t being copied. Where
is the best place to copy the extra data? I see some sugestions
throughout the forums that I will try (GoObject.CopyObject,
GoDocument.CopyFromCollection, etc) but more fundamentally: what is the
process (functions called) during this ctrl+drag operation/how are the
node copies created?

Thanks for your help.

;j

Yes, by default links that don’t have both end ports being copied won’t themselves be copied. (Actually, such links do get copied, but they are deleted in the second pass of GoDocument.CopyFromCollection.)
GoView.CopySelection (which is called by GoToolDragging for a ctrl-drag-drop) is what calls GoDocument.CopyFromCollection.
I think the simplest solution would be to define a GoView.SelectionCopied event handler that looked at the GoView.Selection (which will contain references to the newly copied objects). It would find the root nodes that needed to be linked to existing “parent” nodes, and actually do that linking.
Re: extra data in nodes. Yes, that should be done in your override of GoObject.CopyObject.

Thank-you for your reply. This solution does allow me to add
links onto the copied selection. However, I have two issues with
this solution:

(1) the link isn’t added until after the drop, while I would rather have the link visible during the drag.

(2) MyGoView.OnSelectionCopied() does not know which node is supposed to be the parent of the copied subtree.

One issue is more of an aesthetic concern, and the other can be worked
around with a bit of uglyness, but isn’t there some function that I
could override to create the link when the drag starts, but after the
effective selection has been computed and copied?

;j

[QUOTE=walter]

Yes, by default links that don’t have both end ports
being copied won’t themselves be copied. (Actually, such
links do get copied, but they are deleted in the second pass of
GoDocument.CopyFromCollection.)

GoView.CopySelection (which is called by GoToolDragging for a ctrl-drag-drop) is what calls GoDocument.CopyFromCollection.

I think the simplest solution would be to define a GoView.SelectionCopied event handler that looked at the GoView.Selection (which will contain references to the newly copied objects). It would find the root nodes that needed to be linked to existing "parent" nodes, and actually do that linking.

Re: extra data in nodes. Yes, that should be done in your override of GoObject.CopyObject.

[/quote]

A couple things to consider:
Don’t you want this copying behavior to occur on a Ctrl-C Ctrl-V?
Can’t the user select multiple subtrees and copy them all together, so that there are multiple “parent” nodes?
For (2), and because of the issue of multiple “parent” nodes, I was assuming that you could examine a node, see if it already has a link to its “parent”, and if it didn’t that it could find the desired “parent” node from information available in that (copied) node.
For (1), I suppose you could override GoDocument.CreateCopyDictionary, along with a new document flag that would be set when called from GoToolDragging.DoDragging, that would initialize the GoCopyDictionary to map the “parent” node and port(s) to themselves. That way you could add the “parent” node and link to that “parent” node to the collection of objects being copied, as you may already have done for the link only when extending the effective selection, but that “parent” node and its port(s) wouldn’t actually be copied. Instead the copied link would have its port set to point to the original “parent” port.

  • ctrl+c,ctrl+v would be a nice feature, but the visual nature of the dragged copy is more important for this application.
  • I currently have GoView.MaximumSelectionCount = 1. The selection only has one node and that node is the root of the subtree that will be moved/copied.

GoDocument.CreateCopyDictionary is called after the drag is
complete. I should be clearer about my request-- given the
following tree:

a --> b --> c

if I do a ctrl-drag on the b node I want:

a --> b --> c | \--> b' --> c'

and I want the new link to the copied b’ node to be created on drag start so that while draging the link is displayed.

After much poking and prodding, I found my misunderstanding: during a
ctrl-drag, the created DragSelection is only an image of the selection
– there are actually no nodes copied at this point to attach a link to
until the drag is complete.

I originally thought that a ctrl-drag was a copy of the selection followed by a move of the copies.

Here is a solution. In GoToolDragging:

public override GoSelection CreateDragSelection() { GoSelection dragSelection = base.CreateDragSelection();
Node dragNode = (Node) DragSelectionOriginalObject;

GoPort p = new GoPort();
p.Style = GoPortStyle.None;
p.Location = dragNode.LeftPort.Location;
View.Document.Add(p);
dragSelection.Add(p);

View.Document.Add(new NodeArc((GoPort) dragNode.GetParentLink().FromPort, p));

return dragSelection;

}

(Node and NodeArc are essentially equivalent to GoTextNode and
GoLink). This gets me half-way there by providing the
link-to-parent during the drag, but link created above disappears when
the drag is complete. To make it stick, in your GoDocument:

public override GoCopyDictionary CopyFromCollection(
IGoCollection collection,
bool copyableOnly,
bool dragging,
SizeF offset,
GoCopyDictionary dictBuffer)

{

GoCopyDictionary dictionary = base.CopyFromCollection(
collection,
copyableOnly,
dragging,
offset,
dictBuffer);

IEnumerator e = collection.GetEnumerator();
if (e.MoveNext())
{
Node dragNode = (Node) e.Current;
Add(new NodeArc(
(GoPort) dragNode.GetParentLink().FromPort,
(GoPort) dictionary[dragNode.LeftPort]));

}

return dictionary;

}

I don’t know if this is a good solution, but it seems to be doing what
I wanted without much mucking. One thing I don’t know is what
ever happens to the port and link that is created by the dragging tool
and added to the view’s document?

… if anybody has any ideas I’d love to hear them!

;j

(Thanks for your help walter).

Thanks for the detailed info.
I suspect your solution works because it depends on the MaximumSelectionCount being only 1. Otherwise different kinds of objects could be in the collection being copied, including links and including nodes that you wouldn’t want to connect to some “parent” node. It would be wise to remove the dependence on such an assumption.
Perhaps this will work for copy/paste too, since it too calls GoDocument.CopyFromCollection.
But other code that calls CopyFromCollection might do this extra link creation too. It would be very wise to only create that link when called in known context, such as when dragging or copy/paste.