blob: 380f5ba161ec31c622cc6db1f439c29778282851 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.netbeans.modules.j2ee.core.support.java.method;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.text.JTextComponent;
import org.netbeans.api.java.source.ClasspathInfo;
import org.netbeans.modules.j2ee.core.api.support.java.method.MethodModel;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
/**
*
* @author Martin Adamek
*/
public final class ParametersPanel extends javax.swing.JPanel {
private static final int COL_NAME_INDEX = 0;
private static final int COL_TYPE_INDEX = 1;
private static final int COL_FINAL_INDEX = 2;
private static final String[] columnNames = {
NbBundle.getMessage(ParametersPanel.class, "ParametersPanel.LBL_Name"), // NOI18N
NbBundle.getMessage(ParametersPanel.class, "ParametersPanel.LBL_Type"), // NOI18N
NbBundle.getMessage(ParametersPanel.class, "ParametersPanel.LBL_Final"), // NOI18N
};
public static final String SELECTION = "selection"; // NOI18N
private final ParamsTableModel tableModel;
public ParametersPanel(ClasspathInfo cpInfo, List<MethodModel.Variable> parameters) {
initComponents();
tableModel = new ParamsTableModel(parameters);
table.setModel(tableModel);
tableModel.addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
firePropertyChange("parameters", null, null); // NOI18N
}
});
if (parameters.isEmpty()) {
table.setFocusable(false);
}
JComboBox typeCombo = new JComboBox();
ReturnTypeUIHelper.connect(typeCombo, cpInfo);
TableColumn typeTableColumn = table.getColumnModel().getColumn(COL_TYPE_INDEX);
typeTableColumn.setCellEditor(new DefaultCellEditor(typeCombo));
// #147884 fix
typeCombo.addActionListener(new TypeComboListener(typeCombo));
table.setRowHeight(typeCombo.getPreferredSize().height);
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); // NOI18N
ListSelectionListener listSelectionListener = new ListSelectionListenerImpl();
table.getSelectionModel().addListSelectionListener(listSelectionListener);
table.getColumnModel().getSelectionModel().addListSelectionListener(listSelectionListener);
table.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
updateButtons();
}
});
table.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
updateButtons();
}
});
updateButtons();
}
public List<MethodModel.Variable> getParameters() {
return tableModel.getParameters();
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
table = new javax.swing.JTable();
addButton = new javax.swing.JButton();
removeButton = new javax.swing.JButton();
upButton = new javax.swing.JButton();
downButton = new javax.swing.JButton();
table.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
}
));
jScrollPane1.setViewportView(table);
table.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ParametersPanel.class, "ACSN_ParametersTab")); // NOI18N
table.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ParametersPanel.class, "ACSD_ParametersTab")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(addButton, org.openide.util.NbBundle.getMessage(ParametersPanel.class, "ParametersPanel.addButton.text")); // NOI18N
addButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
addButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(removeButton, org.openide.util.NbBundle.getMessage(ParametersPanel.class, "ParametersPanel.removeButton.text")); // NOI18N
removeButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
removeButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(upButton, org.openide.util.NbBundle.getMessage(ParametersPanel.class, "ParametersPanel.upButton.text")); // NOI18N
upButton.setEnabled(false);
upButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
upButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(downButton, org.openide.util.NbBundle.getMessage(ParametersPanel.class, "ParametersPanel.downButton.text")); // NOI18N
downButton.setEnabled(false);
downButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
downButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 241, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(addButton)
.addComponent(removeButton)
.addComponent(upButton)
.addComponent(downButton))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {addButton, downButton, removeButton, upButton});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(addButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(removeButton)
.addGap(22, 22, 22)
.addComponent(upButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(downButton))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE))
.addContainerGap())
);
addButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ParametersPanel.class, "ACSD_AddParameterIntoTab")); // NOI18N
removeButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ParametersPanel.class, "ACSD_RemoveParameterIntoTab")); // NOI18N
upButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ParametersPanel.class, "ACSD_MoveUpInParamTab")); // NOI18N
downButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ParametersPanel.class, "ACSD_MoveDownInParamTab")); // NOI18N
}// </editor-fold>//GEN-END:initComponents
private void upButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_upButtonActionPerformed
int selIndex = table.getSelectedRow();
int newIndex = selIndex - 1;
if (newIndex >= 0) {
tableModel.set(newIndex, tableModel.set(selIndex, tableModel.getParameter(newIndex)));
table.setRowSelectionInterval(newIndex, newIndex);
updateButtons();
}
}//GEN-LAST:event_upButtonActionPerformed
private void downButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downButtonActionPerformed
int selIndex = table.getSelectedRow();
int newIndex = selIndex + 1;
if (newIndex < tableModel.getParameters().size()) {
tableModel.set(newIndex, tableModel.set(selIndex, tableModel.getParameter(newIndex)));
table.setRowSelectionInterval(newIndex, newIndex);
updateButtons();
}
}//GEN-LAST:event_downButtonActionPerformed
private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
int selectedRow = table.getSelectedRow();
if (selectedRow > -1) {
tableModel.removeParameter(selectedRow);
}
if (selectedRow == table.getRowCount()) {
selectedRow--;
}
table.getSelectionModel().setSelectionInterval(selectedRow, selectedRow);
updateButtons();
}//GEN-LAST:event_removeButtonActionPerformed
private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
int index = tableModel.addParameter();
table.getSelectionModel().setSelectionInterval(index, index);
table.getColumnModel().getSelectionModel().setSelectionInterval(COL_NAME_INDEX, COL_NAME_INDEX);
updateButtons();
}//GEN-LAST:event_addButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton addButton;
private javax.swing.JButton downButton;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JButton removeButton;
private javax.swing.JTable table;
private javax.swing.JButton upButton;
// End of variables declaration//GEN-END:variables
private void updateButtons() {
int selIndex = table.getSelectedRow();
boolean oneSelected = table.getSelectedRowCount() == 1;
removeButton.setEnabled(oneSelected);
upButton.setEnabled(oneSelected && (selIndex > 0));
downButton.setEnabled(oneSelected && (selIndex < tableModel.getRowCount() - 1));
}
// accessible for test
static class ParamsTableModel extends AbstractTableModel {
private final List<MethodModel.Variable> parameters;
public ParamsTableModel(List<MethodModel.Variable> parameters) {
this.parameters = new ArrayList<MethodModel.Variable>(parameters);
}
public List<MethodModel.Variable> getParameters() {
return parameters;
}
public int addParameter() {
String name = generateUniqueName("parameter"); // NOI18N
MethodModel.Variable parameter = MethodModel.Variable.create("java.lang.String", name, false); // NOI18N
int index = parameters.size();
parameters.add(parameter);
fireTableRowsInserted(index, index);
return index;
}
public void removeParameter(int index) {
parameters.remove(index);
fireTableRowsDeleted(index, index);
}
public MethodModel.Variable getParameter(int index) {
return parameters.get(index);
}
public MethodModel.Variable set(int index, MethodModel.Variable parameter) {
return parameters.set(index, parameter);
}
public int getRowCount() {
return parameters.size();
}
public int getColumnCount() {
return 3;
}
public Object getValueAt(int row, int column) {
Object result = null;
if (row >= 0) {
MethodModel.Variable parameter = parameters.get(row);
if (parameter != null) {
switch (column) {
case COL_NAME_INDEX: result = parameter.getName(); break;
case COL_TYPE_INDEX: result = parameter.getType(); break;
case COL_FINAL_INDEX: result = parameter.getFinalModifier(); break;
default:
}
}
}
return result;
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
@Override
public boolean isCellEditable(int row, int column) {
return true;
}
@Override
public void setValueAt(Object aValue, int row, int column) {
// check if inserted name is valid Java identifier
// if not, fall back to old value
if (column == COL_NAME_INDEX) {
String insertedName = (String) aValue;
if (!Utilities.isJavaIdentifier(insertedName.trim())) {
return;
}
}
MethodModel.Variable parameter = parameters.get(row);
MethodModel.Variable changedParameter = MethodModel.Variable.create(
column == COL_TYPE_INDEX ? chooseType(aValue, parameter.getType()) : parameter.getType(),
column == COL_NAME_INDEX ? chooseName(aValue, parameter.getName()) : parameter.getName(),
column == COL_FINAL_INDEX ? (Boolean) aValue : parameter.getFinalModifier()
);
parameters.set(row, changedParameter);
fireTableCellUpdated(row, column);
}
// JTable uses this method to determine the default renderer/editor for each cell.
// If we didn't implement this method, then the last column would contain
// text ("true"/"false"), rather than a check box.
@Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
private String generateUniqueName(String name) {
List<Integer> numberSuffixes = new ArrayList<Integer>();
for (MethodModel.Variable variable : parameters) {
if (!name.equals(variable.getName()) && variable.getName().startsWith(name)) {
String suffix = variable.getName().substring(name.length());
if (isNumber(suffix)) {
numberSuffixes.add(Integer.parseInt(suffix));
}
}
}
Collections.sort(numberSuffixes);
String result = name;
if (numberSuffixes.size() > 0) {
int newSuffix = numberSuffixes.get(numberSuffixes.size() - 1) + 1;
result = name + newSuffix;
} else if (parameters.size() > 0) {
result = name + 1;
}
return result;
}
private boolean isNumber(String value) {
for (char character : value.toCharArray()) {
if (!Character.isDigit(character)) {
return false;
}
}
return true;//!value.trim().equals("");
}
}
private static String chooseType(Object aValue, String typeName) {
if (!(aValue instanceof String)) {
return "*"; // NOI18N
}
String aValueString = ((String)aValue).trim();
if (aValueString.equals("")) { // NOI18N
return typeName;
}
return aValueString;
}
private static String chooseName(Object aValue, String name) {
String aValueString = ((String)aValue).trim();
if (aValueString.equals("")) { // NOI18N
return name;
}
return aValueString;
}
private class ListSelectionListenerImpl implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
table.editCellAt(table.getSelectedRow(), table.getSelectedColumn());
Component editor = table.getEditorComponent();
if (editor instanceof JComboBox) {
editor = ((JComboBox) editor).getEditor().getEditorComponent();
}
if (editor != null) {
editor.requestFocus();
}
if (editor instanceof JTextComponent) {
JTextComponent textComp = (JTextComponent) editor;
textComp.selectAll();
}
}
}
private class TypeComboListener implements ActionListener {
private JComboBox typeCombo;
TypeComboListener(JComboBox combo) {
this.typeCombo = combo;
}
public void actionPerformed(ActionEvent e) {
int selectedRow = table.getSelectedRow();
if (selectedRow >= 0) {
String typeInModel = tableModel.getValueAt(selectedRow, COL_TYPE_INDEX).toString();
if ("*".equals(typeInModel) && typeCombo.getSelectedItem() != null) { // NOI18N
tableModel.setValueAt(typeCombo.getSelectedItem(), selectedRow, COL_TYPE_INDEX);
}
}
}
}
}