diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 57645d9c8..8f0914a53 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -33,6 +33,8 @@ RocketActions.CopyAct.Copy = Copy RocketActions.CopyAct.ttip.Copy = Copy this component (and subcomponents) to the clipboard. RocketActions.PasteAct.Paste = Paste RocketActions.PasteAct.ttip.Paste = Paste the component or simulation on the clipboard to the design. +RocketActions.PasteAct.invalidPosition.msg = Invalid paste position for object '%s', ignoring pasting. +RocketActions.PasteAct.invalidPosition.title = Could not paste RocketActions.DuplicateAct.Duplicate = Duplicate RocketActions.DuplicateAct.ttip.Duplicate = Duplicate this component (and subcomponents). RocketActions.EditAct.Edit = Edit diff --git a/swing/src/net/sf/openrocket/gui/main/RocketActions.java b/swing/src/net/sf/openrocket/gui/main/RocketActions.java index fb1c28bd9..86a3ea6bf 100644 --- a/swing/src/net/sf/openrocket/gui/main/RocketActions.java +++ b/swing/src/net/sf/openrocket/gui/main/RocketActions.java @@ -5,6 +5,7 @@ import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.List; @@ -270,6 +271,15 @@ public class RocketActions { RocketComponent originalParent = components.get(i).getParent(); int originalParentIdx = components.indexOf(originalParent); + result.get(originalParentIdx).addChild(result.get(i)); + } else if (RocketComponent.listContainsParent(components, components.get(i))){ + RocketComponent originalParent = components.get(i); + while (originalParent != components.get(i)) { + if (components.contains(originalParent.getParent())) { + originalParent = originalParent.getParent(); + } + } + int originalParentIdx = components.indexOf(originalParent); result.get(originalParentIdx).addChild(result.get(i)); } } @@ -378,24 +388,41 @@ public class RocketActions { * should be pasted. Returns null if the clipboard is empty or if the * clipboard cannot be pasted to the current selection. * - * @param clipboard the component on the clipboard. + * @param copyComponent the component to be copy-pasted. + * @param pasteComponent the component where copyComponent should be pasted to. * @return a Pair with both components defined, or null. */ - private Pair getPastePosition(RocketComponent clipboard) { + private Pair getPastePosition(RocketComponent copyComponent, RocketComponent pasteComponent) { + if (pasteComponent == null) + return null; + + if (copyComponent == null) + return null; + + if (pasteComponent.isCompatible(copyComponent)) + return new Pair(pasteComponent, pasteComponent.getChildCount()); + + RocketComponent parent = pasteComponent.getParent(); + return getPastePositionFromParent(copyComponent, parent); + } + + /** + * Return the component and position to which the current clipboard + * should be pasted. Returns null if the clipboard is empty or if the + * clipboard cannot be pasted to the current selection. + * + * @param copyComponent the component to be copy-pasted. + * @return a Pair with both components defined, or null. + */ + private Pair getPastePosition(RocketComponent copyComponent) { RocketComponent selected = selectionModel.getSelectedComponent(); - if (selected == null) - return null; + return getPastePosition(copyComponent, selected); + } - if (clipboard == null) - return null; - - if (selected.isCompatible(clipboard)) - return new Pair(selected, selected.getChildCount()); - - RocketComponent parent = selected.getParent(); - if (parent != null && parent.isCompatible(clipboard)) { - int index = parent.getChildPosition(selected) + 1; - return new Pair(parent, index); + private Pair getPastePositionFromParent(RocketComponent component, RocketComponent parent) { + if (parent != null && parent.isCompatible(component)) { + int index = parent.getChildPosition(parent) + 1; + return new Pair<>(parent, index); } return null; @@ -727,11 +754,20 @@ public class RocketActions { document.addUndoPosition("Paste components"); } + List successfullyPasted = new LinkedList<>(); for (int i = 0; i < pasted.size(); i++) { - positions.get(i).getU().addChild(pasted.get(i), positions.get(i).getV()); + if (positions.get(i) == null) { + JOptionPane.showMessageDialog(null, + String.format(trans.get("RocketActions.PasteAct.invalidPosition.msg"), + pasted.get(i).getComponentName()), + trans.get("RocketActions.PasteAct.invalidPosition.title"), JOptionPane.WARNING_MESSAGE); + } else { + positions.get(i).getU().addChild(pasted.get(i), positions.get(i).getV()); + successfullyPasted.add(pasted.get(i)); + } } - selectionModel.setSelectedComponents(pasted); + selectionModel.setSelectedComponents(successfullyPasted); parentFrame.selectTab(BasicFrame.COMPONENT_TAB); @@ -805,7 +841,14 @@ public class RocketActions { List> positions = new LinkedList<>(); for (RocketComponent component : duplicateComponents) { - positions.add(getPastePosition(component)); + Pair pos; + if (RocketComponent.listContainsParent(duplicateComponents, component)) { + pos = getPastePosition(component, component.getParent()); + } else { + RocketComponent pasteParent = components.get(duplicateComponents.indexOf(component)).getParent(); + pos = getPastePosition(component, pasteParent); + } + positions.add(pos); } if (duplicateComponents.size() == 1) { @@ -814,6 +857,9 @@ public class RocketActions { document.addUndoPosition("Duplicate components"); } + Collections.reverse(duplicateComponents); + Collections.reverse(positions); + for (int i = 0; i < duplicateComponents.size(); i++) { positions.get(i).getU().addChild(duplicateComponents.get(i), positions.get(i).getV()); }