/*
* 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.
*/
/*
* Created by IntelliJ IDEA.
* User: dsl
* Date: 17.06.2002
* Time: 16:35:43
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
//package com.intellij.refactoring.ui;
package com.intellij.refactoring.ui;
import com.intellij.psi.*;
import com.intellij.refactoring.classMembers.MemberInfoModel;
import com.intellij.refactoring.genUtils.GenAnalysisUtils;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import com.intellij.ui.ColoredTableCellRenderer;
import com.intellij.ui.JBColor;
import com.intellij.ui.RowIcon;
import com.intellij.ui.SimpleTextAttributes;
import javax.swing.*;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class CustomMemberSelectionTable extends MemberSelectionTable {
protected final Boolean[] directAbstractPullupCheckBoxes;
protected final Boolean[] canGenerifyCheckBoxes ;
protected static final int CAN_MAKE_ABSTRACT_COLUMN = 3 ; // added Julien
protected static String canMakeAbstractColumnHeader = "can make abstract";
protected final ThreeValue[] canMakeAbstractCheckBoxes ;
enum ThreeValue {
YesGenerics {public String toString(){return "Yes (with generics)";}},
YesPlain {public String toString(){return "Yes (without generics)";}} ,
No}
public CustomMemberSelectionTable(final List<MemberInfo> memberInfos, String abstractColumnHeader) {
this(memberInfos, null, abstractColumnHeader);
}
public CustomMemberSelectionTable(final List<MemberInfo> memberInfos,
MemberInfoModel<PsiMember, MemberInfo> memberInfoModel,
String abstractColumnHeader)
{
super(memberInfos, memberInfoModel, abstractColumnHeader);
final int nbLines = memberInfos.size();
directAbstractPullupCheckBoxes = new Boolean[nbLines]; // j
canGenerifyCheckBoxes = new Boolean[nbLines]; // j
canMakeAbstractCheckBoxes = new ThreeValue[nbLines]; // j
GenTableModel t = new GenTableModel (this); //julien
setModel(t); // julien (this is problematic)
configureColumnModel(getColumnModel());
}
protected void configureColumnModel(TableColumnModel m) {
// copy from AbstractMemberSelectionTable
m.getColumn(DISPLAY_NAME_COLUMN).setCellRenderer(new CustomTableRenderer(this));
// to be done again
// (why? because the first time this code is invoked, it acts on the model affected by the first setModel() invocation)
final int checkBoxWidth = new JCheckBox().getPreferredSize().width;
m.getColumn(CHECKED_COLUMN).setMaxWidth(checkBoxWidth);
m.getColumn(CHECKED_COLUMN).setMinWidth(checkBoxWidth);
// FIXME to be done again (why?)
final int width = (int)(1.3 * getFontMetrics(getFont()).charsWidth(myAbstractColumnHeader.toCharArray(), 0, myAbstractColumnHeader.length()));
m.getColumn(ABSTRACT_COLUMN).setMaxWidth(width);
m.getColumn(ABSTRACT_COLUMN).setPreferredWidth(width);
// end copy
int canMakeAbstractColumnWidth = (int)(1.3 * getFontMetrics(getFont()).charsWidth(canMakeAbstractColumnHeader.toCharArray(), 0, canMakeAbstractColumnHeader.length()));
m.getColumn(CAN_MAKE_ABSTRACT_COLUMN).setMaxWidth(canMakeAbstractColumnWidth);
m.getColumn(CAN_MAKE_ABSTRACT_COLUMN).setPreferredWidth(canMakeAbstractColumnWidth);
}
/* --- Compute and Fill properties --- */
/* Need to check the boxes (arrays) and the memberInfo */
void fillCanGenMember(MemberInfo member, PsiClass selectedSuper){
if (GenAnalysisUtils.computeCanGenMember(member, selectedSuper)) {
setCanGenerifyColumnValue(member, true);
}
else {
setCanGenerifyColumnValue(member, false);
member.setChecked(false); //TODO : desactivate the checkbox
member.setToAbstract(false);
}
}
void fillDirectAbstractPullupField(MemberInfo member, PsiClass selectedSuper){
final boolean result = GenAnalysisUtils.computeCanDirectAbstractPullupMember(selectedSuper, member);
setDirectAbstractPullupColumnValue(member, result);
}
void fillCanMakeAbstractField(MemberInfo member) {
//TODO warning : check the dependencies wetween the various informations.
ThreeValue v = ThreeValue.No ;
if (getDirectAbstractPullupColumnValue(member)) v = ThreeValue.YesPlain ;
else if (getCanGenerifyColumnValue(member)) v = ThreeValue.YesGenerics ;
setCanMakeAbstractColumnValue(member, v);
}
public void fillAllCanGenMembers(PsiClass sup){
for (MemberInfo m : myMemberInfos) fillCanGenMember(m, sup);
}
public void fillAllDirectAbstractPullupFields(PsiClass sup){
for (MemberInfo m : myMemberInfos) fillDirectAbstractPullupField(m, sup);
}
public void fillAllCanMakeAbstractFields(){
for (MemberInfo m : myMemberInfos) fillCanMakeAbstractField(m);
}
//new
int getRowForMember(MemberInfo memberInfo){
int rowIndex = -1 ;
int i = 0 ;
int m = myMemberInfos.size();
while (i<m && rowIndex == -1){
if (myMemberInfos.get(i).equals(memberInfo)) rowIndex = i ;
i++ ;
}
if (rowIndex == -1) throw new InternalError("member not found in table");
return rowIndex ;
}
/* --- Getters for boxes --- */
protected Boolean getDirectAbstractPullupColumnValue(MemberInfo memberInfo) {
// rem : the generify flag is not inside memberInfo, but in the generifyCheckBoxes array.
return directAbstractPullupCheckBoxes[getRowForMember(memberInfo)];
}
protected Boolean getCanGenerifyColumnValue(MemberInfo memberInfo) {
// rem : the generify flag is not inside memberInfo, but in the generifyCheckBoxes array.
return canGenerifyCheckBoxes[getRowForMember(memberInfo)];
}
protected ThreeValue getCanMakeAbstractColumnValue(MemberInfo memberInfo) {
return canMakeAbstractCheckBoxes[getRowForMember(memberInfo)];
}
/* --- Setters for boxes --- */
protected void setCanGenerifyColumnValue(MemberInfo memberInfo, boolean b) {
canGenerifyCheckBoxes[getRowForMember(memberInfo)] = b ;
}
protected void setDirectAbstractPullupColumnValue(MemberInfo memberInfo, boolean b) {
directAbstractPullupCheckBoxes[getRowForMember(memberInfo)] = b ;
}
/* this fills the "can make abstract" checkboxes, and also the "to abstract" checkboxes (indirectly) */
protected void setCanMakeAbstractColumnValue(MemberInfo memberInfo, ThreeValue b) {
canMakeAbstractCheckBoxes[getRowForMember(memberInfo)] = b ;
if (b==ThreeValue.No) memberInfo.setToAbstract(false);
else memberInfo.setToAbstract(true);
}
/* --- Test editability of columns --- */
@Override
protected boolean isAbstractColumnEditable(int rowIndex) {
return false;
}
// Added Julien
private static class GenTableModel extends MyTableModel {
private final CustomMemberSelectionTable myTableCopy ;
public GenTableModel(CustomMemberSelectionTable table) {
super(table); //j
myTableCopy = table;
}
public int getColumnCount() {
return (4);
}
public Class getColumnClass(int columnIndex) {
if (columnIndex == CHECKED_COLUMN
|| columnIndex == ABSTRACT_COLUMN
) { //julien
return Boolean.class;
}
if (columnIndex == CAN_MAKE_ABSTRACT_COLUMN) return ThreeValue.class ;
return super.getColumnClass(columnIndex);
}
public Object getValueAt(int rowIndex, int columnIndex) {
final MemberInfo memberInfo = myTableCopy.myMemberInfos.get(rowIndex);
switch (columnIndex) {
case CHECKED_COLUMN:
if (myTableCopy.myMemberInfoModel.isMemberEnabled(memberInfo)) {
return memberInfo.isChecked() ? Boolean.TRUE : Boolean.FALSE;
}
else {
return myTableCopy.myMemberInfoModel.isCheckedWhenDisabled(memberInfo);
}
case ABSTRACT_COLUMN:
{
return myTableCopy.getAbstractColumnValue(memberInfo);
}
case DISPLAY_NAME_COLUMN:
return memberInfo.getDisplayName();
case CAN_MAKE_ABSTRACT_COLUMN: //julien
return myTableCopy.getCanMakeAbstractColumnValue (memberInfo);
default:
throw new RuntimeException("Incorrect column index");
}
}
public String getColumnName(int column) {
switch (column) {
case CHECKED_COLUMN:
return " ";
case ABSTRACT_COLUMN:
return myTableCopy.myAbstractColumnHeader;
case DISPLAY_NAME_COLUMN:
return DISPLAY_NAME_COLUMN_HEADER;
case CAN_MAKE_ABSTRACT_COLUMN: //julien
return canMakeAbstractColumnHeader;
default:
throw new RuntimeException("Incorrect column index: " + column);
}
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
switch (columnIndex) {
case CHECKED_COLUMN:
final MemberInfo m = myTableCopy.myMemberInfos.get(rowIndex);
return (myTableCopy.myMemberInfoModel.isMemberEnabled(m))
&& myTableCopy.getCanMakeAbstractColumnValue(m) != ThreeValue.No; // todo: does that work?
case ABSTRACT_COLUMN:
return myTableCopy.isAbstractColumnEditable(rowIndex);
case CAN_MAKE_ABSTRACT_COLUMN:
return false;
}
return false;
}
public void setValueAt(final Object aValue, final int rowIndex, final int columnIndex) {
if (columnIndex == CHECKED_COLUMN) {
myTableCopy.myMemberInfos.get(rowIndex).setChecked(((Boolean)aValue).booleanValue());
}
else if (columnIndex == ABSTRACT_COLUMN) {
myTableCopy.myMemberInfos.get(rowIndex).setToAbstract(((Boolean)aValue).booleanValue());
}
// TODO : need to add a case for "can make abstract" columns which is not editable?
Collection<MemberInfo> changed = Collections.singletonList(myTableCopy.myMemberInfos.get(rowIndex));
myTableCopy.fireMemberInfoChange(changed);
fireTableDataChanged();
// fireTableRowsUpdated(rowIndex, rowIndex);
}
} //end of inner class
//copy (I would prefer to use the one in AbstractMemberSelectionTable but it is private)
private static class CustomTableRenderer extends ColoredTableCellRenderer {
private final CustomMemberSelectionTable myTable;
public CustomTableRenderer(CustomMemberSelectionTable table) {
myTable = table;
}
public void customizeCellRenderer(JTable table,
final Object value,
boolean isSelected,
boolean hasFocus,
final int row,
final int column) {
final int modelColumn = myTable.convertColumnIndexToModel(column);
final MemberInfo memberInfo = myTable.myMemberInfos.get(row);
setToolTipText(myTable.myMemberInfoModel.getTooltipText(memberInfo));
switch (modelColumn) {
case DISPLAY_NAME_COLUMN:
{
Icon memberIcon = myTable.getMemberIcon(memberInfo, 0);
Icon overrideIcon = myTable.getOverrideIcon(memberInfo);
RowIcon icon = new RowIcon(3);
icon.setIcon(memberIcon, MEMBER_ICON_POSITION);
myTable.setVisibilityIcon(memberInfo, icon);
icon.setIcon(overrideIcon, OVERRIDE_ICON_POSITION);
setIcon(icon);
break;
}
default:
{
setIcon(null);
}
}
setIconOpaque(false);
setOpaque(false);
final boolean cellEditable = myTable.myMemberInfoModel.isMemberEnabled(memberInfo);
setEnabled(cellEditable);
if (value == null) return;
final int problem = myTable.myMemberInfoModel.checkForProblems(memberInfo);
Color c = null;
if (problem == MemberInfoModel.ERROR) {
c = JBColor.RED;
}
else if (problem == MemberInfoModel.WARNING && !isSelected) {
c = JBColor.BLUE;
}
append((String)value, new SimpleTextAttributes(Font.PLAIN, c));
if (myTable.getCanMakeAbstractColumnValue(memberInfo)==ThreeValue.No) { // Julien
this.setForeground(JBColor.LIGHT_GRAY); // Julien
}
}
}
}