KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jmeter > visualizers > GraphVisualizer


1 // $Header: /home/cvs/jakarta-jmeter/src/components/org/apache/jmeter/visualizers/GraphVisualizer.java,v 1.19 2004/03/05 01:33:33 sebb Exp $
2
/*
3  * Copyright 2001-2004 The Apache Software Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17 */

18
19 package org.apache.jmeter.visualizers;
20
21
22 import java.awt.BorderLayout JavaDoc;
23 import java.awt.Color JavaDoc;
24 import java.awt.Component JavaDoc;
25 import java.awt.Dimension JavaDoc;
26 import java.awt.FlowLayout JavaDoc;
27 import java.awt.Image JavaDoc;
28 import java.awt.event.ItemEvent JavaDoc;
29 import java.awt.event.ItemListener JavaDoc;
30
31 import javax.swing.BorderFactory JavaDoc;
32 import javax.swing.Box JavaDoc;
33 import javax.swing.JCheckBox JavaDoc;
34 import javax.swing.JLabel JavaDoc;
35 import javax.swing.JPanel JavaDoc;
36 import javax.swing.JScrollPane JavaDoc;
37 import javax.swing.JTextField JavaDoc;
38 import javax.swing.border.Border JavaDoc;
39 import javax.swing.border.EmptyBorder JavaDoc;
40
41 import org.apache.jmeter.gui.util.JMeterColor;
42 import org.apache.jmeter.samplers.Clearable;
43 import org.apache.jmeter.samplers.SampleResult;
44 import org.apache.jmeter.util.JMeterUtils;
45 import org.apache.jmeter.visualizers.gui.AbstractVisualizer;
46
47
48 /**
49  * This class implements a statistical analyser that calculates both the average
50  * and the standard deviation of the sampling process and outputs them as
51  * autoscaling plots.
52  *
53  * Created February 8, 2001
54  * @version $Revision: 1.19 $ $Date: 2004/03/05 01:33:33 $
55  */

56 public class GraphVisualizer extends AbstractVisualizer
57         implements ImageVisualizer, ItemListener JavaDoc, GraphListener, Clearable
58 {
59     GraphModel model;
60     private JTextField JavaDoc maxYField = null;
61     private JTextField JavaDoc minYField = null;
62     private JTextField JavaDoc noSamplesField = null;
63     String JavaDoc minute = JMeterUtils.getResString("minute");
64
65     private Graph graph;
66     private JCheckBox JavaDoc data;
67     private JCheckBox JavaDoc average;
68     private JCheckBox JavaDoc deviation;
69     private JCheckBox JavaDoc throughput;
70     private JCheckBox JavaDoc median;
71     private JTextField JavaDoc dataField;
72     private JTextField JavaDoc averageField;
73     private JTextField JavaDoc deviationField;
74     private JTextField JavaDoc throughputField;
75     private JTextField JavaDoc medianField;
76     
77     /**
78      * Constructor for the GraphVisualizer object.
79      */

80     public GraphVisualizer()
81     {
82         model = new GraphModel();
83         model.addGraphListener(this);
84         graph = new Graph(model);
85         init();
86     }
87
88     /**
89      * Gets the Image attribute of the GraphVisualizer object.
90      *
91      * @return the Image value
92      */

93     public Image JavaDoc getImage()
94     {
95         Image JavaDoc result = graph.createImage(graph.getWidth(), graph.getHeight());
96
97         graph.paintComponent(result.getGraphics());
98
99         return result;
100     }
101
102     public synchronized void updateGui()
103     {
104         graph.updateGui();
105         noSamplesField.setText(Long.toString(model.getSampleCount()));
106         dataField.setText(Long.toString(model.getCurrentData()));
107         averageField.setText(Long.toString(model.getCurrentAverage()));
108         deviationField.setText(Long.toString(model.getCurrentDeviation()));
109         throughputField.setText(
110             Float.toString(model.getCurrentThroughput()) + "/" + minute);
111         medianField.setText(Long.toString(model.getCurrentMedian()));
112         updateYAxis();
113     }
114
115     public synchronized void updateGui(Sample s)
116     {
117         // We have received one more sample
118
graph.updateGui(s);
119         noSamplesField.setText(Long.toString(model.getSampleCount()));
120         dataField.setText(Long.toString(s.data));
121         averageField.setText(Long.toString(s.average));
122         deviationField.setText(Long.toString(s.deviation));
123         throughputField.setText(Float.toString(s.throughput) + "/" + minute);
124         medianField.setText(Long.toString(s.median));
125         updateYAxis();
126     }
127
128     public void add(SampleResult res)
129     {
130         model.addSample(res);
131     }
132
133     public String JavaDoc getLabelResource()
134     {
135         return "graph_results_title";
136     }
137
138     public void itemStateChanged(ItemEvent JavaDoc e)
139     {
140         if (e.getItem() == data)
141         {
142             this.graph.enableData(e.getStateChange() == ItemEvent.SELECTED);
143         }
144         else if (e.getItem() == average)
145         {
146             this.graph.enableAverage(e.getStateChange() == ItemEvent.SELECTED);
147         }
148         else if (e.getItem() == deviation)
149         {
150             this.graph.enableDeviation(
151                 e.getStateChange() == ItemEvent.SELECTED);
152         }
153         else if (e.getItem() == throughput)
154         {
155             this.graph.enableThroughput(
156                 e.getStateChange() == ItemEvent.SELECTED);
157         }
158         else if(e.getItem() == median)
159         {
160             this.graph.enableMedian(e.getStateChange() == ItemEvent.SELECTED);
161         }
162         this.graph.repaint();
163     }
164
165     public synchronized void clear()
166     {
167         // this.graph.clear();
168
model.clear();
169         dataField.setText("0000");
170         averageField.setText("0000");
171         deviationField.setText("0000");
172         throughputField.setText("0/" + minute);
173         medianField.setText("0000");
174         updateYAxis();
175         repaint();
176     }
177
178     public String JavaDoc toString()
179     {
180         return "Show the samples analysis as dot plots";
181     }
182
183     /**
184      * Update the max and min value of the Y axis.
185      */

186     private void updateYAxis()
187     {
188         maxYField.setText(Long.toString(model.getGraphMax()));
189         minYField.setText("0");
190     }
191
192     /**
193      * Initialize the GUI.
194      */

195     private void init()
196     {
197         this.setLayout(new BorderLayout JavaDoc());
198
199         // MAIN PANEL
200
Border JavaDoc margin = new EmptyBorder JavaDoc(10, 10, 5, 10);
201
202         this.setBorder(margin);
203
204
205         // Set up the graph with header, footer, Y axis and graph display
206
JPanel JavaDoc graphPanel = new JPanel JavaDoc(new BorderLayout JavaDoc());
207         graphPanel.add(createYAxis(), BorderLayout.WEST);
208         graphPanel.add(createChoosePanel(), BorderLayout.NORTH);
209         graphPanel.add(createGraphPanel(), BorderLayout.CENTER);
210         graphPanel.add(createGraphInfoPanel(), BorderLayout.SOUTH);
211
212         // Add the main panel and the graph
213
this.add(makeTitlePanel(), BorderLayout.NORTH);
214         this.add(graphPanel, BorderLayout.CENTER);
215     }
216
217     // Methods used in creating the GUI
218

219     /**
220      * Creates the panel containing the graph's Y axis labels.
221      *
222      * @return the Y axis panel
223      */

224     private JPanel JavaDoc createYAxis()
225     {
226         JPanel JavaDoc graphYAxisPanel = new JPanel JavaDoc();
227         
228         graphYAxisPanel.setLayout(new BorderLayout JavaDoc());
229         
230         maxYField = createYAxisField(5);
231         minYField = createYAxisField(3);
232
233         graphYAxisPanel.add(createYAxisPanel("graph_results_ms", maxYField),
234                         BorderLayout.NORTH);
235         graphYAxisPanel.add(createYAxisPanel("graph_results_ms", minYField),
236                         BorderLayout.SOUTH);
237
238         return graphYAxisPanel;
239     }
240
241     /**
242      * Creates a text field to be used for the value of a Y axis
243      * label. These fields hold the minimum and maximum values
244      * for the graph. The units are kept in a separate label
245      * outside of this field.
246      *
247      * @param length the number of characters which the field
248      * will use to calculate its preferred width.
249      * This should be set to the maximum number
250      * of digits that are expected to be necessary
251      * to hold the label value.
252      *
253      * @see #createYAxisPanel(String, JTextField)
254      *
255      * @return a text field configured to be used in the Y axis
256      */

257     private JTextField JavaDoc createYAxisField(int length)
258     {
259         JTextField JavaDoc field = new JTextField JavaDoc(length);
260         field.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
261         field.setEditable(false);
262         field.setForeground(Color.black);
263         field.setBackground(getBackground());
264         field.setHorizontalAlignment(JTextField.RIGHT);
265         return field;
266     }
267
268     /**
269      * Creates a panel for an entire Y axis label. This includes
270      * the dynamic value as well as the unit label.
271      *
272      * @param labelResourceName the name of the label resource.
273      * This is used to look up the label text using
274      * {@link JMeterUtils#getResString(String)}.
275      *
276      * @return a panel containing both the dynamic and static parts
277      * of a Y axis label
278      */

279     private JPanel JavaDoc createYAxisPanel(String JavaDoc labelResourceName, JTextField JavaDoc field)
280     {
281         JPanel JavaDoc panel = new JPanel JavaDoc(new FlowLayout JavaDoc());
282         JLabel JavaDoc label = new JLabel JavaDoc(JMeterUtils.getResString(labelResourceName));
283         
284         panel.add(field);
285         panel.add(label);
286         return panel;
287     }
288
289
290     /**
291      * Creates a panel which allows the user to choose which graphs
292      * to display. This panel consists of a check box for each type
293      * of graph (current sample, average, deviation, and throughput).
294      *
295      * @return a panel allowing the user to choose which graphs
296      * to display
297      */

298     private JPanel JavaDoc createChoosePanel()
299     {
300         JPanel JavaDoc chooseGraphsPanel = new JPanel JavaDoc();
301         
302         chooseGraphsPanel.setLayout(new FlowLayout JavaDoc());
303         JLabel JavaDoc selectGraphsLabel = new JLabel JavaDoc(
304                         JMeterUtils.getResString("graph_choose_graphs"));
305         data = createChooseCheckBox("graph_results_data", Color.black);
306         average = createChooseCheckBox("graph_results_average", Color.blue);
307         deviation = createChooseCheckBox("graph_results_deviation", Color.red);
308         throughput = createChooseCheckBox("graph_results_throughput",
309                         JMeterColor.dark_green);
310         median =
311             createChooseCheckBox("graph_results_median", JMeterColor.purple);
312
313         chooseGraphsPanel.add(selectGraphsLabel);
314         chooseGraphsPanel.add(data);
315         chooseGraphsPanel.add(average);
316         chooseGraphsPanel.add(median);
317         chooseGraphsPanel.add(deviation);
318         chooseGraphsPanel.add(throughput);
319         return chooseGraphsPanel;
320     }
321
322     /**
323      * Creates a check box configured to be used to in the choose panel
324      * allowing the user to select whether or not a particular kind of
325      * graph data will be displayed.
326      *
327      * @param labelResourceName the name of the label resource.
328      * This is used to look up the label text using
329      * {@link JMeterUtils#getResString(String)}.
330      * @param color the color used for the checkbox text. By
331      * convention this is the same color that is used
332      * to draw the graph and for the corresponding
333      * info field.
334      *
335      * @return a checkbox allowing the user to select whether or
336      * not a kind of graph data will be displayed
337      */

338     private JCheckBox JavaDoc createChooseCheckBox(
339         String JavaDoc labelResourceName,
340         Color JavaDoc color)
341     {
342         JCheckBox JavaDoc checkBox = new JCheckBox JavaDoc(
343                         JMeterUtils.getResString(labelResourceName));
344         checkBox.setSelected(true);
345         checkBox.addItemListener(this);
346         checkBox.setForeground(color);
347         return checkBox;
348     }
349
350
351     /**
352      * Creates a scroll pane containing the actual graph of
353      * the results.
354      *
355      * @return a scroll pane containing the graph
356      */

357     private Component JavaDoc createGraphPanel()
358     {
359         JScrollPane JavaDoc graphScrollPanel =
360             makeScrollPane(
361                 graph,
362                 JScrollPane.VERTICAL_SCROLLBAR_NEVER,
363                 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
364         graphScrollPanel.setViewportBorder(
365                 BorderFactory.createEmptyBorder(2, 2, 2, 2));
366         graphScrollPanel.setPreferredSize(graphScrollPanel.getMinimumSize());
367
368         return graphScrollPanel;
369     }
370
371
372     /**
373      * Creates a panel which numerically displays the current graph
374      * values.
375      *
376      * @return a panel showing the current graph values
377      */

378     private Box JavaDoc createGraphInfoPanel()
379     {
380         Box JavaDoc graphInfoPanel = Box.createHorizontalBox();
381
382         noSamplesField = createInfoField(Color.black, 6);
383         dataField = createInfoField(Color.black, 5);
384         averageField = createInfoField(Color.blue, 5);
385         deviationField = createInfoField(Color.red, 5);
386         throughputField = createInfoField(JMeterColor.dark_green, 15);
387         medianField = createInfoField(JMeterColor.purple,5);
388
389         graphInfoPanel.add(
390             createInfoColumn(
391                 createInfoLabel("graph_results_no_samples", noSamplesField),
392                 noSamplesField,
393                 createInfoLabel("graph_results_deviation", deviationField),
394                 deviationField));
395         graphInfoPanel.add(Box.createHorizontalGlue());
396
397         graphInfoPanel.add(
398             createInfoColumn(
399                 createInfoLabel("graph_results_latest_sample", dataField),
400                 dataField,
401                 createInfoLabel("graph_results_throughput", throughputField),
402                 throughputField));
403         graphInfoPanel.add(Box.createHorizontalGlue());
404
405         graphInfoPanel.add(
406             createInfoColumn(
407                 createInfoLabel("graph_results_average", averageField),
408                 averageField,
409                 createInfoLabel("graph_results_median", medianField),
410                 medianField));
411         graphInfoPanel.add(Box.createHorizontalGlue());
412         return graphInfoPanel;
413     }
414
415     /**
416      * Creates one of the fields used to display the graph's current
417      * values.
418      *
419      * @param color the color used to draw the value. By convention
420      * this is the same color that is used to draw the
421      * graph for this value and in the choose panel.
422      * @param length the number of digits which the field should be
423      * able to display
424      *
425      * @return a text field configured to display one of the
426      * current graph values
427      */

428     private JTextField JavaDoc createInfoField(Color JavaDoc color, int length)
429     {
430         JTextField JavaDoc field = new JTextField JavaDoc(length);
431         field.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
432         field.setEditable(false);
433         field.setForeground(color);
434         field.setBackground(getBackground());
435
436         // The text field should expand horizontally, but have
437
// a fixed height
438
field.setMaximumSize(new Dimension JavaDoc(
439                     field.getMaximumSize().width,
440                     field.getPreferredSize().height));
441         return field;
442     }
443
444
445     /**
446      * Creates a label for one of the fields used to display the graph's
447      * current values. Neither the label created by this method or the
448      * <code>field</code> passed as a parameter is added to the GUI here.
449      *
450      * @param labelResourceName the name of the label resource.
451      * This is used to look up the label text using
452      * {@link JMeterUtils#getResString(String)}.
453      * @param field the field this label is being created for.
454      */

455     private JLabel JavaDoc createInfoLabel(String JavaDoc labelResourceName, JTextField JavaDoc field)
456     {
457         JLabel JavaDoc label = new JLabel JavaDoc(
458                 JMeterUtils.getResString(labelResourceName));
459         label.setForeground(field.getForeground());
460         label.setLabelFor(field);
461         return label;
462     }
463
464     /**
465      * Creates a panel containing two pairs of labels and fields for
466      * displaying the current graph values. This method exists to help with
467      * laying out the fields in columns. If one or more components are null
468      * then these components will be represented by blank space.
469      *
470      * @param label1 the label for the first field. This label will
471      * be placed in the upper left section of the panel.
472      * If this parameter is null, this section of the
473      * panel will be left blank.
474      * @param field1 the field corresponding to the first label. This
475      * field will be placed in the upper right section
476      * of the panel. If this parameter is null, this
477      * section of the panel will be left blank.
478      * @param label2 the label for the second field. This label will
479      * be placed in the lower left section of the panel.
480      * If this parameter is null, this section of the
481      * panel will be left blank.
482      * @param field2 the field corresponding to the second label. This
483      * field will be placed in the lower right section
484      * of the panel. If this parameter is null, this
485      * section of the panel will be left blank.
486      */

487     private Box JavaDoc createInfoColumn(
488         JLabel JavaDoc label1,
489         JTextField JavaDoc field1,
490         JLabel JavaDoc label2,
491         JTextField JavaDoc field2)
492     {
493         // This column actually consists of a row with two sub-columns
494
// The first column contains the labels, and the second
495
// column contains the fields.
496
Box JavaDoc row = Box.createHorizontalBox();
497         Box JavaDoc col = Box.createVerticalBox();
498         col.add(label1 != null ? label1 : Box.createVerticalGlue());
499         col.add(label2 != null ? label2 : Box.createVerticalGlue());
500         row.add(col);
501
502         row.add(Box.createHorizontalStrut(5));
503
504         col = Box.createVerticalBox();
505         col.add(field1 != null ? field1 : Box.createVerticalGlue());
506         col.add(field2 != null ? field2 : Box.createVerticalGlue());
507         row.add(col);
508
509         row.add(Box.createHorizontalStrut(5));
510
511         return row;
512     }
513 }
514
Popular Tags