This is an automated email from the ASF dual-hosted git repository.

nadment pushed a commit to branch 3108
in repository https://gitbox.apache.org/repos/asf/hop.git

commit 4f4a184cc2c9a18195d5ff412b2c82c57ae9eaad
Author: Nicolas Adment <[email protected]>
AuthorDate: Fri Jul 28 21:51:02 2023 +0200

    Copying and pasting notes not working #3108
    
    - Fix copy/paste note without transform/action selected
    - Fix of note position when pasted from clipboard
    - Paste text as pipeline note
    - Add action to copy note to clipboard
---
 .../java/org/apache/hop/workflow/WorkflowMeta.java |  30 ++++--
 .../hopgui/file/pipeline/HopGuiPipelineGraph.java  |  16 ++-
 .../delegates/HopGuiPipelineClipboardDelegate.java | 107 +++++++++++++++------
 .../hopgui/file/workflow/HopGuiWorkflowGraph.java  |  19 +++-
 .../delegates/HopGuiWorkflowClipboardDelegate.java | 103 ++++++++++----------
 .../pipeline/messages/messages_en_US.properties    |   2 +-
 .../workflow/messages/messages_en_US.properties    |   4 +
 7 files changed, 185 insertions(+), 96 deletions(-)

diff --git a/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java 
b/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java
index 93f3ec4198..6fc5d085d5 100644
--- a/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java
+++ b/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java
@@ -122,6 +122,16 @@ public class WorkflowMeta extends AbstractMeta
    */
   public boolean[] max = new boolean[1];
 
+  /** A constant specifying the tag value for the XML node of the actions. */
+  public static final String XML_TAG_ACTIONS = "actions";
+  
+  /** A constant specifying the tag value for the XML node of the notes. */
+  public static final String XML_TAG_NOTEPADS = "notepads";
+  
+  /** A constant specifying the tag value for the XML node of the hops. */
+  public static final String XML_TAG_HOPS = "hops";
+  
+  /** A constant specifying the tag value for the XML node of the workflow 
parameters. */
   protected static final String XML_TAG_PARAMETERS = "parameters";
 
   private List<MissingAction> missingActions;
@@ -383,26 +393,26 @@ public class WorkflowMeta extends AbstractMeta
     }
     xml.append("    
").append(XmlHandler.closeTag(XML_TAG_PARAMETERS)).append(Const.CR);
 
-    xml.append("  ").append(XmlHandler.openTag("actions")).append(Const.CR);
+    xml.append("  
").append(XmlHandler.openTag(XML_TAG_ACTIONS)).append(Const.CR);
     for (int i = 0; i < nrActions(); i++) {
       ActionMeta jge = getAction(i);
       xml.append(jge.getXml());
     }
-    xml.append("  ").append(XmlHandler.closeTag("actions")).append(Const.CR);
+    xml.append("  
").append(XmlHandler.closeTag(XML_TAG_ACTIONS)).append(Const.CR);
 
-    xml.append("  ").append(XmlHandler.openTag("hops")).append(Const.CR);
+    xml.append("  ").append(XmlHandler.openTag(XML_TAG_HOPS)).append(Const.CR);
     for (WorkflowHopMeta hi : workflowHops) {
       // Look at all the hops
       xml.append(hi.getXml());
     }
-    xml.append("  ").append(XmlHandler.closeTag("hops")).append(Const.CR);
+    xml.append("  
").append(XmlHandler.closeTag(XML_TAG_HOPS)).append(Const.CR);
 
-    xml.append("  ").append(XmlHandler.openTag("notepads")).append(Const.CR);
+    xml.append("  
").append(XmlHandler.openTag(XML_TAG_NOTEPADS)).append(Const.CR);
     for (int i = 0; i < nrNotes(); i++) {
       NotePadMeta ni = getNote(i);
       xml.append(ni.getXml());
     }
-    xml.append("  ").append(XmlHandler.closeTag("notepads")).append(Const.CR);
+    xml.append("  
").append(XmlHandler.closeTag(XML_TAG_NOTEPADS)).append(Const.CR);
 
     // Also store the attribute groups
     //
@@ -568,7 +578,7 @@ public class WorkflowMeta extends AbstractMeta
 
       // read the action metadata
       //
-      Node actionsNode = XmlHandler.getSubNode(workflowNode, "actions");
+      Node actionsNode = XmlHandler.getSubNode(workflowNode, XML_TAG_ACTIONS);
       List<Node> actionNodes = XmlHandler.getNodes(actionsNode, 
ActionMeta.XML_TAG);
       for (Node actionNode : actionNodes) {
         ActionMeta actionMeta = new ActionMeta(actionNode, metadataProvider, 
variables);
@@ -588,8 +598,8 @@ public class WorkflowMeta extends AbstractMeta
         addAction(actionMeta);
       }
 
-      Node hopsNode = XmlHandler.getSubNode(workflowNode, "hops");
-      List<Node> hopNodes = XmlHandler.getNodes(hopsNode, "hop");
+      Node hopsNode = XmlHandler.getSubNode(workflowNode, XML_TAG_HOPS);
+      List<Node> hopNodes = XmlHandler.getNodes(hopsNode, 
WorkflowHopMeta.XML_HOP_TAG);
       for (Node hopNode : hopNodes) {
         WorkflowHopMeta hi = new WorkflowHopMeta(hopNode, this);
         workflowHops.add(hi);
@@ -597,7 +607,7 @@ public class WorkflowMeta extends AbstractMeta
 
       // Read the notes...
       //
-      Node notepadsNode = XmlHandler.getSubNode(workflowNode, "notepads");
+      Node notepadsNode = XmlHandler.getSubNode(workflowNode, 
XML_TAG_NOTEPADS);
       List<Node> nodepadNodes = XmlHandler.getNodes(notepadsNode, 
NotePadMeta.XML_TAG);
       for (Node notepadNode : nodepadNodes) {
         NotePadMeta ni = new NotePadMeta(notepadNode);
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
index 8eaa4bef6d..6132ba14a7 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
@@ -2751,6 +2751,20 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
     }
   }
 
+  @GuiContextAction(
+      id = "pipeline-graph-transform-10110-copy-notepad-to-clipboard",
+      parentId = HopGuiPipelineNoteContext.CONTEXT_ID,
+      type = GuiActionType.Custom,
+      name = "i18n::HopGuiPipelineGraph.PipelineAction.CopyToClipboard.Name",
+      tooltip = 
"i18n::HopGuiPipelineGraph.PipelineAction.CopyToClipboard.Tooltip",
+      image = "ui/images/copy.svg",
+      category = "Basic",
+      categoryOrder = "1")
+  public void copyNotePadToClipboard(HopGuiPipelineNoteContext context) {
+    pipelineClipboardDelegate.copySelected(
+        pipelineMeta, Collections.emptyList(), 
Arrays.asList(context.getNotePadMeta()));
+  }
+  
   @GuiContextAction(
       id = "pipeline-graph-edit-pipeline",
       parentId = HopGuiPipelineContext.CONTEXT_ID,
@@ -5199,7 +5213,7 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
     pipelineClipboardDelegate.copySelected(
         pipelineMeta, Arrays.asList(context.getTransformMeta()), 
Collections.emptyList());
   }
-
+  
   @GuiKeyboardShortcut(key = ' ')
   @GuiOsxKeyboardShortcut(key = ' ')
   public void showOutputFields() {
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineClipboardDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineClipboardDelegate.java
index e6cbf3f6d0..98f037f15b 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineClipboardDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineClipboardDelegate.java
@@ -29,14 +29,15 @@ import org.apache.hop.pipeline.PipelineMeta;
 import org.apache.hop.pipeline.transform.ITransformMeta;
 import org.apache.hop.pipeline.transform.TransformErrorMeta;
 import org.apache.hop.pipeline.transform.TransformMeta;
+import org.apache.hop.ui.core.ConstUi;
 import org.apache.hop.ui.core.PropsUi;
 import org.apache.hop.ui.core.dialog.ErrorDialog;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.hopgui.HopGui;
 import org.apache.hop.ui.hopgui.file.pipeline.HopGuiPipelineGraph;
+import org.apache.hop.workflow.WorkflowMeta;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -44,7 +45,7 @@ import java.util.List;
 public class HopGuiPipelineClipboardDelegate {
   private static final Class<?> PKG = HopGui.class; // For Translator
 
-  public static final String XML_TAG_PIPELINE_TRANSFORMS = 
"pipeline-transforms";
+  private static final String XML_TAG_PIPELINE_TRANSFORMS = 
"pipeline-transforms";
   private static final String XML_TAG_TRANSFORMS = "transforms";
 
   private HopGui hopGui;
@@ -82,19 +83,19 @@ public class HopGuiPipelineClipboardDelegate {
     }
   }
 
-  public void pasteXml(PipelineMeta pipelineMeta, String clipcontent, Point 
loc) {
+  public void pasteXml(PipelineMeta pipelineMeta, String clipboardContent, 
Point location) {
 
     try {
-      Document doc = XmlHandler.loadXmlString(clipcontent);
+      Document doc = XmlHandler.loadXmlString(clipboardContent);
       Node pipelineNode = XmlHandler.getSubNode(doc, 
XML_TAG_PIPELINE_TRANSFORMS);
       // De-select all, re-select pasted transforms...
       pipelineMeta.unselectAll();
 
-      Node transformsNode = XmlHandler.getSubNode(pipelineNode, "transforms");
-      int nr = XmlHandler.countNodes(transformsNode, "transform");
+      Node transformsNode = XmlHandler.getSubNode(pipelineNode, 
XML_TAG_TRANSFORMS);
+      int nr = XmlHandler.countNodes(transformsNode, TransformMeta.XML_TAG);
       if (log.isDebug()) {
         // "I found "+nr+" transforms to paste on location: "
-        log.logDebug(BaseMessages.getString(PKG, "HopGui.Log.FoundTransforms", 
"" + nr) + loc);
+        log.logDebug(BaseMessages.getString(PKG, "HopGui.Log.FoundTransforms", 
"" + nr) + location);
       }
       TransformMeta[] transforms = new TransformMeta[nr];
       ArrayList<String> transformOldNames = new ArrayList<>(nr);
@@ -103,10 +104,10 @@ public class HopGuiPipelineClipboardDelegate {
 
       // Load the transforms...
       for (int i = 0; i < nr; i++) {
-        Node transformNode = XmlHandler.getSubNodeByNr(transformsNode, 
"transform", i);
+        Node transformNode = XmlHandler.getSubNodeByNr(transformsNode, 
TransformMeta.XML_TAG, i);
         transforms[i] = new TransformMeta(transformNode, 
hopGui.getMetadataProvider());
 
-        if (loc != null) {
+        if (location != null) {
           Point p = transforms[i].getLocation();
 
           if (min.x > p.x) {
@@ -118,9 +119,32 @@ public class HopGuiPipelineClipboardDelegate {
         }
       }
 
+      // Load the notes...
+      Node notesNode = XmlHandler.getSubNode(pipelineNode, 
WorkflowMeta.XML_TAG_NOTEPADS);
+      nr = XmlHandler.countNodes(notesNode, NotePadMeta.XML_TAG);
+      if (log.isDebug()) {
+        log.logDebug(BaseMessages.getString(PKG, "HopGui.Log.FoundNotepads", 
"" + nr));
+      }
+      NotePadMeta[] notes = new NotePadMeta[nr];
+      for (int i = 0; i < nr; i++) {
+        Node noteNode = XmlHandler.getSubNodeByNr(notesNode, 
NotePadMeta.XML_TAG, i);
+        notes[i] = new NotePadMeta(noteNode);
+
+        if (location != null) {
+          Point p = notes[i].getLocation();
+
+          if (min.x > p.x) {
+            min.x = p.x;
+          }
+          if (min.y > p.y) {
+            min.y = p.y;
+          }
+        }
+      }      
+      
       // Load the hops...
-      Node hopsNode = XmlHandler.getSubNode(pipelineNode, "order");
-      nr = XmlHandler.countNodes(hopsNode, "hop");
+      Node hopsNode = XmlHandler.getSubNode(pipelineNode, 
PipelineMeta.XML_TAG_ORDER);
+      nr = XmlHandler.countNodes(hopsNode, PipelineHopMeta.XML_HOP_TAG);
       if (log.isDebug()) {
         // "I found "+nr+" hops to paste."
         log.logDebug(BaseMessages.getString(PKG, "HopGui.Log.FoundHops", "" + 
nr));
@@ -128,12 +152,12 @@ public class HopGuiPipelineClipboardDelegate {
       PipelineHopMeta[] hops = new PipelineHopMeta[nr];
 
       for (int i = 0; i < nr; i++) {
-        Node hopNode = XmlHandler.getSubNodeByNr(hopsNode, "hop", i);
+        Node hopNode = XmlHandler.getSubNodeByNr(hopsNode, 
PipelineHopMeta.XML_HOP_TAG, i);
         hops[i] = new PipelineHopMeta(hopNode, Arrays.asList(transforms));
       }
 
       // This is the offset:
-      Point offset = new Point(loc.x - min.x, loc.y - min.y);
+      Point offset = new Point(location.x - min.x, location.y - min.y);
 
       // Undo/redo object positions...
       int[] position = new int[transforms.length];
@@ -157,22 +181,12 @@ public class HopGuiPipelineClipboardDelegate {
         pipelineMeta.addPipelineHop(hop);
       }
 
-      // Load the notes...
-      Node notesNode = XmlHandler.getSubNode(pipelineNode, "notepads");
-      nr = XmlHandler.countNodes(notesNode, "notepad");
-      if (log.isDebug()) {
-        // "I found "+nr+" notepads to paste."
-        log.logDebug(BaseMessages.getString(PKG, "HopGui.Log.FoundNotepads", 
"" + nr));
-      }
-      NotePadMeta[] notes = new NotePadMeta[nr];
-
-      for (int i = 0; i < notes.length; i++) {
-        Node noteNode = XmlHandler.getSubNodeByNr(notesNode, "notepad", i);
-        notes[i] = new NotePadMeta(noteNode);
-        Point p = notes[i].getLocation();
-        PropsUi.setLocation(notes[i], p.x + offset.x, p.y + offset.y);
-        pipelineMeta.addNote(notes[i]);
-        notes[i].setSelected(true);
+      // Add the notes...
+      for (NotePadMeta note : notes) {
+        Point p = note.getLocation();
+        PropsUi.setLocation(note, p.x + offset.x, p.y + offset.y);
+        pipelineMeta.addNote(note);
+        note.setSelected(true);
       }
 
       // Set the source and target transforms ...
@@ -231,6 +245,31 @@ public class HopGuiPipelineClipboardDelegate {
       hopGui.undoDelegate.addUndoNew(pipelineMeta, notes, notePos, true);
 
     } catch (HopException e) {
+      // See if this was different (non-XML) content
+      //
+      pasteNoXmlContent(pipelineMeta, clipboardContent, location);
+    }
+    pipelineGraph.redraw();
+  }
+  
+  private void pasteNoXmlContent(PipelineMeta pipelineMeta, String 
clipboardContent, Point location) {
+    try {
+        // Add a notepad
+        //
+        NotePadMeta notePadMeta =
+            new NotePadMeta(
+                clipboardContent,
+                location.x,
+                location.y,
+                ConstUi.NOTE_MIN_SIZE,
+                ConstUi.NOTE_MIN_SIZE);
+        pipelineMeta.addNote(notePadMeta);
+        hopGui.undoDelegate.addUndoNew(
+            pipelineMeta,
+            new NotePadMeta[] {notePadMeta},
+            new int[] {pipelineMeta.indexOfNote(notePadMeta)});
+        shiftLocation(location);
+    } catch (Exception e) {
       // "Error pasting transforms...",
       // "I was unable to paste transforms to this pipeline"
       new ErrorDialog(
@@ -239,12 +278,16 @@ public class HopGuiPipelineClipboardDelegate {
           BaseMessages.getString(PKG, 
"HopGui.Dialog.UnablePasteTransforms.Message"),
           e);
     }
-    pipelineGraph.redraw();
   }
-
+  
+  public void shiftLocation(Point location) {
+    location.x = location.x + (int) (10 * 
PropsUi.getInstance().getZoomFactor());
+    location.y = location.y + (int) (5 * 
PropsUi.getInstance().getZoomFactor());
+  }
+  
   public void copySelected(
       PipelineMeta pipelineMeta, List<TransformMeta> transforms, 
List<NotePadMeta> notes) {
-    if (transforms == null || transforms.size() == 0) {
+    if (transforms == null || transforms.size()+notes.size() == 0) {
       return;
     }
 
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
index e5e1e22e60..77df5c6322 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
@@ -20,6 +20,7 @@ package org.apache.hop.ui.hopgui.file.workflow;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -1952,7 +1953,7 @@ public class HopGuiWorkflowGraph extends 
HopGuiAbstractGraph
         workflowClipboardDelegate.fromClipboard(),
         lastMove == null ? new Point(50, 50) : lastMove);
   }
-
+  
   @GuiContextAction(
       id = "workflow-graph-workflow-clipboard-paste",
       parentId = HopGuiWorkflowContext.CONTEXT_ID,
@@ -1967,6 +1968,20 @@ public class HopGuiWorkflowGraph extends 
HopGuiAbstractGraph
         workflowMeta, workflowClipboardDelegate.fromClipboard(), 
context.getClick());
   }
 
+  @GuiContextAction(
+      id = "workflow-graph-transform-10110-copy-notepad-to-clipboard",
+      parentId = HopGuiWorkflowNoteContext.CONTEXT_ID,
+      type = GuiActionType.Custom,
+      name = "i18n::HopGuiWorkflowGraph.ContextualAction.CopyToClipboard.Name",
+      tooltip = 
"i18n::HopGuiWorkflowGraph.ContextualAction.CopyToClipboard.Tooltip",
+      image = "ui/images/copy.svg",
+      category = "Basic",
+      categoryOrder = "1")
+  public void copyNotePadToClipboard(HopGuiWorkflowNoteContext context) {
+    workflowClipboardDelegate.copySelected(
+        workflowMeta, Collections.emptyList(), 
Arrays.asList(context.getNotePadMeta()));
+  }
+
   @GuiContextAction(
       id = "workflow-graph-edit-workflow",
       parentId = HopGuiWorkflowContext.CONTEXT_ID,
@@ -3013,7 +3028,7 @@ public class HopGuiWorkflowGraph extends 
HopGuiAbstractGraph
   }
 
   @GuiContextAction(
-      id = "pipeline-graph-transform-10010-copy-transform-to-clipboard",
+      id = "workflow-graph-action-10010-copy-notepad-to-clipboard",
       parentId = HopGuiWorkflowActionContext.CONTEXT_ID,
       type = GuiActionType.Custom,
       name = "i18n::HopGuiWorkflowGraph.ContextualAction.CopyAction.Text",
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowClipboardDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowClipboardDelegate.java
index d15f976540..bbf8d6e774 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowClipboardDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowClipboardDelegate.java
@@ -27,7 +27,6 @@ import org.apache.hop.core.logging.LogChannel;
 import org.apache.hop.core.vfs.HopVfs;
 import org.apache.hop.core.xml.XmlHandler;
 import org.apache.hop.i18n.BaseMessages;
-import org.apache.hop.pipeline.PipelineMeta;
 import org.apache.hop.ui.core.ConstUi;
 import org.apache.hop.ui.core.PropsUi;
 import org.apache.hop.ui.core.dialog.ErrorDialog;
@@ -50,8 +49,7 @@ import java.util.List;
 public class HopGuiWorkflowClipboardDelegate {
   private static final Class<?> PKG = HopGui.class; // For Translator
 
-  public static final String XML_TAG_WORKFLOW_ACTIONS = "workflow-actions";
-  public static final String XML_TAG_ACTIONS = "actions";
+  private static final String XML_TAG_WORKFLOW_ACTIONS = "workflow-actions";
 
   private HopGui hopGui;
   private HopGuiWorkflowGraph workflowGraph;
@@ -88,7 +86,7 @@ public class HopGuiWorkflowClipboardDelegate {
     }
   }
 
-  public void pasteXml(WorkflowMeta workflowMeta, String clipboardContent, 
Point locaction) {
+  public void pasteXml(WorkflowMeta workflowMeta, String clipboardContent, 
Point location) {
 
     try {
       Document doc = XmlHandler.loadXmlString(clipboardContent);
@@ -96,20 +94,20 @@ public class HopGuiWorkflowClipboardDelegate {
       // De-select all, re-select pasted transforms...
       workflowMeta.unselectAll();
 
-      Node actionsNode = XmlHandler.getSubNode(workflowNode, XML_TAG_ACTIONS);
+      Node actionsNode = XmlHandler.getSubNode(workflowNode, 
WorkflowMeta.XML_TAG_ACTIONS);      
       int nr = XmlHandler.countNodes(actionsNode, ActionMeta.XML_TAG);
       ActionMeta[] actions = new ActionMeta[nr];
       ArrayList<String> actionsOldNames = new ArrayList<>(nr);
 
       Point min = new Point(99999999, 99999999);
 
-      // Load the entries...
+      // Load the actions...
       for (int i = 0; i < nr; i++) {
         Node actionNode = XmlHandler.getSubNodeByNr(actionsNode, 
ActionMeta.XML_TAG, i);
         actions[i] =
             new ActionMeta(actionNode, hopGui.getMetadataProvider(), 
workflowGraph.getVariables());
 
-        if (locaction != null) {
+        if (location != null) {
           Point p = actions[i].getLocation();
 
           if (min.x > p.x) {
@@ -121,18 +119,41 @@ public class HopGuiWorkflowClipboardDelegate {
         }
       }
 
+      // Load the notes...
+      Node notesNode = XmlHandler.getSubNode(workflowNode, 
WorkflowMeta.XML_TAG_NOTEPADS);
+      nr = XmlHandler.countNodes(notesNode, NotePadMeta.XML_TAG);
+      if (log.isDebug()) {
+        log.logDebug(BaseMessages.getString(PKG, "HopGui.Log.FoundNotepads", 
"" + nr));
+      }
+      NotePadMeta[] notes = new NotePadMeta[nr];
+      for (int i = 0; i < nr; i++) {
+        Node noteNode = XmlHandler.getSubNodeByNr(notesNode, 
NotePadMeta.XML_TAG, i);
+        notes[i] = new NotePadMeta(noteNode);
+
+        if (location != null) {
+          Point p = notes[i].getLocation();
+
+          if (min.x > p.x) {
+            min.x = p.x;
+          }
+          if (min.y > p.y) {
+            min.y = p.y;
+          }
+        }
+      }
+      
       // Load the hops...
-      Node hopsNode = XmlHandler.getSubNode(workflowNode, "order");
-      nr = XmlHandler.countNodes(hopsNode, "hop");
+      Node hopsNode = XmlHandler.getSubNode(workflowNode, 
WorkflowMeta.XML_TAG_HOPS);
+      nr = XmlHandler.countNodes(hopsNode, WorkflowHopMeta.XML_HOP_TAG);
       WorkflowHopMeta[] hops = new WorkflowHopMeta[nr];
 
       for (int i = 0; i < nr; i++) {
-        Node hopNode = XmlHandler.getSubNodeByNr(hopsNode, "hop", i);
+        Node hopNode = XmlHandler.getSubNodeByNr(hopsNode, 
WorkflowHopMeta.XML_HOP_TAG, i);
         hops[i] = new WorkflowHopMeta(hopNode, Arrays.asList(actions));
       }
 
       // This is the offset:
-      Point offset = new Point(locaction.x - min.x, locaction.y - min.y);
+      Point offset = new Point(location.x - min.x, location.y - min.y);
 
       // Undo/redo object positions...
       int[] position = new int[actions.length];
@@ -156,22 +177,12 @@ public class HopGuiWorkflowClipboardDelegate {
         workflowMeta.addWorkflowHop(hop);
       }
 
-      // Load the notes...
-      Node notesNode = XmlHandler.getSubNode(workflowNode, "notepads");
-      nr = XmlHandler.countNodes(notesNode, "notepad");
-      if (log.isDebug()) {
-        // "I found "+nr+" notepads to paste."
-        log.logDebug(BaseMessages.getString(PKG, "HopGui.Log.FoundNotepads", 
"" + nr));
-      }
-      NotePadMeta[] notes = new NotePadMeta[nr];
-
-      for (int i = 0; i < notes.length; i++) {
-        Node noteNode = XmlHandler.getSubNodeByNr(notesNode, "notepad", i);
-        notes[i] = new NotePadMeta(noteNode);
-        Point p = notes[i].getLocation();
-        PropsUi.setLocation(notes[i], p.x + offset.x, p.y + offset.y);
-        workflowMeta.addNote(notes[i]);
-        notes[i].setSelected(true);
+      // Add the notes too...
+      for (NotePadMeta note : notes) {
+        Point p = note.getLocation();
+        PropsUi.setLocation(note, p.x + offset.x, p.y + offset.y);
+        workflowMeta.addNote(note);
+        note.setSelected(true);
       }
 
       // Save undo information too...
@@ -192,7 +203,7 @@ public class HopGuiWorkflowClipboardDelegate {
     } catch (HopException e) {
       // See if this was different (non-XML) content
       //
-      pasteNoXmlContent(workflowMeta, clipboardContent, locaction);
+      pasteNoXmlContent(workflowMeta, clipboardContent, location);
     }
 
     workflowGraph.redraw();
@@ -244,6 +255,8 @@ public class HopGuiWorkflowClipboardDelegate {
       } else {
         // Add a notepad
         //
+        shiftLocation(location);
+        
         NotePadMeta notePadMeta =
             new NotePadMeta(
                 clipboardContent,
@@ -256,7 +269,7 @@ public class HopGuiWorkflowClipboardDelegate {
             workflowMeta,
             new NotePadMeta[] {notePadMeta},
             new int[] {workflowMeta.indexOfNote(notePadMeta)});
-        shiftLocation(location);
+
       }
 
     } catch (Exception e) {
@@ -285,19 +298,9 @@ public class HopGuiWorkflowClipboardDelegate {
     return uniqueName;
   }
 
-  private String getUniqueName(PipelineMeta meta, String name) {
-    String uniqueName = name;
-    int nr = 2;
-    while (meta.findTransform(uniqueName) != null) {
-      uniqueName = name + " " + nr;
-      nr++;
-    }
-    return uniqueName;
-  }
-
   public void copySelected(
       WorkflowMeta workflowMeta, List<ActionMeta> actions, List<NotePadMeta> 
notes) {
-    if (actions == null || actions.size() == 0) {
+    if (actions == null || actions.size()+notes.size() == 0) {
       return;
     }
 
@@ -305,14 +308,14 @@ public class HopGuiWorkflowClipboardDelegate {
     try {
       
xml.append(XmlHandler.openTag(XML_TAG_WORKFLOW_ACTIONS)).append(Const.CR);
 
-      xml.append(XmlHandler.openTag(XML_TAG_ACTIONS)).append(Const.CR);
+      
xml.append(XmlHandler.openTag(WorkflowMeta.XML_TAG_ACTIONS)).append(Const.CR);
       for (ActionMeta action : actions) {
         xml.append(action.getXml());
       }
-      xml.append(XmlHandler.closeTag(XML_TAG_ACTIONS)).append(Const.CR);
+      
xml.append(XmlHandler.closeTag(WorkflowMeta.XML_TAG_ACTIONS)).append(Const.CR);
 
       // Also check for the hops in between the selected transforms...
-      
xml.append(XmlHandler.openTag(PipelineMeta.XML_TAG_ORDER)).append(Const.CR);
+      
xml.append(XmlHandler.openTag(WorkflowMeta.XML_TAG_HOPS)).append(Const.CR);
       for (ActionMeta transform1 : actions) {
         for (ActionMeta transform2 : actions) {
           if (!transform1.equals(transform2)) {
@@ -324,15 +327,15 @@ public class HopGuiWorkflowClipboardDelegate {
           }
         }
       }
-      
xml.append(XmlHandler.closeTag(PipelineMeta.XML_TAG_ORDER)).append(Const.CR);
+      
xml.append(XmlHandler.closeTag(WorkflowMeta.XML_TAG_HOPS)).append(Const.CR);
 
-      
xml.append(XmlHandler.openTag(PipelineMeta.XML_TAG_NOTEPADS)).append(Const.CR);
+      
xml.append(XmlHandler.openTag(WorkflowMeta.XML_TAG_NOTEPADS)).append(Const.CR);
       if (notes != null) {
         for (NotePadMeta note : notes) {
           xml.append(note.getXml());
         }
       }
-      
xml.append(XmlHandler.closeTag(PipelineMeta.XML_TAG_NOTEPADS)).append(Const.CR);
+      
xml.append(XmlHandler.closeTag(WorkflowMeta.XML_TAG_NOTEPADS)).append(Const.CR);
 
       
xml.append(XmlHandler.closeTag(XML_TAG_WORKFLOW_ACTIONS)).append(Const.CR);
 
@@ -350,11 +353,11 @@ public class HopGuiWorkflowClipboardDelegate {
     StringBuilder xml = new 
StringBuilder(5000).append(XmlHandler.getXmlHeader());
     try {
       
xml.append(XmlHandler.openTag(XML_TAG_WORKFLOW_ACTIONS)).append(Const.CR);
-      xml.append(XmlHandler.openTag(XML_TAG_ACTIONS)).append(Const.CR);
+      
xml.append(XmlHandler.openTag(WorkflowMeta.XML_TAG_ACTIONS)).append(Const.CR);
       for (ActionMeta action : actions) {
         xml.append(action.getXml());
       }
-      xml.append(XmlHandler.closeTag(XML_TAG_ACTIONS)).append(Const.CR);
+      
xml.append(XmlHandler.closeTag(WorkflowMeta.XML_TAG_ACTIONS)).append(Const.CR);
       
xml.append(XmlHandler.closeTag(XML_TAG_WORKFLOW_ACTIONS)).append(Const.CR);
 
       GuiResource.getInstance().toClipboard(xml.toString());
@@ -384,14 +387,14 @@ public class HopGuiWorkflowClipboardDelegate {
    *
    * @return value of workflowGraph
    */
-  public HopGuiWorkflowGraph getJobGraph() {
+  public HopGuiWorkflowGraph getWorkflowGraph() {
     return workflowGraph;
   }
 
   /**
    * @param workflowGraph The workflowGraph to set
    */
-  public void setJobGraph(HopGuiWorkflowGraph workflowGraph) {
+  public void setWorkflowGraph(HopGuiWorkflowGraph workflowGraph) {
     this.workflowGraph = workflowGraph;
   }
 
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/hopgui/file/pipeline/messages/messages_en_US.properties
 
b/ui/src/main/resources/org/apache/hop/ui/hopgui/file/pipeline/messages/messages_en_US.properties
index 1ae795ff47..2a56ad0d74 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/hopgui/file/pipeline/messages/messages_en_US.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/hopgui/file/pipeline/messages/messages_en_US.properties
@@ -96,7 +96,7 @@ HopGuiPipelineGraph.PipelineAction.SniffOutput.Tooltip=Take a 
look at 50 rows co
 HopGuiPipelineGraph.PipelineAction.PasteFromClipboard.Name=Paste from the 
clipboard
 HopGuiPipelineGraph.PipelineAction.PasteFromClipboard.Tooltip=Paste 
transforms, notes or a whole pipeline from the clipboard
 HopGuiPipelineGraph.PipelineAction.CopyToClipboard.Name=Copy to clipboard
-HopGuiPipelineGraph.PipelineAction.CopyToClipboard.Tooltip=Copy the XML 
representation of this transform to the clipboard
+HopGuiPipelineGraph.PipelineAction.CopyToClipboard.Tooltip=Copy the XML 
representation of this object to the clipboard
 HopGuiPipelineGraph.DistributionMethodDialog.Header=Select distribution method
 HopGuiPipelineGraph.DistributionMethodDialog.Text=Please select the row 
distribution method:
 
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_en_US.properties
 
b/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_en_US.properties
index 2602e387d9..2b405b642e 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_en_US.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_en_US.properties
@@ -21,6 +21,8 @@ HopGuiWorkflowGraph.ContextualAction.Category.Bulk.Text=Bulk
 HopGuiWorkflowGraph.ContextualAction.Category.Routing.Text=Routing
 HopGuiWorkflowGraph.ContextualAction.CopyAction.Text=Copy Action to clipboard
 HopGuiWorkflowGraph.ContextualAction.CopyAction.Tooltip=Copy the XML 
representation of this Action to the clipboard
+HopGuiWorkflowGraph.ContextualAction.CopyNote.Text=Copy Note to clipboard
+HopGuiWorkflowGraph.ContextualAction.CopyNote.Tooltip=Copy the XML 
representation of this Note to the clipboard
 HopGuiWorkflowGraph.ContextualAction.CreateHop.Text=Create hop
 HopGuiWorkflowGraph.ContextualAction.CreateHop.Tooltip=Create a new hop 
between 2 actions
 HopGuiWorkflowGraph.ContextualAction.CreateNote.Text=Create a note
@@ -59,6 +61,8 @@ HopGuiWorkflowGraph.ContextualAction.InsetAction.Text=Insert 
action
 HopGuiWorkflowGraph.ContextualAction.InsetAction.Tooltip=Split the hop and 
insert a new action
 HopGuiWorkflowGraph.ContextualAction.ParallelExecution.Text=Parallel execution
 HopGuiWorkflowGraph.ContextualAction.ParallelExecution.Tooltip=Enable or 
disable parallel execution of next actions
+HopGuiWorkflowGraph.ContextualAction.CopyToClipboard.Name=Copy to clipboard
+HopGuiWorkflowGraph.ContextualAction.CopyToClipboard.Tooltip=Copy the XML 
representation of this object to the clipboard
 HopGuiWorkflowGraph.ContextualAction.PasteFromClipboard.Text=Paste from the 
clipboard
 HopGuiWorkflowGraph.ContextualAction.PasteFromClipboard.Tooltip=Paste actions, 
notes or a whole workflow from the clipboard
 HopGuiWorkflowGraph.ContextualAction.StartWorkflowHere.Text=Start the workflow 
here

Reply via email to