| /* |
| * Copyright 2000-2009 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.refactoring.rename.naming; |
| |
| import com.intellij.ide.IdeBundle; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.ui.DialogWrapper; |
| import com.intellij.refactoring.RefactoringBundle; |
| import com.intellij.ui.*; |
| import com.intellij.ui.components.panels.ValidatingComponent; |
| import com.intellij.ui.table.JBTable; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import javax.swing.border.EmptyBorder; |
| import javax.swing.event.*; |
| import javax.swing.table.AbstractTableModel; |
| import java.awt.*; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.awt.event.KeyEvent; |
| import java.util.List; |
| |
| /** |
| * @author dsl |
| */ |
| public class AutomaticUsageRenamingDialog<T> extends DialogWrapper { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.rename.AutomaticRenamingDialog"); |
| private static final int CHECK_COLUMN = 0; |
| private static final int OLD_NAME_COLUMN = 1; |
| private static final int NEW_NAME_COLUMN = 2; |
| private final AutomaticUsageRenamer<T> myRenamer; |
| private boolean[] myShouldRename; |
| private String[] myNewNames; |
| private MyTableModel myTableModel; |
| private JBTable myTable; |
| private DocumentAdapter myCellEditorListener; |
| private ValidatingComponent myValidatingComponent; |
| |
| public AutomaticUsageRenamingDialog(Project project, AutomaticUsageRenamer<T> renamer) { |
| super(project, true); |
| myRenamer = renamer; |
| populateData(); |
| setTitle(myRenamer.getDialogTitle()); |
| setOKButtonText(IdeBundle.message("button.ok")); |
| init(); |
| } |
| |
| private void populateData() { |
| myNewNames = new String[getElementCount()]; |
| myShouldRename = new boolean[getElementCount()]; |
| for (int i = 0; i < getElementCount(); i++) { |
| myNewNames[i] = myRenamer.getNewElementName(getElements().get(i)); |
| myShouldRename[i] = myRenamer.isCheckedInitially(getElements().get(i)); |
| } |
| } |
| |
| @Override |
| protected String getDimensionServiceKey() { |
| return "#com.intellij.refactoring.rename.AutomaticRenamingDialog"; |
| } |
| |
| private int getElementCount() { |
| return getElements().size(); |
| } |
| |
| @Override |
| protected JComponent createNorthPanel() { |
| final Box box = Box.createHorizontalBox(); |
| box.add(new JLabel(myRenamer.getDialogDescription())); |
| box.add(Box.createHorizontalGlue()); |
| return box; |
| } |
| |
| @Override |
| public void show() { |
| if (ApplicationManager.getApplication().isUnitTestMode()) return; |
| super.show(); |
| } |
| |
| protected void handleChanges() { |
| updateRenamer(); |
| |
| boolean okActionEnabled = true; |
| for (T element : getElements()) { |
| final String errorText = getErrorText(element); |
| if (errorText != null) { |
| okActionEnabled = false; |
| } |
| } |
| setOKActionEnabled(okActionEnabled); |
| |
| refreshValidatingComponent(); |
| } |
| |
| private void refreshValidatingComponent() { |
| int selectedRow = myTable.getSelectedRow(); |
| if (selectedRow >= 0) { |
| myValidatingComponent.setErrorText(getErrorText(getElements().get(selectedRow))); |
| } |
| } |
| |
| @Nullable |
| private String getErrorText(T element) { |
| return isChecked(element) ? myRenamer.getErrorText(element) : null; |
| } |
| |
| private static SimpleTextAttributes highlightIfNeeded(SimpleTextAttributes attributes, String errorText) { |
| if (errorText != null) { |
| Color errorColor = SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor(); |
| int style = attributes.getStyle() | SimpleTextAttributes.STYLE_ITALIC | SimpleTextAttributes.STYLE_WAVED; |
| return new SimpleTextAttributes(style, errorColor, errorColor); |
| } |
| return attributes; |
| } |
| |
| @Override |
| public JComponent getPreferredFocusedComponent() { |
| return myTable; |
| } |
| |
| @Override |
| protected JComponent createCenterPanel() { |
| final Box box = Box.createVerticalBox(); |
| setupTable(); |
| |
| myTableModel.addTableModelListener(new TableModelListener() { |
| @Override |
| public void tableChanged(TableModelEvent e) { |
| handleChanges(); |
| } |
| }); |
| |
| TableUtil.setupCheckboxColumn(myTable, CHECK_COLUMN); |
| setupOldNameColumn(); |
| setupNewNameColumn(); |
| |
| myValidatingComponent = new ValidatingComponent() { |
| @Override |
| protected JComponent createMainComponent() { |
| return ScrollPaneFactory.createScrollPane(myTable); |
| } |
| }; |
| |
| myValidatingComponent.doInitialize(); |
| |
| box.add(myValidatingComponent); |
| final Box buttonBox = Box.createHorizontalBox(); |
| buttonBox.add(Box.createHorizontalGlue()); |
| final JButton selectAllButton = new JButton(RefactoringBundle.message("select.all.button")); |
| buttonBox.add(selectAllButton); |
| buttonBox.add(Box.createHorizontalStrut(4)); |
| final JButton deselectAllButton = new JButton(RefactoringBundle.message("unselect.all.button")); |
| buttonBox.add(deselectAllButton); |
| selectAllButton.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| for (int i = 0; i < getElementCount(); i++) { |
| myShouldRename[i] = true; |
| } |
| myTableModel.fireTableDataChanged(); |
| } |
| }); |
| selectAllButton.setMnemonic('S'); |
| |
| deselectAllButton.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| for (int i = 0; i < getElementCount(); i++) { |
| myShouldRename[i] = false; |
| } |
| myTableModel.fireTableDataChanged(); |
| } |
| }); |
| deselectAllButton.setMnemonic('U'); |
| box.add(Box.createVerticalStrut(4)); |
| box.add(buttonBox); |
| box.add(Box.createVerticalStrut(4)); |
| |
| return box; |
| } |
| |
| private void setupTable() { |
| myTable = new JBTable(); |
| myTableModel = new MyTableModel(); |
| myTable.setModel(myTableModel); |
| |
| myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { |
| @Override |
| public void valueChanged(ListSelectionEvent e) { |
| refreshValidatingComponent(); |
| } |
| }); |
| myTable.setCellSelectionEnabled(false); |
| myTable.setColumnSelectionAllowed(false); |
| myTable.setRowSelectionAllowed(false); |
| myTable.getTableHeader().setReorderingAllowed(false); |
| } |
| |
| private void setupNewNameColumn() { |
| myTable.getColumnModel().getColumn(NEW_NAME_COLUMN).setCellRenderer(new ColoredTableCellRenderer() { |
| @Override |
| protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) { |
| T element = getElements().get(row); |
| String errorText = getErrorText(element); |
| setToolTipText(errorText); |
| append(String.valueOf(value), highlightIfNeeded(SimpleTextAttributes.REGULAR_ATTRIBUTES, errorText)); |
| } |
| }); |
| |
| final JTextField textField = new JTextField(""); |
| textField.setBorder(new EmptyBorder(0, 0, 0, 0)); |
| myTable.getColumnModel().getColumn(NEW_NAME_COLUMN).setCellEditor(new DefaultCellEditor(textField) { |
| @Override |
| public boolean stopCellEditing() { |
| removeListener(textField); |
| return super.stopCellEditing(); |
| } |
| |
| @Override |
| public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, final int row, final int column) { |
| super.getTableCellEditorComponent(table, value, isSelected, row, column); |
| removeListener(textField); |
| |
| myCellEditorListener = new DocumentAdapter() { |
| @Override |
| protected void textChanged(DocumentEvent e) { |
| myTableModel.setValueAt(getCellEditorValue(), row, column); |
| setChecked(row, true); |
| String errorText = myRenamer.getErrorText(getElements().get(row)); |
| textField.setToolTipText(errorText); |
| Font font = textField.getFont(); |
| if (errorText != null) { |
| textField.setForeground(SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor()); |
| textField.setFont(font.deriveFont(font.getStyle() | Font.ITALIC)); |
| } else { |
| textField.setForeground(SimpleTextAttributes.REGULAR_ATTRIBUTES.getFgColor()); |
| textField.setFont(font.deriveFont(font.getStyle() & (~Font.ITALIC))); |
| } |
| repaintTable(); |
| } |
| }; |
| textField.getDocument().addDocumentListener(myCellEditorListener); |
| return textField; |
| } |
| |
| }); |
| } |
| |
| private void repaintTable() { |
| myTable.invalidate(); |
| myTable.repaint(); |
| } |
| |
| private void setupOldNameColumn() { |
| myTable.getColumnModel().getColumn(OLD_NAME_COLUMN).setCellRenderer(new ColoredTableCellRenderer() { |
| @Override |
| protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) { |
| //noinspection unchecked |
| T element = (T) value; |
| setToolTipText(getErrorText(element)); |
| append(myRenamer.getName(element), SimpleTextAttributes.REGULAR_ATTRIBUTES); |
| String sourceName = myRenamer.getSourceName(element); |
| if (sourceName != null) { |
| append(" (" + sourceName + ")", makeItalic(SimpleTextAttributes.GRAYED_ATTRIBUTES)); |
| } |
| } |
| }); |
| } |
| |
| private void removeListener(JTextField textField) { |
| if (myCellEditorListener != null) { |
| textField.getDocument().removeDocumentListener(myCellEditorListener); |
| } |
| } |
| |
| private static SimpleTextAttributes makeItalic(SimpleTextAttributes attributes) { |
| return new SimpleTextAttributes(SimpleTextAttributes.STYLE_ITALIC | attributes.getStyle(), attributes.getFgColor(), attributes.getWaveColor()); |
| } |
| |
| @Override |
| protected void doOKAction() { |
| TableUtil.stopEditing(myTable); |
| handleChanges(); |
| super.doOKAction(); |
| } |
| |
| private void updateRenamer() { |
| for (int i = 0; i < getElementCount(); i++) { |
| T element = getElements().get(i); |
| if (myShouldRename[i]) { |
| myRenamer.setRename(element, myNewNames[i]); |
| } |
| else { |
| myRenamer.doNotRename(element); |
| } |
| } |
| } |
| |
| protected void setChecked(int rowIndex, boolean checked) { |
| myTableModel.setValueAt(checked, rowIndex, CHECK_COLUMN); |
| } |
| |
| protected String[] getNewNames() { |
| return myNewNames; |
| } |
| |
| protected void setChecked(T element, boolean checked) { |
| setChecked(getElements().indexOf(element), checked); |
| } |
| |
| private List<? extends T> getElements() { |
| return myRenamer.getElements(); |
| } |
| |
| protected boolean isChecked(T element) { |
| return myShouldRename[getElements().indexOf(element)]; |
| } |
| |
| private class MyTableModel extends AbstractTableModel { |
| public MyTableModel() { |
| InputMap inputMap = myTable.getInputMap(); |
| inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "enable_disable"); |
| myTable.getActionMap().put("enable_disable", new MySpaceAction()); |
| inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "enter"); |
| myTable.getActionMap().put("enter", new EnterAction()); |
| } |
| |
| @Override |
| public int getColumnCount() { |
| return 3; |
| } |
| |
| @Override |
| public int getRowCount() { |
| return getElementCount(); |
| } |
| |
| @Override |
| public Object getValueAt(int rowIndex, int columnIndex) { |
| switch(columnIndex) { |
| case CHECK_COLUMN: |
| return myShouldRename[rowIndex]; |
| case OLD_NAME_COLUMN: |
| return getElements().get(rowIndex); |
| case NEW_NAME_COLUMN: |
| return myNewNames[rowIndex]; |
| default: |
| LOG.assertTrue(false); |
| return null; |
| } |
| } |
| |
| @Override |
| public void setValueAt(Object aValue, int rowIndex, int columnIndex) { |
| switch(columnIndex) { |
| case CHECK_COLUMN: |
| myShouldRename[rowIndex] = (Boolean) aValue; |
| break; |
| case NEW_NAME_COLUMN: |
| myNewNames[rowIndex] = (String) aValue; |
| break; |
| default: |
| LOG.assertTrue(false); |
| } |
| handleChanges(); |
| repaintTable(); |
| } |
| |
| @Override |
| public boolean isCellEditable(int rowIndex, int columnIndex) { |
| return columnIndex != OLD_NAME_COLUMN; |
| } |
| |
| @Override |
| @Nullable |
| public Class getColumnClass(int columnIndex) { |
| switch(columnIndex) { |
| case CHECK_COLUMN: return Boolean.class; |
| case OLD_NAME_COLUMN: return String.class; |
| case NEW_NAME_COLUMN: return String.class; |
| default: return null; |
| } |
| } |
| |
| @Override |
| public String getColumnName(int column) { |
| switch(column) { |
| case OLD_NAME_COLUMN: |
| return RefactoringBundle.message("automatic.renamer.enity.name.column", myRenamer.getEntityName()); |
| case NEW_NAME_COLUMN: |
| return RefactoringBundle.message("automatic.renamer.rename.to.column"); |
| default: |
| return " "; |
| } |
| } |
| |
| private class MySpaceAction extends AbstractAction { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| if (myTable.isEditing()) return; |
| |
| int row = myTable.getSelectionModel().getAnchorSelectionIndex(); |
| if (row >= 0 && row < getElementCount()) { |
| myShouldRename[row] = !myShouldRename[row]; |
| fireTableDataChanged(); |
| repaintTable(); |
| myTable.requestFocus(); |
| } |
| } |
| } |
| |
| private class EnterAction extends AbstractAction { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| if (!myTable.isEditing()) { |
| doOKAction(); |
| } |
| } |
| } |
| } |
| |
| |
| |
| } |