001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014: * License for the specific language governing permissions and limitations
015: * under the License.
016: *
017: */
018: package org.apache.jmeter.visualizers;
019:
020: import java.awt.BasicStroke;
021: import java.awt.Color;
022: import java.awt.Dimension;
023: import java.awt.Graphics;
024: import java.awt.Graphics2D;
025: import java.awt.LayoutManager;
026: import java.awt.Paint;
027: import java.awt.Shape;
028: import java.awt.Stroke;
029:
030: import javax.swing.JPanel;
031:
032: import org.jCharts.axisChart.AxisChart;
033: import org.jCharts.chartData.AxisChartDataSet;
034: import org.jCharts.chartData.DataSeries;
035: import org.jCharts.properties.AxisProperties;
036: import org.jCharts.properties.ChartProperties;
037: import org.jCharts.properties.DataAxisProperties;
038: import org.jCharts.properties.LegendProperties;
039: import org.jCharts.properties.LineChartProperties;
040: import org.jCharts.properties.PointChartProperties;
041: import org.jCharts.types.ChartType;
042:
043: /**
044: *
045: * Axis graph is used by StatGraphVisualizer, which generates bar graphs
046: * from the statistical data.
047: */
048: public class LineGraph extends JPanel {
049:
050: protected double[][] data = null;
051: protected String title, xAxisTitle, yAxisTitle;
052: protected String[] xAxisLabels, yAxisLabel;
053: protected int width, height;
054:
055: private static final Shape[] SHAPE_ARRAY = {
056: PointChartProperties.SHAPE_CIRCLE,
057: PointChartProperties.SHAPE_DIAMOND,
058: PointChartProperties.SHAPE_SQUARE,
059: PointChartProperties.SHAPE_TRIANGLE };
060:
061: /**
062: * 12 basic colors for line graphs. If we need more colors than this,
063: * we can add more. Though more than 12 lines per graph will look
064: * rather busy and be hard to read.
065: */
066: private static final Paint[] PAINT_ARRAY = { Color.black,
067: Color.blue, Color.green, Color.magenta, Color.orange,
068: Color.red, Color.yellow, Color.darkGray, Color.gray,
069: Color.lightGray, Color.pink, Color.cyan };// Using lower-case for JDK 1.3 compatibility
070: protected int shape_counter = 0;
071: protected int paint_counter = -1;
072:
073: /**
074: *
075: */
076: public LineGraph() {
077: super ();
078: }
079:
080: /**
081: * @param layout
082: */
083: public LineGraph(LayoutManager layout) {
084: super (layout);
085: }
086:
087: /**
088: * @param layout
089: * @param isDoubleBuffered
090: */
091: public LineGraph(LayoutManager layout, boolean isDoubleBuffered) {
092: super (layout, isDoubleBuffered);
093: }
094:
095: public void setData(double[][] data) {
096: this .data = data;
097: }
098:
099: public void setTitle(String title) {
100: this .title = title;
101: }
102:
103: public void setXAxisTitle(String title) {
104: this .xAxisTitle = title;
105: }
106:
107: public void setYAxisTitle(String title) {
108: this .yAxisTitle = title;
109: }
110:
111: public void setXAxisLabels(String[] labels) {
112: this .xAxisLabels = labels;
113: }
114:
115: public void setYAxisLabels(String[] label) {
116: this .yAxisLabel = label;
117: }
118:
119: public void setWidth(int w) {
120: this .width = w;
121: }
122:
123: public void setHeight(int h) {
124: this .height = h;
125: }
126:
127: public void paintComponent(Graphics g) {
128: // reset the paint counter
129: this .paint_counter = -1;
130: if (data != null && this .title != null
131: && this .xAxisLabels != null && this .xAxisTitle != null
132: && this .yAxisLabel != null && this .yAxisTitle != null) {
133: drawSample(this .title, this .xAxisLabels, this .xAxisTitle,
134: this .yAxisTitle, this .data, this .width,
135: this .height, g);
136: }
137: }
138:
139: private void drawSample(String _title, String[] _xAxisLabels,
140: String _xAxisTitle, String _yAxisTitle, double[][] _data,
141: int _width, int _height, Graphics g) {
142: try {
143: if (_width == 0) {
144: _width = 450;
145: }
146: if (_height == 0) {
147: _height = 250;
148: }
149: this .setPreferredSize(new Dimension(_width, _height));
150: DataSeries dataSeries = new DataSeries(_xAxisLabels,
151: _xAxisTitle, _yAxisTitle, _title);
152: String[] legendLabels = yAxisLabel;
153: Paint[] paints = this .createPaint(_data.length);
154: Shape[] shapes = createShapes(_data.length);
155: Stroke[] lstrokes = createStrokes(_data.length);
156: LineChartProperties lineChartProperties = new LineChartProperties(
157: lstrokes, shapes);
158: AxisChartDataSet axisChartDataSet = new AxisChartDataSet(
159: _data, legendLabels, paints, ChartType.LINE,
160: lineChartProperties);
161: dataSeries.addIAxisPlotDataSet(axisChartDataSet);
162:
163: ChartProperties chartProperties = new ChartProperties();
164: AxisProperties axisProperties = new AxisProperties();
165: // show the grid lines, to turn it off, set it to zero
166: axisProperties.getYAxisProperties().setShowGridLines(1);
167: axisProperties.setXAxisLabelsAreVertical(true);
168: // set the Y Axis to round
169: DataAxisProperties daxp = (DataAxisProperties) axisProperties
170: .getYAxisProperties();
171: daxp.setRoundToNearest(1);
172: LegendProperties legendProperties = new LegendProperties();
173: AxisChart axisChart = new AxisChart(dataSeries,
174: chartProperties, axisProperties, legendProperties,
175: _width, _height);
176: axisChart.setGraphics2D((Graphics2D) g);
177: axisChart.render();
178: } catch (Exception e) {
179: e.printStackTrace();
180: }
181: }
182:
183: /**
184: * Since we only have 4 shapes, the method will start with the
185: * first shape and keep cycling through the shapes in order.
186: * @param count
187: * @return the first n shapes
188: */
189: public Shape[] createShapes(int count) {
190: Shape[] shapes = new Shape[count];
191: for (int idx = 0; idx < count; idx++) {
192: shapes[idx] = nextShape();
193: }
194: return shapes;
195: }
196:
197: /**
198: * Return the next shape
199: * @return the next shape
200: */
201: public Shape nextShape() {
202: this .shape_counter++;
203: if (shape_counter >= (SHAPE_ARRAY.length - 1)) {
204: shape_counter = 0;
205: }
206: return SHAPE_ARRAY[shape_counter];
207: }
208:
209: /**
210: *
211: * @param count
212: * @return the first count strokes
213: */
214: public Stroke[] createStrokes(int count) {
215: Stroke[] str = new Stroke[count];
216: for (int idx = 0; idx < count; idx++) {
217: str[idx] = nextStroke();
218: }
219: return str;
220: }
221:
222: /**
223: * method always return a new BasicStroke with 1.0f weight
224: * @return a new BasicStroke with 1.0f weight
225: */
226: public Stroke nextStroke() {
227: return new BasicStroke(1.0f);
228: }
229:
230: /**
231: * return an array of Paint with different colors. The current
232: * implementation will cycle through 12 colors if a line graph
233: * has more than 12 entries
234: * @param count
235: * @return an array of Paint with different colors
236: */
237: public Paint[] createPaint(int count) {
238: Paint[] pts = new Paint[count];
239: for (int idx = 0; idx < count; idx++) {
240: pts[idx] = nextPaint();
241: }
242: return pts;
243: }
244:
245: /**
246: * The method will return the next paint color in the PAINT_ARRAY.
247: * Rather than return a random color, we want it to always go through
248: * the same sequence. This way, the same charts will always use the
249: * same color and make it easier to compare side by side.
250: * @return the next paint color in the PAINT_ARRAY
251: */
252: public Paint nextPaint() {
253: this .paint_counter++;
254: if (this .paint_counter == (PAINT_ARRAY.length - 1)) {
255: this .paint_counter = 0;
256: }
257: return PAINT_ARRAY[this.paint_counter];
258: }
259: }
|