diff --git a/java/compiler/impl/src/com/intellij/compiler/options/ProcessedModulesTable.java b/java/compiler/impl/src/com/intellij/compiler/options/ProcessedModulesTable.java index 718901122c57..84341f3e049c 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/ProcessedModulesTable.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/ProcessedModulesTable.java @@ -319,6 +319,11 @@ public class ProcessedModulesTable extends JPanel { public void exchangeRows(int oldIndex, int newIndex) { } + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + return false; + } + public void removeElement(Module element) { final boolean reallyRemoved = myElements.remove(element); if (reallyRemoved) { diff --git a/java/compiler/impl/src/com/intellij/compiler/options/ProcessorProfilePanel.java b/java/compiler/impl/src/com/intellij/compiler/options/ProcessorProfilePanel.java index dd5dce226359..403e070b2657 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/ProcessorProfilePanel.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/ProcessorProfilePanel.java @@ -304,6 +304,11 @@ public class ProcessorProfilePanel extends JPanel { public void exchangeRows(int oldIndex, int newIndex) { } + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + return false; + } + public void addRow() { myRows.add(new KeyValuePair()); final int index = myRows.size() - 1; @@ -410,6 +415,11 @@ public class ProcessorProfilePanel extends JPanel { public void exchangeRows(int oldIndex, int newIndex) { } + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + return false; + } + public void addRow() { myRows.add(""); final int index = myRows.size() - 1; diff --git a/java/java-impl/src/com/intellij/refactoring/changeClassSignature/ChangeClassSignatureDialog.java b/java/java-impl/src/com/intellij/refactoring/changeClassSignature/ChangeClassSignatureDialog.java index c35b0b4420b7..b213ff3df308 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeClassSignature/ChangeClassSignatureDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/changeClassSignature/ChangeClassSignatureDialog.java @@ -256,6 +256,11 @@ public class ChangeClassSignatureDialog extends RefactoringDialog { fireTableDataChanged(); //fireTableRowsUpdated(Math.min(index1, index2), Math.max(index1, index2)); } + + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + return true; + } } private class MyCellRenderer extends ColoredTableCellRenderer { diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ExceptionsTableModel.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ExceptionsTableModel.java index 7a36ca5b8cb8..3e49c3d5b9a8 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ExceptionsTableModel.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ExceptionsTableModel.java @@ -64,6 +64,11 @@ public class ExceptionsTableModel extends AbstractTableModel implements Editable } } + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + return true; + } + public int getRowCount() { return myTypeCodeFragments.size(); } diff --git a/java/java-impl/src/com/intellij/refactoring/util/ParameterTablePanel.java b/java/java-impl/src/com/intellij/refactoring/util/ParameterTablePanel.java index dc41ec1a705b..d2985b6a6efb 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/ParameterTablePanel.java +++ b/java/java-impl/src/com/intellij/refactoring/util/ParameterTablePanel.java @@ -400,6 +400,13 @@ public abstract class ParameterTablePanel extends JPanel { myTable.getSelectionModel().setSelectionInterval(targetRow, targetRow); updateSignature(); } + + @Override + public boolean canExchangeRows(int row, int targetRow) { + if (row < 0 || row >= getVariableData().length) return false; + if (targetRow < 0 || targetRow >= getVariableData().length) return false; + return true; + } } private class CheckBoxTableCellRenderer extends BooleanTableCellRenderer { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EditVariableDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EditVariableDialog.java index b9d4f005f254..5852aafa5219 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EditVariableDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EditVariableDialog.java @@ -268,5 +268,10 @@ class EditVariableDialog extends DialogWrapper { public void exchangeRows(int oldIndex, int newIndex) { Collections.swap(myVariables, oldIndex, newIndex); } + + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + return true; + } } } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java index 40ae8e7048f4..744f5d00489b 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java @@ -45,6 +45,7 @@ import com.intellij.util.config.StorageAccessors; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.util.containers.HashMap; +import com.intellij.util.ui.EditableModel; import com.intellij.util.ui.GridBag; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; @@ -77,9 +78,9 @@ class RunConfigurable extends BaseConfigurable { private final Project myProject; private RunDialogBase myRunDialog; @NonNls private final DefaultMutableTreeNode myRoot = new DefaultMutableTreeNode("Root"); - private final Tree myTree = new Tree(myRoot); + private final MyTreeModel myTreeModel = new MyTreeModel(myRoot); + private final Tree myTree = new Tree(myTreeModel); private final JPanel myRightPanel = new JPanel(new BorderLayout()); - private JComponent myToolbarComponent; private final Splitter mySplitter = new Splitter(false); private JPanel myWholePanel; private final StorageAccessors myProperties = StorageAccessors.createGlobal("RunConfigurable"); @@ -89,6 +90,7 @@ class RunConfigurable extends BaseConfigurable { private final JCheckBox myConfirmation = new JCheckBox(ExecutionBundle.message("rerun.confirmation.checkbox"), true); private final List> myAdditionalSettings = new ArrayList>(); private Map myStoredComponents = new HashMap(); + private ToolbarDecorator myToolbarDecorator; public RunConfigurable(final Project project) { this(project, null); @@ -130,7 +132,6 @@ class RunConfigurable extends BaseConfigurable { return o.toString(); } }); - PopupHandler.installFollowingSelectionTreePopup(myTree, createActionsGroup(), ActionPlaces.UNKNOWN, ActionManager.getInstance()); myTree.setCellRenderer(new ColoredTreeCellRenderer() { public void customizeCellRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { @@ -415,17 +416,11 @@ class RunConfigurable extends BaseConfigurable { } private JPanel createLeftPanel() { - final JPanel leftPanel = new JPanel(new BorderLayout()); - myToolbarComponent = ActionManager.getInstance(). - createActionToolbar(ActionPlaces.UNKNOWN, - createActionsGroup(), - true).getComponent(); - leftPanel.add(myToolbarComponent, BorderLayout.NORTH); initTree(); - final JScrollPane pane = ScrollPaneFactory.createScrollPane(myTree); - pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); - leftPanel.add(pane, BorderLayout.CENTER); - return leftPanel; + DefaultActionGroup actionsGroup = createActionsGroup(); + PopupHandler.installFollowingSelectionTreePopup(myTree, actionsGroup, ActionPlaces.UNKNOWN, ActionManager.getInstance()); + myToolbarDecorator = ToolbarDecorator.createDecorator(myTree).setActionGroup(actionsGroup).setForcedDnD(); + return myToolbarDecorator.createPanel(); } private JPanel createSettingsPanel() { @@ -990,7 +985,7 @@ class RunConfigurable extends BaseConfigurable { }); //new TreeSpeedSearch(myTree); - popup.showUnderneathOf(myToolbarComponent); + popup.showUnderneathOf(myToolbarDecorator.getPanel()); } } @@ -1106,7 +1101,7 @@ class RunConfigurable extends BaseConfigurable { configurable.getNameTextField().setSelectionEnd(copyName.length()); } catch (ConfigurationException e1) { - Messages.showErrorDialog(myToolbarComponent, e1.getMessage(), e1.getTitle()); + Messages.showErrorDialog(myToolbarDecorator.getPanel(), e1.getMessage(), e1.getTitle()); } } @@ -1264,4 +1259,57 @@ class RunConfigurable extends BaseConfigurable { void clickDefaultButton(); } + + private class MyTreeModel extends DefaultTreeModel implements EditableModel { + private MyTreeModel(MutableTreeNode root) { + super(root); + } + + @Override + public void addRow() { + } + + @Override + public void removeRow(int index) { + } + + @Override + public void exchangeRows(int oldIndex, int newIndex) { + DefaultMutableTreeNode oldNode = (DefaultMutableTreeNode)myTree.getPathForRow(oldIndex).getLastPathComponent(); + DefaultMutableTreeNode newNode = (DefaultMutableTreeNode)myTree.getPathForRow(newIndex).getLastPathComponent(); + DefaultMutableTreeNode parent = (DefaultMutableTreeNode)oldNode.getParent(); + oldIndex = parent.getIndex(oldNode); + newIndex = parent.getIndex(newNode); + parent.insert(oldNode, newIndex); + parent.insert(newNode, oldIndex); + reload(parent); + } + + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + DefaultMutableTreeNode oldNode = (DefaultMutableTreeNode)myTree.getPathForRow(oldIndex).getLastPathComponent(); + DefaultMutableTreeNode newNode = (DefaultMutableTreeNode)myTree.getPathForRow(newIndex).getLastPathComponent(); + DefaultMutableTreeNode parent = (DefaultMutableTreeNode)oldNode.getParent(); + if (parent == newNode.getParent()) { + RunnerAndConfigurationSettings oldSettings = getSettings(oldNode); + RunnerAndConfigurationSettings newSettings = getSettings(newNode); + if (oldSettings != null && newSettings != null && oldSettings.isTemporary() == newSettings.isTemporary()) { + return true; + } + } + return false; + } + + @Nullable + private RunnerAndConfigurationSettings getSettings(@NotNull DefaultMutableTreeNode treeNode) { + Object userObject = treeNode.getUserObject(); + if (userObject instanceof SingleConfigurationConfigurable) { + SingleConfigurationConfigurable configurable = (SingleConfigurationConfigurable)userObject; + return (RunnerAndConfigurationSettings)configurable.getSettings(); + } else if (userObject instanceof RunnerAndConfigurationSettings) { + return (RunnerAndConfigurationSettings)userObject; + } + return null; + } + } } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java index 58ba805b5f96..515c50632d28 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java @@ -513,11 +513,21 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, } } } - for (BeforeRunTask task : tasks) { + for (int i = 0, size = tasks.size(); i < size; i++) { + BeforeRunTask task = tasks.get(i); if (templateTasks != null) { - BeforeRunTask templateTask = templateTasks.get(task.getProviderId()); - if (task.equals(templateTask)) - continue; // not neccesary saving if the task is the same as template + int j = 0; + BeforeRunTask templateTask = null; + for (Map.Entry, BeforeRunTask> entry : templateTasks.entrySet()) { + if (entry.getKey() == task.getProviderId()) { + templateTask = entry.getValue(); + break; + } + j++; + } + if (task.equals(templateTask) && i == j) { + continue; // not neccesary saving if the task is the same as template and on the same place + } } final Element child = new Element(OPTION); child.setAttribute(NAME_ATTR, task.getProviderId().toString()); diff --git a/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractParameterTablePanel.java b/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractParameterTablePanel.java index 7968ca5edd61..4c21108a50d4 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractParameterTablePanel.java +++ b/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractParameterTablePanel.java @@ -216,5 +216,12 @@ public abstract class AbstractParameterTablePanel extends JPanel { myTable.getSelectionModel().setSelectionInterval(targetRow, targetRow); updateSignature(); } + + @Override + public boolean canExchangeRows(int row, int targetRow) { + if (row < 0 || row >= getVariableData().length) return false; + if (targetRow < 0 || targetRow >= getVariableData().length) return false; + return true; + } } } diff --git a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorSettingsTable.java b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorSettingsTable.java index 1fbddd66a95d..c4c067655110 100644 --- a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorSettingsTable.java +++ b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorSettingsTable.java @@ -258,6 +258,11 @@ public abstract class FileColorSettingsTable extends JBTable { myConfigurations.add(newIndex, myConfigurations.remove(oldIndex)); fireTableRowsUpdated(Math.min(oldIndex, newIndex), Math.max(oldIndex, newIndex)); } + + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + return true; + } } private static class ScopeNameRenderer extends JLabel implements TableCellRenderer { diff --git a/platform/platform-api/src/com/intellij/ui/CollectionListModel.java b/platform/platform-api/src/com/intellij/ui/CollectionListModel.java index 12ddaa9bff41..86e7190e0126 100644 --- a/platform/platform-api/src/com/intellij/ui/CollectionListModel.java +++ b/platform/platform-api/src/com/intellij/ui/CollectionListModel.java @@ -16,6 +16,7 @@ package com.intellij.ui; +import com.intellij.util.ui.EditableModel; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -24,7 +25,7 @@ import java.util.*; /** * @author yole */ -public class CollectionListModel extends AbstractListModel { +public class CollectionListModel extends AbstractListModel implements EditableModel { private final List myItems; public CollectionListModel(@NotNull final List items) { @@ -99,6 +100,27 @@ public class CollectionListModel extends AbstractListModel { add(elements); } + @Override + public void addRow() { + } + + @Override + public void removeRow(int index) { + remove(index); + } + + @Override + public void exchangeRows(int oldIndex, int newIndex) { + Collections.swap(myItems, oldIndex, newIndex); + fireContentsChanged(this, oldIndex, oldIndex); + fireContentsChanged(this, newIndex, newIndex); + } + + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + return true; + } + @Override public String toString() { return getClass().getName() + " (" + getSize() + " elements)"; diff --git a/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java index 7c458e2cb95d..7736d79e5876 100644 --- a/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java +++ b/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java @@ -15,6 +15,8 @@ */ package com.intellij.ui; +import com.intellij.util.ui.EditableModel; + import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; @@ -111,4 +113,14 @@ class ListToolbarDecorator extends ToolbarDecorator { myList.setVisibleRowCount(rowCount); return this; } + + @Override + protected boolean isModelEditable() { + return myList.getModel() instanceof EditableModel; + } + + @Override + protected void installDnDSupport() { + RowsDnDSupport.install(myList, (EditableModel)myList.getModel()); + } } diff --git a/platform/platform-api/src/com/intellij/ui/RowsDnDSupport.java b/platform/platform-api/src/com/intellij/ui/RowsDnDSupport.java new file mode 100644 index 000000000000..1a8438cc511e --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/RowsDnDSupport.java @@ -0,0 +1,178 @@ +/* + * Copyright 2000-2011 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 com.intellij.ui; + +import com.intellij.ide.dnd.*; +import com.intellij.ui.awt.RelativeRectangle; +import com.intellij.util.Function; +import com.intellij.util.ui.EditableModel; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class RowsDnDSupport { + private RowsDnDSupport() { + } + + public static void install(@NotNull final JTable table, @NotNull final EditableModel model) { + table.setDragEnabled(true); + installImpl(table, model); + } + + public static void install(@NotNull final JList list, @NotNull final EditableModel model) { + list.setDragEnabled(true); + installImpl(list, model); + } + + public static void install(@NotNull final JTree tree, @NotNull final EditableModel model) { + tree.setDragEnabled(true); + installImpl(tree, model); + } + + private static void installImpl(@NotNull final JComponent component, @NotNull final EditableModel model) { + DnDSupport.createBuilder(component) + .setBeanProvider(new Function() { + @Override + public DnDDragStartBean fun(DnDActionInfo info) { + final Point p = info.getPoint(); + return new DnDDragStartBean(new RowDragInfo(component, Integer.valueOf(getRow(component, p)))); + } + }) + .setTargetChecker(new DnDTargetChecker() { + @Override + public boolean update(DnDEvent event) { + final Object o = event.getAttachedObject(); + event.setDropPossible(o instanceof RowDragInfo && ((RowDragInfo)o).component == component); + int oldIndex = ((RowDragInfo)o).row; + int newIndex = getRow(component, event.getPoint()); + if (oldIndex != newIndex && newIndex != -1 && model.canExchangeRows(oldIndex, newIndex)) { + Rectangle cellBounds = getCellBounds(component, newIndex); + if (oldIndex < newIndex) { + cellBounds.y += cellBounds.height - 2; + } + RelativeRectangle rectangle = new RelativeRectangle(component, cellBounds); + rectangle.getDimension().height = 2; + event.setHighlighting(rectangle, 2); + } + else { + event.setDropPossible(false); + event.hideHighlighter(); + } + return false; + } + }) + .setDropHandler(new DnDDropHandler() { + @Override + public void drop(DnDEvent event) { + final Object o = event.getAttachedObject(); + final Point p = event.getPoint(); + if (o instanceof RowDragInfo && ((RowDragInfo)o).component == component) { + int oldIndex = ((RowDragInfo)o).row; + if (oldIndex == -1) return; + int newIndex = getRow(component, p); + if (newIndex == -1) { + newIndex = getRowCount(component) - 1; + } + if (model.canExchangeRows(oldIndex, newIndex)) { + int min = Math.min(oldIndex, newIndex); + int max = Math.max(oldIndex, newIndex); + if (newIndex > oldIndex) { + while (min < max) { + model.exchangeRows(min, min + 1); + min++; + } + setSelectedRow(component, min); + } + else { + while (max > min) { + model.exchangeRows(max, max - 1); + max--; + } + setSelectedRow(component, max); + } + } + } + event.hideHighlighter(); + } + }) + .install(); + + } + + private static int getRow(JComponent component, Point point) { + if (component instanceof JTable) { + return ((JTable)component).rowAtPoint(point); + } else if (component instanceof JList) { + return ((JList)component).locationToIndex(point); + } else if (component instanceof JTree) { + return ((JTree)component).getRowForLocation(point.x, point.y); + } else { + throw new IllegalArgumentException("Unsupported component: " + component); + } + } + + private static int getRowCount(JComponent component) { + if (component instanceof JTable) { + return ((JTable)component).getRowCount(); + } else if (component instanceof JList) { + return ((JList)component).getModel().getSize(); + } else if (component instanceof JTree) { + return ((JTree)component).getRowCount(); + } else { + throw new IllegalArgumentException("Unsupported component: " + component); + } + } + + private static Rectangle getCellBounds(JComponent component, int row) { + if (component instanceof JTable) { + Rectangle rectangle = ((JTable)component).getCellRect(row, 0, true); + rectangle.width = component.getWidth(); + return rectangle; + } else if (component instanceof JList) { + return ((JList)component).getCellBounds(row, row); + } else if (component instanceof JTree) { + return ((JTree)component).getRowBounds(row); + } else { + throw new IllegalArgumentException("Unsupported component: " + component); + } + } + + private static void setSelectedRow(JComponent component, int row) { + if (component instanceof JTable) { + ((JTable)component).getSelectionModel().setSelectionInterval(row, row); + } else if (component instanceof JList) { + ((JList)component).setSelectedIndex(row); + } else if (component instanceof JTree) { + ((JTree)component).setSelectionRow(row); + } else { + throw new IllegalArgumentException("Unsupported component: " + component); + } + } + + private static class RowDragInfo { + public final JComponent component; + public final int row; + + RowDragInfo(JComponent component, int row) { + this.component = component; + this.row = row; + } + } +} diff --git a/platform/platform-api/src/com/intellij/ui/TableRowsDnDSupport.java b/platform/platform-api/src/com/intellij/ui/TableRowsDnDSupport.java deleted file mode 100644 index d199d2694e61..000000000000 --- a/platform/platform-api/src/com/intellij/ui/TableRowsDnDSupport.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2000-2011 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 com.intellij.ui; - -import com.intellij.ide.dnd.*; -import com.intellij.util.Function; -import com.intellij.util.ui.EditableModel; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; -import javax.swing.table.TableCellEditor; -import java.awt.*; - -/** - * @author Konstantin Bulenkov - */ -public class TableRowsDnDSupport { - private TableRowsDnDSupport() { - } - - public static void install(@NotNull final JTable table, @NotNull final EditableModel model) { - table.setDragEnabled(true); - //table.setDropMode(DropMode.ON); - DnDSupport.createBuilder(table) - .setBeanProvider(new Function() { - @Override - public DnDDragStartBean fun(DnDActionInfo info) { - final Point p = info.getPoint(); - final TableCellEditor cellEditor = table.getCellEditor(); - if (cellEditor != null) { - cellEditor.stopCellEditing(); - } - return new DnDDragStartBean(new TableRowDragInfo(table, Integer.valueOf(table.rowAtPoint(p)))); - } - }) - .setTargetChecker(new DnDTargetChecker() { - @Override - public boolean update(DnDEvent event) { - final Object o = event.getAttachedObject(); - event.setDropPossible(o instanceof TableRowDragInfo && ((TableRowDragInfo)o).table == table); - return false; - } - }) - .setDropHandler(new DnDDropHandler() { - @Override - public void drop(DnDEvent event) { - final Object o = event.getAttachedObject(); - final Point p = event.getPoint(); - if (o instanceof TableRowDragInfo && ((TableRowDragInfo)o).table == table) { - int oldIndex = ((TableRowDragInfo)o).row; - if (oldIndex == -1) return; - int newIndex = table.rowAtPoint(p); - if (newIndex == -1) { - newIndex = table.getRowCount() - 1; - } - int min = Math.min(oldIndex, newIndex); - int max = Math.max(oldIndex, newIndex); - if (newIndex > oldIndex) { - while (min < max) { - model.exchangeRows(min, min + 1); - min++; - } - table.getSelectionModel().setSelectionInterval(min, min); - } - else { - while (max > min) { - model.exchangeRows(max, max - 1); - max--; - } - table.getSelectionModel().setSelectionInterval(max, max); - } - } - } - }).install(); - } - - static class TableRowDragInfo { - public final JTable table; - public final int row; - - TableRowDragInfo(JTable table, int row) { - this.table = table; - this.row = row; - } - } -} diff --git a/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java index 5b76354a1973..407b03341389 100644 --- a/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java +++ b/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java @@ -15,7 +15,6 @@ */ package com.intellij.ui; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.util.ui.EditableModel; import com.intellij.util.ui.ElementProducer; import com.intellij.util.ui.ListTableModel; @@ -39,8 +38,8 @@ class TableToolbarDecorator extends ToolbarDecorator { TableToolbarDecorator(@NotNull JTable table, @Nullable final ElementProducer producer) { myTable = table; myProducer = producer; - myAddActionEnabled = myRemoveActionEnabled = myUpActionEnabled = myDownActionEnabled = myTable.getModel() instanceof EditableModel; - if (myTable.getModel() instanceof EditableModel) { + myAddActionEnabled = myRemoveActionEnabled = myUpActionEnabled = myDownActionEnabled = isModelEditable(); + if (isModelEditable()) { createDefaultTableActions(producer); } myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @@ -191,12 +190,11 @@ class TableToolbarDecorator extends ToolbarDecorator { } @Override - protected void installDnD() { - if (myUpAction != null && myUpActionEnabled - && myDownAction != null && myDownActionEnabled - && !ApplicationManager.getApplication().isHeadlessEnvironment() - && myTable.getModel() instanceof EditableModel) { - TableRowsDnDSupport.install(myTable, (EditableModel)myTable.getModel()); - } + protected void installDnDSupport() { + RowsDnDSupport.install(myTable, (EditableModel)myTable.getModel()); + } + + protected boolean isModelEditable() { + return myTable.getModel() instanceof EditableModel; } } diff --git a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java index 87fbe17a5258..256160799b14 100644 --- a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java +++ b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java @@ -17,6 +17,7 @@ package com.intellij.ui; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.border.CustomLineBorder; @@ -80,12 +81,13 @@ public abstract class ToolbarDecorator implements DataProvider, CommonActionsPan private Comparator myButtonComparator; private boolean myAsTopToolbar = false; private Icon myAddIcon; + private boolean myForcedDnD = false; protected abstract JComponent getComponent(); protected abstract void updateButtons(); - final CommonActionsPanel getPanel() { + public final CommonActionsPanel getPanel() { return myPanel; } @@ -273,6 +275,20 @@ public abstract class ToolbarDecorator implements DataProvider, CommonActionsPan return this; } + public ToolbarDecorator setForcedDnD() { + myForcedDnD = true; + return this; + + } + + public ToolbarDecorator setActionGroup(@NotNull ActionGroup actionGroup) { + AnAction[] actions = actionGroup.getChildren(null); + for (AnAction action : actions) { + addExtraAction(AnActionButton.fromAction(action)); + } + return this; + } + public ToolbarDecorator setPreferredSize(Dimension size) { myPreferredSize = size; return this; @@ -354,8 +370,18 @@ public abstract class ToolbarDecorator implements DataProvider, CommonActionsPan } protected void installDnD() { + if ((myForcedDnD || (myUpAction != null && myUpActionEnabled + && myDownAction != null && myDownActionEnabled)) + && !ApplicationManager.getApplication().isHeadlessEnvironment() + && isModelEditable()) { + installDnDSupport(); + } } + protected abstract void installDnDSupport(); + + protected abstract boolean isModelEditable(); + @Override public Object getData(@NonNls String dataId) { if (PlatformDataKeys.ACTIONS_SORTER.is(dataId)) { diff --git a/platform/platform-api/src/com/intellij/ui/TreeToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/TreeToolbarDecorator.java index 4b10c2e0d0e8..9cfe8a95b792 100644 --- a/platform/platform-api/src/com/intellij/ui/TreeToolbarDecorator.java +++ b/platform/platform-api/src/com/intellij/ui/TreeToolbarDecorator.java @@ -18,6 +18,7 @@ package com.intellij.ui; import com.intellij.openapi.actionSystem.ActionToolbarPosition; import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.treeStructure.SimpleNode; +import com.intellij.util.ui.EditableModel; import com.intellij.util.ui.EditableTreeModel; import com.intellij.util.ui.ElementProducer; import com.intellij.util.ui.tree.TreeUtil; @@ -123,4 +124,14 @@ class TreeToolbarDecorator extends ToolbarDecorator { myTree.setVisibleRowCount(rowCount); return this; } + + @Override + protected boolean isModelEditable() { + return myTree.getModel() instanceof EditableModel; + } + + @Override + protected void installDnDSupport() { + RowsDnDSupport.install(myTree, (EditableModel)myTree.getModel()); + } } diff --git a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTableModel.java b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTableModel.java index 318fbf380d1a..0dce4bb1dba4 100644 --- a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTableModel.java +++ b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTableModel.java @@ -85,6 +85,14 @@ public abstract class JBListTableModel extends AbstractTableModel implements Edi fireTableRowsDeleted(index, index); } + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + if (myModel instanceof EditableModel) { + return ((EditableModel)myModel).canExchangeRows(oldIndex, newIndex); + } + return false; + } + @Override public void exchangeRows(int oldIndex, int newIndex) { if (myModel instanceof EditableModel) { diff --git a/platform/util/src/com/intellij/util/ui/EditableModel.java b/platform/util/src/com/intellij/util/ui/EditableModel.java index ab1c522943b3..f468979965b2 100644 --- a/platform/util/src/com/intellij/util/ui/EditableModel.java +++ b/platform/util/src/com/intellij/util/ui/EditableModel.java @@ -25,4 +25,6 @@ public interface EditableModel { void removeRow(int index); void exchangeRows(int oldIndex, int newIndex); + + boolean canExchangeRows(int oldIndex, int newIndex); } diff --git a/platform/util/src/com/intellij/util/ui/ListTableModel.java b/platform/util/src/com/intellij/util/ui/ListTableModel.java index 7eb77f1c826b..09028186666e 100644 --- a/platform/util/src/com/intellij/util/ui/ListTableModel.java +++ b/platform/util/src/com/intellij/util/ui/ListTableModel.java @@ -160,6 +160,11 @@ public class ListTableModel extends TableViewModel implements ItemRe } } + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + return true; + } + public void addRow(Item item) { myItems.add(item); fireTableRowsInserted(myItems.size() - 1, myItems.size() - 1); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java index 32895e611535..ffbba118b5a6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java @@ -71,6 +71,10 @@ public class GrParameterTableModel extends AbstractTableModel implements Editabl fireTableRowsUpdated(Math.min(index1, index2), Math.max(index1, index2)); } + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + return true; + } public int getRowCount() { return infos.size(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java index 09da21bc3bce..db93d9e8aab7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java @@ -249,6 +249,13 @@ public abstract class ParameterTablePanel extends JPanel { updateSignature(); } + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + if (oldIndex < 0 || newIndex < 0) return false; + if (oldIndex >= myParameterInfos.length || newIndex >= myParameterInfos.length) return false; + return true; + } + public int getRowCount() { return myParameterInfos.length; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java index 4ba4e6383b7f..a18506460cae 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java @@ -102,6 +102,15 @@ public class SvnHistoryProvider @Override protected void updateButtons() { } + + @Override + protected void installDnDSupport() { + } + + @Override + protected boolean isModelEditable() { + return false; + } }.initPosition() .addExtraAction(AnActionButton.fromAction(sourceAction)) .createPanel();