Java tutorial
/* * 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.visualizers; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.FileWriter; import java.io.IOException; import java.text.DecimalFormat; import java.text.Format; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JColorChooser; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.table.TableCellRenderer; import org.apache.commons.lang3.ArrayUtils; import org.apache.jmeter.gui.action.ActionNames; import org.apache.jmeter.gui.action.ActionRouter; import org.apache.jmeter.gui.action.SaveGraphics; import org.apache.jmeter.gui.util.FileDialoger; import org.apache.jmeter.gui.util.FilePanel; import org.apache.jmeter.gui.util.HeaderAsPropertyRenderer; import org.apache.jmeter.gui.util.VerticalPanel; import org.apache.jmeter.samplers.Clearable; import org.apache.jmeter.samplers.SampleResult; import org.apache.jmeter.save.CSVSaveService; import org.apache.jmeter.util.JMeterUtils; import org.apache.jmeter.visualizers.gui.AbstractVisualizer; import org.apache.jorphan.gui.GuiUtils; import org.apache.jorphan.gui.JLabeledTextField; import org.apache.jorphan.gui.NumberRenderer; import org.apache.jorphan.gui.ObjectTableModel; import org.apache.jorphan.gui.RateRenderer; import org.apache.jorphan.gui.RendererUtils; import org.apache.jorphan.logging.LoggingManager; import org.apache.jorphan.reflect.Functor; import org.apache.jorphan.util.JOrphanUtils; import org.apache.log.Logger; /** * Aggregrate Table-Based Reporting Visualizer for JMeter. Props to the people * who've done the other visualizers ahead of me (Stefano Mazzocchi), who I * borrowed code from to start me off (and much code may still exist). Thank * you! * */ public class StatGraphVisualizer extends AbstractVisualizer implements Clearable, ActionListener { private static final long serialVersionUID = 240L; private static final String pct1Label = JMeterUtils.getPropDefault("aggregate_rpt_pct1", "90"); private static final String pct2Label = JMeterUtils.getPropDefault("aggregate_rpt_pct2", "95"); private static final String pct3Label = JMeterUtils.getPropDefault("aggregate_rpt_pct3", "99"); private static final Float pct1Value = new Float(Float.parseFloat(pct1Label) / 100); private static final Float pct2Value = new Float(Float.parseFloat(pct2Label) / 100); private static final Float pct3Value = new Float(Float.parseFloat(pct3Label) / 100); private static final Logger log = LoggingManager.getLoggerForClass(); static final String[] COLUMNS = { "sampler_label", //$NON-NLS-1$ "aggregate_report_count", //$NON-NLS-1$ "average", //$NON-NLS-1$ "aggregate_report_median", //$NON-NLS-1$ "aggregate_report_xx_pct1_line", //$NON-NLS-1$ "aggregate_report_xx_pct2_line", //$NON-NLS-1$ "aggregate_report_xx_pct3_line", //$NON-NLS-1$ "aggregate_report_min", //$NON-NLS-1$ "aggregate_report_max", //$NON-NLS-1$ "aggregate_report_error%", //$NON-NLS-1$ "aggregate_report_rate", //$NON-NLS-1$ "aggregate_report_bandwidth" }; //$NON-NLS-1$ static final Object[][] COLUMNS_MSG_PARAMETERS = { null, //$NON-NLS-1$ null, //$NON-NLS-1$ null, //$NON-NLS-1$ null, //$NON-NLS-1$ new Object[] { pct1Label }, //$NON-NLS-1$ new Object[] { pct2Label }, //$NON-NLS-1$ new Object[] { pct3Label }, //$NON-NLS-1$ null, //$NON-NLS-1$ null, //$NON-NLS-1$ null, //$NON-NLS-1$ null, //$NON-NLS-1$ null }; //$NON-NLS-1$ private final String[] GRAPH_COLUMNS = { "average", //$NON-NLS-1$ "aggregate_report_median", //$NON-NLS-1$ "aggregate_report_xx_pct1_line", //$NON-NLS-1$ "aggregate_report_xx_pct2_line", //$NON-NLS-1$ "aggregate_report_xx_pct3_line", //$NON-NLS-1$ "aggregate_report_min", //$NON-NLS-1$ "aggregate_report_max" }; //$NON-NLS-1$ private final String TOTAL_ROW_LABEL = JMeterUtils.getResString("aggregate_report_total_label"); //$NON-NLS-1$ private static final Font FONT_DEFAULT = UIManager.getDefaults().getFont("TextField.font"); //$NON-NLS-1$ private static final Font FONT_SMALL = new Font("SansSerif", Font.PLAIN, //$NON-NLS-1$ (int) Math.round(FONT_DEFAULT.getSize() * 0.8)); private JTable myJTable; private JScrollPane myScrollPane; private transient ObjectTableModel model; /** * Lock used to protect tableRows update + model update */ private final transient Object lock = new Object(); private final Map<String, SamplingStatCalculator> tableRows = new ConcurrentHashMap<>(); private AxisGraph graphPanel = null; private JPanel settingsPane = null; private JSplitPane spane = null; //NOT USED protected double[][] data = null; private JTabbedPane tabbedGraph = new JTabbedPane(SwingConstants.TOP); private JButton displayButton = new JButton(JMeterUtils.getResString("aggregate_graph_display")); //$NON-NLS-1$ private JButton saveGraph = new JButton(JMeterUtils.getResString("aggregate_graph_save")); //$NON-NLS-1$ private JButton saveTable = new JButton(JMeterUtils.getResString("aggregate_graph_save_table")); //$NON-NLS-1$ private JButton chooseForeColor = new JButton( JMeterUtils.getResString("aggregate_graph_choose_foreground_color")); //$NON-NLS-1$ private JButton syncWithName = new JButton(JMeterUtils.getResString("aggregate_graph_sync_with_name")); //$NON-NLS-1$ private JCheckBox saveHeaders = // should header be saved with the data? new JCheckBox(JMeterUtils.getResString("aggregate_graph_save_table_header")); //$NON-NLS-1$ private JLabeledTextField graphTitle = new JLabeledTextField( JMeterUtils.getResString("aggregate_graph_user_title")); //$NON-NLS-1$ private JLabeledTextField maxLengthXAxisLabel = new JLabeledTextField( JMeterUtils.getResString("aggregate_graph_max_length_xaxis_label"), 8);//$NON-NLS-1$ private JLabeledTextField maxValueYAxisLabel = new JLabeledTextField( JMeterUtils.getResString("aggregate_graph_yaxis_max_value"), 8);//$NON-NLS-1$ /** * checkbox for use dynamic graph size */ private JCheckBox dynamicGraphSize = new JCheckBox(JMeterUtils.getResString("aggregate_graph_dynamic_size")); // $NON-NLS-1$ private JLabeledTextField graphWidth = new JLabeledTextField(JMeterUtils.getResString("aggregate_graph_width"), //$NON-NLS-1$ 6); private JLabeledTextField graphHeight = new JLabeledTextField( JMeterUtils.getResString("aggregate_graph_height"), 6); //$NON-NLS-1$ private String yAxisLabel = JMeterUtils.getResString("aggregate_graph_response_time");//$NON-NLS-1$ private String yAxisTitle = JMeterUtils.getResString("aggregate_graph_ms"); //$NON-NLS-1$ private boolean saveGraphToFile = false; private int defaultWidth = 400; private int defaultHeight = 300; private JComboBox<String> columnsList = new JComboBox<>(GRAPH_COLUMNS); private List<BarGraph> eltList = new ArrayList<>(); private JCheckBox columnSelection = new JCheckBox(JMeterUtils.getResString("aggregate_graph_column_selection"), //$NON-NLS-1$ false); private JTextField columnMatchLabel = new JTextField(); private JButton applyFilterBtn = new JButton(JMeterUtils.getResString("graph_apply_filter")); // $NON-NLS-1$ private JCheckBox caseChkBox = new JCheckBox(JMeterUtils.getResString("search_text_chkbox_case"), false); // $NON-NLS-1$ private JCheckBox regexpChkBox = new JCheckBox(JMeterUtils.getResString("search_text_chkbox_regexp"), true); // $NON-NLS-1$ private JComboBox<String> titleFontNameList = new JComboBox<>( StatGraphProperties.getFontNameMap().keySet().toArray(ArrayUtils.EMPTY_STRING_ARRAY)); private JComboBox<String> titleFontSizeList = new JComboBox<>(StatGraphProperties.fontSize); private JComboBox<String> titleFontStyleList = new JComboBox<>( StatGraphProperties.getFontStyleMap().keySet().toArray(ArrayUtils.EMPTY_STRING_ARRAY)); private JComboBox<String> valueFontNameList = new JComboBox<>( StatGraphProperties.getFontNameMap().keySet().toArray(ArrayUtils.EMPTY_STRING_ARRAY)); private JComboBox<String> valueFontSizeList = new JComboBox<>(StatGraphProperties.fontSize); private JComboBox<String> valueFontStyleList = new JComboBox<>( StatGraphProperties.getFontStyleMap().keySet().toArray(ArrayUtils.EMPTY_STRING_ARRAY)); private JComboBox<String> fontNameList = new JComboBox<>( StatGraphProperties.getFontNameMap().keySet().toArray(ArrayUtils.EMPTY_STRING_ARRAY)); private JComboBox<String> fontSizeList = new JComboBox<>(StatGraphProperties.fontSize); private JComboBox<String> fontStyleList = new JComboBox<>( StatGraphProperties.getFontStyleMap().keySet().toArray(ArrayUtils.EMPTY_STRING_ARRAY)); private JComboBox<String> legendPlacementList = new JComboBox<>( StatGraphProperties.getPlacementNameMap().keySet().toArray(ArrayUtils.EMPTY_STRING_ARRAY)); private JCheckBox drawOutlinesBar = new JCheckBox(JMeterUtils.getResString("aggregate_graph_draw_outlines"), true); // Default checked // $NON-NLS-1$ private JCheckBox numberShowGrouping = new JCheckBox( JMeterUtils.getResString("aggregate_graph_number_grouping"), true); // Default checked // $NON-NLS-1$ private JCheckBox valueLabelsVertical = new JCheckBox( JMeterUtils.getResString("aggregate_graph_value_labels_vertical"), true); // Default checked // $NON-NLS-1$ private Color colorBarGraph = Color.YELLOW; private Color colorForeGraph = Color.BLACK; private int nbColToGraph = 1; private Pattern pattern = null; private transient Matcher matcher = null; public StatGraphVisualizer() { super(); model = createObjectTableModel(); eltList.add(new BarGraph(JMeterUtils.getResString("average"), true, new Color(202, 0, 0))); eltList.add( new BarGraph(JMeterUtils.getResString("aggregate_report_median"), false, new Color(49, 49, 181))); eltList.add(new BarGraph(MessageFormat.format(JMeterUtils.getResString("aggregate_report_xx_pct1_line"), new Object[] { pct1Label }), false, new Color(42, 121, 42))); eltList.add(new BarGraph(MessageFormat.format(JMeterUtils.getResString("aggregate_report_xx_pct2_line"), new Object[] { pct2Label }), false, new Color(242, 226, 8))); eltList.add(new BarGraph(MessageFormat.format(JMeterUtils.getResString("aggregate_report_xx_pct3_line"), new Object[] { pct3Label }), false, new Color(202, 10, 232))); eltList.add(new BarGraph(JMeterUtils.getResString("aggregate_report_min"), false, Color.LIGHT_GRAY)); eltList.add(new BarGraph(JMeterUtils.getResString("aggregate_report_max"), false, Color.DARK_GRAY)); clearData(); init(); } /** * Creates that Table model * @return ObjectTableModel */ static ObjectTableModel createObjectTableModel() { return new ObjectTableModel(COLUMNS, SamplingStatCalculator.class, new Functor[] { new Functor("getLabel"), //$NON-NLS-1$ new Functor("getCount"), //$NON-NLS-1$ new Functor("getMeanAsNumber"), //$NON-NLS-1$ new Functor("getMedian"), //$NON-NLS-1$ new Functor("getPercentPoint", //$NON-NLS-1$ new Object[] { pct1Value }), new Functor("getPercentPoint", //$NON-NLS-1$ new Object[] { pct2Value }), new Functor("getPercentPoint", //$NON-NLS-1$ new Object[] { pct3Value }), new Functor("getMin"), //$NON-NLS-1$ new Functor("getMax"), //$NON-NLS-1$ new Functor("getErrorPercentage"), //$NON-NLS-1$ new Functor("getRate"), //$NON-NLS-1$ new Functor("getKBPerSecond") }, //$NON-NLS-1$ new Functor[] { null, null, null, null, null, null, null, null, null, null, null, null }, new Class[] { String.class, Long.class, Long.class, Long.class, Long.class, Long.class, Long.class, Long.class, Long.class, String.class, String.class, String.class }); } // Column formats static final Format[] FORMATS = new Format[] { null, // Label null, // count null, // Mean null, // median null, // 90% null, // 95% null, // 99% null, // Min null, // Max new DecimalFormat("#0.00%"), // Error %age //$NON-NLS-1$ new DecimalFormat("#.0"), // Throughput //$NON-NLS-1$ new DecimalFormat("#.0") // pageSize //$NON-NLS-1$ }; // Column renderers static final TableCellRenderer[] RENDERERS = new TableCellRenderer[] { null, // Label null, // count null, // Mean null, // median null, // 90% null, // 95% null, // 99% null, // Min null, // Max new NumberRenderer("#0.00%"), // Error %age //$NON-NLS-1$ new RateRenderer("#.0"), // Throughput //$NON-NLS-1$ new NumberRenderer("#.0"), // pageSize //$NON-NLS-1$ }; public static boolean testFunctors() { StatGraphVisualizer instance = new StatGraphVisualizer(); return instance.model.checkFunctors(null, instance.getClass()); } @Override public String getLabelResource() { return "aggregate_graph_title"; //$NON-NLS-1$ } @Override public void add(final SampleResult res) { final String sampleLabel = res.getSampleLabel(); // Sampler selection if (columnSelection.isSelected() && pattern != null) { matcher = pattern.matcher(sampleLabel); } if ((matcher == null) || (matcher.find())) { JMeterUtils.runSafe(false, new Runnable() { @Override public void run() { SamplingStatCalculator row = null; synchronized (lock) { row = tableRows.get(sampleLabel); if (row == null) { row = new SamplingStatCalculator(sampleLabel); tableRows.put(row.getLabel(), row); model.insertRow(row, model.getRowCount() - 1); } } row.addSample(res); tableRows.get(TOTAL_ROW_LABEL).addSample(res); model.fireTableDataChanged(); } }); } } /** * Clears this visualizer and its model, and forces a repaint of the table. */ @Override public void clearData() { synchronized (lock) { model.clearData(); tableRows.clear(); tableRows.put(TOTAL_ROW_LABEL, new SamplingStatCalculator(TOTAL_ROW_LABEL)); model.addRow(tableRows.get(TOTAL_ROW_LABEL)); } } /** * Main visualizer setup. */ private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final) this.setLayout(new BorderLayout()); // MAIN PANEL JPanel mainPanel = new JPanel(); Border margin = new EmptyBorder(10, 10, 5, 10); Border margin2 = new EmptyBorder(10, 10, 5, 10); mainPanel.setBorder(margin); mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); mainPanel.add(makeTitlePanel()); myJTable = new JTable(model); JMeterUtils.applyHiDPI(myJTable); // Fix centering of titles myJTable.getTableHeader().setDefaultRenderer(new HeaderAsPropertyRenderer(COLUMNS_MSG_PARAMETERS)); myJTable.setPreferredScrollableViewportSize(new Dimension(500, 70)); RendererUtils.applyRenderers(myJTable, RENDERERS); myScrollPane = new JScrollPane(myJTable); settingsPane = new VerticalPanel(); settingsPane.setBorder(margin2); graphPanel = new AxisGraph(); graphPanel.setPreferredSize(new Dimension(defaultWidth, defaultHeight)); settingsPane.add(createGraphActionsPane()); settingsPane.add(createGraphColumnPane()); settingsPane.add(createGraphTitlePane()); settingsPane.add(createGraphDimensionPane()); JPanel axisPane = new JPanel(new BorderLayout()); axisPane.add(createGraphXAxisPane(), BorderLayout.WEST); axisPane.add(createGraphYAxisPane(), BorderLayout.CENTER); settingsPane.add(axisPane); settingsPane.add(createLegendPane()); tabbedGraph.addTab(JMeterUtils.getResString("aggregate_graph_tab_settings"), settingsPane); //$NON-NLS-1$ tabbedGraph.addTab(JMeterUtils.getResString("aggregate_graph_tab_graph"), graphPanel); //$NON-NLS-1$ // If clic on the Graph tab, make the graph (without apply interval or filter) ChangeListener changeListener = new ChangeListener() { @Override public void stateChanged(ChangeEvent changeEvent) { JTabbedPane srcTab = (JTabbedPane) changeEvent.getSource(); int index = srcTab.getSelectedIndex(); if (srcTab.getTitleAt(index).equals(JMeterUtils.getResString("aggregate_graph_tab_graph"))) { //$NON-NLS-1$ actionMakeGraph(); } } }; tabbedGraph.addChangeListener(changeListener); spane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); spane.setLeftComponent(myScrollPane); spane.setRightComponent(tabbedGraph); spane.setResizeWeight(.2); spane.setBorder(null); // see bug jdk 4131528 spane.setContinuousLayout(true); this.add(mainPanel, BorderLayout.NORTH); this.add(spane, BorderLayout.CENTER); } public void makeGraph() { nbColToGraph = getNbColumns(); Dimension size = graphPanel.getSize(); String lstr = maxLengthXAxisLabel.getText(); // canvas size int width = (int) size.getWidth(); int height = (int) size.getHeight(); if (!dynamicGraphSize.isSelected()) { String wstr = graphWidth.getText(); String hstr = graphHeight.getText(); if (wstr.length() != 0) { width = Integer.parseInt(wstr); } if (hstr.length() != 0) { height = Integer.parseInt(hstr); } } if (lstr.length() == 0) { lstr = "20";//$NON-NLS-1$ } int maxLength = Integer.parseInt(lstr); String yAxisStr = maxValueYAxisLabel.getText(); int maxYAxisScale = yAxisStr.length() == 0 ? 0 : Integer.parseInt(yAxisStr); graphPanel.setData(this.getData()); graphPanel.setTitle(graphTitle.getText()); graphPanel.setMaxLength(maxLength); graphPanel.setMaxYAxisScale(maxYAxisScale); graphPanel.setXAxisLabels(getAxisLabels()); graphPanel.setXAxisTitle(JMeterUtils.getResString((String) columnsList.getSelectedItem())); graphPanel.setYAxisLabels(this.yAxisLabel); graphPanel.setYAxisTitle(this.yAxisTitle); graphPanel.setLegendLabels(getLegendLabels()); graphPanel.setColor(getBackColors()); graphPanel.setForeColor(colorForeGraph); graphPanel.setOutlinesBarFlag(drawOutlinesBar.isSelected()); graphPanel.setShowGrouping(numberShowGrouping.isSelected()); graphPanel.setValueOrientation(valueLabelsVertical.isSelected()); graphPanel.setLegendPlacement( StatGraphProperties.getPlacementNameMap().get(legendPlacementList.getSelectedItem()).intValue()); graphPanel.setTitleFont( new Font(StatGraphProperties.getFontNameMap().get(titleFontNameList.getSelectedItem()), StatGraphProperties.getFontStyleMap().get(titleFontStyleList.getSelectedItem()).intValue(), Integer.parseInt((String) titleFontSizeList.getSelectedItem()))); graphPanel.setLegendFont(new Font(StatGraphProperties.getFontNameMap().get(fontNameList.getSelectedItem()), StatGraphProperties.getFontStyleMap().get(fontStyleList.getSelectedItem()).intValue(), Integer.parseInt((String) fontSizeList.getSelectedItem()))); graphPanel.setValueFont( new Font(StatGraphProperties.getFontNameMap().get(valueFontNameList.getSelectedItem()), StatGraphProperties.getFontStyleMap().get(valueFontStyleList.getSelectedItem()).intValue(), Integer.parseInt((String) valueFontSizeList.getSelectedItem()))); graphPanel.setHeight(height); graphPanel.setWidth(width); spane.repaint(); } public double[][] getData() { if (model.getRowCount() > 1) { int count = model.getRowCount() - 1; int size = nbColToGraph; double[][] data = new double[size][count]; int s = 0; int cpt = 0; for (BarGraph bar : eltList) { if (bar.getChkBox().isSelected()) { int col = model.findColumn(columnsList.getItemAt(cpt)); for (int idx = 0; idx < count; idx++) { data[s][idx] = ((Number) model.getValueAt(idx, col)).doubleValue(); } s++; } cpt++; } return data; } // API expects null, not empty array return null; } public String[] getAxisLabels() { if (model.getRowCount() > 1) { int count = model.getRowCount() - 1; String[] labels = new String[count]; for (int idx = 0; idx < count; idx++) { labels[idx] = (String) model.getValueAt(idx, 0); } return labels; } // API expects null, not empty array return null; } private String[] getLegendLabels() { String[] legends = new String[nbColToGraph]; int i = 0; for (BarGraph bar : eltList) { if (bar.getChkBox().isSelected()) { legends[i] = bar.getLabel(); i++; } } return legends; } private Color[] getBackColors() { Color[] backColors = new Color[nbColToGraph]; int i = 0; for (BarGraph bar : eltList) { if (bar.getChkBox().isSelected()) { backColors[i] = bar.getBackColor(); i++; } } return backColors; } private int getNbColumns() { int i = 0; for (BarGraph bar : eltList) { if (bar.getChkBox().isSelected()) { i++; } } return i; } /** * We use this method to get the data, since we are using * ObjectTableModel, so the calling getDataVector doesn't * work as expected. * @param model {@link ObjectTableModel} * @param formats Array of {@link Format} array can contain null formatters in this case value is added as is * @return the data from the model */ public static List<List<Object>> getAllTableData(ObjectTableModel model, Format[] formats) { List<List<Object>> data = new ArrayList<>(); if (model.getRowCount() > 0) { for (int rw = 0; rw < model.getRowCount(); rw++) { int cols = model.getColumnCount(); List<Object> column = new ArrayList<>(); data.add(column); for (int idx = 0; idx < cols; idx++) { Object val = model.getValueAt(rw, idx); if (formats[idx] != null) { column.add(formats[idx].format(val)); } else { column.add(val); } } } } return data; } @Override public void actionPerformed(ActionEvent event) { boolean forceReloadData = false; final Object eventSource = event.getSource(); if (eventSource == displayButton) { actionMakeGraph(); } else if (eventSource == saveGraph) { saveGraphToFile = true; try { ActionRouter.getInstance().getAction(ActionNames.SAVE_GRAPHICS, SaveGraphics.class.getName()) .doAction(new ActionEvent(this, event.getID(), ActionNames.SAVE_GRAPHICS)); } catch (Exception e) { log.error(e.getMessage()); } } else if (eventSource == saveTable) { JFileChooser chooser = FileDialoger.promptToSaveFile("statistics.csv"); //$NON-NLS-1$ if (chooser == null) { return; } FileWriter writer = null; try { writer = new FileWriter(chooser.getSelectedFile()); // TODO Charset ? CSVSaveService.saveCSVStats(getAllTableData(model, FORMATS), writer, saveHeaders.isSelected() ? getLabels(COLUMNS) : null); } catch (IOException e) { JMeterUtils.reportErrorToUser(e.getMessage(), "Error saving data"); } finally { JOrphanUtils.closeQuietly(writer); } } else if (eventSource == chooseForeColor) { Color color = JColorChooser.showDialog(null, JMeterUtils.getResString("aggregate_graph_choose_color"), //$NON-NLS-1$ colorBarGraph); if (color != null) { colorForeGraph = color; } } else if (eventSource == syncWithName) { graphTitle.setText(namePanel.getName()); } else if (eventSource == dynamicGraphSize) { // if use dynamic graph size is checked, we disable the dimension fields if (dynamicGraphSize.isSelected()) { graphWidth.setEnabled(false); graphHeight.setEnabled(false); } else { graphWidth.setEnabled(true); graphHeight.setEnabled(true); } } else if (eventSource == columnSelection) { if (columnSelection.isSelected()) { columnMatchLabel.setEnabled(true); applyFilterBtn.setEnabled(true); caseChkBox.setEnabled(true); regexpChkBox.setEnabled(true); } else { columnMatchLabel.setEnabled(false); applyFilterBtn.setEnabled(false); caseChkBox.setEnabled(false); regexpChkBox.setEnabled(false); // Force reload data forceReloadData = true; } } // Not 'else if' because forceReloadData if (eventSource == applyFilterBtn || forceReloadData) { if (columnSelection.isSelected() && columnMatchLabel.getText() != null && columnMatchLabel.getText().length() > 0) { pattern = createPattern(columnMatchLabel.getText()); } else if (forceReloadData) { pattern = null; matcher = null; } if (getFile() != null && getFile().length() > 0) { clearData(); FilePanel filePanel = (FilePanel) getFilePanel(); filePanel.actionPerformed(event); } } else if (eventSource instanceof JButton) { // Changing color for column JButton btn = ((JButton) eventSource); if (btn.getName() != null) { try { BarGraph bar = eltList.get(Integer.parseInt(btn.getName())); Color color = JColorChooser.showDialog(null, bar.getLabel(), bar.getBackColor()); if (color != null) { bar.setBackColor(color); btn.setBackground(bar.getBackColor()); } } catch (NumberFormatException nfe) { } // nothing to do } } } /** * * @param keys I18N keys * @return labels */ static String[] getLabels(String[] keys) { String[] labels = new String[keys.length]; for (int i = 0; i < labels.length; i++) { labels[i] = MessageFormat.format(JMeterUtils.getResString(keys[i]), COLUMNS_MSG_PARAMETERS[i]); } return labels; } private void actionMakeGraph() { if (model.getRowCount() > 1) { makeGraph(); tabbedGraph.setSelectedIndex(1); } else { JOptionPane.showMessageDialog(null, JMeterUtils.getResString("aggregate_graph_no_values_to_graph"), // $NON-NLS-1$ JMeterUtils.getResString("aggregate_graph_no_values_to_graph"), // $NON-NLS-1$ JOptionPane.WARNING_MESSAGE); } } @Override public JComponent getPrintableComponent() { if (saveGraphToFile) { saveGraphToFile = false; // (re)draw the graph first to take settings into account (Bug 58329) if (model.getRowCount() > 1) { makeGraph(); } graphPanel.setBounds(graphPanel.getLocation().x, graphPanel.getLocation().y, graphPanel.width, graphPanel.height); return graphPanel; } return this; } private JPanel createGraphActionsPane() { JPanel buttonPanel = new JPanel(new BorderLayout()); JPanel displayPane = new JPanel(); displayPane.add(displayButton); displayButton.addActionListener(this); buttonPanel.add(displayPane, BorderLayout.WEST); JPanel savePane = new JPanel(); savePane.add(saveGraph); savePane.add(saveTable); savePane.add(saveHeaders); saveGraph.addActionListener(this); saveTable.addActionListener(this); syncWithName.addActionListener(this); buttonPanel.add(savePane, BorderLayout.EAST); return buttonPanel; } private JPanel createGraphColumnPane() { JPanel colPanel = new JPanel(); colPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); JLabel label = new JLabel(JMeterUtils.getResString("aggregate_graph_columns_to_display")); //$NON-NLS-1$ colPanel.add(label); for (BarGraph bar : eltList) { colPanel.add(bar.getChkBox()); colPanel.add(createColorBarButton(bar, eltList.indexOf(bar))); } colPanel.add(Box.createRigidArea(new Dimension(5, 0))); chooseForeColor.setFont(FONT_SMALL); colPanel.add(chooseForeColor); chooseForeColor.addActionListener(this); JPanel optionsPanel = new JPanel(); optionsPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); optionsPanel.add(createGraphFontValuePane()); optionsPanel.add(drawOutlinesBar); optionsPanel.add(numberShowGrouping); optionsPanel.add(valueLabelsVertical); JPanel barPane = new JPanel(new BorderLayout()); barPane.add(colPanel, BorderLayout.NORTH); barPane.add(Box.createRigidArea(new Dimension(0, 3)), BorderLayout.CENTER); barPane.add(optionsPanel, BorderLayout.SOUTH); JPanel columnPane = new JPanel(new BorderLayout()); columnPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), JMeterUtils.getResString("aggregate_graph_column_settings"))); // $NON-NLS-1$ columnPane.add(barPane, BorderLayout.NORTH); columnPane.add(Box.createRigidArea(new Dimension(0, 3)), BorderLayout.CENTER); columnPane.add(createGraphSelectionSubPane(), BorderLayout.SOUTH); return columnPane; } private JButton createColorBarButton(BarGraph barGraph, int index) { // Button JButton colorBtn = new JButton(); colorBtn.setName(String.valueOf(index)); colorBtn.setFont(FONT_SMALL); colorBtn.addActionListener(this); colorBtn.setBackground(barGraph.getBackColor()); return colorBtn; } private JPanel createGraphSelectionSubPane() { // Search field JPanel searchPanel = new JPanel(); searchPanel.setLayout(new BoxLayout(searchPanel, BoxLayout.X_AXIS)); searchPanel.setBorder(BorderFactory.createEmptyBorder(3, 0, 3, 0)); searchPanel.add(columnSelection); columnMatchLabel.setEnabled(false); applyFilterBtn.setEnabled(false); caseChkBox.setEnabled(false); regexpChkBox.setEnabled(false); columnSelection.addActionListener(this); searchPanel.add(columnMatchLabel); searchPanel.add(Box.createRigidArea(new Dimension(5, 0))); // Button applyFilterBtn.setFont(FONT_SMALL); applyFilterBtn.addActionListener(this); searchPanel.add(applyFilterBtn); // checkboxes caseChkBox.setFont(FONT_SMALL); searchPanel.add(caseChkBox); regexpChkBox.setFont(FONT_SMALL); searchPanel.add(regexpChkBox); return searchPanel; } private JPanel createGraphTitlePane() { JPanel titleNamePane = new JPanel(new BorderLayout()); syncWithName.setFont(new Font("SansSerif", Font.PLAIN, 10)); titleNamePane.add(graphTitle, BorderLayout.CENTER); titleNamePane.add(syncWithName, BorderLayout.EAST); JPanel titleStylePane = new JPanel(); titleStylePane.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 5)); titleStylePane.add(GuiUtils.createLabelCombo(JMeterUtils.getResString("aggregate_graph_font"), //$NON-NLS-1$ titleFontNameList)); titleFontNameList.setSelectedIndex(0); // default: sans serif titleStylePane.add(GuiUtils.createLabelCombo(JMeterUtils.getResString("aggregate_graph_size"), //$NON-NLS-1$ titleFontSizeList)); titleFontSizeList.setSelectedItem(StatGraphProperties.fontSize[6]); // default: 16 titleStylePane.add(GuiUtils.createLabelCombo(JMeterUtils.getResString("aggregate_graph_style"), //$NON-NLS-1$ titleFontStyleList)); titleFontStyleList.setSelectedItem(JMeterUtils.getResString("fontstyle.bold")); // $NON-NLS-1$ // default: bold JPanel titlePane = new JPanel(new BorderLayout()); titlePane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), JMeterUtils.getResString("aggregate_graph_title_group"))); // $NON-NLS-1$ titlePane.add(titleNamePane, BorderLayout.NORTH); titlePane.add(titleStylePane, BorderLayout.SOUTH); return titlePane; } private JPanel createGraphFontValuePane() { JPanel fontValueStylePane = new JPanel(); fontValueStylePane.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); fontValueStylePane.add(GuiUtils.createLabelCombo(JMeterUtils.getResString("aggregate_graph_value_font"), //$NON-NLS-1$ valueFontNameList)); valueFontNameList.setSelectedIndex(0); // default: sans serif fontValueStylePane.add(GuiUtils.createLabelCombo(JMeterUtils.getResString("aggregate_graph_size"), //$NON-NLS-1$ valueFontSizeList)); valueFontSizeList.setSelectedItem(StatGraphProperties.fontSize[2]); // default: 10 fontValueStylePane.add(GuiUtils.createLabelCombo(JMeterUtils.getResString("aggregate_graph_style"), //$NON-NLS-1$ valueFontStyleList)); valueFontStyleList.setSelectedItem(JMeterUtils.getResString("fontstyle.normal")); // default: normal //$NON-NLS-1$ return fontValueStylePane; } private JPanel createGraphDimensionPane() { JPanel dimensionPane = new JPanel(); dimensionPane.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); dimensionPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), JMeterUtils.getResString("aggregate_graph_dimension"))); // $NON-NLS-1$ dimensionPane.add(dynamicGraphSize); dynamicGraphSize.setSelected(true); // default option graphWidth.setEnabled(false); graphHeight.setEnabled(false); dynamicGraphSize.addActionListener(this); dimensionPane.add(Box.createRigidArea(new Dimension(10, 0))); dimensionPane.add(graphWidth); dimensionPane.add(Box.createRigidArea(new Dimension(5, 0))); dimensionPane.add(graphHeight); return dimensionPane; } /** * Create pane for X Axis options * @return X Axis pane */ private JPanel createGraphXAxisPane() { JPanel xAxisPane = new JPanel(); xAxisPane.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); xAxisPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), JMeterUtils.getResString("aggregate_graph_xaxis_group"))); // $NON-NLS-1$ xAxisPane.add(maxLengthXAxisLabel); return xAxisPane; } /** * Create pane for Y Axis options * @return Y Axis pane */ private JPanel createGraphYAxisPane() { JPanel yAxisPane = new JPanel(); yAxisPane.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); yAxisPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), JMeterUtils.getResString("aggregate_graph_yaxis_group"))); // $NON-NLS-1$ yAxisPane.add(maxValueYAxisLabel); return yAxisPane; } /** * Create pane for legend settings * @return Legend pane */ private JPanel createLegendPane() { JPanel legendPanel = new JPanel(); legendPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); legendPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), JMeterUtils.getResString("aggregate_graph_legend"))); // $NON-NLS-1$ legendPanel.add(GuiUtils.createLabelCombo(JMeterUtils.getResString("aggregate_graph_legend_placement"), //$NON-NLS-1$ legendPlacementList)); legendPlacementList.setSelectedItem(JMeterUtils.getResString("aggregate_graph_legend.placement.bottom")); // $NON-NLS-1$ // default: bottom legendPanel.add(GuiUtils.createLabelCombo(JMeterUtils.getResString("aggregate_graph_font"), //$NON-NLS-1$ fontNameList)); fontNameList.setSelectedIndex(0); // default: sans serif legendPanel.add(GuiUtils.createLabelCombo(JMeterUtils.getResString("aggregate_graph_size"), //$NON-NLS-1$ fontSizeList)); fontSizeList.setSelectedItem(StatGraphProperties.fontSize[2]); // default: 10 legendPanel.add(GuiUtils.createLabelCombo(JMeterUtils.getResString("aggregate_graph_style"), //$NON-NLS-1$ fontStyleList)); fontStyleList.setSelectedItem(JMeterUtils.getResString("fontstyle.normal")); // $NON-NLS-1$ // default: normal return legendPanel; } /** * @param textToFind * @return pattern ready to search */ private Pattern createPattern(String textToFind) { String textToFindQ = Pattern.quote(textToFind); if (regexpChkBox.isSelected()) { textToFindQ = textToFind; } Pattern pattern = null; try { if (caseChkBox.isSelected()) { pattern = Pattern.compile(textToFindQ); } else { pattern = Pattern.compile(textToFindQ, Pattern.CASE_INSENSITIVE); } } catch (PatternSyntaxException pse) { return null; } return pattern; } }