You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by mi...@apache.org on 2012/08/14 17:30:33 UTC

svn commit: r1372926 - in /jmeter/trunk: bin/ src/components/org/apache/jmeter/visualizers/ src/components/org/apache/jmeter/visualizers/utils/ src/core/org/apache/jmeter/resources/ xdocs/ xdocs/usermanual/

Author: milamber
Date: Tue Aug 14 15:30:32 2012
New Revision: 1372926

URL: http://svn.apache.org/viewvc?rev=1372926&view=rev
Log:
Add a new visualizer to draw a line graph showing the evolution of response time for a test
Bugzilla Id: 53718

Added:
    jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphChart.java   (with props)
    jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphLineBean.java   (with props)
    jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphVisualizer.java   (with props)
    jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/
    jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/Colors.java   (with props)
    jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/colors.properties   (with props)
Modified:
    jmeter/trunk/bin/saveservice.properties
    jmeter/trunk/src/components/org/apache/jmeter/visualizers/StatGraphProperties.java
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
    jmeter/trunk/xdocs/changes.xml
    jmeter/trunk/xdocs/usermanual/component_reference.xml

Modified: jmeter/trunk/bin/saveservice.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/bin/saveservice.properties?rev=1372926&r1=1372925&r2=1372926&view=diff
==============================================================================
--- jmeter/trunk/bin/saveservice.properties (original)
+++ jmeter/trunk/bin/saveservice.properties Tue Aug 14 15:30:32 2012
@@ -186,6 +186,7 @@ LDAPExtSampler=org.apache.jmeter.protoco
 LdapExtTestSamplerGui=org.apache.jmeter.protocol.ldap.control.gui.LdapExtTestSamplerGui
 LDAPSampler=org.apache.jmeter.protocol.ldap.sampler.LDAPSampler
 LdapTestSamplerGui=org.apache.jmeter.protocol.ldap.control.gui.LdapTestSamplerGui
+LGraphVisualizer=org.apache.jmeter.visualizers.LGraphVisualizer
 LineChart=org.apache.jmeter.testelement.LineChart
 LineGraphGui=org.apache.jmeter.report.gui.LineGraphGui
 LogicControllerGui=org.apache.jmeter.control.gui.LogicControllerGui

Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphChart.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphChart.java?rev=1372926&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphChart.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphChart.java Tue Aug 14 15:30:32 2012
@@ -0,0 +1,365 @@
+/* 
+ * 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.BasicStroke;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.LayoutManager;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.math.BigDecimal;
+
+import javax.swing.JPanel;
+
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.log.Logger;
+import org.jCharts.axisChart.AxisChart;
+import org.jCharts.chartData.AxisChartDataSet;
+import org.jCharts.chartData.ChartDataException;
+import org.jCharts.chartData.DataSeries;
+import org.jCharts.properties.AxisProperties;
+import org.jCharts.properties.ChartProperties;
+import org.jCharts.properties.DataAxisProperties;
+import org.jCharts.properties.LabelAxisProperties;
+import org.jCharts.properties.LegendAreaProperties;
+import org.jCharts.properties.LegendProperties;
+import org.jCharts.properties.LineChartProperties;
+import org.jCharts.properties.PointChartProperties;
+import org.jCharts.properties.PropertyException;
+import org.jCharts.properties.util.ChartFont;
+import org.jCharts.types.ChartType;
+
+public class LGraphChart extends JPanel {
+
+    private static final long serialVersionUID = 280L;
+
+    private static final Logger log = LoggingManager.getLoggerForClass();
+
+    protected double[][] data = null;
+    protected String title, xAxisTitle, yAxisTitle, yAxisLabel;
+    protected String[] xAxisLabels;
+    protected int width, height;
+
+    protected String[] legendLabels = { JMeterUtils.getResString("aggregate_graph_legend") };
+
+    protected int maxYAxisScale;
+
+    protected Font titleFont;
+
+    protected Font legendFont;
+
+    protected Color[] color;
+
+    protected boolean showGrouping = true;
+
+    protected int legendPlacement = LegendProperties.BOTTOM;
+
+    protected Shape pointShape = PointChartProperties.SHAPE_CIRCLE;
+
+    protected float strokeWidth = 3.5f;
+
+    /**
+    *
+    */
+   public LGraphChart() {
+       super();
+   }
+
+   /**
+    * @param layout
+    */
+   public LGraphChart(LayoutManager layout) {
+       super(layout);
+   }
+
+   /**
+    * @param layout
+    * @param isDoubleBuffered
+    */
+   public LGraphChart(LayoutManager layout, boolean isDoubleBuffered) {
+       super(layout, isDoubleBuffered);
+   }
+
+    public void setData(double[][] data) {
+        this.data = data;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public void setXAxisTitle(String title) {
+        this.xAxisTitle = title;
+    }
+
+    public void setYAxisTitle(String title) {
+        this.yAxisTitle = title;
+    }
+
+    public void setXAxisLabels(String[] labels) {
+        this.xAxisLabels = labels;
+    }
+
+    public void setYAxisLabels(String label) {
+        this.yAxisLabel = label;
+    }
+
+    public void setLegendLabels(String[] labels) {
+        this.legendLabels = labels;
+    }
+
+    public void setWidth(int w) {
+        this.width = w;
+    }
+
+    public void setHeight(int h) {
+        this.height = h;
+    }
+
+    /**
+     * @return the maxYAxisScale
+     */
+    public int getMaxYAxisScale() {
+        return maxYAxisScale;
+    }
+
+    /**
+     * @param maxYAxisScale the maxYAxisScale to set
+     */
+    public void setMaxYAxisScale(int maxYAxisScale) {
+        this.maxYAxisScale = maxYAxisScale;
+    }
+
+    /**
+     * @return the color
+     */
+    public Color[] getColor() {
+        return color;
+    }
+
+    /**
+     * @param color the color to set
+     */
+    public void setColor(Color[] color) {
+        this.color = color;
+    }
+
+    /**
+     * @return the titleFont
+     */
+    public Font getTitleFont() {
+        return titleFont;
+    }
+
+    /**
+     * @param titleFont the titleFont to set
+     */
+    public void setTitleFont(Font titleFont) {
+        this.titleFont = titleFont;
+    }
+
+    /**
+     * @return the legendFont
+     */
+    public Font getLegendFont() {
+        return legendFont;
+    }
+
+    /**
+     * @param legendFont the legendFont to set
+     */
+    public void setLegendFont(Font legendFont) {
+        this.legendFont = legendFont;
+    }
+
+    /**
+     * @return the legendPlacement
+     */
+    public int getLegendPlacement() {
+        return legendPlacement;
+    }
+
+    /**
+     * @param legendPlacement the legendPlacement to set
+     */
+    public void setLegendPlacement(int legendPlacement) {
+        this.legendPlacement = legendPlacement;
+    }
+
+    /**
+     * @return the pointShape
+     */
+    public Shape getPointShape() {
+        return pointShape;
+    }
+
+    /**
+     * @param pointShape the pointShape to set
+     */
+    public void setPointShape(Shape pointShape) {
+        this.pointShape = pointShape;
+    }
+
+    /**
+     * @return the strokeWidth
+     */
+    public float getStrokeWidth() {
+        return strokeWidth;
+    }
+
+    /**
+     * @param strokeWidth the strokeWidth to set
+     */
+    public void setStrokeWidth(float strokeWidth) {
+        this.strokeWidth = strokeWidth;
+    }
+
+    /**
+     * @return the showGrouping
+     */
+    public boolean isShowGrouping() {
+        return showGrouping;
+    }
+
+    /**
+     * @param showGrouping the showGrouping to set
+     */
+    public void setShowGrouping(boolean showGrouping) {
+        this.showGrouping = showGrouping;
+    }
+
+    private void drawSample(String _title, String[] _xAxisLabels, String _xAxisTitle2,
+            String _yAxisTitle, String[] _legendLabels, double[][] _data, int _width, int _height, Color[] _color, Font font, Graphics g) {
+        
+        double max = maxYAxisScale > 0 ? maxYAxisScale : findMax(_data); // define max scale y axis
+        try {
+            // if the title graph is empty, we can assume some default
+            if (_title.length() == 0 ) {
+                _title = JMeterUtils.getResString("graph_line_title"); //$NON-NLS-1$
+            }
+            this.setPreferredSize(new Dimension(_width,_height));
+            DataSeries dataSeries = new DataSeries( _xAxisLabels, null, _yAxisTitle, _title ); // replace _xAxisTitle to null (don't display x axis title)
+
+            // Stroke and shape line settings
+            Stroke[] strokes = new Stroke[_legendLabels.length];
+            for (int i = 0; i < _legendLabels.length; i++) {
+                strokes[i] = new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 5f);
+            }
+            Shape[] shapes = new Shape[_legendLabels.length];
+            for (int i = 0; i < _legendLabels.length; i++) {
+                shapes[i] = pointShape;
+            }
+            LineChartProperties lineChartProperties= new LineChartProperties(strokes, shapes);
+
+            // Lines colors
+            Paint[] paints = new Paint[_color.length];
+            for (int i = 0; i < _color.length; i++) {
+                paints[i] =  _color[i] ;
+            }
+            
+            // Define chart type (line)
+            AxisChartDataSet axisChartDataSet =
+                new AxisChartDataSet( _data, _legendLabels, paints, ChartType.LINE, lineChartProperties );
+            dataSeries.addIAxisPlotDataSet(axisChartDataSet);
+
+            ChartProperties chartProperties= new ChartProperties();
+            LabelAxisProperties xaxis = new LabelAxisProperties();
+            DataAxisProperties yaxis = new DataAxisProperties();
+            yaxis.setUseCommas(showGrouping);
+
+            if (legendFont != null) {
+                yaxis.setAxisTitleChartFont(new ChartFont(legendFont, new Color(20)));
+                yaxis.setScaleChartFont(new ChartFont(legendFont, new Color(20)));
+                xaxis.setAxisTitleChartFont(new ChartFont(legendFont, new Color(20)));
+                xaxis.setScaleChartFont(new ChartFont(legendFont, new Color(20)));
+            }
+            if (titleFont != null) {
+                chartProperties.setTitleFont(new ChartFont(titleFont, new Color(0)));
+            }
+
+            // Y Axis ruler
+            try {
+                BigDecimal round = new BigDecimal(max / 1000d);
+                round = round.setScale(0, BigDecimal.ROUND_UP);
+                double topValue = round.doubleValue() * 1000;
+                yaxis.setUserDefinedScale(0, 500);
+                yaxis.setNumItems((int) (topValue / 500)+1);
+                yaxis.setShowGridLines(1);
+            } catch (PropertyException e) {
+                log.warn("",e);
+            }
+
+            AxisProperties axisProperties= new AxisProperties(xaxis, yaxis);
+            axisProperties.setXAxisLabelsAreVertical(true);
+            LegendProperties legendProperties= new LegendProperties();
+            legendProperties.setBorderStroke(null);
+            legendProperties.setPlacement(legendPlacement);
+            legendProperties.setIconBorderPaint(Color.WHITE);
+            legendProperties.setIconBorderStroke(new BasicStroke(0f, BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE));
+            // Manage legend placement
+            legendProperties.setNumColumns(LegendProperties.COLUMNS_FIT_TO_IMAGE);
+            if (legendPlacement == LegendAreaProperties.RIGHT || legendPlacement == LegendAreaProperties.LEFT) {
+                legendProperties.setNumColumns(1);
+            }
+            if (legendFont != null) {
+                legendProperties.setFont(legendFont);
+            }
+            AxisChart axisChart = new AxisChart(
+                    dataSeries, chartProperties, axisProperties,
+                    legendProperties, _width, _height );
+            axisChart.setGraphics2D((Graphics2D) g);
+            axisChart.render();
+        } catch (ChartDataException e) {
+            log.warn("", e);
+        } catch (PropertyException e) {
+            log.warn("", e);
+        }
+    }
+
+    @Override
+    public void paintComponent(Graphics graphics) {
+        if (data != null && this.title != null && this.xAxisLabels != null &&
+                this.yAxisLabel != null && this.yAxisTitle != null) {
+            drawSample(this.title, this.xAxisLabels,
+                    this.xAxisTitle, this.yAxisTitle, this.legendLabels,
+                    this.data, this.width, this.height, this.color,
+                    this.legendFont, graphics);
+        }
+    }
+
+    private double findMax(double _data[][]) {
+        double max = 0;
+        max = _data[0][0];
+        for (int i = 0; i < _data.length; i++) {
+            for (int j = 0; j < _data[i].length; j++) {
+                 if (Double.isNaN(max) || ((_data[i][j] != Double.NaN) && (_data[i][j] > max))) {
+                    max = _data[i][j];
+                }
+            }
+        }
+        return max;
+    }
+}

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphChart.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphChart.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphLineBean.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphLineBean.java?rev=1372926&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphLineBean.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphLineBean.java Tue Aug 14 15:30:32 2012
@@ -0,0 +1,67 @@
+/* 
+ * 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.Color;
+
+public class LGraphLineBean {
+
+    private String label;
+
+    private Color lineColor;
+
+    /**
+     * @param label
+     * @param lineColor
+     */
+    public LGraphLineBean(String label, Color lineColor) {
+        super();
+        this.label = label;
+        this.lineColor = lineColor;
+    }
+
+    /**
+     * @return the label
+     */
+    public String getLabel() {
+        return label;
+    }
+
+    /**
+     * @param label the label to set
+     */
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    /**
+     * @return the lineColor
+     */
+    public Color getLineColor() {
+        return lineColor;
+    }
+
+    /**
+     * @param lineColor the lineColor to set
+     */
+    public void setLineColor(Color lineColor) {
+        this.lineColor = lineColor;
+    }
+}

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphLineBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphLineBean.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphVisualizer.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphVisualizer.java?rev=1372926&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphVisualizer.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphVisualizer.java Tue Aug 14 15:30:32 2012
@@ -0,0 +1,715 @@
+/*
+ * 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.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Set;
+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.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextField;
+import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
+
+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.FilePanel;
+import org.apache.jmeter.gui.util.VerticalPanel;
+import org.apache.jmeter.samplers.Clearable;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jmeter.visualizers.gui.AbstractVisualizer;
+import org.apache.jmeter.visualizers.utils.Colors;
+import org.apache.jorphan.gui.JLabeledTextField;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.log.Logger;
+
+public class LGraphVisualizer extends AbstractVisualizer implements ActionListener, Clearable {
+
+    private static final long serialVersionUID = 280L;
+
+    private static final Logger log = LoggingManager.getLoggerForClass();
+
+    private final Font FONT_SMALL = new Font("SansSerif", Font.PLAIN, 10);
+
+    private final Border MARGIN = new EmptyBorder(0, 5, 0, 5);
+
+    private final String yAxisLabel = JMeterUtils.getResString("aggregate_graph_response_time");//$NON-NLS-1$
+
+    private final String yAxisTitle = JMeterUtils.getResString("aggregate_graph_ms"); //$NON-NLS-1$
+
+    private LGraphChart graphPanel = null;
+
+    private JPanel settingsPane = null;
+
+    private final JTabbedPane tabbedGraph = new JTabbedPane(JTabbedPane.TOP);
+    
+    private boolean saveGraphToFile = false;
+
+    private final int defaultWidth = 400;
+
+    private final int defaultHeight = 300;
+    
+    private final static int INTERVAL_DEFAULT = 10000; // in milli-seconds // TODO: properties?
+    
+    private int intervalValue = INTERVAL_DEFAULT;
+    
+    private final JLabeledTextField intervalField =
+            new JLabeledTextField(JMeterUtils.getResString("graph_line_interval_label"), 7); //$NON-NLS-1$
+
+    private final JButton intervalButton = new JButton(JMeterUtils.getResString("graph_line_interval_reload")); // $NON-NLS-1$
+
+    private final 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 final JCheckBox samplerSelection = new JCheckBox(JMeterUtils.getResString("graph_line_series_selection"), false); //$NON-NLS-1$
+
+    private final JTextField samplerMatchLabel = new JTextField();
+
+    private final JButton reloadButton = new JButton(JMeterUtils.getResString("aggregate_graph_reload_data")); // $NON-NLS-1$
+
+    private final JCheckBox caseChkBox = new JCheckBox(JMeterUtils.getResString("search_text_chkbox_case"), false); // $NON-NLS-1$
+
+    private final JCheckBox regexpChkBox = new JCheckBox(JMeterUtils.getResString("search_text_chkbox_regexp"), true); // $NON-NLS-1$
+
+    private final JComboBox titleFontNameList = new JComboBox(StatGraphProperties.getFontNameMap().keySet().toArray());
+
+    private final JComboBox titleFontSizeList = new JComboBox(StatGraphProperties.fontSize);
+
+    private final JComboBox titleFontStyleList = new JComboBox(StatGraphProperties.getFontStyleMap().keySet().toArray());
+
+    private final JComboBox fontNameList = new JComboBox(StatGraphProperties.getFontNameMap().keySet().toArray());
+
+    private final JComboBox fontSizeList = new JComboBox(StatGraphProperties.fontSize);
+
+    private final JComboBox fontStyleList = new JComboBox(StatGraphProperties.getFontStyleMap().keySet().toArray());
+
+    private final JComboBox legendPlacementList = new JComboBox(StatGraphProperties.getPlacementNameMap().keySet().toArray());
+    
+    private final JComboBox pointShapeLine = new JComboBox(StatGraphProperties.getPointShapeMap().keySet().toArray());
+
+    private final JComboBox strokeWidthList = new JComboBox(StatGraphProperties.strokeWidth);
+
+    private final JCheckBox numberShowGrouping = new JCheckBox(JMeterUtils.getResString("aggregate_graph_number_grouping"), true); // Default checked // $NON-NLS-1$
+
+    private final JButton syncWithName =
+            new JButton(JMeterUtils.getResString("aggregate_graph_sync_with_name"));  //$NON-NLS-1$
+
+    private final JLabeledTextField graphTitle =
+            new JLabeledTextField(JMeterUtils.getResString("graph_line_title_label")); //$NON-NLS-1$
+
+    private final JLabeledTextField xAxisTimeFormat =
+            new JLabeledTextField(JMeterUtils.getResString("graph_line_xaxis_time_format"), 10); //$NON-NLS-1$ $NON-NLS-2$
+
+    private final JLabeledTextField maxValueYAxisLabel =
+            new JLabeledTextField(JMeterUtils.getResString("aggregate_graph_yaxis_max_value"), 8); //$NON-NLS-1$
+
+    /**
+     * checkbox for use dynamic graph size
+     */
+    private final JCheckBox dynamicGraphSize = new JCheckBox(JMeterUtils.getResString("aggregate_graph_dynamic_size")); // $NON-NLS-1$
+
+    private final JLabeledTextField graphWidth =
+            new JLabeledTextField(JMeterUtils.getResString("aggregate_graph_width"), 6); //$NON-NLS-1$
+    private final JLabeledTextField graphHeight =
+            new JLabeledTextField(JMeterUtils.getResString("aggregate_graph_height"), 6); //$NON-NLS-1$
+
+    private int minStartTime = Integer.MAX_VALUE;
+
+    private int maxStartTime = Integer.MIN_VALUE;
+
+    private final HashMap<String, LGraphLineBean> seriesNames = new HashMap<String, LGraphLineBean>();
+
+    private final LinkedHashMap<String, LinkedHashMap<Integer, Long>> pList = new LinkedHashMap<String, LinkedHashMap<Integer, Long>>();
+
+    private int durationTest = 0;
+    
+    private int colorIdx = 0;
+
+    private final List<Color> listColors = Colors.getColors();
+
+    public LGraphVisualizer() {
+        init();
+    }
+
+    public synchronized void add(final SampleResult sampleResult) {
+        final String sampleLabel = sampleResult.getSampleLabel();
+        Matcher matcher = null;
+        // Sampler selection
+        if (samplerSelection.isSelected() && samplerMatchLabel.getText() != null
+                && samplerMatchLabel.getText().length() > 0) {
+            Pattern pattern = createPattern(samplerMatchLabel.getText());
+            matcher = pattern.matcher(sampleLabel);
+        }
+        if ((matcher == null) || (matcher.find())) {
+            final long startTimeMS = sampleResult.getStartTime();
+            final int startTimeInterval = (int) startTimeMS / intervalValue;
+            JMeterUtils.runSafe(new Runnable() {
+                public void run() {
+                    // Use for x-axis scale
+                    if (startTimeInterval < minStartTime) {
+                        minStartTime = startTimeInterval;
+                    } else if (startTimeInterval > maxStartTime) {
+                        maxStartTime = startTimeInterval;
+                    }
+                    // Generate x-axis label and associated color
+                    if (!seriesNames.containsKey(sampleLabel)) {
+                        seriesNames.put(sampleLabel, 
+                                new LGraphLineBean(sampleLabel, listColors.get(colorIdx++)));
+                        // reset colors index
+                        if (colorIdx >= listColors.size()) {
+                            colorIdx = 0;
+                        }
+                    }
+                    // List of value by sampler
+                    if (pList.containsKey(sampleLabel)) {
+                        LinkedHashMap<Integer, Long> subList = pList.get(sampleLabel);
+                        long respTime = sampleResult.getTime();
+                        if (subList.containsKey(startTimeInterval)) {
+                            respTime = (subList.get(startTimeInterval) + respTime) / 2;
+                        }
+                        subList.put(startTimeInterval, respTime);
+                    } else {
+                        LinkedHashMap<Integer, Long> newSubList = new LinkedHashMap<Integer, Long>();
+                        newSubList.put(startTimeInterval, sampleResult.getTime());
+                        pList.put(sampleLabel, newSubList);
+                    }
+                }
+            });
+        }
+    }
+
+    public void makeGraph() {
+        // Calculate the test duration. Needs to xAxis Labels and getData.
+        durationTest = maxStartTime - minStartTime;
+        if (durationTest <= 0) {
+            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);
+            return;
+        }
+        Dimension size = graphPanel.getSize();
+        // 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);
+            }
+        }
+
+        String yAxisStr = maxValueYAxisLabel.getText();
+        int maxYAxisScale = yAxisStr.length() == 0 ? 0 : Integer.parseInt(yAxisStr);
+
+        graphPanel.setData(this.getData());
+        graphPanel.setTitle(graphTitle.getText());
+        graphPanel.setMaxYAxisScale(maxYAxisScale);
+
+        graphPanel.setYAxisLabels(this.yAxisLabel);
+        graphPanel.setYAxisTitle(this.yAxisTitle);
+        graphPanel.setXAxisLabels(getXAxisLabels());
+        graphPanel.setLegendLabels(getLegendLabels());
+        graphPanel.setColor(getLinesColors());
+        graphPanel.setShowGrouping(numberShowGrouping.isSelected());
+        graphPanel.setLegendPlacement(StatGraphProperties.getPlacementNameMap()
+                .get(legendPlacementList.getSelectedItem()).intValue());
+        graphPanel.setPointShape(StatGraphProperties.getPointShapeMap().get(pointShapeLine.getSelectedItem()));
+        graphPanel.setStrokeWidth(Float.parseFloat((String) strokeWidthList.getSelectedItem()));
+
+        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.setHeight(height);
+        graphPanel.setWidth(width);
+        // Draw the graph
+        graphPanel.repaint();
+    }
+
+    /**
+     * Generate the data for the jChart API
+     * @return array of array of data to draw
+     */
+    public double[][] getData() {
+        int size = pList.size();
+        int max = durationTest;
+
+        double[][] data = new double[size][max];
+
+        double nanLast = 0;
+        double nanBegin = 0;
+        ArrayList<Double> nanList = new ArrayList<Double>();
+        Set<String> pointsKeys = pList.keySet();
+        int s = 0;
+        for (String pointKey : pointsKeys) {
+            LinkedHashMap<Integer, Long> subList = pList.get(pointKey);
+
+            int idx = 0;
+            while (idx < durationTest) {
+                int keyShift = minStartTime + idx;
+                if (subList.containsKey(keyShift)) {
+                    nanLast = subList.get(keyShift);
+
+                    data[s][idx] = nanLast;
+
+                    // Calculate intermediate values (if needed)
+                    int nlsize = nanList.size();
+                    if (nlsize > 0) {
+                        double valPrev = nanBegin;
+                        for (int cnt = 0; cnt < nlsize; cnt++) {
+                            int pos = idx - (nlsize - cnt);
+                            if (pos < 0) { pos = 0; }
+                            valPrev = (valPrev + ((nanLast - nanBegin) / (nlsize + 2)));
+                            data[s][pos] = valPrev;
+                        }
+                        nanList.clear();
+                    }
+                } else {
+                    nanList.add(Double.NaN);
+                    nanBegin = nanLast;
+                    data[s][idx] = Double.NaN;
+                }
+                // log.debug("data["+s+"]["+idx+"]: " + data[s][idx]);
+                idx++;
+            }
+            s++;
+        }
+        return data;
+    }
+
+    public String getLabelResource() {
+        return "graph_line_title"; // $NON-NLS-1$
+    }
+
+    public synchronized void clearData() {
+        seriesNames.clear();
+        pList.clear();
+        minStartTime = Integer.MAX_VALUE;
+        maxStartTime = Integer.MIN_VALUE;
+        durationTest = 0;
+        colorIdx = 0;
+    }
+
+    /**
+     * Initialize the GUI.
+     */
+    private void init() {
+        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());
+
+        settingsPane = new VerticalPanel();
+        settingsPane.setBorder(margin2);
+
+        graphPanel = new LGraphChart();
+        graphPanel.setPreferredSize(new Dimension(defaultWidth, defaultHeight));
+
+        settingsPane.add(createGraphActionsPane());
+        settingsPane.add(createGraphSettingsPane());
+        settingsPane.add(createGraphTitlePane());
+        settingsPane.add(createLinePane());
+        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$
+
+        this.add(mainPanel, BorderLayout.NORTH);
+        this.add(tabbedGraph, BorderLayout.CENTER);
+
+    }
+
+    @Override
+    public JComponent getPrintableComponent() {
+        if (saveGraphToFile == true) {
+            saveGraphToFile = false;
+            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);
+        saveGraph.addActionListener(this);
+        syncWithName.addActionListener(this);
+        buttonPanel.add(savePane, BorderLayout.EAST);
+
+        return buttonPanel;
+    }
+
+    public String[] getXAxisLabels() {
+        SimpleDateFormat formatter = new SimpleDateFormat(xAxisTimeFormat.getText()); //$NON-NLS-1$ 
+        String[] xAxisLabels = new String[durationTest];
+        for (int j = 0; j < durationTest; j++) {
+            xAxisLabels[j] = formatter.format(new Date((minStartTime + j) * intervalValue));
+        }
+        return xAxisLabels;
+    }
+
+    private String[] getLegendLabels() {
+        String[] legends = new String[seriesNames.size()];
+        int i = 0;
+        for (String key : seriesNames.keySet()) {
+            LGraphLineBean val = seriesNames.get(key);
+            legends[i] = val.getLabel();
+            i++;
+        }
+        return legends;
+    }
+
+    private Color[] getLinesColors() {
+        Color[] linesColors = new Color[seriesNames.size()];
+        int i = 0;
+        for (String key : seriesNames.keySet()) {
+            LGraphLineBean val = seriesNames.get(key);
+            linesColors[i] = val.getLineColor();
+            i++;
+        }
+        return linesColors;
+    }
+
+    public void actionPerformed(ActionEvent event) {
+        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,1,ActionNames.SAVE_GRAPHICS));
+            } catch (Exception e) {
+                log.error(e.getMessage());
+            }
+        } 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 == samplerSelection) {
+            if (samplerSelection.isSelected()) {
+                samplerMatchLabel.setEnabled(true);
+                reloadButton.setEnabled(true);
+                caseChkBox.setEnabled(true);
+                regexpChkBox.setEnabled(true);
+            } else {
+                samplerMatchLabel.setEnabled(false);
+                reloadButton.setEnabled(false);
+                caseChkBox.setEnabled(false);
+                regexpChkBox.setEnabled(false);
+            }
+        } else if (eventSource == reloadButton || eventSource == intervalButton) {
+            if (eventSource == intervalButton) {
+                intervalValue = Integer.parseInt(intervalField.getText());
+            }
+            if (getFile() != null && getFile().length() > 0) {
+                clearData();
+                FilePanel filePanel = (FilePanel) getFilePanel();
+                filePanel.actionPerformed(event);
+            }
+        } 
+
+    }
+    
+    private void actionMakeGraph() {
+        String msgErr = null;
+        // Calculate the test duration. Needs to xAxis Labels and getData.
+        durationTest = maxStartTime - minStartTime;
+        if (seriesNames.size() <= 0) {
+            msgErr = JMeterUtils.getResString("aggregate_graph_no_values_to_graph"); // $NON-NLS-1$
+        } else   if (durationTest <= 1) {
+            msgErr = JMeterUtils.getResString("graph_line_no_duration"); // $NON-NLS-1$
+        }
+        if (msgErr == null) {
+            makeGraph();
+            tabbedGraph.setSelectedIndex(1);
+        } else {
+            JOptionPane.showMessageDialog(null, msgErr, msgErr, JOptionPane.WARNING_MESSAGE);
+        }
+    }
+
+    private JComponent createLabelCombo(String label, JComboBox comboBox) {
+        JPanel labelCombo = new JPanel();
+        labelCombo.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
+        JLabel caption = new JLabel(label);
+        caption.setBorder(MARGIN);
+        labelCombo.add(caption);
+        labelCombo.add(comboBox);
+        return labelCombo;
+    }
+
+    private JPanel createGraphSettingsPane() {
+        JPanel settingsPane = new JPanel(new BorderLayout());
+        settingsPane.setBorder(BorderFactory.createTitledBorder(
+                BorderFactory.createEtchedBorder(),
+                JMeterUtils.getResString("graph_line_settings_pane"))); // $NON-NLS-1$
+        
+        JPanel intervalPane = new JPanel();
+        intervalPane.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
+        intervalField.setText(String.valueOf(INTERVAL_DEFAULT));
+        intervalPane.add(intervalField);
+        
+        // Button
+        intervalButton.setFont(FONT_SMALL);
+        intervalButton.addActionListener(this);
+        intervalPane.add(intervalButton);
+
+        settingsPane.add(intervalPane, BorderLayout.NORTH);
+        settingsPane.add(createGraphSelectionSubPane(), BorderLayout.SOUTH);
+
+        return settingsPane;
+    }
+
+    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(samplerSelection);
+        samplerMatchLabel.setEnabled(false);
+        reloadButton.setEnabled(false);
+        caseChkBox.setEnabled(false);
+        regexpChkBox.setEnabled(false);
+        samplerSelection.addActionListener(this);
+
+        searchPanel.add(samplerMatchLabel);
+        searchPanel.add(Box.createRigidArea(new Dimension(5,0)));
+
+        // Button
+        reloadButton.setFont(FONT_SMALL);
+        reloadButton.addActionListener(this);
+        searchPanel.add(reloadButton);
+
+        // 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(FONT_SMALL);
+        titleNamePane.add(graphTitle, BorderLayout.CENTER);
+        titleNamePane.add(syncWithName, BorderLayout.EAST);
+
+        JPanel titleStylePane = new JPanel();
+        titleStylePane.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 5));
+        titleStylePane.add(createLabelCombo(JMeterUtils.getResString("aggregate_graph_font"), //$NON-NLS-1$
+                titleFontNameList));
+        titleFontNameList.setSelectedIndex(0); // default: sans serif
+        titleStylePane.add(createLabelCombo(JMeterUtils.getResString("aggregate_graph_size"), //$NON-NLS-1$
+                titleFontSizeList));
+        titleFontSizeList.setSelectedItem(StatGraphProperties.fontSize[6]); // default: 16
+        titleStylePane.add(createLabelCombo(JMeterUtils.getResString("aggregate_graph_style"), //$NON-NLS-1$
+                titleFontStyleList));
+        titleFontStyleList.setSelectedItem(JMeterUtils.getResString("fontstyle.bold")); // 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 createLinePane() {       
+        JPanel lineStylePane = new JPanel();
+        lineStylePane.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
+        lineStylePane.setBorder(BorderFactory.createTitledBorder(
+                BorderFactory.createEtchedBorder(),
+                JMeterUtils.getResString("graph_line_settings_line"))); // $NON-NLS-1$
+        lineStylePane.add(createLabelCombo(JMeterUtils.getResString("graph_line_stroke_width"), //$NON-NLS-1$
+                strokeWidthList));
+        strokeWidthList.setSelectedItem(StatGraphProperties.strokeWidth[4]); // default: 3.0f
+        lineStylePane.add(createLabelCombo(JMeterUtils.getResString("graph_line_shape_label"), //$NON-NLS-1$
+                pointShapeLine));
+        pointShapeLine.setSelectedIndex(0); // default: circle
+        return lineStylePane;
+    }
+
+    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$
+        xAxisTimeFormat.setText("HH:mm:ss"); // $NON-NLS-1$
+        xAxisPane.add(xAxisTimeFormat);
+        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);
+
+        yAxisPane.add(numberShowGrouping);
+        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(createLabelCombo(JMeterUtils.getResString("aggregate_graph_legend_placement"), //$NON-NLS-1$
+                legendPlacementList));
+        legendPlacementList.setSelectedItem(JMeterUtils.getResString("aggregate_graph_legend.placement.bottom")); // default: bottom
+        legendPanel.add(createLabelCombo(JMeterUtils.getResString("aggregate_graph_font"), //$NON-NLS-1$
+                fontNameList));
+        fontNameList.setSelectedIndex(0); // default: sans serif
+        legendPanel.add(createLabelCombo(JMeterUtils.getResString("aggregate_graph_size"), //$NON-NLS-1$
+                fontSizeList));
+        fontSizeList.setSelectedItem(StatGraphProperties.fontSize[2]); // default: 10
+        legendPanel.add(createLabelCombo(JMeterUtils.getResString("aggregate_graph_style"), //$NON-NLS-1$
+                fontStyleList));
+        fontStyleList.setSelectedItem(JMeterUtils.getResString("fontstyle.normal")); // 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;
+    }
+}

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphVisualizer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/LGraphVisualizer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/src/components/org/apache/jmeter/visualizers/StatGraphProperties.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/visualizers/StatGraphProperties.java?rev=1372926&r1=1372925&r2=1372926&view=diff
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/visualizers/StatGraphProperties.java (original)
+++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/StatGraphProperties.java Tue Aug 14 15:30:32 2012
@@ -20,11 +20,14 @@
 package org.apache.jmeter.visualizers;
 
 import java.awt.Font;
+import java.awt.Shape;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import org.apache.jmeter.util.JMeterUtils;
 import org.jCharts.properties.LegendAreaProperties;
+import org.jCharts.properties.PointChartProperties;
 
 public class StatGraphProperties {
 
@@ -55,4 +58,17 @@ public class StatGraphProperties {
         placementNameMap.put(JMeterUtils.getResString("aggregate_graph_legend.placement.top"), LegendAreaProperties.TOP);
         return placementNameMap;
     }
+    
+    @SuppressWarnings("boxing")
+    public static Map<String, Shape> getPointShapeMap() {
+        Map<String, Shape> pointShapeMap = new LinkedHashMap<String, Shape>();
+        pointShapeMap.put(JMeterUtils.getResString("graph_pointshape_circle"), PointChartProperties.SHAPE_CIRCLE);
+        pointShapeMap.put(JMeterUtils.getResString("graph_pointshape_diamond"), PointChartProperties.SHAPE_DIAMOND);
+        pointShapeMap.put(JMeterUtils.getResString("graph_pointshape_square"), PointChartProperties.SHAPE_SQUARE);
+        pointShapeMap.put(JMeterUtils.getResString("graph_pointshape_triangle"), PointChartProperties.SHAPE_TRIANGLE);
+        pointShapeMap.put(JMeterUtils.getResString("graph_pointshape_none"), null);
+        return pointShapeMap;
+    }
+    
+    public static final String[] strokeWidth = { "1.0f", "1.5f", "2.0f", "2.5f", "3.0f", "3.5f", "4.0f", "4.5f", "5.0f", "5.5f", "6.0f", "6.5f"};
 }

Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/Colors.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/Colors.java?rev=1372926&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/Colors.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/Colors.java Tue Aug 14 15:30:32 2012
@@ -0,0 +1,96 @@
+/* 
+ * 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.utils;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import javax.swing.JOptionPane;
+
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.log.Logger;
+
+public class Colors {
+
+    private static final Logger log = LoggingManager.getLoggerForClass();
+
+    private static final String ENTRY_SEP = ",";  //$NON-NLS-1$
+
+    private static final String ORDER_PROP_NAME = "order"; //$NON-NLS-1$
+
+    protected static final String DEFAULT_COLORS_PROPERTY_FILE = "org/apache/jmeter/visualizers/utils/colors.properties"; //$NON-NLS-1$
+
+    protected static final String USER_DEFINED_COLORS_PROPERTY_FILE = "jmeter.colors"; //$NON-NLS-1$
+    
+    private static final String COLORS_ORDER = "jmeter.order";
+    
+    /**
+     * Parse icon set file.
+     * @return List of icons/action definition
+     */
+    public static List<Color> getColors() {
+        Properties defaultProps = JMeterUtils.loadProperties(DEFAULT_COLORS_PROPERTY_FILE);
+        if (defaultProps == null) {
+            JOptionPane.showMessageDialog(null, 
+                    JMeterUtils.getResString("toolbar_icon_set_not_found"), // $NON-NLS-1$
+                    JMeterUtils.getResString("toolbar_icon_set_not_found"), // $NON-NLS-1$
+                    JOptionPane.WARNING_MESSAGE);
+            return null;
+        }
+        Properties p;
+        String userProp = JMeterUtils.getProperty(USER_DEFINED_COLORS_PROPERTY_FILE); 
+        if (userProp != null){
+            p = JMeterUtils.loadProperties(userProp, defaultProps);
+        } else {
+            p=defaultProps;
+        }
+
+        String order = JMeterUtils.getPropDefault(COLORS_ORDER, p.getProperty(ORDER_PROP_NAME));
+
+        if (order == null) {
+            log.warn("Could not find order list");
+            JOptionPane.showMessageDialog(null, 
+                    JMeterUtils.getResString("toolbar_icon_set_not_found"), // $NON-NLS-1$
+                    JMeterUtils.getResString("toolbar_icon_set_not_found"), // $NON-NLS-1$
+                    JOptionPane.WARNING_MESSAGE);
+            return null;
+        }
+
+        String[] oList = order.split(ENTRY_SEP);
+
+        List<Color> listColors = new ArrayList<Color>();
+        for (String key : oList) {
+            String trimmed = key.trim();
+            String property = p.getProperty(trimmed);
+            try {
+                String[] lcol = property.split(ENTRY_SEP);
+                Color itb = new Color(Integer.parseInt(lcol[0]), Integer.parseInt(lcol[1]), Integer.parseInt(lcol[2]));
+                listColors.add(itb);
+            } catch (java.lang.Exception e) {
+                log.warn("Error in colors.properties, current property=" + property); // $NON-NLS-1$
+            }
+        }
+        return listColors;
+    }
+
+}

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/Colors.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/Colors.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/colors.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/colors.properties?rev=1372926&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/colors.properties (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/colors.properties Tue Aug 14 15:30:32 2012
@@ -0,0 +1,49 @@
+#   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.
+
+# Color order. Keys separate by comma.
+order=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
+
+# R,G,B code
+1=7,4,56
+2=220,20,60
+3=0,139,69
+4=255,193,37
+5=139,0,139
+6=91,91,91
+7=255,106,106
+8=205,91,69
+9=0,205,205
+10=176,23,31
+11=0,178,238
+12=139,139,0
+13=238,0,238
+14=3,168,158
+15=139,54,38
+16=143,188,143
+17=184,184,184
+18=113,198,113
+19=255,105,180
+20=135,206,255
+21=124,252,0
+22=79,148,205
+23=10,10,10
+24=139,131,120
+25=64,224,208
+26=198,113,113
+27=255,0,255
+28=205,104,137
+29=192,255,62
+30=197,193,170
\ No newline at end of file

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/colors.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/utils/colors.properties
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties?rev=1372926&r1=1372925&r2=1372926&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Tue Aug 14 15:30:32 2012
@@ -318,6 +318,22 @@ get_xml_from_file=File with SOAP XML Dat
 get_xml_from_random=Message(s) Folder
 graph_choose_graphs=Graphs to Display
 graph_full_results_title=Graph Full Results
+graph_line_interval_label=Interval (ms):
+graph_line_interval_reload=Apply interval
+graph_line_no_duration=Test with no duration. Unable to graph.
+graph_line_series_selection=Sampler label selection:
+graph_line_settings_line=Line settings
+graph_line_settings_pane=Graph settings
+graph_line_shape_label=Shape point:
+graph_line_stroke_width=Stroke width:
+graph_line_title=Line Graph
+graph_line_title_label=Graph title:
+graph_line_xaxis_time_format=Time format (SimpleDateFormat):
+graph_pointshape_circle=Circle
+graph_pointshape_diamond=Diamond
+graph_pointshape_square=Square
+graph_pointshape_triangle=Triangle
+graph_pointshape_none=None
 graph_results_average=Average
 graph_results_data=Data
 graph_results_deviation=Deviation

Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties?rev=1372926&r1=1372925&r2=1372926&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties Tue Aug 14 15:30:32 2012
@@ -312,6 +312,22 @@ get_xml_from_file=Fichier avec les donn\
 get_xml_from_random=R\u00E9pertoire contenant les fichier(s) \:
 graph_choose_graphs=Graphique \u00E0 afficher
 graph_full_results_title=Graphique de r\u00E9sultats complets
+graph_line_interval_label=Interval (ms) \:
+graph_line_interval_reload=Appliquer l'interval
+graph_line_no_duration=Test sans dur\u00E9e. Impossible de dessiner le graphique.
+graph_line_series_selection=S\u00E9lection des \u00E9chantillons par libell\u00E9 \:
+graph_line_settings_line=Param\u00E9tres de la courbe
+graph_line_settings_pane=Param\u00E9tres du graphique
+graph_line_shape_label=Forme de la jonction \:
+graph_line_stroke_width=Largeur de ligne \:
+graph_line_title=Graphique \u00E9volution temps de r\u00E9ponses
+graph_line_title_label=Titre du graphique \:  
+graph_line_xaxis_time_format=Formatage heure (SimpleDateFormat) \:
+graph_pointshape_circle=Cercle
+graph_pointshape_diamond=Diamant
+graph_pointshape_none=Aucun
+graph_pointshape_square=Carr\u00E9
+graph_pointshape_triangle=Triangle
 graph_results_average=Moyenne
 graph_results_data=Donn\u00E9es
 graph_results_deviation=Ecart type

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1372926&r1=1372925&r2=1372926&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml (original)
+++ jmeter/trunk/xdocs/changes.xml Tue Aug 14 15:30:32 2012
@@ -134,6 +134,7 @@ JSR223 Test Elements using Script file a
 <ul>
 <li><bugzilla>53566</bugzilla> - Don't log partial responses to the jmeter log</li>
 <li><bugzilla>53716</bugzilla> - Small improvements in aggregate graph: legend at left or right is now on 1 column (instead of 1 large line), no border to the reference's square color, reduce width on some fields</li>
+<li><bugzilla>53718</bugzilla> - Add a new visualizer to draw a line graph showing the evolution of response time for a test</li>
 </ul>
 
 <h3>Timers, Assertions, Config, Pre- &amp; Post-Processors</h3>

Modified: jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=1372926&r1=1372925&r2=1372926&view=diff
==============================================================================
--- jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jmeter/trunk/xdocs/usermanual/component_reference.xml Tue Aug 14 15:30:32 2012
@@ -2734,6 +2734,15 @@ the graph as a PNG file.</description>
 </div>
 </component>
 
+<component name="Line Graph" index="&sect-num;.3.12" >
+<description>To do</description>
+<div align="center">
+<p>
+    The figure below shows an example of settings to draw this graph.
+</p>
+</div>
+</component>
+
 <component name="Mailer Visualizer" index="&sect-num;.3.13"  width="860" height="463" screenshot="mailervisualizer.png">
 <description><p>The mailer visualizer can be set up to send email if a test run receives too many
 failed responses from the server.</p></description>