Allow drag and drop reordering in project explorer

This commit is contained in:
Bane Stojkovic
2022-12-07 23:43:05 +01:00
parent a9c4f2807f
commit be996d6494
8 changed files with 247 additions and 26 deletions
@@ -342,16 +342,6 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
// */
// Rectangle2D getSelectedAreaRect();
/**
* Sends each of the selected components one step back.
*/
void sendSelectionToBack();
/**
* Brings each of the selected components one step to front.
*/
void bringSelectionToFront();
/**
* Causes the display to refresh.
*/
@@ -137,5 +137,21 @@ public interface ISelectionProcessor {
*
* @param model
*/
void applyModelToSelection(String[] model);
void applyModelToSelection(String[] model);
/**
* Sends each of the selected components one step back.
*/
void sendSelectionToBack();
/**
* Brings each of the selected components one step to front.
*/
void bringSelectionToFront();
/**
* Move selected components to z index starting from the provided value
* @param zIndex
*/
void moveSelectionToZIndex(int zIndex);
}
@@ -1946,6 +1946,42 @@ public class Presenter implements IPlugInPort {
messageDispatcher.dispatchMessage(EventType.REPAINT);
}
}
@Override
public void moveSelectionToZIndex(int zIndex) {
LOG.info(String.format("moveSelectionToZIndex(%d)", zIndex));
Project oldProject = currentProject.clone();
// sort the selection in Z-order
List<IDIYComponent<?>> selection = new ArrayList<IDIYComponent<?>>(selectedComponents);
Collections.sort(selection, new Comparator<IDIYComponent<?>>() {
@Override
public int compare(IDIYComponent<?> o1, IDIYComponent<?> o2) {
return new Integer(currentProject.getComponents().indexOf(o1))
.compareTo(currentProject.getComponents().indexOf(o2));
}
});
for (IDIYComponent<?> component : selection) {
int index = currentProject.getComponents().indexOf(component);
if (index < 0) {
LOG.warn("Component not found in the project: " + component.getName());
} else {
if (index < zIndex)
zIndex--;
currentProject.getComponents().remove(index);
currentProject.getComponents().add(zIndex, component);
}
}
if (!oldProject.equals(currentProject)) {
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, currentProject,
"Change Z-order");
projectFileManager.notifyFileChange();
messageDispatcher.dispatchMessage(EventType.REPAINT);
}
}
@Override
public void refresh() {
+1
View File
@@ -55,6 +55,7 @@ Box
C-B-E BJT
Circle
Coil(s)
Component reordering is possible only when Project Explorer is sorted by z-index
Configuration
Could not apply changes. Check the log for details.
D-G-S JFET
@@ -0,0 +1,129 @@
/*
*
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
* This file is part of DIYLC.
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.diylc.swing.gui;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import javax.swing.DropMode;
import javax.swing.JList;
import javax.swing.TransferHandler;
public class DragDropList<T> extends JList<T> {
private static final long serialVersionUID = 1L;
public DragDropList(IDragDropListListener listener) {
super();
setDragEnabled(true);
setDropMode(DropMode.INSERT);
setTransferHandler(new MyListDropHandler(this, listener));
new MyDragListener(this);
}
}
class MyDragListener implements DragSourceListener, DragGestureListener {
DragDropList<?> list;
DragSource ds = new DragSource();
public MyDragListener(DragDropList<?> list) {
this.list = list;
ds.createDefaultDragGestureRecognizer(list, DnDConstants.ACTION_MOVE, this);
}
public void dragGestureRecognized(DragGestureEvent dge) {
StringSelection transferable = new StringSelection(Integer.toString(list.getSelectedIndex()));
ds.startDrag(dge, DragSource.DefaultMoveDrop, transferable, this);
}
public void dragEnter(DragSourceDragEvent dsde) {}
public void dragExit(DragSourceEvent dse) {}
public void dragOver(DragSourceDragEvent dsde) {}
public void dragDropEnd(DragSourceDropEvent dsde) {
// if (dsde.getDropSuccess()) {
// System.out.println("Succeeded");
// } else {
// System.out.println("Failed");
// }
}
public void dropActionChanged(DragSourceDragEvent dsde) {}
}
class MyListDropHandler extends TransferHandler {
private static final long serialVersionUID = 1L;
private DragDropList<?> dragDropList;
private IDragDropListListener listener;
public MyListDropHandler() {}
public MyListDropHandler(DragDropList<?> dragDropList, IDragDropListListener listener) {
this.dragDropList = dragDropList;
this.listener = listener;
}
public boolean canImport(TransferHandler.TransferSupport support) {
if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
return false;
}
if (support.getComponent() != dragDropList) {
return false;
}
JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
if (dl.getIndex() == -1) {
return false;
} else {
return true;
}
}
public boolean importData(TransferHandler.TransferSupport support) {
if (!canImport(support)) {
return false;
}
Transferable transferable = support.getTransferable();
String indexString;
try {
indexString = (String) transferable.getTransferData(DataFlavor.stringFlavor);
} catch (Exception e) {
return false;
}
int selectedIndex = Integer.parseInt(indexString);
JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
int dropTargetIndex = dl.getIndex();
return listener.dropComplete(selectedIndex, dropTargetIndex);
}
}
@@ -0,0 +1,22 @@
/*
*
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
* This file is part of DIYLC.
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.diylc.swing.gui;
public interface IDragDropListListener {
boolean dropComplete(int selectedIndex, int dropTargetIndex);
}
@@ -10,6 +10,7 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
@@ -30,18 +31,26 @@ import org.apache.log4j.Logger;
import org.diylc.common.IPlugInPort;
import org.diylc.core.IDIYComponent;
import org.diylc.lang.LangUtil;
import org.diylc.swing.ISwingUI;
import org.diylc.swing.gui.ComponentPopupMenu;
import org.diylc.swing.gui.DragDropList;
import org.diylc.swing.gui.IDragDropListListener;
import org.diylc.swing.gui.SearchTextField;
public class ExplorerPane extends JPanel {
private static final long serialVersionUID = 1L;
private static final String REORDERING_NOT_POSSIBLE = LangUtil.translate(
"Component reordering is possible only when Project Explorer is sorted by z-index.");
private static final Logger LOG = Logger.getLogger(ExplorerPane.class);
public static Font DEFAULT_FONT = new Font("Square721 BT", Font.PLAIN, 12);
private ISwingUI swingUI;
private IPlugInPort plugInPort;
private JTextField searchField;
private JScrollPane componentScrollPane;
private ComponentListModel componentListModel;
@@ -49,8 +58,9 @@ public class ExplorerPane extends JPanel {
private ComponentPopupMenu popupMenu;
private JComboBox<Sort> sortBox;
public ExplorerPane(IPlugInPort plugInPort) {
public ExplorerPane(ISwingUI swingUI, IPlugInPort plugInPort) {
super();
this.swingUI = swingUI;
this.plugInPort = plugInPort;
setName("Project Explorer");
@@ -64,14 +74,6 @@ public class ExplorerPane extends JPanel {
gbc.gridwidth = 1;
add(getSearchField(), gbc);
gbc.gridy++;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0;
gbc.weighty = 0;
add(getSortBox(), gbc);
gbc.gridy++;
@@ -81,6 +83,14 @@ public class ExplorerPane extends JPanel {
add(getComponentScrollPane(), gbc);
gbc.gridy++;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0;
gbc.weighty = 0;
add(getSortBox(), gbc);
setPreferredSize(new Dimension(180, 200));
}
@@ -117,7 +127,18 @@ public class ExplorerPane extends JPanel {
public JList<IDIYComponent<?>> getComponentList() {
if (componentList == null) {
componentList = new JList<IDIYComponent<?>>();
componentList = new DragDropList<IDIYComponent<?>>(new IDragDropListListener() {
@Override
public boolean dropComplete(int selectedIndex, int dropTargetIndex) {
if (getComponentListModel().getSort() != Sort.Z_INDEX) {
swingUI.showMessage(REORDERING_NOT_POSSIBLE, "Error", ISwingUI.ERROR_MESSAGE);
return false;
}
plugInPort.moveSelectionToZIndex(getComponentListModel().getSize() - dropTargetIndex);
return true;
}
});
componentList.setModel(getComponentListModel());
componentList.setFont(DEFAULT_FONT);
componentList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
@@ -183,8 +204,10 @@ public class ExplorerPane extends JPanel {
return popupMenu;
}
public void setComponents(List<IDIYComponent<?>> components) {
public void setComponents(List<IDIYComponent<?>> components,
Collection<IDIYComponent<?>> selectedComponents) {
this.getComponentListModel().setComponents(components);
setSelection(new HashSet<IDIYComponent<?>>(selectedComponents));
}
public void setSelection(Set<IDIYComponent<?>> selectedComponents) {
@@ -230,7 +253,7 @@ public class ExplorerPane extends JPanel {
private List<IDIYComponent<?>> components;
private String searchText;
private Sort sort;
private Sort sort = Sort.Z_INDEX;
public void setComponents(List<IDIYComponent<?>> components) {
this.componentsRaw = components;
@@ -243,6 +266,10 @@ public class ExplorerPane extends JPanel {
return components;
}
public Sort getSort() {
return sort;
}
public void setSort(Sort sort) {
this.sort = sort;
@@ -64,10 +64,10 @@ public class ExplorerPlugin implements IPlugIn {
public void processMessage(EventType eventType, Object... params) {
switch (eventType) {
case PROJECT_MODIFIED:
getExplorerPane().setComponents(((Project)params[1]).getComponents());
getExplorerPane().setComponents(((Project)params[1]).getComponents(), plugInPort.getSelectedComponents());
break;
case PROJECT_LOADED:
getExplorerPane().setComponents(((Project)params[0]).getComponents());
getExplorerPane().setComponents(((Project)params[0]).getComponents(), plugInPort.getSelectedComponents());
break;
case SELECTION_CHANGED:
getExplorerPane().setSelection((Set<IDIYComponent<?>>)params[0]);
@@ -103,7 +103,7 @@ public class ExplorerPlugin implements IPlugIn {
public ExplorerPane getExplorerPane() {
if (explorerPane == null) {
explorerPane = new ExplorerPane(plugInPort);
explorerPane = new ExplorerPane(swingUI, plugInPort);
}
return explorerPane;
}