Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: cor/gui/prf/JspmPerfHisto.java


1   /*-----------------------------------------------------------------------------------------------------*/
2   /*                                                                                                     */
3   /*  Copyright (C)                                                                                      */ 
4   /*                                                                                                     */
5   /*  This program is free software; you can redistribute it and/or modify it under the terms of the GNU */
6   /*  General Public License as published by the Free Software Foundation; either version 2 of the       */
7   /*  License, or (at your option) any later version.                                                    */
8   /*                                                                                                     */
9   /*  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;          */
10  /*  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR                   */
11  /*  PURPOSE. See the GNU General Public License for more details.                                      */
12  /*                                                                                                     */
13  /*  You should have received a copy of the GNU General Public License along with this program; if      */
14  /*  not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA           */
15  /*  02111-1307 USA                                                                                     */
16  /*                                                                                                     */
17  /*-----------------------------------------------------------------------------------------------------*/
18  /*                                                                                                     */
19  /* $Author: strand01 $ $Revision: 1.3 $ $Date: 2001/12/20 14:23:02 $                                    */
20  /*                                                                                                     */
21  /*-----------------------------------------------------------------------------------------------------*/
22  
23  package cor.gui.prf;
24  
25  // Java packages
26  import java.awt.event.*;
27  import java.awt.*;
28  import java.applet.*;
29  import java.util.*;
30  
31  // Swing packages
32  import javax.swing.*;
33  
34  /**
35   * This class generated the the histograms for the Jspm performance management GUI. Each histogram can contains
36   * several charts, which are overlayed.
37   *
38   * Options can be set by using one of the following function:
39   *  - SetStrAttr: Set a string attribute. String attributes can be:
40   *     -# FrameLayout: Set the frame layout (shadow or not).
41   *     -# Title: Set the title of the histogram.
42   *     -# Legend: Sets the legend string which describes the different charts
43   *  - SetBoolAttr: Set a boolean attribute. Boolean attrbutes can be one of:
44   *     -# FixedMinY: Set the YAxis minimum to a certain value.
45   *     -# FixedMaxY: Set the YAxis maximum to a certain value.
46   *     -# ShowThres: Set the show threshold flag.
47   *     -# GridX: Set the X-Grid ON/OFF.
48   *     -# GridX: Set the Y-Grid ON/OFF.
49   *  - SetColor: Will set one of the colors. Color attributes can be:
50   *     -# GraphColor: Sets the graph color.
51   *     -# TitleColor: Sets the title color.
52   *     -# LabelColor: Sets the label color.
53   *  - SetFontAttr: Sets one of the fonts. Valid font attributes are:
54   *     -# Title: Sets the title font.
55   *     -# X-Labels: Sets the X label font.
56   *     -# Y-Labels: Sets the Y label font.
57   *     -# Legend: Sets the legend font.
58   *  - SetIntAttr: Sets one of the integer attributes. Valid integer attributes are:
59   *     -# PXSIZE: Width of the histogram.
60   *     -# PYSIZE: Height of the histogram.
61   *     -# XLMARGIN: Left margin of the histogram.
62   *     -# XRMARGIN: Right Margin of the histogram.
63   *     -# YTMARGIN: Top Y margin.
64   *     -# YBMARGIN: Bottom Y margin.
65   *     -# currentTime: Current time for the real time histogram.
66   *  - SetDoubleAttr: Sets one of the double attributes. Valid double attributes are:
67   *     -# ymin: Minimum Y axis.
68   *     -# ymax: Maximum Y axis.
69   * 
70   * All attributes should be given as they appear here in the list.
71   *
72   * Several options can be set for the histogram. In detail this are:
73   * - logarithmic scale. All labels, grids and values will be transformed to a logarithmic scale.
74   * - grid in X and Y in light gray.
75   * - fixed minimum Y. In case fixedMinY is switched ON the user has to give the minimum value for the
76   *   display of the graphs.
77   * - fixed maximum Y. In case fixedMaxY is switched ON the user has to give the maximum value for the
78   *   display of the graphs.
79   *
80   * @author Steve Randall (strand012001@yahoo.com)
81   * @version 0.0.2
82   * @date 27/08/2001
83   */
84  public class JspmPerfHisto extends JPanel implements Runnable
85  {
86      /**
87       * Width of the histogram space
88       */
89      private int  PXSIZE;
90  
91      /**
92       * Height of the histogram space
93       */
94      private int PYSIZE;
95  
96      /**
97       * Left margin of the histogram itself
98       */
99      private int XLMARGIN;
100 
101     /**
102      * Right margin of the histogram itself
103      */
104     private int XRMARGIN;
105 
106     /**
107      * Top margin
108      */ 
109     private int YTMARGIN;
110     
111     /**
112      * Bottom margin.
113      */
114     private int YBMARGIN;
115 
116     /**
117      * Maximal number of overlayed histos
118      */
119     private int MAX_HISTO = 8;
120 
121     /**
122      * Number of data points for the different charts.
123      */
124     private int np[];
125 
126     /**
127      * Number of X-axis labels
128      */
129     private int nxLabels = 25;
130 
131     /**
132      * Number of charts.
133      */
134     private int nHist = 0;
135     
136     /**
137      * Total number of all points in all charts.
138      */
139     private int nt = 0;
140 
141     /**
142      * Data points in X
143      */
144     private double xData[];
145 
146     /**
147      * Y coordinate of all points
148      */
149     private double yData[];
150 
151     /**
152      * Minimum in Y
153      */
154     private double ymin = 0.0;
155 
156     /**
157      * Maximum in Y
158      */
159     private double ymax = 100.0;
160 
161     /**
162      * Gap in Y.
163      */
164     private double ygap = 10.0;
165 
166     /**
167      * Scale in X
168      */
169     private double xscale = 0.0;
170 
171     /**
172      * Scale in X
173      */
174     private double yscale = 0.0;
175 
176     /**
177      * Minimum critical thresholds
178      */
179     private double minCrit[];
180 
181     /**
182      * Minimum warning thresholds
183      */
184     private double minWarn[];
185     
186     /**
187      * Maximum warning thresholds
188      */
189     private double maxWarn[];
190     
191     /**
192      * Maximum critical thresholds
193      */
194     private double maxCrit[];
195 
196     /**
197      * Fixed minimum Y axis flag
198      */
199     private boolean fixedMinY = false;
200 
201     /**
202      * Fixed maximum Y axis flag
203      */
204     private boolean fixedMaxY = false;
205 
206     /**
207      * X-grid flag
208      */
209     private boolean XGRID = true;
210 
211     /**
212      * Y-grid
213      */
214     private boolean YGRID = true;
215 
216     /**
217      * Small X ticks.
218      */
219     private int smallTicks = 3;
220 
221     /**
222      * Data initialization flag
223      */
224     private boolean dataSet = false;
225 
226     /**
227      * Log scale flag
228      */
229     private boolean logScale = false;
230 
231     /**
232      * Show thresholds flag
233      */
234     private boolean showThres = false;
235 
236     /**
237      * Label color
238      */
239     private Color labelColor;
240 
241     /**
242      * Title color
243      */
244     private Color titleColor;
245     
246     /**
247      * The color table for the charts
248      */
249     private Color graphColor[] = {Color.red, Color.green, Color.magenta, Color.cyan, Color.blue, Color.pink, 
250           Color.orange, Color.yellow};
251 
252     /**
253      * The frame layout
254      */
255     String frameLayout = "Shadow";
256 
257     /**
258      * Title
259      */
260     private String title = "Jspm Performance Management";
261 
262     /**
263      * Legend vector
264      */
265     private Vector legend = new Vector();
266     
267     /**
268      * X-labels
269      */
270     private String xLabels[];
271 
272     /**
273      * Current time for real time view
274      */
275     int currentTime = 0;
276 
277     /**
278      * Realtime flag
279      */
280     private boolean realTime = false;
281     
282     /** 
283      * Title font. Default is Courir, bold, 12.
284      */
285     private Font titleFont = new Font( "Courir", Font.BOLD, 12 );
286     
287     /**
288      * X axis labels font
289      */
290     private Font xLabelFont = new Font( "Ariel", Font.PLAIN, 10 );
291     
292     /**
293      * Y axis labels font
294      */
295     private Font yLabelFont = new Font( "Ariel", Font.PLAIN, 10 );
296     
297     /**
298      * X axis labels font
299      */
300     private Font legendFont = new Font( "Ariel", Font.PLAIN, 10 );
301     
302     /**
303      * Blinking thread
304      */
305     private Thread histoThread;
306 
307     /**
308      * Running flag.
309      */
310     private boolean running;
311 
312     /**
313      * Constructor.
314      *
315      * The following defaults will be set:
316      *   - PXSIZE: 700
317      *   - PYSIZE: 400
318      *   - XLMARGIN: 80
319      *   - XRMARGIN: 80
320      *   - YTMARGIN: 30
321      *   - YBMARGIN: 60
322      *   - GridX: true
323      *   - GridY: true
324      *   - Frame: "Shadow"
325      *   - TitleColor: black
326      *   - LabelColor: black
327      */
328     public JspmPerfHisto() {
329   np = new int[MAX_HISTO];
330   setIntAttr("PXSIZE", 700);
331   setIntAttr("PYSIZE", 400);
332   setIntAttr("XLMARGIN", 80);
333   setIntAttr("XRMARGIN", 80);
334   setIntAttr("YTMARGIN", 30);
335   setIntAttr("YBMARGIN", 60);
336   setBoolAttr("GridX", true);
337   setBoolAttr("GridY", true);
338   setStrAttr("Frame", "Shadow");
339   setColor("TitleColor", Color.black);
340   setColor("LabelColor", Color.black);
341   setSize(PXSIZE, PYSIZE);
342     }
343     
344     /**
345      * Sets an String attribute.
346      *
347      * Valid attributes are:
348      *   - FrameLayout: Frame type (shadow).
349      *   - Title: Histogram title.
350      *   - Legend: Legend attribute.
351      *
352      * @param attr (String) attribute name.
353      * @param value (String) attribute value.
354      */
355     public void setStrAttr(String attr, String value) {
356   if(attr.equals("FrameLayout")) frameLayout = value;
357   else if(attr.equals("Title")) title = value;
358   else if(attr.equals("Legend")) legend.addElement(value);
359     }
360     
361     /**
362      * Sets a boolean attribute
363      *
364      * Valid attributes are:
365      *   - FixedMinY: Set the YAxis minimum to a certain value.
366      *   - FixedMaxY: Set the YAxis maximum to a certain value.
367      *   - ShowThres: Set the show threshold flag.
368      *   - GridX: Set the X-Grid ON/OFF.
369      *   - GridX: Set the Y-Grid ON/OFF.
370      *   - LogScale: Set the Y-axis linear/logarithmic
371      *   - RealTime: Sets the realtime flag, which displays a vertical line at the current time.
372      *
373      * @param attr (String) attribute name.
374      * @param value (boolean) attribute value.
375      */
376     public void setBoolAttr(String attr, boolean value) {
377   if(attr.equals("FixedMinY")) fixedMinY = value;
378   else if(attr.equals("FixedMaxY")) fixedMaxY = value;
379   else if(attr.equals("ShowThres")) showThres = value;
380   else if(attr.equals("GridX")) XGRID = value;
381   else if(attr.equals("GridY")) YGRID = value;
382   else if(attr.equals("RealTime")) realTime = value;
383   else if(attr.equals("LogScale")) logScale = value;
384     }
385     
386     /**
387      * Sets a color attribute
388      *
389      * Valid attributes are:
390      *   - GraphColor: Sets the graph color.
391      *   - TitleColor: Sets the title color.
392      *   - LabelColor: Sets the label color.
393      *
394      * @param attr (String) attribute name.
395      * @param col (Color) attribute color.
396      */
397     public void setColor(String attr, Color col) {
398   if(attr.equals("GraphColor")) graphColor[nHist] = col;
399   else if(attr.equals("TitleColor")) titleColor = col;
400   else if(attr.equals("LabelColor")) labelColor = col;
401     }
402     
403     /**
404      * Sets an font attribute
405      *
406      * Valid attributes are
407      *   - Title: Sets the title font.
408      *   - X-Labels: Sets the X label font.
409      *   - Y-Labels: Sets the Y label font.
410      *   - Legend: Sets the legend font.
411      *
412      * @param attr (String) attribute name.
413      * @param font (Font) attribute font.
414      */
415     public void setFont(String attr, Font font) {
416   if(attr.equals("Title")) titleFont = font;
417   if(attr.equals("X-Labels")) xLabelFont = font;
418   if(attr.equals("Y-Labels")) yLabelFont = font;
419   if(attr.equals("Legend")) legendFont = font;
420     }
421     
422     /**
423      * Sets an integer attribute.
424      *
425      * Valid attributes are:
426      *   - PXSIZE: Width of the histogram.
427      *   - PYSIZE: Height of the histogram.
428      *   - XLMARGIN: Left margin of the histogram.
429      *   - XRMARGIN: Right margin of the histogram.
430      *   - YTMARGIN: Top Y margin.
431      *   - YBMARGIN: Bottom Y margin.
432      *
433      * @param attr (String) attribute name.
434      * @param value (int) attribute value.
435      */
436     public void setIntAttr(String attr, int value) {
437   if(attr.equals("PXSIZE")) PXSIZE = value;
438   else if(attr.equals("PYSIZE")) PYSIZE = value;
439   else if(attr.equals("XLMARGIN")) XLMARGIN = value;
440   else if(attr.equals("XRMARGIN")) XRMARGIN = value;
441   else if(attr.equals("YTMARGIN")) YTMARGIN = value;
442   else if(attr.equals("YBMARGIN")) YBMARGIN = value;  
443       else if(attr.equals("smallXTicks")) smallTicks = value;  
444       else if(attr.equals("currentTime")) currentTime = value;  
445     }
446     
447     /**
448      * Sets a double attribute.
449      *
450      * Valid attribute names are:
451      *   - ymin: Minimum Y axis.
452      *   - ymax: Maximum Y axis.
453      *
454      * @param attr (String) attribute name.
455      * @param value (double) attribute value.
456      */
457     public void setDoubleAttr(String attr, double value) {
458   if( attr.equals( "ymin" ) ) ymin = value;
459   else if( attr.equals( "ymax" ) ) ymax = value;
460     }
461     
462     /**
463      * Sets the X labels
464      * 
465      * @param l (String[]) label strings.
466      * @param num (int) number of labels.
467      */
468     public void setXLabels(String l[], int num) {
469   xLabels = new String[num];
470   
471   nxLabels = num;  
472   for(int i = 0; i < nxLabels; i++) 
473       xLabels[i] = l[i];
474     }
475     
476     /**
477      * Sets the data arrays
478      *
479      * @param y (double[]) Y-values.
480      * @param n (int) number of values.
481      */
482     public void setData(double y[], int n) 
483     {  
484   if( nHist == 0 ) {
485       yData = new double[n];
486       for( int i = 0; i < n; i++ ) {
487     yData[i] = y[i];
488       }
489   } else {
490       double ytmp[] = new double[nt+n];
491       
492       for( int i = 0; i < nt; i++ ) {
493     ytmp[i] = yData[i];
494       }
495       for( int i = 0; i < n; i++ ) {
496     ytmp[nt+i] = y[i];
497       }
498       
499       yData = new double[nt+n];
500       for( int i = 0; i < nt+n; i++ ) {
501     yData[i] = ytmp[i];
502       }
503   }
504   nt += n;
505   np[nHist] = n;
506   nHist++;
507   dataSet = true;
508     }
509 
510     /**
511      * Calculates the logarithm to base 10.
512      *
513      * @param x (double) value.
514      * @return x (double) log10(x)
515      */
516     double log10( double x )
517     {
518   return (Math.log(x)/Math.log(10) );
519     }
520 
521     /**
522      * Sets the thresholds arrays.
523      *
524      * @param minCrit (double[]) minimum critical thresholds.
525      * @param minCrit (double[]) minimum warning thresholds.
526      * @param minCrit (double[]) maximum warning thresholds.
527      * @param minCrit (double[]) maximum critical thresholds.
528      * @param n (int) number of values.
529      */
530     public void setThres(double minC[], double minW[], double maxW[], double maxC[], int n) {
531   
532   minCrit = new double[n];
533   minWarn = new double[n];
534   maxWarn = new double[n];
535   maxCrit = new double[n];
536   for(int i = 0; i < n; i++) {
537       minCrit[i] = minC[i];
538       minWarn[i] = minW[i];
539       maxWarn[i] = maxW[i];
540       maxCrit[i] = maxC[i];
541   }
542     }
543     
544     /**
545      * Draws the X-ticks
546      *
547      * @param g (Graphics) Graphics device.
548      */
549     private void drawXTicks( Graphics g) {
550   for(int i = 0; i < smallTicks * (nxLabels - 1); i++)
551       g.drawLine(XLMARGIN+(int)(i*(PXSIZE-XLMARGIN-XRMARGIN)/(smallTicks*(nxLabels-1))), PYSIZE-YBMARGIN,
552            XLMARGIN+(int)(i*(PXSIZE-XLMARGIN-XRMARGIN)/(smallTicks*(nxLabels-1))), PYSIZE-YBMARGIN+4);
553     }
554 
555     /**
556      * Draws the Y-ticks
557      *
558      * @param g (Graphics) Graphics device.
559      */
560     private void drawYTicks( Graphics g) {
561   
562   for(int i = 0; i < 11; i++) {
563       if(logScale) {
564     double dd = log10(i*( ymax-ymin )/ygap/11);
565     if(i == 0) {
566         g.drawLine(XLMARGIN-6, PYSIZE-YBMARGIN, XLMARGIN, PYSIZE-YBMARGIN);
567     } else {
568         g.drawLine(XLMARGIN-6, PYSIZE-YBMARGIN-(int)(log10(i*10)/2*(PYSIZE-YTMARGIN-YBMARGIN)),
569              XLMARGIN,   PYSIZE-YBMARGIN-(int)(log10(i*10)/2*(PYSIZE-YTMARGIN-YBMARGIN)));
570         if(dd > 0)
571       g.drawLine(XLMARGIN-4, PYSIZE-YBMARGIN-(int)(dd/2*(PYSIZE-YTMARGIN-YBMARGIN)),
572            XLMARGIN,   PYSIZE-YBMARGIN-(int)(dd/2*(PYSIZE-YTMARGIN-YBMARGIN)));
573     }
574     
575     if(i % 2 == 0)
576         g.drawLine(XLMARGIN-4, PYSIZE-YBMARGIN-(int)(log10(i*(( ymax - ymin )/ygap/11)+10)/2*
577                  (PYSIZE-YTMARGIN-YBMARGIN)),
578              XLMARGIN,   PYSIZE-YBMARGIN-(int)(log10(i*(( ymax - ymin )/ygap/11)+10)/2*
579                  (PYSIZE-YTMARGIN-YBMARGIN)));
580     if(i % 3 == 0)
581         g.drawLine(XLMARGIN-4, PYSIZE-YBMARGIN-(int)(log10(i*(( ymax - ymin )/ygap/11)+20)/2*
582                  (PYSIZE-YTMARGIN-YBMARGIN)),
583              XLMARGIN,   PYSIZE-YBMARGIN-(int)(log10(i*(( ymax - ymin )/ygap/11)+20)/2*
584                  (PYSIZE-YTMARGIN-YBMARGIN)));
585     if(i % 5 == 0)
586         g.drawLine(XLMARGIN-4, PYSIZE-YBMARGIN-(int)(log10(i*(( ymax - ymin )/ygap/11)+30)/2*
587                  (PYSIZE-YTMARGIN-YBMARGIN)),
588              XLMARGIN,   PYSIZE-YBMARGIN-(int)(log10(i*(( ymax - ymin )/ygap/11)+30)/2*
589                  (PYSIZE-YTMARGIN-YBMARGIN)));
590     
591       } else {
592     g.drawLine(XLMARGIN-4, YTMARGIN+(int)(i*((PYSIZE-YTMARGIN-YBMARGIN)/ygap)),
593          XLMARGIN,   YTMARGIN+(int)(i*((PYSIZE-YTMARGIN-YBMARGIN)/ygap)));
594             }    
595   }  
596     }
597 
598     /**
599      * Draws the X-Grid
600      *
601      * @param g (Graphics) Graphics device.
602      */
603     private void drawXGrid(Graphics g)
604     {
605   g.setColor( Color.lightGray );
606   for(int i = 0; i < smallTicks*(nxLabels-1); i++)
607       g.drawLine(XLMARGIN+(int)(i*(PXSIZE-XLMARGIN-XRMARGIN)/(smallTicks*(nxLabels-1))), PYSIZE-YBMARGIN,
608            XLMARGIN+(int)(i*(PXSIZE-XLMARGIN-XRMARGIN)/(smallTicks*(nxLabels-1))), YTMARGIN);
609     }
610     
611     /**
612      * Draws the thresholds
613      *
614      * @param g (Graphics) Graphics device.
615      */
616     private void drawThres( Graphics g )
617     {
618         int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
619         for(int j = 0; j < np[0]-1; j++) {
620             x1 = XLMARGIN+(int)(j*xscale)+2;
621             x2 = XLMARGIN+(int)((j+1)*xscale)+2;
622             y1 = PYSIZE-YBMARGIN-(int)(maxCrit[j]*yscale)-1;
623             y2 = PYSIZE-YBMARGIN-(int)(maxCrit[j]*yscale)-1;
624             if(y1 < YTMARGIN) y1 = YTMARGIN+2;
625             if(y2 < YTMARGIN) y2 = YTMARGIN+2;
626             if(y1 != YTMARGIN+2 || y2 != YTMARGIN+2)
627                 g.drawLine(x1, y1, x2, y2);
628         }
629     }
630 
631     /**
632      * Draws the Y-Grid
633      *
634      * @param g (Graphics) Graphics device.
635      */
636     private void drawYGrid(Graphics g)
637     {
638   g.setColor(Color.lightGray);
639   for(int i = 0; i < 11; i++) {
640       if( logScale ) {
641     g.drawLine(XLMARGIN, YTMARGIN+(int)(log10(i*10)/2*(PYSIZE-YTMARGIN-YBMARGIN)),
642          PXSIZE-XRMARGIN, YTMARGIN+(int)(log10(i*10)/2*(PYSIZE-YTMARGIN-YBMARGIN)));
643       } else {
644     g.drawLine(XLMARGIN, YTMARGIN+(int)(i*((PYSIZE-YTMARGIN-YBMARGIN)/ygap)),
645          PXSIZE-XRMARGIN, YTMARGIN+(int)(i*((PYSIZE-YTMARGIN-YBMARGIN)/ygap)));
646       }
647   }
648     }
649     
650     /**
651      * Paints the graphic, with all values which were set by using setData.
652      *
653      * @param g (Graphics) graphics device.
654      */
655     public void paint(Graphics g) 
656     {  
657   // General Background
658   g.setColor( getBackground() );
659   g.fillRect( 0, 0, PXSIZE, PYSIZE );
660   
661   // Graph background
662   g.setColor(Color.white);
663   g.fill3DRect( XLMARGIN, YTMARGIN, PXSIZE-XLMARGIN-XRMARGIN, PYSIZE-YTMARGIN-YBMARGIN, true );
664 
665   // Title
666   g.setColor(titleColor);
667   FontMetrics titleFontMetrics = getFontMetrics(titleFont);
668   g.setFont(titleFont);
669   
670   g.drawString((String)title, PXSIZE/2 - titleFontMetrics.stringWidth(title)/2, 
671          YTMARGIN - titleFont.getSize() - titleFontMetrics.getDescent()+5);    
672   
673   // Data points
674   if( !fixedMinY && dataSet )
675       ymin = findMinY( yData );
676   
677   if( !fixedMaxY && dataSet )
678       ymax = findMaxY( yData );
679   
680   xscale = (double)(PXSIZE-XLMARGIN-XRMARGIN-4)/np[0];
681   yscale = (double)(PYSIZE-YTMARGIN-YBMARGIN-4)/(ymax - ymin);
682   
683   // xticks
684   drawXTicks( g );
685 
686   // xgrid
687   if(XGRID)
688       drawXGrid( g );
689   
690   // xlabels
691   g.setColor(labelColor);
692   FontMetrics xlabelFontMetrics = getFontMetrics(xLabelFont);
693   g.setFont(xLabelFont);
694   
695   for(int i = 0; i < nxLabels; i++)
696       g.drawString((String)xLabels[i], XLMARGIN+(int)(i*3*(PXSIZE-XLMARGIN-XRMARGIN)/(3*(nxLabels-1))) - 
697        xlabelFontMetrics.stringWidth(xLabels[i])/2,
698        PYSIZE-YBMARGIN + xLabelFont.getSize() + xlabelFontMetrics.getDescent());
699   
700   // yticks
701   drawYTicks( g );
702   
703   // yGrid
704   if( YGRID )
705       drawYGrid( g );
706   
707   // ylabels
708   g.setColor(labelColor);
709   FontMetrics ylabelFontMetrics = getFontMetrics(yLabelFont);
710   g.setFont(yLabelFont);
711   
712       for(int i = 0; i < 11; i++) {  
713       if( logScale ) {
714     String yLabel = String.valueOf( ymax - i * ymax / ygap );
715     if(i > 0)
716         g.drawString(yLabel, XLMARGIN - ylabelFontMetrics.stringWidth(yLabel) - 5,
717          YTMARGIN+(int)(log10(i*ygap)/2*(PYSIZE-YTMARGIN-YBMARGIN)) + 
718          yLabelFont.getSize() - ylabelFontMetrics.getDescent() - 4);
719     else
720         g.drawString(yLabel, XLMARGIN - ylabelFontMetrics.stringWidth(yLabel) - 5,
721          YTMARGIN + yLabelFont.getSize() - ylabelFontMetrics.getDescent() - 4);
722     
723       } else {
724     
725     String yLabel = String.valueOf( Math.round( ymin + i * (-ymin + ymax) / ygap) );
726     g.drawString(yLabel, 
727            XLMARGIN - ylabelFontMetrics.stringWidth(yLabel) - 5,
728            PYSIZE-YBMARGIN-(int)(i*((PYSIZE-YTMARGIN-YBMARGIN)/10)) + 
729            yLabelFont.getSize() - ylabelFontMetrics.getDescent() - 4);
730       }
731       
732   }
733   // Legend
734   FontMetrics legendFontMetrics = getFontMetrics(legendFont);
735   g.setFont(legendFont);
736   for(int i = 0; i < nHist; i++){
737       g.setColor(graphColor[i]);  
738       if(i < 4)
739     g.fillRect(XLMARGIN, PYSIZE-YBMARGIN+i*10+20, 20, 8);
740       else
741     g.fillRect(XLMARGIN+PXSIZE/2, PYSIZE-YBMARGIN+(i-4)*10+20, 20, 8);
742       
743       g.setColor(Color.black);  
744       if( i < 4 && i < legend.size() )
745     g.drawString((String)legend.elementAt(i), XLMARGIN+30,
746            PYSIZE-YBMARGIN + legendFont.getSize() + legendFontMetrics.getDescent()+i*10+15);
747       else if( i < legend.size() )
748     g.drawString((String)legend.elementAt(i), XLMARGIN+PXSIZE/2+30,
749            PYSIZE-YBMARGIN + legendFont.getSize() + legendFontMetrics.getDescent()+(i-4)*10+15);
750   }
751   
752   // Draw the graphs
753   int k = 0;
754   int x1, x2, y1, y2, ylast = 0, xlast = 0;
755   for( int i = 0; i < nHist; i++ ){
756       g.setColor( graphColor[i] );  
757       for( int j = 0; j < np[i]-1; j++, k++ ) {
758                 if( j == 0 )
759                     x1 = XLMARGIN+(int)(j*xscale)+2;
760                 else
761                     x1 = xlast;
762 
763     x2 = XLMARGIN+(int)((j+1)*xscale)+2;
764     if( logScale ) {
765         
766                     if( j == 0 )
767                         y1 = PYSIZE-YBMARGIN+(int)((log10(yData[k]/ymax))/log10(ymax)*
768                                                    (PYSIZE-YBMARGIN-YTMARGIN));        
769                     else
770                         y1 = ylast;
771 
772         y2 = PYSIZE-YBMARGIN+(int)((log10(yData[k+1]/ymax))/log10(ymax)*
773                  (PYSIZE-YBMARGIN-YTMARGIN));  
774                     
775                     g.drawLine(x1, y1, x2, y2);
776 
777     } else {
778                     if( j == 0 )
779                         y1 = PYSIZE-YBMARGIN-(int)Math.round(((-ymin+yData[k])*yscale)+1);
780                     else
781                         y1 = ylast;
782 
783         y2 = PYSIZE-YBMARGIN-(int)Math.round(((-ymin+yData[k+1])*yscale)+1);
784 
785         if(y1 < YTMARGIN) y1 = YTMARGIN+2;
786         if(y2 < YTMARGIN) y2 = YTMARGIN+2;
787         if( y1 != YTMARGIN + 2 || y2 != YTMARGIN + 2 )
788                        g.drawLine(x1, y1, x2, y2);
789     }
790                 ylast = y2;
791                 xlast = x2;
792       }
793        k++;
794   }
795 
796   // Draw the thresholds
797   if( showThres ) {
798             g.setColor( Color.red );  
799             drawThres( g );
800         }
801 
802   // Realtime
803   if( realTime && np[0] > 0) {
804       g.setColor(Color.red);
805       g.drawLine(XLMARGIN+(int)(currentTime*(PXSIZE-XLMARGIN-XRMARGIN)/np[0]), YTMARGIN,
806            XLMARGIN+(int)(currentTime*(PXSIZE-XLMARGIN-XRMARGIN)/np[0]), PYSIZE-YBMARGIN);
807   }  
808     }
809     
810     /**
811      * Calculates the minimum Y-value. The minimum will be the next following
812      * value which can be divided by 10^x. For instance if the minimum is -1
813      * the minimum value will be -10.
814      * 
815      * @param vec (double[]) value vector.
816      */
817     private double findMinY(double vec[]) {
818   
819   double min = 0.0;
820   
821   for(int i = 0; i < vec.length; i++)
822       if(vec[i] < min) min = vec[i];
823   
824   if( min > 0 )
825       return 0.0;
826 
827   for(int i = 0; i < 20; i++) {
828       if(min > -0.000001*Math.pow(10.0,(double)i)) {
829     min = -0.000001*Math.pow(10.0, (double)i);
830     break;
831       }
832   }
833   
834   return min;
835     }
836     
837     /**
838      * Determines the maximum Y-value. The maximum will be the next following
839      * value which can be divided by 10^x. For instance if the maximum is 4000
840      * the maximum value will be 10000.
841      * 
842      * @param vec (double[]) value vector.
843      */
844     private double findMaxY(double vec[]) {
845   
846   double max = 0.0;
847   
848   for(int i = 0; i < vec.length; i++)
849       if(vec[i] > max) max = vec[i];
850   
851   if( max < 0.9 )
852       return 1.0;
853   
854   for(int i = 0; i < 20; i++) {
855       if(max < 0.000001*Math.pow(10.0,(double)i)) {
856     max = 0.000001*Math.pow(10.0, (double)i);
857     break;
858       }
859   }
860   
861   return max;
862     }
863     
864     /**
865      * Deletes the histogram
866      */
867     public void del() {
868   
869   nt = 0;
870   nHist = 0;
871   legend.removeAllElements();
872   dataSet = false;
873     }
874     
875     /**
876      * Updates the histogram
877      */
878     public void histUpdate() {    
879   paint( getGraphics() );
880         if( showThres && ! running )
881             start();
882         else if( running )
883             stop();
884     }
885     
886     /**
887      * Return the title string.
888      *
889      * @return title (String) histogram title
890      */
891     public String getTitle() {
892   return(title);
893     }
894     
895     /**
896      * Return the X-Grid flag.
897      *
898      * @return xGrid (boolean) X-grid flag.
899      */
900     public boolean getXGrid() {
901   return(XGRID);
902     }
903     
904     /**
905      * Return the Y-Grid flag.
906      *
907      * @return yGrid (boolean) Y-grid flag.
908      */
909     public boolean getYGrid() {
910   return(YGRID);
911     }
912     
913     /**
914      * Return the X-size.
915      *
916      * @return xSize (int) width of the histogram.
917      */
918     public int getXSize() {
919   return(PXSIZE);
920     }
921     
922     /**
923      * Return the Y-size.
924      *
925      * @return ySize (int) height of the histogram.
926      */
927     public int getYSize() { return(PYSIZE); }
928     
929     /**
930      * Returns the maximum fixed-Y flag.
931      *
932      * @return fixedMaxY (boolean) fixed-Y flag.
933      */
934     public boolean getFixedMaxY() { return(fixedMaxY); }
935     
936     /**
937      * Returns the minimum fixed-Y flag.
938      *
939      * @return fixedMinY (boolean) fixed minimum Y flag.
940      */
941     public boolean getFixedMinY() { return(fixedMinY); }
942     
943     /**
944      * Return the minimum Y value.
945      *
946      * @return ymin (double) minimum Y value.
947      */
948     public double getYmin() { return(ymin); }
949     
950     /**
951      * Return the maximum Y value.
952      *
953      * @return ymax (double) maximum Y value.
954      */
955     public double getYmax() { return(ymax); }
956     
957     /**
958      * Return the log scale flag.
959      *
960      * @return logScale (boolean) logScale flag.
961      */
962     public boolean getLogScale() { return logScale; }
963     
964     /**
965      * Return the show threshold flag.
966      *
967      * @return showThres (boolean) show threshold flag.
968      */
969     public boolean getShowThres() { return showThres; }
970     
971     /**
972      * Return the legend.
973      *
974      * @param index (int) index of the legend string.
975      * @return legend (String) legend string.
976      */
977     public String getLegend( int index ) { return( ( String )legend.elementAt( index )); }  
978 
979     /**
980      * Returns a image of the current plot
981      *
982      * @return img (Image) the image of the current histogram.
983      */
984     public Image getImage()
985     {
986   Image image = createImage( PXSIZE, PYSIZE );
987   paint( image.getGraphics() );
988   return image;
989     }
990 
991     public void run()
992     {
993         running = true;
994 
995         Graphics g = getGraphics();
996         g.setPaintMode();
997         g.setXORMode( Color.red );
998         while( histoThread == Thread.currentThread() ) {
999       
1000            drawThres( g );
1001            
1002      try {
1003    
1004    Thread.sleep( 1000 );
1005    
1006      } catch (InterruptedException e) {
1007      }
1008  }
1009    }
1010
1011    /**
1012     * Starts the blinking thread.
1013     */
1014    public void start() 
1015    {  
1016  // Start the histo thread.
1017  histoThread = new Thread( this );
1018  histoThread.start();
1019    }
1020    
1021    /**
1022     * Stops the thread.
1023     */
1024    public void stop() 
1025    {  
1026  // Stop the Chart thread.
1027  histoThread = null;
1028    }
1029}
1030
1031