[fixes #358] Implement multi-selection for component tree - Move up, down, Delete, Cut, Copy, Paste
This commit is contained in:
parent
4ba92905b4
commit
aacc101f3a
@ -181,7 +181,7 @@ public class BasicFrame extends JFrame {
|
||||
|
||||
// Create the component tree selection model that will be used
|
||||
componentSelectionModel = new DefaultTreeSelectionModel();
|
||||
componentSelectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
||||
componentSelectionModel.setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
|
||||
|
||||
// Obtain the simulation selection model that will be used
|
||||
simulationPanel = new SimulationPanel(document);
|
||||
|
@ -79,9 +79,20 @@ public class DocumentSelectionModel {
|
||||
* @return the currently selected rocket component, or <code>null</code>.
|
||||
*/
|
||||
public RocketComponent getSelectedComponent() {
|
||||
if (componentSelection == null || componentSelection.size() == 0) return null;
|
||||
if (componentSelection.size() == 0) return null;
|
||||
return componentSelection.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the currently selected rocket components. Returns <code>null</code>
|
||||
* if no rocket component is selected.
|
||||
*
|
||||
* @return the currently selected rocket components, or <code>null</code>.
|
||||
*/
|
||||
public List<RocketComponent> getSelectedComponents() {
|
||||
if (componentSelection.size() == 0) return null;
|
||||
return componentSelection;
|
||||
}
|
||||
|
||||
public void setSelectedComponent(RocketComponent component) {
|
||||
componentSelection.clear();
|
||||
@ -142,7 +153,7 @@ public class DocumentSelectionModel {
|
||||
|
||||
|
||||
public void clearComponentSelection() {
|
||||
if (componentSelection == null || componentSelection.size() == 0)
|
||||
if (componentSelection.size() == 0)
|
||||
return;
|
||||
|
||||
componentSelection.clear();
|
||||
@ -177,15 +188,17 @@ public class DocumentSelectionModel {
|
||||
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
TreePath path = componentTreeSelectionModel.getSelectionPath();
|
||||
if (path == null) {
|
||||
TreePath[] paths = componentTreeSelectionModel.getSelectionPaths();
|
||||
if (paths == null || paths.length == 0) {
|
||||
componentSelection.clear();
|
||||
fireDocumentSelection(DocumentSelectionListener.COMPONENT_SELECTION_CHANGE);
|
||||
return;
|
||||
}
|
||||
|
||||
componentSelection.clear();
|
||||
componentSelection.add((RocketComponent)path.getLastPathComponent());
|
||||
for (TreePath path : paths) {
|
||||
componentSelection.add((RocketComponent)path.getLastPathComponent());
|
||||
}
|
||||
|
||||
clearSimulationSelection();
|
||||
fireDocumentSelection(DocumentSelectionListener.COMPONENT_SELECTION_CHANGE);
|
||||
|
@ -1,6 +1,8 @@
|
||||
package net.sf.openrocket.gui.main;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
@ -8,10 +10,10 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
|
||||
public final class OpenRocketClipboard {
|
||||
|
||||
private static RocketComponent clipboardComponent = null;
|
||||
private static final List<RocketComponent> clipboardComponents = new LinkedList<>();
|
||||
private static Simulation[] clipboardSimulations = null;
|
||||
|
||||
private static List<ClipboardListener> listeners = new ArrayList<ClipboardListener>();
|
||||
private static final List<ClipboardListener> listeners = new ArrayList<ClipboardListener>();
|
||||
|
||||
private OpenRocketClipboard() {
|
||||
// Disallow instantiation
|
||||
@ -26,16 +28,91 @@ public final class OpenRocketClipboard {
|
||||
* @return the rocket component contained in the clipboard, or <code>null</code>
|
||||
* if the clipboard does not currently contain a rocket component.
|
||||
*/
|
||||
public static RocketComponent getClipboardComponent() {
|
||||
return clipboardComponent;
|
||||
public static List<RocketComponent> getClipboardComponents() {
|
||||
return clipboardComponents;
|
||||
}
|
||||
|
||||
|
||||
public static void setClipboard(RocketComponent component) {
|
||||
clipboardComponent = component;
|
||||
public static void setClipboard(List<RocketComponent> components) {
|
||||
clipboardComponents.clear();
|
||||
components = RocketActions.copyComponentsMaintainParent(components);
|
||||
if (components != null) {
|
||||
clipboardComponents.addAll(components);
|
||||
}
|
||||
filterClipboardComponents(new LinkedList<>(clipboardComponents));
|
||||
clipboardSimulations = null;
|
||||
fireClipboardChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out children from clipboardComponents and the children's list of the components, based on the selection
|
||||
* (see {@link #filterClipboardComponent} to see how the actual filtering is done.
|
||||
* @param components components to be filtered
|
||||
*/
|
||||
private static void filterClipboardComponents(List<RocketComponent> components) {
|
||||
if (components == null || components.size() == 0) return;
|
||||
List<RocketComponent> checkedComponents = new ArrayList<>();
|
||||
for (RocketComponent component : components) {
|
||||
// Make sure a parent component is processed before the child components
|
||||
RocketComponent temp = component;
|
||||
while (temp.getParent() != null && clipboardComponents.contains(temp.getParent())
|
||||
&& !checkedComponents.contains(temp.getParent())) {
|
||||
filterClipboardComponent(temp.getParent());
|
||||
checkedComponents.add(temp.getParent());
|
||||
temp = temp.getParent();
|
||||
}
|
||||
filterClipboardComponent(component);
|
||||
checkedComponents.add(component);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iteratively (over all children of component and their children), filter clipboard components according to
|
||||
* the following rules:
|
||||
* - If all children of component are selected, then remove those children from clipboardComponents, but keep them
|
||||
* as children of component
|
||||
* - If one of the children of component is selected, but some are not, then remove the unselected children as child
|
||||
* from component, but keep the selected children as children of component + remove the selected children from
|
||||
* clipboardComponents
|
||||
* - If no children are selected, then no children are removed from component + no children are removed from
|
||||
* clipboardComponents
|
||||
* @param component component to filter
|
||||
*/
|
||||
private static void filterClipboardComponent(RocketComponent component) {
|
||||
if (component == null) return;
|
||||
|
||||
boolean allChildrenSelected = clipboardComponents.containsAll(component.getChildren());
|
||||
boolean someChildrenSelected = false;
|
||||
for (RocketComponent child : component.getChildren()) {
|
||||
if (clipboardComponents.contains(child)) {
|
||||
someChildrenSelected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allChildrenSelected) {
|
||||
for (RocketComponent child : component.getChildren()) {
|
||||
clipboardComponents.remove(child);
|
||||
filterClipboardComponents(child.getChildren());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (someChildrenSelected) {
|
||||
for (RocketComponent child : component.getChildren()) {
|
||||
if (!clipboardComponents.contains(child)) {
|
||||
component.removeChild(child);
|
||||
} else {
|
||||
clipboardComponents.remove(child);
|
||||
filterClipboardComponents(child.getChildren());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (RocketComponent child : component.getChildren()) {
|
||||
filterClipboardComponents(child.getChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Simulation[] getClipboardSimulations() {
|
||||
@ -46,7 +123,7 @@ public final class OpenRocketClipboard {
|
||||
|
||||
public static void setClipboard(Simulation[] simulations) {
|
||||
clipboardSimulations = simulations.clone();
|
||||
clipboardComponent = null;
|
||||
clipboardComponents.clear();
|
||||
fireClipboardChanged();
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,9 @@ import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
@ -181,6 +184,14 @@ public class RocketActions {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isDeletable(List<RocketComponent> components) {
|
||||
if (components == null || components.size() == 0) return false;
|
||||
for (RocketComponent component : components) {
|
||||
if (!isDeletable(component)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void delete(RocketComponent c) {
|
||||
if (!isDeletable(c)) {
|
||||
throw new IllegalArgumentException("Report bug! Component " + c +
|
||||
@ -191,6 +202,16 @@ public class RocketActions {
|
||||
parent.removeChild(c);
|
||||
}
|
||||
|
||||
private void delete(List<RocketComponent> components) {
|
||||
if (!isDeletable(components)) {
|
||||
throw new IllegalArgumentException("Report bug! Components not deletable.");
|
||||
}
|
||||
|
||||
for (RocketComponent component : components) {
|
||||
delete(component);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCopyable(RocketComponent c) {
|
||||
if (c==null)
|
||||
return false;
|
||||
@ -199,6 +220,119 @@ public class RocketActions {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isCopyable(List<RocketComponent> components) {
|
||||
if (components == null || components.size() == 0) return false;
|
||||
for (RocketComponent component : components) {
|
||||
if (!isCopyable(component)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies components, but with maintaining parent-relations with the newly copied components
|
||||
* @param components components to copy
|
||||
* @return copied components
|
||||
*/
|
||||
public static List<RocketComponent> copyComponentsMaintainParent(List<RocketComponent> components) {
|
||||
if (components == null) return null;
|
||||
List<RocketComponent> result = new LinkedList<>();
|
||||
for (RocketComponent component : components) {
|
||||
result.add(component.copy());
|
||||
}
|
||||
|
||||
for (int i = 0; i < components.size(); i++) {
|
||||
if (components.contains(components.get(i).getParent())) {
|
||||
RocketComponent oldChild = components.get(i);
|
||||
RocketComponent oldParent = oldChild.getParent();
|
||||
|
||||
int index = components.indexOf(oldParent);
|
||||
int childPos = oldParent.getChildPosition(oldChild);
|
||||
|
||||
RocketComponent newChild = result.get(i);
|
||||
RocketComponent newParent = result.get(index);
|
||||
|
||||
// Add the newly copied child to the parent
|
||||
newParent.addChild(newChild, childPos);
|
||||
|
||||
// Remove the old child from the parent
|
||||
newParent.removeChild(oldChild);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iteratively checks whether the list of components contains the parent or super-parent (parent of parent of parent of...)
|
||||
* of component.
|
||||
* @param components list of components that may contain the parent
|
||||
* @param component component to check the parent for
|
||||
* @return true if the list contains the parent, false if not
|
||||
*/
|
||||
public static boolean listContainsParent(List<RocketComponent> components, RocketComponent component) {
|
||||
RocketComponent c = component;
|
||||
while (c.getParent() != null) {
|
||||
if (components.contains(c.getParent())) {
|
||||
return true;
|
||||
}
|
||||
c = c.getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the children of a parent are not selected, add them to the selection. Do this recursively for the children
|
||||
* of the children as well.
|
||||
* @param selections list of currently selected components
|
||||
* @param parent parent component to parse the children of
|
||||
*/
|
||||
private void selectAllUnselectedInParent(List<RocketComponent> selections, RocketComponent parent) {
|
||||
if (parent.getChildCount() == 0) return;
|
||||
|
||||
boolean noChildrenSelected = true;
|
||||
for (RocketComponent child : parent.getChildren()) {
|
||||
if (selections.contains(child)) {
|
||||
noChildrenSelected = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add children to selection if none of them were selected
|
||||
if (noChildrenSelected) {
|
||||
selections.addAll(parent.getChildren());
|
||||
}
|
||||
|
||||
// Recursively select all unselected children. Unselected children will not undergo this recursive updating.
|
||||
for (RocketComponent child : parent.getChildren()) {
|
||||
if (!noChildrenSelected && selections.contains(child)) {
|
||||
selectAllUnselectedInParent(selections, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method fills in some selections in selections. If there is a parent where none of its children are selected,
|
||||
* add all the children to the selection. If there is a component whose parent is not selected, but it does have
|
||||
* a super-parent in the selection, add the parent to the selection.
|
||||
* @param selections component selections to be filled up
|
||||
*/
|
||||
private void fillInMissingSelections(List<RocketComponent> selections) {
|
||||
List<RocketComponent> initSelections = new LinkedList<>(selections);
|
||||
for (RocketComponent component : initSelections) {
|
||||
selectAllUnselectedInParent(selections, component);
|
||||
|
||||
// If there is a component in the selection, but its parent (or the parent of the parent) is still
|
||||
// not selected, add it to the selection
|
||||
RocketComponent temp = component;
|
||||
if (listContainsParent(selections, temp) && !selections.contains(temp.getParent())) {
|
||||
while (!selections.contains(temp.getParent())) {
|
||||
selections.add(temp.getParent());
|
||||
temp = temp.getParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean isSimulationSelected() {
|
||||
Simulation[] selection = selectionModel.getSelectedSimulations();
|
||||
@ -269,8 +403,26 @@ public class RocketActions {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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 clipboard the component on the clipboard.
|
||||
* @return a Pair with both components defined, or null.
|
||||
*/
|
||||
private List<Pair<RocketComponent, Integer>> getPastePositions(List<RocketComponent> clipboard) {
|
||||
List<Pair<RocketComponent, Integer>> result = new LinkedList<>();
|
||||
for (RocketComponent component : clipboard) {
|
||||
Pair<RocketComponent, Integer> position = getPastePosition(component);
|
||||
if (position != null) {
|
||||
result.add(position);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -306,15 +458,30 @@ public class RocketActions {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
RocketComponent c = selectionModel.getSelectedComponent();
|
||||
List<RocketComponent> components = new ArrayList<>(selectionModel.getSelectedComponents());
|
||||
if (components.size() == 0) return;
|
||||
components.sort(Comparator.comparing(c -> c.getParent().getChildPosition(c)));
|
||||
|
||||
if (isDeletable(c)) {
|
||||
if (components.size() == 1) {
|
||||
document.addUndoPosition("Delete " + components.get(0).getComponentName());
|
||||
} else {
|
||||
document.addUndoPosition("Delete components");
|
||||
}
|
||||
|
||||
for (RocketComponent component : components) {
|
||||
deleteComponent(component);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteComponent(RocketComponent component) {
|
||||
if (isDeletable(component)) {
|
||||
ComponentConfigDialog.hideDialog();
|
||||
|
||||
c.getRocket().removeComponentChangeListener(ComponentConfigDialog.getDialog());
|
||||
try {
|
||||
component.getRocket().removeComponentChangeListener(ComponentConfigDialog.getDialog());
|
||||
|
||||
document.addUndoPosition("Delete " + c.getComponentName());
|
||||
delete(c);
|
||||
delete(component);
|
||||
} catch (IllegalStateException ignored) { }
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,15 +586,28 @@ public class RocketActions {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
RocketComponent c = selectionModel.getSelectedComponent();
|
||||
List<RocketComponent> components = selectionModel.getSelectedComponents();
|
||||
if (components != null) {
|
||||
components = new ArrayList<>(components);
|
||||
fillInMissingSelections(components);
|
||||
|
||||
components.sort(Comparator.comparing(c -> c.getParent() != null ? -c.getParent().getChildPosition(c) : 0));
|
||||
}
|
||||
Simulation[] sims = selectionModel.getSelectedSimulations();
|
||||
|
||||
if (isDeletable(c) && isCopyable(c)) {
|
||||
if (isDeletable(components) && isCopyable(components)) {
|
||||
ComponentConfigDialog.hideDialog();
|
||||
|
||||
document.addUndoPosition("Cut " + c.getComponentName());
|
||||
OpenRocketClipboard.setClipboard(c.copy());
|
||||
delete(c);
|
||||
|
||||
if (components.size() == 1) {
|
||||
document.addUndoPosition("Cut " + components.get(0).getComponentName());
|
||||
} else {
|
||||
document.addUndoPosition("Cut components");
|
||||
}
|
||||
|
||||
List<RocketComponent> copiedComponents = new LinkedList<>(copyComponentsMaintainParent(components));
|
||||
|
||||
OpenRocketClipboard.setClipboard(copiedComponents);
|
||||
delete(components);
|
||||
parentFrame.selectTab(BasicFrame.COMPONENT_TAB);
|
||||
} else if (isSimulationSelected()) {
|
||||
|
||||
@ -446,8 +626,8 @@ public class RocketActions {
|
||||
|
||||
@Override
|
||||
public void clipboardChanged() {
|
||||
RocketComponent c = selectionModel.getSelectedComponent();
|
||||
this.setEnabled((isDeletable(c) && isCopyable(c)) || isSimulationSelected());
|
||||
List<RocketComponent> components = selectionModel.getSelectedComponents();
|
||||
this.setEnabled((isDeletable(components) && isCopyable(components)) || isSimulationSelected());
|
||||
}
|
||||
}
|
||||
|
||||
@ -472,13 +652,21 @@ public class RocketActions {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
RocketComponent c = selectionModel.getSelectedComponent();
|
||||
List<RocketComponent> components = selectionModel.getSelectedComponents();
|
||||
if (components != null) {
|
||||
components = new ArrayList<>(components);
|
||||
fillInMissingSelections(components);
|
||||
|
||||
components.sort(Comparator.comparing(c -> c.getParent() != null ? -c.getParent().getChildPosition(c) : 0));
|
||||
}
|
||||
Simulation[] sims = selectionModel.getSelectedSimulations();
|
||||
|
||||
if (isCopyable(c)) {
|
||||
OpenRocketClipboard.setClipboard(c.copy());
|
||||
if (isCopyable(components)) {
|
||||
List<RocketComponent> copiedComponents = new LinkedList<>(copyComponentsMaintainParent(components));
|
||||
|
||||
OpenRocketClipboard.setClipboard(copiedComponents);
|
||||
parentFrame.selectTab(BasicFrame.COMPONENT_TAB);
|
||||
} else if (sims.length >= 0) {
|
||||
} else if (sims.length > 0) {
|
||||
|
||||
Simulation[] simsCopy = new Simulation[sims.length];
|
||||
for (int i=0; i < sims.length; i++) {
|
||||
@ -520,17 +708,33 @@ public class RocketActions {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
RocketComponent clipboard = OpenRocketClipboard.getClipboardComponent();
|
||||
List<RocketComponent> components = new LinkedList<>(OpenRocketClipboard.getClipboardComponents());
|
||||
Simulation[] sims = OpenRocketClipboard.getClipboardSimulations();
|
||||
|
||||
Pair<RocketComponent, Integer> position = getPastePosition(clipboard);
|
||||
if (position != null) {
|
||||
|
||||
if (components.size() > 0) {
|
||||
ComponentConfigDialog.hideDialog();
|
||||
|
||||
RocketComponent pasted = clipboard.copy();
|
||||
document.addUndoPosition("Paste " + pasted.getComponentName());
|
||||
position.getU().addChild(pasted, position.getV());
|
||||
selectionModel.setSelectedComponent(pasted);
|
||||
List<RocketComponent> pasted = new LinkedList<>();
|
||||
for (RocketComponent component : components) {
|
||||
pasted.add(component.copy());
|
||||
}
|
||||
|
||||
List<Pair<RocketComponent, Integer>> positions = new LinkedList<>();
|
||||
for (RocketComponent component : pasted) {
|
||||
positions.add(getPastePosition(component));
|
||||
}
|
||||
|
||||
if (pasted.size() == 1) {
|
||||
document.addUndoPosition("Paste " + pasted.get(0).getComponentName());
|
||||
} else {
|
||||
document.addUndoPosition("Paste components");
|
||||
}
|
||||
|
||||
for (int i = 0; i < pasted.size(); i++) {
|
||||
positions.get(i).getU().addChild(pasted.get(i), positions.get(i).getV());
|
||||
}
|
||||
|
||||
selectionModel.setSelectedComponents(pasted);
|
||||
|
||||
parentFrame.selectTab(BasicFrame.COMPONENT_TAB);
|
||||
|
||||
@ -556,7 +760,7 @@ public class RocketActions {
|
||||
@Override
|
||||
public void clipboardChanged() {
|
||||
this.setEnabled(
|
||||
(getPastePosition(OpenRocketClipboard.getClipboardComponent()) != null) ||
|
||||
(getPastePositions(OpenRocketClipboard.getClipboardComponents()).size() > 0) ||
|
||||
(OpenRocketClipboard.getClipboardSimulations() != null));
|
||||
}
|
||||
}
|
||||
@ -656,22 +860,40 @@ public class RocketActions {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
RocketComponent selected = selectionModel.getSelectedComponent();
|
||||
if (!canMove(selected))
|
||||
List<RocketComponent> components = selectionModel.getSelectedComponents();
|
||||
if (components == null || components.size() == 0) return;
|
||||
components = new ArrayList<>(components);
|
||||
components.sort(Comparator.comparing(c -> c.getParent() != null ? c.getParent().getChildPosition(c) : 0));
|
||||
|
||||
if (components.size() == 1) {
|
||||
document.addUndoPosition("Move " + components.get(0).getComponentName());
|
||||
} else {
|
||||
document.addUndoPosition("Move components");
|
||||
}
|
||||
|
||||
for (RocketComponent component : components) {
|
||||
// Only move top components, don't move its children
|
||||
if (!listContainsParent(components, component)) {
|
||||
moveUp(component);
|
||||
}
|
||||
}
|
||||
rocket.fireComponentChangeEvent(ComponentChangeEvent.TREE_CHANGE);
|
||||
selectionModel.setSelectedComponents(components);
|
||||
}
|
||||
|
||||
private void moveUp(RocketComponent component) {
|
||||
if (!canMove(component))
|
||||
return;
|
||||
|
||||
|
||||
ComponentConfigDialog.hideDialog();
|
||||
|
||||
RocketComponent parent = selected.getParent();
|
||||
document.addUndoPosition("Move "+selected.getComponentName());
|
||||
parent.moveChild(selected, parent.getChildPosition(selected)-1);
|
||||
rocket.fireComponentChangeEvent( ComponentChangeEvent.TREE_CHANGE );
|
||||
selectionModel.setSelectedComponent(selected);
|
||||
RocketComponent parent = component.getParent();
|
||||
parent.moveChild(component, parent.getChildPosition(component) - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clipboardChanged() {
|
||||
this.setEnabled(canMove(selectionModel.getSelectedComponent()));
|
||||
this.setEnabled(canMove(selectionModel.getSelectedComponents()));
|
||||
}
|
||||
|
||||
private boolean canMove(RocketComponent c) {
|
||||
@ -682,6 +904,17 @@ public class RocketActions {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean canMove(List<RocketComponent> components) {
|
||||
if (components == null || components.size() == 0)
|
||||
return false;
|
||||
|
||||
for (RocketComponent component : components) {
|
||||
if (!listContainsParent(components, component) && !canMove(component))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -702,22 +935,40 @@ public class RocketActions {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
RocketComponent selected = selectionModel.getSelectedComponent();
|
||||
if (!canMove(selected))
|
||||
List<RocketComponent> components = selectionModel.getSelectedComponents();
|
||||
if (components == null || components.size() == 0) return;
|
||||
components = new ArrayList<>(components);
|
||||
components.sort(Comparator.comparing(c -> c.getParent() != null ? -c.getParent().getChildPosition(c) : 0));
|
||||
|
||||
if (components.size() == 1) {
|
||||
document.addUndoPosition("Move " + components.get(0).getComponentName());
|
||||
} else {
|
||||
document.addUndoPosition("Move components");
|
||||
}
|
||||
|
||||
for (RocketComponent component : components) {
|
||||
// Only move top components, don't move its children
|
||||
if (!listContainsParent(components, component)) {
|
||||
moveDown(component);
|
||||
}
|
||||
}
|
||||
rocket.fireComponentChangeEvent(ComponentChangeEvent.TREE_CHANGE);
|
||||
selectionModel.setSelectedComponents(components);
|
||||
}
|
||||
|
||||
private void moveDown(RocketComponent component) {
|
||||
if (!canMove(component))
|
||||
return;
|
||||
|
||||
|
||||
ComponentConfigDialog.hideDialog();
|
||||
|
||||
RocketComponent parent = selected.getParent();
|
||||
document.addUndoPosition("Move "+selected.getComponentName());
|
||||
parent.moveChild(selected, parent.getChildPosition(selected)+1);
|
||||
rocket.fireComponentChangeEvent( ComponentChangeEvent.TREE_CHANGE );
|
||||
selectionModel.setSelectedComponent(selected);
|
||||
RocketComponent parent = component.getParent();
|
||||
parent.moveChild(component, parent.getChildPosition(component) + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clipboardChanged() {
|
||||
this.setEnabled(canMove(selectionModel.getSelectedComponent()));
|
||||
this.setEnabled(canMove(selectionModel.getSelectedComponents()));
|
||||
}
|
||||
|
||||
private boolean canMove(RocketComponent c) {
|
||||
@ -728,6 +979,17 @@ public class RocketActions {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean canMove(List<RocketComponent> components) {
|
||||
if (components == null || components.size() == 0)
|
||||
return false;
|
||||
|
||||
for (RocketComponent component : components) {
|
||||
if (!listContainsParent(components, component) && !canMove(component))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user