revert accidentally introduced constant
[fedora-idea.git] / lang-impl / src / com / intellij / refactoring / ui / AbstractMemberSelectionTable.java
blobb200ca65ad3e15127b23ce4094642fe2b85876a5
1 package com.intellij.refactoring.ui;
3 import com.intellij.openapi.actionSystem.DataKey;
4 import com.intellij.openapi.actionSystem.DataSink;
5 import com.intellij.openapi.actionSystem.LangDataKeys;
6 import com.intellij.openapi.actionSystem.TypeSafeDataProvider;
7 import com.intellij.openapi.util.IconLoader;
8 import com.intellij.psi.PsiElement;
9 import com.intellij.refactoring.RefactoringBundle;
10 import com.intellij.refactoring.classMembers.MemberInfoBase;
11 import com.intellij.refactoring.classMembers.MemberInfoChange;
12 import com.intellij.refactoring.classMembers.MemberInfoChangeListener;
13 import com.intellij.refactoring.classMembers.MemberInfoModel;
14 import com.intellij.ui.BooleanTableCellRenderer;
15 import com.intellij.ui.ColoredTableCellRenderer;
16 import com.intellij.ui.RowIcon;
17 import com.intellij.ui.SimpleTextAttributes;
18 import com.intellij.util.ui.EmptyIcon;
19 import com.intellij.util.ui.Table;
20 import org.jetbrains.annotations.NotNull;
22 import javax.swing.*;
23 import javax.swing.table.AbstractTableModel;
24 import javax.swing.table.TableColumnModel;
25 import java.awt.*;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.List;
31 /**
32 * @author Dennis.Ushakov
34 public abstract class AbstractMemberSelectionTable<T extends PsiElement, M extends MemberInfoBase<T>> extends Table implements TypeSafeDataProvider {
35 protected static final int CHECKED_COLUMN = 0;
36 protected static final int DISPLAY_NAME_COLUMN = 1;
37 protected static final int ABSTRACT_COLUMN = 2;
38 protected static final Icon OVERRIDING_METHOD_ICON = IconLoader.getIcon("/general/overridingMethod.png");
39 protected static final Icon IMPLEMENTING_METHOD_ICON = IconLoader.getIcon("/general/implementingMethod.png");
40 protected static final Icon EMPTY_OVERRIDE_ICON = new EmptyIcon(16, 16);
41 protected final String myAbstractColumnHeader;
42 protected static final String DISPLAY_NAME_COLUMN_HEADER = RefactoringBundle.message("member.column");
43 protected List<M> myMemberInfos;
44 protected final boolean myAbstractEnabled;
45 protected MemberInfoModel<T, M> myMemberInfoModel;
46 protected MyTableModel<T, M> myTableModel;
47 protected static final int OVERRIDE_ICON_POSITION = 2;
48 protected static final int VISIBILITY_ICON_POSITION = 1;
49 protected static final int MEMBER_ICON_POSITION = 0;
51 public AbstractMemberSelectionTable(Collection<M> memberInfos, MemberInfoModel<T, M> memberInfoModel, String abstractColumnHeader) {
52 myAbstractEnabled = abstractColumnHeader != null;
53 myAbstractColumnHeader = abstractColumnHeader;
54 myTableModel = new MyTableModel<T, M>(this);
56 myMemberInfos = new ArrayList<M>(memberInfos);
57 if (memberInfoModel != null) {
58 myMemberInfoModel = memberInfoModel;
60 else {
61 myMemberInfoModel = new DefaultMemberInfoModel<T, M>();
64 setModel(myTableModel);
66 TableColumnModel model = getColumnModel();
67 model.getColumn(DISPLAY_NAME_COLUMN).setCellRenderer(new MyTableRenderer<T, M>(this));
68 model.getColumn(CHECKED_COLUMN).setCellRenderer(new MyBooleanRenderer<T, M>(this));
69 final int checkBoxWidth = new JCheckBox().getPreferredSize().width;
70 model.getColumn(CHECKED_COLUMN).setMaxWidth(checkBoxWidth);
71 model.getColumn(CHECKED_COLUMN).setMinWidth(checkBoxWidth);
73 if (myAbstractEnabled) {
74 int width =
75 (int)(1.3 * getFontMetrics(getFont()).charsWidth(myAbstractColumnHeader.toCharArray(), 0,
76 myAbstractColumnHeader.length()));
77 model.getColumn(ABSTRACT_COLUMN).setMaxWidth(width);
78 model.getColumn(ABSTRACT_COLUMN).setPreferredWidth(width);
79 model.getColumn(ABSTRACT_COLUMN).setCellRenderer(new MyBooleanRenderer<T, M>(this));
82 setPreferredScrollableViewportSize(new Dimension(400, getRowHeight() * 12));
83 getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
84 setShowGrid(false);
85 setIntercellSpacing(new Dimension(0, 0));
87 new MyEnableDisableAction().register();
90 public Collection<M> getSelectedMemberInfos() {
91 ArrayList<M> list = new ArrayList<M>(myMemberInfos.size());
92 for (M info : myMemberInfos) {
93 if (isMemberInfoSelected(info)) {
94 // if (info.isChecked() || (!myMemberInfoModel.isMemberEnabled(info) && myMemberInfoModel.isCheckedWhenDisabled(info))) {
95 list.add(info);
98 return list;
101 private boolean isMemberInfoSelected(final M info) {
102 final boolean memberEnabled = myMemberInfoModel.isMemberEnabled(info);
103 return (memberEnabled && info.isChecked()) || (!memberEnabled && myMemberInfoModel.isCheckedWhenDisabled(info));
106 public MemberInfoModel<T, M> getMemberInfoModel() {
107 return myMemberInfoModel;
110 public void setMemberInfoModel(MemberInfoModel<T, M> memberInfoModel) {
111 myMemberInfoModel = memberInfoModel;
114 public void fireExternalDataChange() {
115 myTableModel.fireTableDataChanged();
118 public void setMemberInfos(Collection<M> memberInfos) {
119 myMemberInfos = new ArrayList<M>(memberInfos);
120 fireMemberInfoChange(memberInfos);
121 myTableModel.fireTableDataChanged();
124 public void addMemberInfoChangeListener(MemberInfoChangeListener<T, M> l) {
125 listenerList.add(MemberInfoChangeListener.class, l);
128 protected void fireMemberInfoChange(Collection<M> changedMembers) {
129 Object[] list = listenerList.getListenerList();
131 MemberInfoChange event = new MemberInfoChange<T, M>(changedMembers);
132 for (Object element : list) {
133 if (element instanceof MemberInfoChangeListener) {
134 ((MemberInfoChangeListener<T, M>)element).memberInfoChanged(event);
139 public void calcData(final DataKey key, final DataSink sink) {
140 if (key == LangDataKeys.PSI_ELEMENT) {
141 final Collection<M> memberInfos = getSelectedMemberInfos();
142 if (memberInfos.size() > 0) {
143 sink.put(LangDataKeys.PSI_ELEMENT, memberInfos.iterator().next().getMember());
148 public void scrollSelectionInView() {
149 for(int i=0; i<myMemberInfos.size(); i++) {
150 if (isMemberInfoSelected(myMemberInfos.get(i))) {
151 Rectangle rc = getCellRect(i, 0, false);
152 scrollRectToVisible(rc);
153 break;
158 public void addNotify() {
159 super.addNotify();
160 scrollSelectionInView();
163 protected abstract Object getAbstractColumnValue(M memberInfo);
165 protected abstract boolean isAbstractColumnEditable(int rowIndex);
167 protected abstract void setVisibilityIcon(M memberInfo, RowIcon icon);
169 protected abstract Icon getOverrideIcon(M memberInfo);
171 private static class DefaultMemberInfoModel<T extends PsiElement, M extends MemberInfoBase<T>> implements MemberInfoModel<T, M> {
172 public boolean isMemberEnabled(M member) {
173 return true;
176 public boolean isCheckedWhenDisabled(M member) {
177 return false;
180 public boolean isAbstractEnabled(M member) {
181 return true;
184 public boolean isAbstractWhenDisabled(M member) {
185 return false;
189 public int checkForProblems(@NotNull M member) {
190 return OK;
193 public void memberInfoChanged(MemberInfoChange<T, M> event) {
196 public Boolean isFixedAbstract(M member) {
197 return null;
200 public String getTooltipText(M member) {
201 return null;
205 private static class MyTableModel<T extends PsiElement, M extends MemberInfoBase<T>> extends AbstractTableModel {
206 private final AbstractMemberSelectionTable<T, M> myTable;
208 public MyTableModel(AbstractMemberSelectionTable<T, M> table) {
209 myTable = table;
212 public int getColumnCount() {
213 if (myTable.myAbstractEnabled) {
214 return 3;
216 else {
217 return 2;
221 public int getRowCount() {
222 return myTable.myMemberInfos.size();
225 public Class getColumnClass(int columnIndex) {
226 if (columnIndex == CHECKED_COLUMN || columnIndex == ABSTRACT_COLUMN) {
227 return Boolean.class;
229 return super.getColumnClass(columnIndex);
232 public Object getValueAt(int rowIndex, int columnIndex) {
233 final M memberInfo = myTable.myMemberInfos.get(rowIndex);
234 switch (columnIndex) {
235 case CHECKED_COLUMN:
236 if (myTable.myMemberInfoModel.isMemberEnabled(memberInfo)) {
237 return memberInfo.isChecked() ? Boolean.TRUE : Boolean.FALSE;
239 else {
240 return myTable.myMemberInfoModel.isCheckedWhenDisabled(memberInfo);
242 case ABSTRACT_COLUMN:
244 return myTable.getAbstractColumnValue(memberInfo);
246 case DISPLAY_NAME_COLUMN:
247 return memberInfo.getDisplayName();
248 default:
249 throw new RuntimeException("Incorrect column index");
253 public String getColumnName(int column) {
254 switch (column) {
255 case CHECKED_COLUMN:
256 return " ";
257 case ABSTRACT_COLUMN:
258 return myTable.myAbstractColumnHeader;
259 case DISPLAY_NAME_COLUMN:
260 return DISPLAY_NAME_COLUMN_HEADER;
261 default:
262 throw new RuntimeException("Incorrect column index");
266 public boolean isCellEditable(int rowIndex, int columnIndex) {
267 switch (columnIndex) {
268 case CHECKED_COLUMN:
269 return myTable.myMemberInfoModel.isMemberEnabled(myTable.myMemberInfos.get(rowIndex));
270 case ABSTRACT_COLUMN:
271 return myTable.isAbstractColumnEditable(rowIndex);
273 return false;
277 public void setValueAt(final Object aValue, final int rowIndex, final int columnIndex) {
278 if (columnIndex == CHECKED_COLUMN) {
279 myTable.myMemberInfos.get(rowIndex).setChecked(((Boolean)aValue).booleanValue());
281 else if (columnIndex == ABSTRACT_COLUMN) {
282 myTable.myMemberInfos.get(rowIndex).setToAbstract(((Boolean)aValue).booleanValue());
285 Collection<M> changed = Collections.singletonList(myTable.myMemberInfos.get(rowIndex));
286 myTable.fireMemberInfoChange(changed);
287 fireTableDataChanged();
288 // fireTableRowsUpdated(rowIndex, rowIndex);
292 private class MyEnableDisableAction extends EnableDisableAction {
294 protected JTable getTable() {
295 return AbstractMemberSelectionTable.this;
298 protected void applyValue(int[] rows, boolean valueToBeSet) {
299 List<M> changedInfo = new ArrayList<M>();
300 for (int row : rows) {
301 final M memberInfo = myMemberInfos.get(row);
302 memberInfo.setChecked(valueToBeSet);
303 changedInfo.add(memberInfo);
305 fireMemberInfoChange(changedInfo);
306 final int selectedRow = getSelectedRow();
307 myTableModel.fireTableDataChanged();
308 setRowSelectionInterval(selectedRow, selectedRow);
311 protected boolean isRowChecked(final int row) {
312 return myMemberInfos.get(row).isChecked();
316 private static class MyTableRenderer<T extends PsiElement, M extends MemberInfoBase<T>> extends ColoredTableCellRenderer {
317 private final AbstractMemberSelectionTable<T, M> myTable;
319 public MyTableRenderer(AbstractMemberSelectionTable<T, M> table) {
320 myTable = table;
323 public void customizeCellRenderer(JTable table, final Object value,
324 boolean isSelected, boolean hasFocus, final int row, final int column) {
326 final int modelColumn = myTable.convertColumnIndexToModel(column);
327 final M memberInfo = myTable.myMemberInfos.get(row);
328 setToolTipText(myTable.myMemberInfoModel.getTooltipText(memberInfo));
329 T member = memberInfo.getMember();
330 switch (modelColumn) {
331 case DISPLAY_NAME_COLUMN:
333 Icon memberIcon = myTable.getMemberIcon(memberInfo, 0);
334 Icon overrideIcon = myTable.getOverrideIcon(memberInfo);
336 RowIcon icon = new RowIcon(3);
337 icon.setIcon(memberIcon, MEMBER_ICON_POSITION);
338 myTable.setVisibilityIcon(memberInfo, icon);
339 icon.setIcon(overrideIcon, OVERRIDE_ICON_POSITION);
340 setIcon(icon);
341 break;
343 default:
345 setIcon(null);
348 final boolean cellEditable = myTable.myMemberInfoModel.isMemberEnabled(memberInfo);
349 setEnabled(cellEditable);
351 if (value == null) return;
352 final int problem = myTable.myMemberInfoModel.checkForProblems(memberInfo);
353 Color c = null;
354 if (problem == MemberInfoModel.ERROR) {
355 c = Color.red;
357 else if (problem == MemberInfoModel.WARNING && !isSelected) {
358 c = Color.blue;
360 append((String)value, new SimpleTextAttributes(Font.PLAIN, c));
365 protected Icon getMemberIcon(M memberInfo, int flags) {
366 return memberInfo.getMember().getIcon(flags);
369 private static class MyBooleanRenderer<T extends PsiElement, M extends MemberInfoBase<T>> extends BooleanTableCellRenderer {
370 private final AbstractMemberSelectionTable<T, M> myTable;
372 public MyBooleanRenderer(AbstractMemberSelectionTable<T, M> table) {
373 myTable = table;
376 public Component getTableCellRendererComponent(JTable table, Object value,
377 boolean isSelected, boolean hasFocus,
378 int row, int column) {
379 Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
380 if (component instanceof JComponent) {
381 JComponent jComponent = (JComponent)component;
382 int modelColumn = myTable.convertColumnIndexToModel(column);
383 final M memberInfo = myTable.myMemberInfos.get(row);
385 jComponent.setEnabled(
386 (modelColumn == CHECKED_COLUMN && myTable.myMemberInfoModel.isMemberEnabled(memberInfo)
387 || (modelColumn == ABSTRACT_COLUMN && memberInfo.isChecked() && myTable.isAbstractColumnEditable(row)))
390 return component;