I have a feature to be implemented for copy paste scenario.It is like there are number of nodes and links and when I select a bunch of them and Ctrl+C it should copy the selected ones and when I Ctrl+V a frame should be formed which will be sticking to my mouse location and the place I click on diagram it should paste the nodes and links.
Does GoXam has this kind of behavior ?
I have implemented the copy-paste scenario but I want to have the behavior for copy-paste as mentioned above.
Can you suggest something about this? I tried to make use of UnboundNodes but it didn’t help as I am creating diagram object programmatically in C#.
Would you mind if the paste actually added the copied Nodes and Links immediately, and that the command would automatically immediately start a DraggingTool dragging around those new nodes and links? Or something like that? Here’s an example:
public class CustomCommandHandler : CommandHandler {
public override void Paste() {
base.Paste();
if (this.Diagram.SelectedParts.Count > 0) {
var tool = new CustomDraggingTool();
// start and activate this special dragging tool
this.Diagram.CurrentTool = tool;
tool.DoActivate();
}
}
}
public class CustomDraggingTool : DraggingTool {
private Boolean InitialMove = false;
protected override void StandardMouseSelect() {
// don't do the usual selection behavior;
// just pick any selected Part as the CurrentPart
this.CurrentPart = this.Diagram.SelectedParts.First();
}
public override void DoMouseMove() {
if (!this.Active) return;
if (!InitialMove) {
InitialMove = true;
// the mouse might not be anywhere near the pasted parts
var bounds = this.Diagram.Panel.ComputeBounds(this.Diagram.SelectedParts);
MoveParts(this.DraggedParts, new Point(this.Diagram.LastMousePointInModel.X - (bounds.X + bounds.Width/2),
this.Diagram.LastMousePointInModel.Y - (bounds.Y + bounds.Height/2)));
this.StartPoint = this.Diagram.LastMousePointInModel;
}
base.DoMouseMove();
}
public override void DoMouseDown() {
// finish tool on mouse down, not on the usual mouse up
DoMouseUp();
}
public override void DoCancel() {
base.DoCancel();
// this tool is invoked only by CommandHandler.Paste,
// so we need to undo the result of the paste
this.Diagram.PartManager.DeleteParts(this.Diagram.SelectedParts);
}
}
Install with:
myDiagram.CommandHandler = new CustomCommandHandler();
Thanks Walter. The solution provided worked perfectly for the first copy paste of single node. But the consecutive paste doesn’t move the pasted node to the mouse position(LastMousePointInModel). Also in case of multiple nodes and links the mouse position get the left top corner of the bounds and in this case also if I paste it consecutively the locations of the elements is not consistent. Also I would like the mouse be at the center of bounds. I have changed the solution a little and its as follows:
public override void DoMouseMove()
{
if (!this.Active)
{
return;
}
MoveParts(this.DraggedParts, new Point(this.Diagram.LastMousePointInModel.X, this.Diagram.LastMousePointInModel.Y));
base.DoMouseMove();
}
Also, I have binded CustomDraggingTool in the diagram and want to make use of the same tool rather than creating new DraggingTool every time. This change I have done and its working.
When I paste consecutively the location of the pasted elements is not consistent. Can you provide some solution to it? I used the exact same code that you provided.
Its not about customization. My question is with the code sample you gave the paste works only when the source node is selected while pasting. If I do not select the source node the pasted elements are pasted randomly
in the diagram though the code says to move to the diagram.LastMousePointInModel. Just want to know the reason for the same
I had a requirement where once I paste the pasted element should be sticking to the mouse location and should move along with it. With some customization over the code provided by you I was able to get it to stick to the mouse location but,
The pasted node is put at the right place only when the copied node is selected. Follow the Gif below:
Here I am selecting the node and doing Ctrl+C and pasting it and the pasted node moves with mouse and is pasted to the same location where the click is made.
However, when I don’t select the copied node and do Ctrl +V, the node is pasted at random place. Refer the gif below:
Here I select a node to copy and after Ctrl+C I click on empty place on diagram and de-select it. Then when I do Ctrl + V the pasted node sticks to the mouse but when I click it goes to random place. This is really annoying.
Why there is different behavior in these two cases and how does the behavior change with the node selected.
Also I was able to reproduce the same in your sample apps(Draggable Link) too. I have attached the code for the same.
class CustomDraggingTool : DraggingTool
{
protected override void StandardMouseSelect()
{
// don't do the usual selection behavior;
// just pick any selected Part as the CurrentPart
if (this.Diagram.SelectedParts.Count > 0)
{
this.CurrentPart = this.Diagram.SelectedParts.First();
}
}
public override void DoMouseMove()
{
base.DoMouseMove();
this.Diagram.Cursor = System.Windows.Input.Cursors.SizeAll;
//var a = this.Diagram.InitialDiagramBoundsSpot;
//this.Diagram.Cursor = Cursors.Arrow;
if (!this.Active)
{
return;
}
// the mouse might not be anywhere near the pasted parts
if (this.DraggedParts.Any())
{
var nodeLoc = this.DraggedParts.First().Value.Point;
MoveParts(this.DraggedParts, new Point(this.Diagram.LastMousePointInModel.X - nodeLoc.X, this.Diagram.LastMousePointInModel.Y - nodeLoc.Y));
//System.Diagnostics.Debug.WriteLine("######################---Before");
//System.Diagnostics.Debug.WriteLine(this.DraggedParts.First().Value.Point.ToString(), this.Diagram.LastMousePointInModel.ToString());
//System.Diagnostics.Debug.WriteLine("######################---After");
//System.Diagnostics.Debug.WriteLine(this.DraggedParts.First().Value.Point.ToString());
//System.Diagnostics.Debug.WriteLine("######################---Pasted");
//System.Diagnostics.Debug.WriteLine(this.Diagram.SelectedNode.Location.ToString());
}
}
public override void DoMouseDown()
{
// finish tool on mouse down, not on the usual mouse up
base.DoMouseUp();
}
public override void DoCancel()
{
base.DoCancel();
// this tool is invoked only by CommandHandler.Paste,
// so we need to undo the result of the paste
this.Diagram.PartManager.DeleteParts(this.Diagram.SelectedParts);
}
}
public class CustomCommandHandler : CommandHandler
{
public override void Paste()
{
base.Paste();
if (this.Diagram.SelectedParts.Count > 0)
{
var tool = this.Diagram.DraggingTool as CustomDraggingTool;
// start and activate this special dragging tool
this.Diagram.CurrentTool = tool;
tool.DoActivate();
}
}
}
CustomCommandHandler and the CustomDraggingTool to be installed in the xaml
I think that requires some modification to the CustomCommandHandler.Paste method. Currently the first Node of the copied Parts is what follows the mouse around, as if the user had started dragging that Node.