blob: aab87a9812ac348a3c1329dc66ea7e9d164cf4c6 [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.apache.jmeter.modifiers.gui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import org.apache.jmeter.gui.util.HeaderAsPropertyRenderer;
import org.apache.jmeter.gui.util.PowerTableModel;
import org.apache.jmeter.gui.util.VerticalPanel;
import org.apache.jmeter.modifiers.UserParameters;
import org.apache.jmeter.processor.gui.AbstractPreProcessorGui;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.CollectionProperty;
import org.apache.jmeter.testelement.property.PropertyIterator;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.gui.GuiUtils;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
public class UserParametersGui extends AbstractPreProcessorGui {
private static final long serialVersionUID = 240L;
private static final Logger log = LoggingManager.getLoggerForClass();
private static final String NAME_COL_RESOURCE = "name"; // $NON-NLS-1$
private static final String USER_COL_RESOURCE = "user"; // $NON-NLS-1$
private static final String UNDERSCORE = "_"; // $NON-NLS-1$
private JTable paramTable;
private PowerTableModel tableModel;
private int numUserColumns = 1;
private JButton addParameterButton, addUserButton, deleteRowButton, deleteColumnButton;
private JCheckBox perIterationCheck;
private JPanel paramPanel;
public UserParametersGui() {
super();
init();
}
@Override
public String getLabelResource() {
return "user_parameters_title"; // $NON-NLS-1$
}
@Override
public void configure(TestElement el) {
initTableModel();
paramTable.setModel(tableModel);
UserParameters params = (UserParameters) el;
CollectionProperty names = params.getNames();
CollectionProperty threadValues = params.getThreadLists();
tableModel.setColumnData(0, (List<?>) names.getObjectValue());
PropertyIterator iter = threadValues.iterator();
if (iter.hasNext()) {
tableModel.setColumnData(1, (List<?>) iter.next().getObjectValue());
}
int count = 2;
while (iter.hasNext()) {
String colName = getUserColName(count);
tableModel.addNewColumn(colName, String.class);
tableModel.setColumnData(count, (List<?>) iter.next().getObjectValue());
count++;
}
setColumnWidths();
perIterationCheck.setSelected(params.isPerIteration());
super.configure(el);
}
/**
* @see org.apache.jmeter.gui.JMeterGUIComponent#createTestElement()
*/
@Override
public TestElement createTestElement() {
UserParameters params = new UserParameters();
modifyTestElement(params);
return params;
}
/**
* Modifies a given TestElement to mirror the data in the gui components.
*
* @see org.apache.jmeter.gui.JMeterGUIComponent#modifyTestElement(TestElement)
*/
@Override
public void modifyTestElement(TestElement params) {
GuiUtils.stopTableEditing(paramTable);
UserParameters userParams = ((UserParameters) params);
userParams.setNames(new CollectionProperty(UserParameters.NAMES, tableModel.getColumnData(NAME_COL_RESOURCE)));
CollectionProperty threadLists = new CollectionProperty(UserParameters.THREAD_VALUES, new ArrayList<>());
log.debug("making threadlists from gui");
for (int col = 1; col < tableModel.getColumnCount(); col++) {
threadLists.addItem(tableModel.getColumnData(getUserColName(col)));
if (log.isDebugEnabled()) {
log.debug("Adding column to threadlist: " + tableModel.getColumnData(getUserColName(col)));
log.debug("Threadlists now = " + threadLists);
}
}
if (log.isDebugEnabled()) {
log.debug("In the end, threadlists = " + threadLists);
}
userParams.setThreadLists(threadLists);
userParams.setPerIteration(perIterationCheck.isSelected());
super.configureTestElement(params);
}
/**
* Implements JMeterGUIComponent.clearGui
*/
@Override
public void clearGui() {
super.clearGui();
initTableModel();
paramTable.setModel(tableModel);
HeaderAsPropertyRenderer defaultRenderer = new HeaderAsPropertyRenderer(){
private static final long serialVersionUID = 240L;
@Override
protected String getText(Object value, int row, int column) {
if (column >= 1){ // Don't process the NAME column
String val = value.toString();
if (val.startsWith(USER_COL_RESOURCE+UNDERSCORE)){
return JMeterUtils.getResString(USER_COL_RESOURCE)+val.substring(val.indexOf(UNDERSCORE));
}
}
return super.getText(value, row, column);
}
};
paramTable.getTableHeader().setDefaultRenderer(defaultRenderer);
perIterationCheck.setSelected(false);
}
private String getUserColName(int user){
return USER_COL_RESOURCE+UNDERSCORE+user;
}
private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final)
setBorder(makeBorder());
setLayout(new BorderLayout());
JPanel vertPanel = new VerticalPanel();
vertPanel.add(makeTitlePanel());
perIterationCheck = new JCheckBox(JMeterUtils.getResString("update_per_iter"), true); // $NON-NLS-1$
Box perIterationPanel = Box.createHorizontalBox();
perIterationPanel.add(perIterationCheck);
perIterationPanel.add(Box.createHorizontalGlue());
vertPanel.add(perIterationPanel);
add(vertPanel, BorderLayout.NORTH);
add(makeParameterPanel(), BorderLayout.CENTER);
}
private JPanel makeParameterPanel() {
JLabel tableLabel = new JLabel(JMeterUtils.getResString("user_parameters_table")); // $NON-NLS-1$
initTableModel();
paramTable = new JTable(tableModel);
// paramTable.setRowSelectionAllowed(true);
// paramTable.setColumnSelectionAllowed(true);
paramTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
paramTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// paramTable.setCellSelectionEnabled(true);
// paramTable.setPreferredScrollableViewportSize(new Dimension(100,
// 70));
JMeterUtils.applyHiDPI(paramTable);
paramPanel = new JPanel(new BorderLayout());
paramPanel.add(tableLabel, BorderLayout.NORTH);
JScrollPane scroll = new JScrollPane(paramTable);
scroll.setPreferredSize(scroll.getMinimumSize());
paramPanel.add(scroll, BorderLayout.CENTER);
paramPanel.add(makeButtonPanel(), BorderLayout.SOUTH);
return paramPanel;
}
protected void initTableModel() {
tableModel = new PowerTableModel(new String[] { NAME_COL_RESOURCE, // $NON-NLS-1$
getUserColName(numUserColumns) }, new Class[] { String.class, String.class });
}
private JPanel makeButtonPanel() {
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(2, 2));
addParameterButton = new JButton(JMeterUtils.getResString("add_parameter")); // $NON-NLS-1$
addUserButton = new JButton(JMeterUtils.getResString("add_user")); // $NON-NLS-1$
deleteRowButton = new JButton(JMeterUtils.getResString("delete_parameter")); // $NON-NLS-1$
deleteColumnButton = new JButton(JMeterUtils.getResString("delete_user")); // $NON-NLS-1$
buttonPanel.add(addParameterButton);
buttonPanel.add(deleteRowButton);
buttonPanel.add(addUserButton);
buttonPanel.add(deleteColumnButton);
addParameterButton.addActionListener(new AddParamAction());
addUserButton.addActionListener(new AddUserAction());
deleteRowButton.addActionListener(new DeleteRowAction());
deleteColumnButton.addActionListener(new DeleteColumnAction());
return buttonPanel;
}
/**
* Set Column size
*/
private void setColumnWidths() {
int margin = 10;
int minwidth = 150;
JTableHeader tableHeader = paramTable.getTableHeader();
FontMetrics headerFontMetrics = tableHeader.getFontMetrics(tableHeader.getFont());
for (int i = 0; i < tableModel.getColumnCount(); i++) {
int headerWidth = headerFontMetrics.stringWidth(paramTable.getColumnName(i));
int maxWidth = getMaximalRequiredColumnWidth(i, headerWidth);
paramTable.getColumnModel().getColumn(i).setPreferredWidth(Math.max(maxWidth + margin, minwidth));
}
}
/**
* Compute max width between width of the largest column at columnIndex and headerWidth
* @param columnIndex Column index
* @param headerWidth Header width based on Font
*/
private int getMaximalRequiredColumnWidth(int columnIndex, int headerWidth) {
int maxWidth = headerWidth;
TableColumn column = paramTable.getColumnModel().getColumn(columnIndex);
TableCellRenderer cellRenderer = column.getCellRenderer();
if(cellRenderer == null) {
cellRenderer = new DefaultTableCellRenderer();
}
for(int row = 0; row < paramTable.getModel().getRowCount(); row++) {
Component rendererComponent = cellRenderer.getTableCellRendererComponent(paramTable,
paramTable.getModel().getValueAt(row, columnIndex),
false,
false,
row,
columnIndex);
double valueWidth = rendererComponent.getPreferredSize().getWidth();
maxWidth = (int) Math.max(maxWidth, valueWidth);
}
return maxWidth;
}
private class AddParamAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
GuiUtils.stopTableEditing(paramTable);
tableModel.addNewRow();
tableModel.fireTableDataChanged();
// Enable DELETE (which may already be enabled, but it won't hurt)
deleteRowButton.setEnabled(true);
// Highlight (select) the appropriate row.
int rowToSelect = tableModel.getRowCount() - 1;
paramTable.setRowSelectionInterval(rowToSelect, rowToSelect);
}
}
private class AddUserAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
GuiUtils.stopTableEditing(paramTable);
tableModel.addNewColumn(getUserColName(tableModel.getColumnCount()), String.class);
tableModel.fireTableDataChanged();
setColumnWidths();
// Enable DELETE (which may already be enabled, but it won't hurt)
deleteColumnButton.setEnabled(true);
// Highlight (select) the appropriate row.
int colToSelect = tableModel.getColumnCount() - 1;
paramTable.setColumnSelectionInterval(colToSelect, colToSelect);
}
}
private class DeleteRowAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
GuiUtils.cancelEditing(paramTable);
int rowSelected = paramTable.getSelectedRow();
if (rowSelected >= 0) {
tableModel.removeRow(rowSelected);
tableModel.fireTableDataChanged();
// Disable DELETE if there are no rows in the table to delete.
if (tableModel.getRowCount() == 0) {
deleteRowButton.setEnabled(false);
}
// Table still contains one or more rows, so highlight (select)
// the appropriate one.
else {
int rowToSelect = rowSelected;
if (rowSelected >= tableModel.getRowCount()) {
rowToSelect = rowSelected - 1;
}
paramTable.setRowSelectionInterval(rowToSelect, rowToSelect);
}
}
}
}
private class DeleteColumnAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
GuiUtils.cancelEditing(paramTable);
int colSelected = paramTable.getSelectedColumn();
if (colSelected == 0 || colSelected == 1) {
JOptionPane.showMessageDialog(null,
JMeterUtils.getResString("column_delete_disallowed"), // $NON-NLS-1$
"Error",
JOptionPane.ERROR_MESSAGE);
return;
}
if (colSelected >= 0) {
tableModel.removeColumn(colSelected);
tableModel.fireTableDataChanged();
// Disable DELETE if there are no rows in the table to delete.
if (tableModel.getColumnCount() == 0) {
deleteColumnButton.setEnabled(false);
}
// Table still contains one or more rows, so highlight (select)
// the appropriate one.
else {
if (colSelected >= tableModel.getColumnCount()) {
colSelected = colSelected - 1;
}
paramTable.setColumnSelectionInterval(colSelected, colSelected);
}
setColumnWidths();
}
}
}
}