[Hg]: Multi drag and drop for MQ Unapplied Patch table via Transferred handler

This commit is contained in:
Nadya Zabrodina
2015-08-26 18:37:46 +03:00
parent 4a98357da7
commit de48cf8952
3 changed files with 166 additions and 33 deletions
@@ -30,17 +30,12 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.PopupHandler;
import com.intellij.ui.RowsDnDSupport;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.TableSpeedSearch;
import com.intellij.ui.table.JBTable;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.EditableModel;
import org.jetbrains.annotations.CalledInAwt;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.*;
import org.zmlx.hg4idea.HgUpdater;
import org.zmlx.hg4idea.HgVcs;
import org.zmlx.hg4idea.command.mq.HgQDeleteCommand;
@@ -96,8 +91,10 @@ public class HgMqUnAppliedPatchesPanel extends JPanel implements DataProvider, H
myPatchTable.setFillsViewportHeight(true);
myPatchTable.getEmptyText().setText("Nothing to show");
myPatchTable.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), START_EDITING);
RowsDnDSupport.install(myPatchTable, myPatchTable.getModel());
myPatchTable.setDragEnabled(true);
new TableSpeedSearch(myPatchTable);
myPatchTable.setDropMode(DropMode.INSERT_ROWS);
myPatchTable.setTransferHandler(new TableRowsTransferHandler(myPatchTable));
add(createToolbar(), BorderLayout.WEST);
@@ -201,7 +198,13 @@ public class HgMqUnAppliedPatchesPanel extends JPanel implements DataProvider, H
@NotNull
@CalledInAwt
public List<String> getSelectedPatchNames() {
return ContainerUtil.map(Ints.asList(myPatchTable.getSelectedRows()), new Function<Integer, String>() {
return getPatchNames(myPatchTable.getSelectedRows());
}
@NotNull
@CalledInAny
private List<String> getPatchNames(int[] rows) {
return ContainerUtil.map(Ints.asList(rows), new Function<Integer, String>() {
@Override
public String fun(Integer integer) {
return getPatchName(integer);
@@ -285,7 +288,7 @@ public class HgMqUnAppliedPatchesPanel extends JPanel implements DataProvider, H
model.updatePatches(myRepository.getUnappliedPatchNames());
}
private class MyPatchModel extends AbstractTableModel implements EditableModel {
private class MyPatchModel extends AbstractTableModel implements MultiReorderedModel {
@NotNull private final MqPatchDetails.MqPatchEnum[] myColumnNames = MqPatchDetails.MqPatchEnum.values();
@NotNull private final Map<String, MqPatchDetails> myPatchesWithDetails = ContainerUtil.newHashMap();
@@ -349,30 +352,6 @@ public class HgMqUnAppliedPatchesPanel extends JPanel implements DataProvider, H
myPatches.set(rowIndex, newPatchName);
}
@Override
public void addRow() {
throw new UnsupportedOperationException();
}
@Override
public void exchangeRows(int oldIndex, int newIndex) {
String tmp = myPatches.get(oldIndex);
myPatches.remove(oldIndex);
myPatches.add(newIndex, tmp);
myNeedToUpdateFileContent = true;
fireTableDataChanged();
}
@Override
public boolean canExchangeRows(int oldIndex, int newIndex) {
return true;
}
@Override
public void removeRow(int idx) {
throw new UnsupportedOperationException();
}
public void updatePatches(List<String> newNames) {
myPatches.clear();
myPatches.addAll(newNames);
@@ -380,6 +359,25 @@ public class HgMqUnAppliedPatchesPanel extends JPanel implements DataProvider, H
readMqPatchesDetails();
fireTableDataChanged();
}
@Override
public boolean canMoveRows() {
return true;
}
@Override
public int[] moveRows(int[] rowsIndexes, int destination) {
List<String> names = getPatchNames(rowsIndexes);
myPatches.removeAll(ContainerUtil.newArrayList(names));
int[] selection = new int[rowsIndexes.length];
for (int i = 0; i < rowsIndexes.length; i++) {
selection[i] = destination;
myPatches.add(destination++, names.get(i));
}
myNeedToUpdateFileContent = true;
fireTableDataChanged();
return selection;
}
}
private class MyPatchTable extends JBTable {
@@ -0,0 +1,37 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.zmlx.hg4idea.ui;
/**
* Interface for a Table components to allow multiSelection drag and drop
*/
public interface MultiReorderedModel {
/**
* @return is rows drag and drop possible
*/
boolean canMoveRows();
/**
* Reorder component rows
*
* @param rowsIndexes source array to drag
* @param destination destination index, already updated according to rowsToMove indexes before/after destination
* @return new rows indexes to select
*/
int[] moveRows(int[] rowsIndexes, int destination);
}
@@ -0,0 +1,98 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.zmlx.hg4idea.ui;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.ui.TableUtil;
import javax.activation.ActivationDataFlavor;
import javax.activation.DataHandler;
import javax.swing.*;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DragSource;
public class TableRowsTransferHandler extends TransferHandler {
private static final Logger LOG = Logger.getInstance(TableRowsTransferHandler.class);
private final DataFlavor myDataFlavor = new ActivationDataFlavor(RowsDragInfo.class, DataFlavor.stringFlavor.getMimeType());
private JTable myTable = null;
public TableRowsTransferHandler(JTable table) {
myTable = table;
}
@Override
protected Transferable createTransferable(JComponent c) {
assert (c == myTable);
return new DataHandler(new RowsDragInfo(myTable.getSelectedRows()), myDataFlavor.getMimeType());
}
@Override
public boolean canImport(TransferHandler.TransferSupport support) {
boolean canImport = support.getComponent() == myTable && support.isDrop();
myTable.setCursor(canImport ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop);
return canImport;
}
@Override
public int getSourceActions(JComponent c) {
return TransferHandler.COPY_OR_MOVE;
}
@Override
public boolean importData(TransferHandler.TransferSupport support) {
TableModel tableModel = myTable.getModel();
if (!(tableModel instanceof MultiReorderedModel) || !((MultiReorderedModel)tableModel).canMoveRows()) return false;
JTable.DropLocation dl = (JTable.DropLocation)support.getDropLocation();
int index = dl.getRow();
int max = tableModel.getRowCount();
if (index < 0 || index > max) {
index = max;
}
myTable.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
try {
int[] rows = ((RowsDragInfo)support.getTransferable().getTransferData(myDataFlavor)).myRows;
if (rows != null && rows.length > 0) {
int dist = 0;
for (int row : rows) {
if (index > row) {
dist++;
}
}
index -= dist;
int[] newSelection = ((MultiReorderedModel)tableModel).moveRows(rows, index);
TableUtil.selectRows(myTable, newSelection);
return true;
}
}
catch (Exception e) {
LOG.error("Couldn't move transferred data.");
}
return false;
}
private static class RowsDragInfo {
final int[] myRows;
public RowsDragInfo(int[] rows) {
myRows = rows;
}
}
}