package krasa.grepconsole.gui.table;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.ui.treeStructure.treetable.TreeTableModelAdapter;
import com.intellij.ui.treeStructure.treetable.TreeTableTree;
import com.intellij.util.ArrayUtil;
import krasa.grepconsole.gui.SettingsDialog;
import javax.activation.ActivationDataFlavor;
import javax.activation.DataHandler;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DragSource;
import java.util.*;
import java.util.List;
public class TableRowTransferHandler extends TransferHandler {
private static final Logger log = Logger.getInstance(TableRowTransferHandler.class.getName());
/* this seems useless */
private final DataFlavor localObjectFlavor = new ActivationDataFlavor(Integer.class,
DataFlavor.javaJVMLocalObjectMimeType, "Integer Row Index");
private CheckboxTreeTable table = null;
private SettingsDialog settingsDialog;
public TableRowTransferHandler(CheckboxTreeTable table, SettingsDialog settingsDialog) {
this.table = table;
this.settingsDialog = settingsDialog;
}
@Override
protected Transferable createTransferable(JComponent c) {
assert (c == table);
return new DataHandler(table.getTree().getSelectionPaths(), localObjectFlavor.getMimeType());
}
@Override
public boolean canImport(TransferHandler.TransferSupport info) {
boolean b = info.getComponent() == table && info.isDrop();
table.setCursor(b ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop);
return b;
}
@Override
public void exportToClipboard(JComponent comp, Clipboard clip, int action) throws IllegalStateException {
return;
}
@Override
public int getSourceActions(JComponent c) {
return TransferHandler.COPY_OR_MOVE;
}
/** this sucks, we all know it */
@SuppressWarnings("unchecked")
@Override
public boolean importData(TransferHandler.TransferSupport info) {
try {
final TreeTableModelAdapter model = (TreeTableModelAdapter) table.getModel();
JTable target = (JTable) info.getComponent();
if (!info.isDrop()) {
return false;
}
JTable.DropLocation dl = (JTable.DropLocation) info.getDropLocation();
int rowTo = dl.getRow();
int indexOffset = 0;
DefaultMutableTreeNode destinationNode = (DefaultMutableTreeNode) model.getValueAt(rowTo, 0);
if (destinationNode == null) {
destinationNode = (DefaultMutableTreeNode) table.getTree().getModel().getRoot();
}
TreeTableTree tree = table.getTree();
int[] selectionRows = tree.getSelectionRows();
Arrays.sort(selectionRows);
selectionRows = ArrayUtil.reverseArray(selectionRows);
java.util.List<DefaultMutableTreeNode> nodesToSelect = new ArrayList<>();
java.util.List<DefaultMutableTreeNode> nodesToExpand = new ArrayList<>();
java.util.List<DefaultMutableTreeNode> selectedNodes = new ArrayList<>();
for (int selectionRow : selectionRows) {
TreePath treePath = tree.getPathForRow(selectionRow);
selectedNodes.add((DefaultMutableTreeNode) treePath.getLastPathComponent());
}
if (destinationNode instanceof GrepExpressionGroupTreeNode) {
// reverse it back
Collections.reverse(selectedNodes);
for (DefaultMutableTreeNode nodeToMove : selectedNodes) {
if (nodeToMove instanceof GrepExpressionGroupTreeNode) {
if (destinationNode == nodeToMove) {
continue;
}
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) destinationNode.getParent();
int index = parent.getIndex(destinationNode);
int nodeToMoveIndex = parent.getIndex(nodeToMove);
if (nodeToMoveIndex < index) {
index--;
}
parent.insert(nodeToMove, index);
} else if (nodeToMove instanceof GrepExpressionItemTreeNode) {
TreeNode parent = destinationNode.getParent();
int index = parent.getIndex(destinationNode);
if (index > 0) {
DefaultMutableTreeNode destinationNode1 = (DefaultMutableTreeNode) parent.getChildAt(index - 1);
destinationNode1.add(nodeToMove);
} else {
destinationNode.add(nodeToMove);
}
nodesToExpand.add(nodeToMove);
}
nodesToSelect.add(nodeToMove);
}
} else if (destinationNode instanceof GrepExpressionItemTreeNode) {
GrepExpressionGroupTreeNode destination = (GrepExpressionGroupTreeNode) destinationNode.getParent();
int index = destination.getIndex(destinationNode) + indexOffset;
for (DefaultMutableTreeNode nodeToMove : selectedNodes) {
if (nodeToMove instanceof GrepExpressionGroupTreeNode) {
if (destination == nodeToMove) {
continue;
}
List<DefaultMutableTreeNode> children = getChildren(nodeToMove);
nodesToSelect.addAll(children);
for (DefaultMutableTreeNode node : children) {
destination.insert(node, index);
index++;
}
} else if (nodeToMove instanceof GrepExpressionItemTreeNode) {
TreeNode parent = nodeToMove.getParent();
if (parent == destination && index > parent.getIndex(nodeToMove)) {
index--;
}
destination.insert(nodeToMove, index);
nodesToSelect.add(nodeToMove);
nodesToExpand.add(nodeToMove);
}
}
} else {
//destinationNode is root
Collections.reverse(selectedNodes);
for (DefaultMutableTreeNode nodeToMove : selectedNodes) {
if (nodeToMove instanceof GrepExpressionGroupTreeNode) {
destinationNode.add(nodeToMove);
nodesToSelect.add(nodeToMove);
} else if (nodeToMove instanceof GrepExpressionItemTreeNode) {
GrepExpressionGroupTreeNode lastChild = (GrepExpressionGroupTreeNode) destinationNode.getLastChild();
lastChild.add(nodeToMove);
nodesToSelect.add(nodeToMove);
}
}
}
TableUtils.reloadTree(table);
TableUtils.expand(nodesToExpand, table);
TableUtils.selectNodes(nodesToSelect, table);
settingsDialog.rebuildProfile();
target.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} catch (Exception e) {
log.error(e);
}
return false;
}
public List<DefaultMutableTreeNode> getChildren(DefaultMutableTreeNode parent) {
Enumeration children = parent.children();
List<DefaultMutableTreeNode> list = new ArrayList<>();
while (children.hasMoreElements()) {
DefaultMutableTreeNode o = (DefaultMutableTreeNode) children.nextElement();
list.add(o);
}
return list;
}
@Override
protected void exportDone(JComponent c, Transferable t, int act) {
if (act == TransferHandler.MOVE) {
table.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}