rewrite toolbar decorator to make it easy to support new components

This commit is contained in:
Konstantin Bulenkov
2011-08-22 11:12:12 +02:00
parent 8774dbe130
commit 47429a6399
4 changed files with 338 additions and 246 deletions
@@ -0,0 +1,81 @@
/*
* 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 javax.swing.*;
/**
* @author Konstantin Bulenkov
*/
class ListToolbarDecorator extends ToolbarDecorator {
private final JList myList;
ListToolbarDecorator(JList list) {
myList = list;
myAddActionEnabled = myRemoveActionEnabled = myUpActionEnabled = myDownActionEnabled = true;
createActions();
}
private void createActions() {
myRemoveAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
ListUtil.removeSelectedItems(myList);
updateButtons();
}
};
myUpAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
ListUtil.moveSelectedItemsUp(myList);
updateButtons();
}
};
myDownAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
ListUtil.moveSelectedItemsDown(myList);
updateButtons();
}
};
}
@Override
protected JComponent getComponent() {
return myList;
}
@Override
protected void updateButtons() {
final AddRemoveUpDownPanel p = getPanel();
if (myList.isEnabled() && p != null) {
final int index = myList.getSelectedIndex();
if (0 <= index && index < myList.getModel().getSize()) {
final boolean downEnable = myList.getMaxSelectionIndex() < myList.getModel().getSize() - 1;
final boolean upEnable = myList.getMinSelectionIndex() > 0;
p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, true);
p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, upEnable);
p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, downEnable);
} else {
p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, false);
p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, false);
p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, false);
}
p.setEnabled(AddRemoveUpDownPanel.Buttons.ADD, true);
}
}
}
@@ -0,0 +1,170 @@
/*
* 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.openapi.application.ApplicationManager;
import com.intellij.util.ui.EditableModel;
import com.intellij.util.ui.ElementProducer;
import com.intellij.util.ui.ListTableModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableModel;
import java.awt.*;
/**
* @author Konstantin Bulenkov
*/
class TableToolbarDecorator extends ToolbarDecorator {
private final JTable myTable;
private TableModel myTableModel;
TableToolbarDecorator(@NotNull JTable table, @Nullable final ElementProducer<?> producer) {
myTable = table;
myTableModel = table.getModel();
myAddActionEnabled = myRemoveActionEnabled = myUpActionEnabled = myDownActionEnabled = myTableModel instanceof EditableModel;
if (myTableModel instanceof EditableModel) {
createDefaultTableActions(producer);
}
myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
updateButtons();
}
});
}
@Override
protected JComponent getComponent() {
return myTable;
}
protected void updateButtons() {
final AddRemoveUpDownPanel p = getPanel();
if (myTable.isEnabled() && p != null) {
final int index = myTable.getSelectedRow();
final int size = myTableModel.getRowCount();
if (0 <= index && index < size) {
final boolean downEnable = myTable.getSelectionModel().getMaxSelectionIndex() < size - 1;
final boolean upEnable = myTable.getSelectionModel().getMinSelectionIndex() > 0;
p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, true);
p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, upEnable);
p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, downEnable);
} else {
p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, false);
p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, false);
p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, false);
}
p.setEnabled(AddRemoveUpDownPanel.Buttons.ADD, true);
}
}
private void createDefaultTableActions(@Nullable final ElementProducer<?> producer) {
final JTable table = myTable;
final EditableModel tableModel = (EditableModel)myTableModel;
myAddAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
TableUtil.stopEditing(table);
final int rowCount = table.getRowCount();
if (tableModel instanceof ListTableModel && producer != null) {
//noinspection unchecked
((ListTableModel)tableModel).addRow(producer.createElement());
} else {
tableModel.addRow();
}
if (rowCount == table.getRowCount()) return;
final int index = myTableModel.getRowCount() - 1;
table.editCellAt(index, 0);
table.setRowSelectionInterval(index, index);
table.setColumnSelectionInterval(0, 0);
table.getParent().repaint();
final Component editorComponent = table.getEditorComponent();
if (editorComponent != null) {
final Rectangle bounds = editorComponent.getBounds();
table.scrollRectToVisible(bounds);
editorComponent.requestFocus();
}
}
};
myRemoveAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
TableUtil.stopEditing(table);
int index = table.getSelectedRow();
if (0 <= index && index < myTableModel.getRowCount()) {
tableModel.removeRow(index);
if (index < myTableModel.getRowCount()) {
table.setRowSelectionInterval(index, index);
}
else {
if (index > 0) {
table.setRowSelectionInterval(index - 1, index - 1);
}
}
updateButtons();
}
table.getParent().repaint();
table.requestFocus();
}
};
myUpAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
TableUtil.stopEditing(table);
final int[] indexes = table.getSelectedRows();
for (int index : indexes) {
if (0 < index && index < myTableModel.getRowCount()) {
tableModel.exchangeRows(index, index - 1);
table.setRowSelectionInterval(index - 1, index - 1);
}
}
table.requestFocus();
}
};
myDownAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
TableUtil.stopEditing(table);
final int[] indexes = table.getSelectedRows();
for (int index : indexes) {
if (0 <= index && index < myTableModel.getRowCount() - 1) {
tableModel.exchangeRows(index, index + 1);
table.setRowSelectionInterval(index + 1, index + 1);
}
}
table.requestFocus();
}
};
}
@Override
protected void installDnD() {
if (myUpAction != null && myUpActionEnabled
&& myDownAction != null && myDownActionEnabled
&& !ApplicationManager.getApplication().isHeadlessEnvironment()) {
TableRowsDnDSupport.install(myTable, (EditableModel)myTableModel);
}
}
}
@@ -17,24 +17,17 @@ 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.SystemInfo;
import com.intellij.ui.border.CustomLineBorder;
import com.intellij.ui.table.TableView;
import com.intellij.util.ui.EditableModel;
import com.intellij.util.ui.ElementProducer;
import com.intellij.util.ui.ListTableModel;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableModel;
import java.awt.*;
import java.util.ArrayList;
import java.util.Comparator;
@@ -44,23 +37,20 @@ import java.util.List;
* @author Konstantin Bulenkov
*/
@SuppressWarnings("UnusedDeclaration")
public class ToolbarDecorator implements DataProvider, AddRemoveUpDownPanel.ListenerFactory {
private JTable myTable;
private JTree myTree;
private TableModel myTableModel;
public abstract class ToolbarDecorator implements DataProvider, AddRemoveUpDownPanel.ListenerFactory {
private ListModel myListModel;
private Border myToolbarBorder;
private boolean myAddActionEnabled;
private boolean myRemoveActionEnabled;
private boolean myUpActionEnabled;
private boolean myDownActionEnabled;
private Border myBorder;
protected Border myToolbarBorder;
protected boolean myAddActionEnabled;
protected boolean myRemoveActionEnabled;
protected boolean myUpActionEnabled;
protected boolean myDownActionEnabled;
protected Border myBorder;
private List<AnActionButton> myExtraActions = new ArrayList<AnActionButton>();
private ActionToolbarPosition myToolbarPosition;
private AnActionButtonRunnable myAddAction;
private AnActionButtonRunnable myRemoveAction;
private AnActionButtonRunnable myUpAction;
private AnActionButtonRunnable myDownAction;
protected AnActionButtonRunnable myAddAction;
protected AnActionButtonRunnable myRemoveAction;
protected AnActionButtonRunnable myUpAction;
protected AnActionButtonRunnable myDownAction;
private String myAddName;
private String myRemoveName;
private String myMoveUpName;
@@ -69,6 +59,15 @@ public class ToolbarDecorator implements DataProvider, AddRemoveUpDownPanel.List
private AddRemoveUpDownPanel myPanel;
private JList myList;
public ToolbarDecorator() {
}
protected abstract JComponent getComponent();
protected abstract void updateButtons();
final AddRemoveUpDownPanel getPanel() {
return myPanel;
}
private static final Comparator<AnAction> ACTION_BUTTONS_SORTER = new Comparator<AnAction>() {
@Override
public int compare(AnAction a1, AnAction a2) {
@@ -79,214 +78,33 @@ public class ToolbarDecorator implements DataProvider, AddRemoveUpDownPanel.List
}
return 0;
}
};
};
private ToolbarDecorator(JTable table) {
myTable = table;
myTableModel = table.getModel();
initPositionAndBorder();
myAddActionEnabled = myRemoveActionEnabled = myUpActionEnabled = myDownActionEnabled = myTableModel instanceof EditableModel;
if (myTableModel instanceof EditableModel) {
createDefaultTableActions(null);
}
}
private ToolbarDecorator(JList list) {
myList = list;
myListModel = list.getModel();
myAddActionEnabled = myRemoveActionEnabled = myUpActionEnabled = myDownActionEnabled = true;
initPositionAndBorder();
createDefaultListActions();
}
private <T> ToolbarDecorator(TableView<T> table, ElementProducer<T> producer) {
myTable = table;
myTableModel = table.getListTableModel();
initPositionAndBorder();
myAddActionEnabled = myRemoveActionEnabled = myUpActionEnabled = myDownActionEnabled = myTableModel instanceof ListTableModel;
if (myTableModel instanceof ListTableModel) {
createDefaultTableActions(producer);
}
}
public ToolbarDecorator(JTree tree) {
myTree = tree;
initPositionAndBorder();
}
private void createDefaultListActions() {
myRemoveAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
ListUtil.removeSelectedItems(myList);
updateListButtons(myList, myPanel);
}
};
myUpAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
ListUtil.moveSelectedItemsUp(myList);
updateListButtons(myList, myPanel);
}
};
myDownAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
ListUtil.moveSelectedItemsDown(myList);
updateListButtons(myList, myPanel);
}
};
}
private void initPositionAndBorder() {
myToolbarPosition = SystemInfo.isMac ? ActionToolbarPosition.BOTTOM : myTree == null ? ActionToolbarPosition.RIGHT : ActionToolbarPosition.TOP;
protected ToolbarDecorator initPositionAndBorder() {
myToolbarPosition = SystemInfo.isMac ? ActionToolbarPosition.BOTTOM : ActionToolbarPosition.RIGHT;
myBorder = SystemInfo.isMac ? new CustomLineBorder(0,1,1,1) : new CustomLineBorder(0, 1, 0, 0);
if (myTable != null) {
myTable.setBorder(IdeBorderFactory.createEmptyBorder(0));
}
if (myTree != null) {
myTree.setBorder(IdeBorderFactory.createEmptyBorder(0));
final JComponent c = getComponent();
if (c != null) {
c.setBorder(IdeBorderFactory.createEmptyBorder(0));
}
return this;
}
private void createDefaultTableActions(@Nullable final ElementProducer<?> producer) {
final JTable table = myTable;
final EditableModel tableModel = (EditableModel)myTableModel;
myAddAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
TableUtil.stopEditing(table);
final int rowCount = table.getRowCount();
if (tableModel instanceof ListTableModel && producer != null) {
//noinspection unchecked
((ListTableModel)tableModel).addRow(producer.createElement());
} else {
tableModel.addRow();
}
if (rowCount == table.getRowCount()) return;
final int index = myTableModel.getRowCount() - 1;
table.editCellAt(index, 0);
table.setRowSelectionInterval(index, index);
table.setColumnSelectionInterval(0, 0);
table.getParent().repaint();
final Component editorComponent = table.getEditorComponent();
if (editorComponent != null) {
final Rectangle bounds = editorComponent.getBounds();
table.scrollRectToVisible(bounds);
editorComponent.requestFocus();
}
}
};
myRemoveAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
TableUtil.stopEditing(table);
int index = table.getSelectedRow();
if (0 <= index && index < myTableModel.getRowCount()) {
tableModel.removeRow(index);
if (index < myTableModel.getRowCount()) {
table.setRowSelectionInterval(index, index);
}
else {
if (index > 0) {
table.setRowSelectionInterval(index - 1, index - 1);
}
}
updateTableButtons(table, tableModel, myPanel);
}
table.getParent().repaint();
table.requestFocus();
}
};
myUpAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
TableUtil.stopEditing(table);
final int[] indexes = table.getSelectedRows();
for (int index : indexes) {
if (0 < index && index < myTableModel.getRowCount()) {
tableModel.exchangeRows(index, index - 1);
table.setRowSelectionInterval(index - 1, index - 1);
}
}
table.requestFocus();
}
};
myDownAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
TableUtil.stopEditing(table);
final int[] indexes = table.getSelectedRows();
for (int index : indexes) {
if (0 <= index && index < myTableModel.getRowCount() - 1) {
tableModel.exchangeRows(index, index + 1);
table.setRowSelectionInterval(index + 1, index + 1);
}
}
table.requestFocus();
}
};
}
private static void updateListButtons(final JList list, final AddRemoveUpDownPanel p) {
if (list.isEnabled() && p != null) {
final int index = list.getSelectedIndex();
if (0 <= index && index < list.getModel().getSize()) {
final boolean downEnable = list.getMaxSelectionIndex() < list.getModel().getSize() - 1;
final boolean upEnable = list.getMinSelectionIndex() > 0;
p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, true);
p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, upEnable);
p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, downEnable);
} else {
p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, false);
p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, false);
p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, false);
}
p.setEnabled(AddRemoveUpDownPanel.Buttons.ADD, true);
}
}
private static void updateTableButtons(final JTable table,
final EditableModel tableModel,
final AddRemoveUpDownPanel p) {
if (table.isEnabled() && p != null) {
final int index = table.getSelectedRow();
final int size = ((TableModel)tableModel).getRowCount();
if (0 <= index && index < size) {
final boolean downEnable = table.getSelectionModel().getMaxSelectionIndex() < size - 1;
final boolean upEnable = table.getSelectionModel().getMinSelectionIndex() > 0;
p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, true);
p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, upEnable);
p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, downEnable);
} else {
p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, false);
p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, false);
p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, false);
}
p.setEnabled(AddRemoveUpDownPanel.Buttons.ADD, true);
}
}
public static ToolbarDecorator createDecorator(@NotNull JTable table) {
return new ToolbarDecorator(table);
return new TableToolbarDecorator(table, null).initPositionAndBorder();
}
public static ToolbarDecorator createDecorator(@NotNull JTree tree) {
return new ToolbarDecorator(tree);
return new TreeToolbarDecorator(tree).initPositionAndBorder();
}
public static ToolbarDecorator createDecorator(@NotNull JList list) {
return new ToolbarDecorator(list);
return new ListToolbarDecorator(list).initPositionAndBorder();
}
public static <T> ToolbarDecorator createDecorator(@NotNull TableView<T> table, ElementProducer<T> producer) {
return new ToolbarDecorator(table, producer);
return new TableToolbarDecorator(table, producer).initPositionAndBorder();
}
public ToolbarDecorator disableAddAction() {
@@ -385,14 +203,14 @@ public class ToolbarDecorator implements DataProvider, AddRemoveUpDownPanel.List
public JPanel createPanel() {
final AddRemoveUpDownPanel.Buttons[] buttons = getButtons();
myPanel = new AddRemoveUpDownPanel(this,
myTable == null ? myList == null ? myTree : myList : myTable,
final JComponent contextComponent = getComponent();
myPanel = new AddRemoveUpDownPanel(this, contextComponent,
myToolbarPosition == ActionToolbarPosition.TOP || myToolbarPosition == ActionToolbarPosition.BOTTOM,
myExtraActions.toArray(new AnActionButton[myExtraActions.size()]),
myAddName, myRemoveName, myMoveUpName, myMoveDownName,
buttons);
myPanel.setBorder(myBorder);
final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable == null ? myList == null ? myTree : myList : myTable);
final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(contextComponent);
if (myPreferredSize != null) {
scrollPane.setPreferredSize(myPreferredSize);
}
@@ -401,46 +219,22 @@ public class ToolbarDecorator implements DataProvider, AddRemoveUpDownPanel.List
@Override
public void addNotify() {
super.addNotify();
if (myList != null) {
updateListButtons(myList, myPanel);
}
if (myTable != null && myTableModel instanceof EditableModel) {
updateTableButtons(myTable, (EditableModel)myTableModel, myPanel);
}
updateButtons();
}
};
panel.add(scrollPane, BorderLayout.CENTER);
panel.add(myPanel, getPlacement());
if (myTableModel instanceof EditableModel && buttons.length > 0) {
updateTableButtons(myTable, (EditableModel)myTableModel, myPanel);
if (myUpAction != null && myUpActionEnabled
&& myDownAction != null && myDownActionEnabled
&& !ApplicationManager.getApplication().isHeadlessEnvironment()) {
TableRowsDnDSupport.install(myTable, (EditableModel)myTableModel);
}
myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
updateTableButtons(myTable, (EditableModel)myTableModel, myPanel);
}
});
}
if (myList != null) {
updateListButtons(myList, myPanel);
myList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
updateListButtons(myList, myPanel);
}
});
}
updateButtons();
installDnD();
panel.setBorder(new LineBorder(UIUtil.getBorderColor()));
panel.putClientProperty(ActionToolbar.ACTION_TOOLBAR_PROPERTY_KEY, myPanel.getComponent(0));
DataManager.registerDataProvider(panel, this);
return panel;
}
protected void installDnD() {
}
@Override
public Object getData(@NonNls String dataId) {
if (PlatformDataKeys.ACTIONS_SORTER.is(dataId)) {
@@ -0,0 +1,47 @@
/*
* 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.openapi.actionSystem.ActionToolbarPosition;
import com.intellij.openapi.util.SystemInfo;
import javax.swing.*;
/**
* @author Konstantin Bulenkov
*/
class TreeToolbarDecorator extends ToolbarDecorator {
private final JTree myTree;
TreeToolbarDecorator(JTree tree) {
myTree = tree;
}
@Override
protected ToolbarDecorator initPositionAndBorder() {
return super.initPositionAndBorder()
.setToolbarPosition(SystemInfo.isMac ? ActionToolbarPosition.BOTTOM : ActionToolbarPosition.TOP);
}
@Override
protected JComponent getComponent() {
return myTree;
}
@Override
protected void updateButtons() {
}
}