Refactoring: Extract AbstractParameterTablePanel class

This commit is contained in:
Alexey Sedunov
2016-07-12 19:37:40 +03:00
parent 9e339c12e9
commit 6b0968c939
5 changed files with 281 additions and 163 deletions
@@ -0,0 +1,183 @@
/*
* Copyright 2010-2015 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 org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui;
import com.intellij.ui.components.JBComboBoxLabel;
import com.intellij.ui.components.editors.JBComboBoxTableCellEditorComponent;
import com.intellij.ui.table.JBTable;
import com.intellij.util.Function;
import com.intellij.util.ui.AbstractTableCellEditor;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.Parameter;
import org.jetbrains.kotlin.idea.refactoring.introduce.ui.AbstractParameterTablePanel;
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers;
import org.jetbrains.kotlin.types.KotlinType;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class ExtractFunctionParameterTablePanel extends AbstractParameterTablePanel<Parameter, ParameterInfo> {
@Override
protected TableModelBase createTableModel() {
return new MyTableModel();
}
@Override
protected void createAdditionalColumns() {
JBTable table = getTable();
TableColumn parameterTypeColumn = table.getColumnModel().getColumn(MyTableModel.PARAMETER_TYPE_COLUMN);
parameterTypeColumn.setHeaderValue("Type");
parameterTypeColumn.setCellRenderer(new DefaultTableCellRenderer() {
private final JBComboBoxLabel myLabel = new JBComboBoxLabel();
@Override
@NotNull
public Component getTableCellRendererComponent(
@NotNull JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column
) {
myLabel.setText(IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType((KotlinType) value));
myLabel.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
myLabel.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
if (isSelected) {
myLabel.setSelectionIcon();
}
else {
myLabel.setRegularIcon();
}
return myLabel;
}
});
parameterTypeColumn.setCellEditor(new AbstractTableCellEditor() {
final JBComboBoxTableCellEditorComponent myEditorComponent = new JBComboBoxTableCellEditorComponent();
@Override
@Nullable
public Object getCellEditorValue() {
return myEditorComponent.getEditorValue();
}
@Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column
) {
ParameterInfo info = parameterInfos.get(row);
myEditorComponent.setCell(table, row, column);
myEditorComponent.setOptions(info.getOriginalParameter().getParameterTypeCandidates(false).toArray());
myEditorComponent.setDefaultValue(info.getType());
myEditorComponent.setToString(new Function<Object, String>() {
@Override
public String fun(Object o) {
return IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType((KotlinType) o);
}
});
return myEditorComponent;
}
});
}
public void init(@Nullable Parameter receiver, @NotNull List<Parameter> parameters) {
parameterInfos = CollectionsKt.mapTo(
parameters,
receiver != null
? CollectionsKt.arrayListOf(new ParameterInfo(receiver, true))
: new ArrayList<ParameterInfo>(),
new Function1<Parameter, ParameterInfo>() {
@Override
public ParameterInfo invoke(Parameter parameter) {
return new ParameterInfo(parameter, false);
}
}
);
super.init();
}
private class MyTableModel extends TableModelBase {
public static final int PARAMETER_TYPE_COLUMN = 2;
@Override
public int getColumnCount() {
return 3;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == PARAMETER_TYPE_COLUMN) return parameterInfos.get(rowIndex).getType();
return super.getValueAt(rowIndex, columnIndex);
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == PARAMETER_TYPE_COLUMN) {
parameterInfos.get(rowIndex).setType((KotlinType) aValue);
updateSignature();
return;
}
super.setValueAt(aValue, rowIndex, columnIndex);
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
ParameterInfo info = parameterInfos.get(rowIndex);
switch (columnIndex) {
case PARAMETER_NAME_COLUMN:
return super.isCellEditable(rowIndex, columnIndex) && !info.isReceiver();
case PARAMETER_TYPE_COLUMN:
return isEnabled() && info.isEnabled() && info.getOriginalParameter().getParameterTypeCandidates(false).size() > 1;
default:
return super.isCellEditable(rowIndex, columnIndex);
}
}
}
@Nullable
public ParameterInfo getReceiverInfo() {
return CollectionsKt.singleOrNull(
parameterInfos,
new Function1<ParameterInfo, Boolean>() {
@Override
public Boolean invoke(ParameterInfo info) {
return info.isEnabled() && info.isReceiver();
}
}
);
}
@NotNull
public List<ParameterInfo> getParameterInfos() {
return CollectionsKt.filter(
parameterInfos,
new Function1<ParameterInfo, Boolean>() {
@Override
public Boolean invoke(ParameterInfo info) {
return info.isEnabled() && !info.isReceiver();
}
}
);
}
}
@@ -56,7 +56,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper {
private JLabel functionNameLabel;
private JComboBox returnTypeBox;
private JPanel returnTypePanel;
private KotlinParameterTablePanel parameterTablePanel;
private ExtractFunctionParameterTablePanel parameterTablePanel;
private final Project project;
@@ -103,7 +103,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper {
private boolean checkNames() {
if (!KotlinNameSuggester.INSTANCE.isIdentifier(getFunctionName())) return false;
for (KotlinParameterTablePanel.ParameterInfo parameterInfo : parameterTablePanel.getParameterInfos()) {
for (ParameterInfo parameterInfo : parameterTablePanel.getParameterInfos()) {
if (!KotlinNameSuggester.INSTANCE.isIdentifier(parameterInfo.getName())) return false;
}
return true;
@@ -192,7 +192,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper {
}
);
parameterTablePanel = new KotlinParameterTablePanel() {
parameterTablePanel = new ExtractFunctionParameterTablePanel() {
@Override
protected void updateSignature() {
KotlinExtractFunctionDialog.this.update();
@@ -276,12 +276,12 @@ public class KotlinExtractFunctionDialog extends DialogWrapper {
@NotNull ExtractableCodeDescriptor originalDescriptor,
@NotNull String newName,
@NotNull String newVisibility,
@Nullable KotlinParameterTablePanel.ParameterInfo newReceiverInfo,
@NotNull List<KotlinParameterTablePanel.ParameterInfo> newParameterInfos,
@Nullable ParameterInfo newReceiverInfo,
@NotNull List<ParameterInfo> newParameterInfos,
@Nullable KotlinType returnType
) {
Map<Parameter, Parameter> oldToNewParameters = ContainerUtil.newLinkedHashMap();
for (KotlinParameterTablePanel.ParameterInfo parameterInfo : newParameterInfos) {
for (ParameterInfo parameterInfo : newParameterInfos) {
oldToNewParameters.put(parameterInfo.getOriginalParameter(), parameterInfo.toParameter());
}
Parameter originalReceiver = originalDescriptor.getReceiverParameter();
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2016 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 org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui;
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.Parameter;
import org.jetbrains.kotlin.idea.refactoring.introduce.ui.AbstractParameterTablePanel;
import org.jetbrains.kotlin.types.KotlinType;
public class ParameterInfo extends AbstractParameterTablePanel.AbstractParameterInfo<Parameter> {
private final boolean receiver;
private KotlinType type;
public ParameterInfo(Parameter originalParameter, boolean receiver) {
super(originalParameter);
this.receiver = receiver;
this.type = originalParameter.getParameterType(false);
setName(receiver ? "<receiver>" : originalParameter.getName());
}
public boolean isReceiver() {
return receiver;
}
public KotlinType getType() {
return type;
}
public void setType(KotlinType type) {
this.type = type;
}
@Override
public Parameter toParameter() {
return getOriginalParameter().copy(getName(), type);
}
}
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.idea.refactoring.isMultiLine
import org.jetbrains.kotlin.idea.refactoring.runRefactoringWithPostprocessing
import org.jetbrains.kotlin.idea.refactoring.validateElement
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui.KotlinExtractFunctionDialog
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui.KotlinParameterTablePanel
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui.ExtractFunctionParameterTablePanel
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.psi.*
@@ -87,7 +87,7 @@ class KotlinIntroduceParameterDialog private constructor(
private var replaceAllCheckBox: JCheckBox? = null
private var defaultValueCheckBox: JCheckBox? = null
private val removeParamsCheckBoxes = LinkedHashMap<JCheckBox, KtElement>(descriptor.parametersToRemove.size)
private var parameterTablePanel: KotlinParameterTablePanel? = null
private var parameterTablePanel: ExtractFunctionParameterTablePanel? = null
private val commandName = if (lambdaExtractionDescriptor != null) INTRODUCE_LAMBDA_PARAMETER else INTRODUCE_PARAMETER
init {
@@ -152,7 +152,7 @@ class KotlinIntroduceParameterDialog private constructor(
if (lambdaExtractionDescriptor != null
&& (lambdaExtractionDescriptor.parameters.isNotEmpty() || lambdaExtractionDescriptor.receiverParameter != null)) {
val parameterTablePanel = object : KotlinParameterTablePanel() {
val parameterTablePanel = object : ExtractFunctionParameterTablePanel() {
override fun onEnterAction() {
doOKAction()
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2016 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.
@@ -14,61 +14,41 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui;
package org.jetbrains.kotlin.idea.refactoring.introduce.ui;
import com.intellij.ui.BooleanTableCellRenderer;
import com.intellij.ui.TableUtil;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.components.JBComboBoxLabel;
import com.intellij.ui.components.editors.JBComboBoxTableCellEditorComponent;
import com.intellij.ui.table.JBTable;
import com.intellij.util.Function;
import com.intellij.util.ui.AbstractTableCellEditor;
import com.intellij.util.ui.EditableModel;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester;
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.Parameter;
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers;
import org.jetbrains.kotlin.types.KotlinType;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
public class KotlinParameterTablePanel extends JPanel {
public static class ParameterInfo {
private final Parameter originalParameter;
private final boolean receiver;
private String name;
private KotlinType type;
public abstract class AbstractParameterTablePanel<Param, UIParam extends AbstractParameterTablePanel.AbstractParameterInfo<Param>> extends JPanel {
public static abstract class AbstractParameterInfo<Param> {
private final Param originalParameter;
private boolean enabled = true;
private String name;
public ParameterInfo(Parameter originalParameter, boolean receiver) {
public AbstractParameterInfo(Param originalParameter) {
this.originalParameter = originalParameter;
this.receiver = receiver;
this.name = receiver ? "<receiver>" : originalParameter.getName();
this.type = originalParameter.getParameterType(false);
}
public Parameter getOriginalParameter() {
public Param getOriginalParameter() {
return originalParameter;
}
public boolean isReceiver() {
return receiver;
}
public boolean isEnabled() {
return enabled;
}
@@ -85,43 +65,28 @@ public class KotlinParameterTablePanel extends JPanel {
this.name = name;
}
public KotlinType getType() {
return type;
}
public void setType(KotlinType type) {
this.type = type;
}
public Parameter toParameter() {
return originalParameter.copy(name, type);
}
public abstract Param toParameter();
}
private List<ParameterInfo> parameterInfos;
protected List<UIParam> parameterInfos;
private JBTable myTable;
private MyTableModel myTableModel;
private TableModelBase myTableModel;
public KotlinParameterTablePanel() {
public AbstractParameterTablePanel() {
super(new BorderLayout());
}
public void init(@Nullable Parameter receiver, @NotNull List<Parameter> parameters) {
parameterInfos = CollectionsKt.mapTo(
parameters,
receiver != null
? CollectionsKt.arrayListOf(new ParameterInfo(receiver, true))
: new ArrayList<ParameterInfo>(),
new Function1<Parameter, ParameterInfo>() {
@Override
public ParameterInfo invoke(Parameter parameter) {
return new ParameterInfo(parameter, false);
}
}
);
protected TableModelBase createTableModel() {
return new TableModelBase();
}
myTableModel = new MyTableModel();
protected void createAdditionalColumns() {
}
public void init() {
myTableModel = createTableModel();
myTable = new JBTable(myTableModel);
DefaultCellEditor defaultEditor = (DefaultCellEditor) myTable.getDefaultEditor(Object.class);
defaultEditor.setClickCountToStart(1);
@@ -129,7 +94,7 @@ public class KotlinParameterTablePanel extends JPanel {
myTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myTable.setCellSelectionEnabled(true);
TableColumn checkBoxColumn = myTable.getColumnModel().getColumn(MyTableModel.CHECKMARK_COLUMN);
TableColumn checkBoxColumn = myTable.getColumnModel().getColumn(TableModelBase.CHECKMARK_COLUMN);
TableUtil.setupCheckboxColumn(checkBoxColumn);
checkBoxColumn.setHeaderValue("");
checkBoxColumn.setCellRenderer(
@@ -140,64 +105,15 @@ public class KotlinParameterTablePanel extends JPanel {
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column
) {
Component rendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
rendererComponent.setEnabled(KotlinParameterTablePanel.this.isEnabled());
rendererComponent.setEnabled(AbstractParameterTablePanel.this.isEnabled());
return rendererComponent;
}
}
);
myTable.getColumnModel().getColumn(MyTableModel.PARAMETER_NAME_COLUMN).setHeaderValue("Name");
myTable.getColumnModel().getColumn(TableModelBase.PARAMETER_NAME_COLUMN).setHeaderValue("Name");
TableColumn parameterTypeColumn = myTable.getColumnModel().getColumn(MyTableModel.PARAMETER_TYPE_COLUMN);
parameterTypeColumn.setHeaderValue("Type");
parameterTypeColumn.setCellRenderer(new DefaultTableCellRenderer() {
private final JBComboBoxLabel myLabel = new JBComboBoxLabel();
@Override
@NotNull
public Component getTableCellRendererComponent(
@NotNull JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column
) {
myLabel.setText(IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType((KotlinType) value));
myLabel.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
myLabel.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
if (isSelected) {
myLabel.setSelectionIcon();
}
else {
myLabel.setRegularIcon();
}
return myLabel;
}
});
parameterTypeColumn.setCellEditor(new AbstractTableCellEditor() {
final JBComboBoxTableCellEditorComponent myEditorComponent = new JBComboBoxTableCellEditorComponent();
@Override
@Nullable
public Object getCellEditorValue() {
return myEditorComponent.getEditorValue();
}
@Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column
) {
ParameterInfo info = parameterInfos.get(row);
myEditorComponent.setCell(table, row, column);
myEditorComponent.setOptions(info.getOriginalParameter().getParameterTypeCandidates(false).toArray());
myEditorComponent.setDefaultValue(info.getType());
myEditorComponent.setToString(new Function<Object, String>() {
@Override
public String fun(Object o) {
return IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType((KotlinType) o);
}
});
return myEditorComponent;
}
});
createAdditionalColumns();
myTable.setPreferredScrollableViewportSize(new Dimension(250, myTable.getRowHeight() * 5));
myTable.setShowGrid(false);
@@ -275,10 +191,9 @@ public class KotlinParameterTablePanel extends JPanel {
}
private class MyTableModel extends AbstractTableModel implements EditableModel {
protected class TableModelBase extends AbstractTableModel implements EditableModel {
public static final int CHECKMARK_COLUMN = 0;
public static final int PARAMETER_NAME_COLUMN = 1;
public static final int PARAMETER_TYPE_COLUMN = 2;
@Override
public void addRow() {
@@ -295,7 +210,7 @@ public class KotlinParameterTablePanel extends JPanel {
if (oldIndex < 0 || newIndex < 0) return;
if (oldIndex >= parameterInfos.size() || newIndex >= parameterInfos.size()) return;
ParameterInfo old = parameterInfos.get(oldIndex);
UIParam old = parameterInfos.get(oldIndex);
parameterInfos.set(oldIndex, parameterInfos.get(newIndex));
parameterInfos.set(newIndex, old);
@@ -311,13 +226,13 @@ public class KotlinParameterTablePanel extends JPanel {
}
@Override
public int getRowCount() {
return parameterInfos.size();
public int getColumnCount() {
return 2;
}
@Override
public int getColumnCount() {
return 3;
public int getRowCount() {
return parameterInfos.size();
}
@Override
@@ -327,8 +242,6 @@ public class KotlinParameterTablePanel extends JPanel {
return parameterInfos.get(rowIndex).isEnabled();
case PARAMETER_NAME_COLUMN:
return parameterInfos.get(rowIndex).getName();
case PARAMETER_TYPE_COLUMN:
return parameterInfos.get(rowIndex).getType();
default:
return null;
}
@@ -336,7 +249,7 @@ public class KotlinParameterTablePanel extends JPanel {
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
ParameterInfo info = parameterInfos.get(rowIndex);
AbstractParameterInfo info = parameterInfos.get(rowIndex);
switch (columnIndex) {
case CHECKMARK_COLUMN: {
info.setEnabled((Boolean) aValue);
@@ -353,24 +266,17 @@ public class KotlinParameterTablePanel extends JPanel {
updateSignature();
break;
}
case PARAMETER_TYPE_COLUMN: {
info.setType((KotlinType) aValue);
updateSignature();
break;
}
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
ParameterInfo info = parameterInfos.get(rowIndex);
AbstractParameterInfo info = parameterInfos.get(rowIndex);
switch (columnIndex) {
case CHECKMARK_COLUMN:
return isEnabled();
case PARAMETER_NAME_COLUMN:
return isEnabled() && info.isEnabled() && !info.isReceiver();
case PARAMETER_TYPE_COLUMN:
return isEnabled() && info.isEnabled() && info.getOriginalParameter().getParameterTypeCandidates(false).size() > 1;
return isEnabled() && info.isEnabled();
default:
return false;
}
@@ -386,34 +292,13 @@ public class KotlinParameterTablePanel extends JPanel {
}
}
@Nullable
public ParameterInfo getReceiverInfo() {
return CollectionsKt.singleOrNull(
parameterInfos,
new Function1<ParameterInfo, Boolean>() {
@Override
public Boolean invoke(ParameterInfo info) {
return info.isEnabled() && info.isReceiver();
}
}
);
}
@NotNull
public List<ParameterInfo> getParameterInfos() {
return CollectionsKt.filter(
parameterInfos,
new Function1<ParameterInfo, Boolean>() {
@Override
public Boolean invoke(ParameterInfo info) {
return info.isEnabled() && !info.isReceiver();
}
}
);
}
@NotNull
public JBTable getTable() {
return myTable;
}
@NotNull
public TableModelBase getTableModel() {
return myTableModel;
}
}