KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > excalibur > instrument > client > LineChart


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. 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
14  * implied.
15  *
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */

19
20 package org.apache.excalibur.instrument.client;
21
22 import java.awt.Color JavaDoc;
23 import java.awt.Dimension JavaDoc;
24 import java.awt.FontMetrics JavaDoc;
25 import java.awt.Graphics JavaDoc;
26 import java.awt.Graphics2D JavaDoc;
27 import java.awt.Insets JavaDoc;
28 import java.awt.RenderingHints JavaDoc;
29 import java.awt.event.MouseEvent JavaDoc;
30 import java.awt.event.MouseListener JavaDoc;
31 import java.awt.event.MouseMotionListener JavaDoc;
32 import java.text.DecimalFormat JavaDoc;
33 import java.text.MessageFormat JavaDoc;
34 import java.util.Calendar JavaDoc;
35 import java.util.Date JavaDoc;
36
37 import javax.swing.JComponent JavaDoc;
38
39 /**
40  * Draws a nice pretty chart given a set of data.
41  *
42  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
43  */

44 public class LineChart
45     extends JComponent JavaDoc
46     implements MouseListener JavaDoc, MouseMotionListener JavaDoc
47 {
48     /** Stores the time-zone offset for this JVM. */
49     private static long m_zoneOffset;
50     
51     private Color JavaDoc m_lineColor = Color.red;
52     private Color JavaDoc m_lightLineColor = new Color JavaDoc( 255, 128, 128 );
53     private Color JavaDoc m_lightGridColor = new Color JavaDoc( 192, 192, 192 );
54     private Color JavaDoc m_darkGridColor = new Color JavaDoc( 128, 128, 128 );
55     private Color JavaDoc m_frameColor = Color.black;
56     private Color JavaDoc m_crossColor = Color.blue;
57     private Color JavaDoc m_maskFrameColor = new Color JavaDoc( 128, 128, 255, 192 );
58     private Color JavaDoc m_maskColor = new Color JavaDoc( 224, 224, 255, 192 );
59
60     /** Number of sample points between vertical lines. */
61     private int m_lineSampleInterval;
62
63     /** The number of milliseconds represented by each data sample. */
64     private long m_sampleInterval;
65
66     /**
67      * Format of the text which is displayed along the x (time) axis of the
68      * chart.
69      */

70     private String JavaDoc m_format;
71
72     /**
73      * Format of the text which is displayed over the component as
74      * the user moves the mouse over the line chart.
75      */

76     private String JavaDoc m_dFormat;
77
78     /** Number of sample points to use when calculating the moving average. */
79     private int m_averageWindow;
80     
81     /** True if Antialiasing should be used when rendering the chart. */
82     private boolean m_antialias;
83     
84     /** Time of the last sample point. */
85     private long m_time;
86
87     /** Sample point data. */
88     private int[] m_values;
89
90     /** Moving average of the sample point data. */
91     private float[] m_averageWindowValues;
92
93     /** Minimum value in m_values. */
94     private int m_min;
95
96     /** Maximum value in m_values. */
97     private int m_max;
98
99     /** Integer number format. */
100     private DecimalFormat JavaDoc m_intFormat = new DecimalFormat JavaDoc( "###,###,###,##0" );
101
102     /** Decimal number format. */
103     private DecimalFormat JavaDoc m_floatFormat = new DecimalFormat JavaDoc( "###,###,###,##0.00" );
104
105     private boolean m_mouseOver;
106     private boolean m_mousePressed;
107     private int m_mouseX;
108     private int m_mouseY;
109
110     /*---------------------------------------------------------------
111      * Static Initializer
112      *-------------------------------------------------------------*/

113     static
114     {
115         Calendar JavaDoc now = Calendar.getInstance();
116         m_zoneOffset = now.get( Calendar.ZONE_OFFSET );
117     }
118
119     /*---------------------------------------------------------------
120      * Constructor
121      *-------------------------------------------------------------*/

122     /**
123      * @param lineSampleInterval The interval in data points at which to place vertical
124      * lines and labels along the x (time) axis.
125      * @param sampleInterval The number of milliseconds represented by each data sample.
126      * @param format Format of the text which is displayed along the x (time) axis of
127      * the chart. The text will display the time of the line chart at a particular
128      * interval. The text should take the format "{0}/{1}/{2} {3}:{4}:{5}.{6}" where
129      * {0} is replaced by the year, {1} by the month, {2} by the day, {3} by the hour,
130      * {4} by the minute, {5} by the second, and {6} by the hundereths of a second.
131      * @param detailFormat Format of the text which is displayed over the component as
132      * the user moves the mouse over the line chart. The text will display the exact
133      * value of the line chart at a particular point. The text should take the format
134      * "{0}/{1}/{2} {3}:{4}:{5}.{6}" where {0} is replaced by the year, {1} by the
135      * month, {2} by the day, {3} by the hour, {4} by the minute, {5} by the second,
136      * and {6} by the hundereths of a second.
137      * @param averageWindow Number of data points to do a moving average over when the
138      * mouse is pressed on the component.
139      * @param antialias True if Antialiasing should be used when rendering the chart.
140      */

141     public LineChart( int lineSampleInterval,
142                       long sampleInterval,
143                       String JavaDoc format,
144                       String JavaDoc detailFormat,
145                       int averageWindow,
146                       boolean antialias )
147     {
148         m_lineSampleInterval = lineSampleInterval;
149         m_sampleInterval = sampleInterval;
150         m_format = format;
151         m_dFormat = detailFormat;
152         m_averageWindow = averageWindow;
153         m_antialias = antialias;
154
155         setBackground( Color.white );
156         setValues( new int[ 0 ], System.currentTimeMillis() );
157         addMouseListener( this );
158         addMouseMotionListener( this );
159     }
160
161     /*---------------------------------------------------------------
162      * Methods
163      *-------------------------------------------------------------*/

164     /**
165      * Sets the antialias flag to control whether or not antialiasing will be
166      * used when rendering the component.
167      *
168      * @param antialias True to use antialiasing.
169      */

170     public void setAntialias( boolean antialias )
171     {
172         m_antialias = antialias;
173     }
174     
175     /**
176      * Sets the data samples to be displayed by the line chart.
177      *
178      * @param values Array of data samples.
179      * @param time The time of the start of the last sample point.
180      */

181     public void setValues( int[] values, long time )
182     {
183         int max = 0;
184         int min = Integer.MAX_VALUE;
185         for( int i = 0; i < values.length; i++ )
186         {
187             int v = values[ i ];
188             if( v > max )
189             {
190                 max = v;
191             }
192             if( v < min )
193             {
194                 min = v;
195             }
196         }
197         if( ( max - min ) < 10 )
198         {
199             max += ( ( 10 - ( max - min ) ) / 2 );
200             min -= ( 10 - ( max - min ) );
201         }
202         if( min < 0 )
203         {
204             max += -min;
205             min = 0;
206         }
207
208         float[] averageValues = new float[ values.length ];
209         if( m_averageWindow > 1 )
210         {
211             int total = 0;
212             for( int i = 0; i < values.length; i++ )
213             {
214                 total += values[ i ];
215                 if( i >= m_averageWindow - 1 )
216                 {
217                     if( i >= m_averageWindow )
218                     {
219                         total -= values[ i - m_averageWindow ];
220                     }
221                     averageValues[ i ] = (float)total / m_averageWindow;
222                 }
223                 else
224                 {
225                     averageValues[ i ] = Float.MIN_VALUE;
226                 }
227             }
228         }
229
230         synchronized( this )
231         {
232             m_time = time;
233             m_values = values;
234             m_averageWindowValues = averageValues;
235             m_min = min;
236             m_max = max;
237         }
238
239         repaint();
240     }
241
242     private String JavaDoc getFormattedTime( Date JavaDoc dTime, boolean detailed )
243     {
244         Calendar JavaDoc calendar = Calendar.getInstance();
245         calendar.setTime( dTime );
246
247         int v;
248         String JavaDoc year, month, day, hour, minute, second, hundreths;
249
250         // Substitute the year
251
v = calendar.get( Calendar.YEAR );
252         year = Integer.toString( v );
253         
254         // Substitute the month
255
v = calendar.get( Calendar.MONTH ) - Calendar.JANUARY + 1;
256         if( v < 10 )
257         {
258             month = "0" + Integer.toString( v );
259         }
260         else
261         {
262             month = Integer.toString( v );
263         }
264
265         // Substitute the Day
266
v = calendar.get( Calendar.DAY_OF_MONTH );
267         if( v < 10 )
268         {
269             day = "0" + Integer.toString( v );
270         }
271         else
272         {
273             day = Integer.toString( v );
274         }
275
276         // Substitute the Hour
277
v = calendar.get( Calendar.HOUR_OF_DAY );
278         if( v < 10 )
279         {
280             hour = "0" + Integer.toString( v );
281         }
282         else
283         {
284             hour = Integer.toString( v );
285         }
286
287         // Substitute the Minute
288
v = calendar.get( Calendar.MINUTE );
289         if( v < 10 )
290         {
291             minute = "0" + Integer.toString( v );
292         }
293         else
294         {
295             minute = Integer.toString( v );
296         }
297
298         // Substitute the Second
299
v = calendar.get( Calendar.SECOND );
300         if( v < 10 )
301         {
302             second = "0" + Integer.toString( v );
303         }
304         else
305         {
306             second = Integer.toString( v );
307         }
308
309         // Substitute the Hudreths of a Second
310
v = calendar.get( Calendar.MILLISECOND ) / 10;
311         if( v < 10 )
312         {
313             hundreths = "0" + Integer.toString( v );
314         }
315         else
316         {
317             hundreths = Integer.toString( v );
318         }
319
320         String JavaDoc format;
321         if( detailed )
322         {
323             format = MessageFormat.format( m_dFormat,
324                 new Object JavaDoc[]{year, month, day, hour, minute, second, hundreths} );
325         }
326         else
327         {
328             format = MessageFormat.format( m_format,
329                 new Object JavaDoc[]{year, month, day, hour, minute, second, hundreths} );
330         }
331         return format;
332     }
333     
334     /**
335      * Draws the horizontal lines which make up the background of the chart.
336      *
337      * @param g Graphics object to paint with.
338      * @param yLabelInterval Interval at which the lines should be labeled.
339      * @param fontHeight The height of the current font.
340      * @param chartLeft Left edge of the chart.
341      * @param chartTop Top edge of the chart.
342      * @param chartWidth Width of the chart.
343      * @param chartHeight Height of the chart.
344      */

345     private void paintHorizontalGrid( Graphics JavaDoc g,
346                                       int yLabelInterval,
347                                       int fontHeight,
348                                       int chartLeft,
349                                       int chartTop,
350                                       int chartWidth,
351                                       int chartHeight )
352     {
353         if( chartHeight > 0 )
354         {
355             int horizonalLineLabeledInterval = (int)Math.ceil( (float)fontHeight
356                 / ( (long)yLabelInterval * chartHeight / ( m_max - m_min ) ) );
357             int horizontalLineNumber = 0;
358             for( int i = ( (int)Math.ceil( (float)m_min / yLabelInterval ) ) * yLabelInterval;
359                  i < m_max; i += yLabelInterval )
360             {
361                 // Calculate the location of the line on the y-axis. Be careful
362
// of very large numbers.
363
int y = chartTop + chartHeight -
364                     (int)( (long)chartHeight * ( i - m_min ) / ( m_max - m_min ) );
365
366                 if( horizontalLineNumber >= horizonalLineLabeledInterval )
367                 {
368                     horizontalLineNumber = 0;
369                 }
370                 if( horizontalLineNumber == 0 )
371                 {
372                     String JavaDoc lbl = m_intFormat.format( i );
373                     g.setColor( m_frameColor );
374                     g.drawString( lbl, chartLeft - 5 - g.getFontMetrics().stringWidth( lbl ),
375                                   y + ( fontHeight >> 1 ) );
376
377                     g.setColor( m_darkGridColor );
378                 }
379                 else
380                 {
381                     g.setColor( m_lightGridColor );
382                 }
383                 horizontalLineNumber++;
384
385                 if( chartWidth > 0 )
386                 {
387                     g.drawLine( chartLeft, y, chartLeft + chartWidth, y );
388                 }
389             }
390         }
391     }
392
393     /**
394      * Draws the vertical lines which make up the background of the chart.
395      *
396      * @param g Graphics object to paint with.
397      * @param fontHeight The height of the current font.
398      * @param chartLeft Left edge of the chart.
399      * @param chartTop Top edge of the chart.
400      * @param chartWidth Width of the chart.
401      * @param chartHeight Height of the chart.
402      */

403     private void paintVerticalGrid( Graphics JavaDoc g,
404                                     int fontHeight,
405                                     int chartLeft,
406                                     int chartTop,
407                                     int chartWidth,
408                                     int chartHeight )
409     {
410         if( chartWidth > 0 )
411         {
412             FontMetrics JavaDoc fontMetrics = g.getFontMetrics();
413             
414             // Figure out how wide a label is for formatting.
415
String JavaDoc format = MessageFormat.format( m_format, new String JavaDoc[]{"00", "00", "00", "00"} );
416             int fw = fontMetrics.stringWidth( format ) + 10;
417
418             // Figure out what internal of lines we can place labels under.
419
int verticalLineLabeledInterval;
420             if( ( m_values.length > 0 ) && ( chartWidth > 0 ) )
421             {
422                 verticalLineLabeledInterval = (int)Math.ceil(
423                     (float)fw / ( m_lineSampleInterval * chartWidth / ( m_values.length ) ) );
424             }
425             else
426             {
427                 verticalLineLabeledInterval = 1;
428             }
429
430             // Calculate a base time for drawing the vertical lines.
431
long baseTime = ( ( m_time - m_values.length * m_sampleInterval ) /
432                 ( m_sampleInterval * m_lineSampleInterval ) ) *
433                 ( m_sampleInterval * m_lineSampleInterval ) - m_zoneOffset;
434
435             // Draw each of the lines.
436
int verticalLineNumber = 0;
437             for( int i = 0; i < m_values.length; i++ )
438             {
439                 long time = m_time - ( m_values.length - i - 1 ) * m_sampleInterval;
440                 if( ( ( ( time - baseTime ) / m_sampleInterval ) % m_lineSampleInterval ) == 0 )
441                 {
442                     int x = chartLeft + i * chartWidth / ( m_values.length - 1 );
443
444                     // Draw a label under the line if line should have a label.
445
if( ( verticalLineNumber >= verticalLineLabeledInterval ) ||
446                         ( verticalLineNumber == 0 ) )
447                     {
448                         format = getFormattedTime( new Date JavaDoc( time ), false );
449
450                         if( x - fontMetrics.stringWidth( format ) / 2 >= chartLeft )
451                         {
452                             g.setColor( m_frameColor );
453                             g.drawString( format, x - fontMetrics.stringWidth( format ) / 2,
454                                           chartTop + chartHeight + fontHeight );
455
456                             g.setColor( m_darkGridColor );
457                             verticalLineNumber = 1;
458                         }
459                         else
460                         {
461                             g.setColor( m_lightGridColor );
462                         }
463                     }
464                     else
465                     {
466                         g.setColor( m_lightGridColor );
467                         verticalLineNumber++;
468                     }
469
470                     // Draw the vertical line
471
if( chartHeight > 0 )
472                     {
473                         g.drawLine( x, chartTop, x, chartTop + chartHeight );
474                     }
475                 }
476             }
477         }
478     }
479     
480     /**
481      * Draws the frame around the whole chart.
482      *
483      * @param g Graphics object to paint with.
484      * @param chartLeft Left edge of the chart.
485      * @param chartTop Top edge of the chart.
486      * @param chartWidth Width of the chart.
487      * @param chartHeight Height of the chart.
488      */

489     private void paintFrame( Graphics JavaDoc g,
490                              int chartLeft,
491                              int chartTop,
492                              int chartWidth,
493                              int chartHeight )
494     {
495         if( ( chartWidth > 0 ) && ( chartHeight > 0 ) )
496         {
497             g.setColor( m_frameColor );
498             g.drawLine( chartLeft, chartTop, chartLeft, chartTop + chartHeight );
499             g.drawLine( chartLeft, chartTop + chartHeight, chartLeft + chartWidth,
500                         chartTop + chartHeight );
501         }
502     }
503     
504     /**
505      * Draws the data values which to be displayed in the chart.
506      *
507      * @param g Graphics object to paint with.
508      * @param chartLeft Left edge of the chart.
509      * @param chartTop Top edge of the chart.
510      * @param chartWidth Width of the chart.
511      * @param chartHeight Height of the chart.
512      */

513     private void paintValues( Graphics JavaDoc g,
514                               int chartLeft,
515                               int chartTop,
516                               int chartWidth,
517                               int chartHeight )
518     {
519         if( ( m_averageWindow > 0 ) && ( m_mousePressed ) )
520         {
521             g.setColor( m_lightLineColor );
522         }
523         else
524         {
525             g.setColor( m_lineColor );
526         }
527
528         int lastX = 0;
529         int lastY = 0;
530         for( int i = 0; i < m_values.length; i++ )
531         {
532             // Calculate the location of the point on the x-axis.
533
int x = chartLeft + i * chartWidth / ( m_values.length - 1 );
534
535             // Calculate the location of the line on the y-axis. Be careful
536
// of very large numbers.
537
int y = chartTop + chartHeight -
538                 (int)( (long)chartHeight * ( m_values[ i ] - m_min ) / ( m_max - m_min ) );
539
540             if( i > 0 )
541             {
542                 g.drawLine( lastX, lastY, x, y );
543             }
544
545             lastX = x;
546             lastY = y;
547         }
548         
549         // Draw the averaged values of the chart
550
if( ( m_averageWindow > 0 ) && ( m_mousePressed ) )
551         {
552             g.setColor( m_lineColor );
553             lastX = 0;
554             lastY = 0;
555             for( int i = m_averageWindow; i < m_averageWindowValues.length; i++ )
556             {
557                 // Calculate the location of the point on the x-axis.
558
int x = chartLeft + i * chartWidth / ( m_averageWindowValues.length - 1 );
559
560                 // Calculate the location of the line on the y-axis. Be careful of very large
561
// numbers. The float value average valus makes this easy here.
562
int y = chartTop + chartHeight -
563                     (int)( chartHeight * ( m_averageWindowValues[ i ] - m_min ) /
564                     ( m_max - m_min ) );
565
566                 if( i > m_averageWindow )
567                 {
568                     g.drawLine( lastX, lastY, x, y );
569                 }
570
571                 lastX = x;
572                 lastY = y;
573             }
574         }
575     }
576     
577     /**
578      * Draws the overlay label at the specified location.
579      *
580      * @param g Graphics object to paint with.
581      * @param fontHeight The height of the current font.
582      * @param chartLeft Left edge of the chart.
583      * @param chartTop Top edge of the chart.
584      * @param chartWidth Width of the chart.
585      * @param chartHeight Height of the chart.
586      */

587     private void paintOverlayAt( Graphics JavaDoc g,
588                                  int fontHeight,
589                                  int chartLeft,
590                                  int chartTop,
591                                  int chartWidth,
592                                  int chartHeight,
593                                  int mouseDataPointX,
594                                  int mouseDataPointY,
595                                  String JavaDoc mouseDataPointValue,
596                                  long mouseDataPointTime )
597     {
598         // Draw a cross at the point being to be labeled.
599
g.setColor( m_crossColor );
600         g.drawLine(
601             mouseDataPointX, chartTop, mouseDataPointX, chartTop + chartHeight );
602         g.drawLine(
603             chartLeft, mouseDataPointY, chartLeft + chartWidth, mouseDataPointY );
604
605         // Get the text of the label
606
String JavaDoc mouseDataPointLabel = mouseDataPointValue + " : " +
607             getFormattedTime( new Date JavaDoc( mouseDataPointTime ), true );
608         int mouseDataPointLabelWidth =
609             g.getFontMetrics().stringWidth( mouseDataPointLabel );
610         int mouseDataPointLabelLeft;
611         int mouseDataPointLabelTop;
612
613         // If the point is near the edges of the chart, then it
614
// would run off the chart. To avoid this, the label is
615
// moved around relative to the location of the cross.
616
// Decide where it should go.
617
if( mouseDataPointX + 5 + mouseDataPointLabelWidth < chartLeft + chartWidth )
618         {
619             // Ok on the right
620
mouseDataPointLabelLeft = mouseDataPointX + 4;
621             if( mouseDataPointY + 5 + fontHeight < chartTop + chartHeight )
622             {
623                 // Ok on the bottom
624
mouseDataPointLabelTop = mouseDataPointY + 4;
625             }
626             else
627             {
628                 // Must go on the top
629
mouseDataPointLabelTop = mouseDataPointY - 4 - fontHeight;
630             }
631         }
632         else
633         {
634             // Must go on the left
635
mouseDataPointLabelLeft = mouseDataPointX - 4 - mouseDataPointLabelWidth;
636             if( mouseDataPointY + 5 + fontHeight < chartTop + chartHeight )
637             {
638                 // Ok on the bottom
639
mouseDataPointLabelTop = mouseDataPointY + 4;
640             }
641             else
642             {
643                 // Must go on the top
644
mouseDataPointLabelTop = mouseDataPointY - 4 - fontHeight;
645             }
646         }
647
648         // Draw an outline around the location of the label.
649
g.setColor( m_maskFrameColor );
650         g.drawRect( mouseDataPointLabelLeft - 1, mouseDataPointLabelTop - 1,
651                     mouseDataPointLabelWidth + 2, fontHeight + 2 );
652
653         // Draw the background of the label. By default this is partly transparent and
654
// looks better on top of the outline.
655
g.setColor( m_maskColor );
656         g.fillRect( mouseDataPointLabelLeft - 1, mouseDataPointLabelTop - 1,
657                     mouseDataPointLabelWidth + 2, fontHeight + 2 );
658
659         // Draw the text of the label.
660
g.setColor( m_crossColor );
661         g.drawString( mouseDataPointLabel, mouseDataPointLabelLeft,
662                       mouseDataPointLabelTop + fontHeight );
663     }
664     
665     /**
666      * Draws the overlay label at the mouse location.
667      *
668      * @param g Graphics object to paint with.
669      * @param fontHeight The height of the current font.
670      * @param chartLeft Left edge of the chart.
671      * @param chartTop Top edge of the chart.
672      * @param chartWidth Width of the chart.
673      * @param chartHeight Height of the chart.
674      */

675     private void paintOverlay( Graphics JavaDoc g,
676                                int fontHeight,
677                                int chartLeft,
678                                int chartTop,
679                                int chartWidth,
680                                int chartHeight )
681     {
682         if( ( m_mouseOver ) && ( m_mouseX >= chartLeft ) &&
683             ( m_mouseX <= chartLeft + chartWidth ) )
684         {
685             // Figure out the index of the data point where the mouse is.
686
int index = (int)Math.round(
687                 (float)( m_values.length - 1 ) * ( m_mouseX - chartLeft ) / chartWidth );
688
689             // Draw the label
690
int mouseDataPointX = 0;
691             int mouseDataPointY = 0;
692             String JavaDoc mouseDataPointValue = null;
693             long mouseDataPointTime = 0;
694             boolean showLabel = false;
695
696             if( ( m_averageWindow > 0 ) && ( m_mousePressed ) )
697             {
698                 if( ( index >= m_averageWindow ) && ( index < m_averageWindowValues.length ) )
699                 {
700                     // Draw the label for the average data
701

702                     // Calculate the location of the point on the x-axis.
703
mouseDataPointX = chartLeft + index * chartWidth /
704                         ( m_averageWindowValues.length - 1 );
705
706                     // Calculate the location of the line on the y-axis. Be
707
// careful of very large numbers. The float value
708
// average valus makes this easy here.
709
mouseDataPointY = chartTop + chartHeight -
710                         (int)( chartHeight * ( m_averageWindowValues[ index ] - m_min ) /
711                         ( m_max - m_min ) );
712
713                     // Round the average value to 2 decimal places.
714
mouseDataPointValue =
715                         m_floatFormat.format( m_averageWindowValues[ index ] );
716
717                     // Get the time at the mouse data point
718
mouseDataPointTime = m_time -
719                         ( m_averageWindowValues.length - index - 1 ) * m_sampleInterval;
720
721                     showLabel = true;
722                 }
723             }
724             else
725             {
726                 if( ( index >= 0 ) && ( index < m_values.length ) )
727                 {
728                     // Draw the label for the regular data.
729

730                     // Calculate the location of the point on the x-axis.
731
mouseDataPointX =
732                         chartLeft + index * chartWidth / ( m_values.length - 1 );
733
734                     // Calculate the location of the line on the y-axis.
735
// Be careful of very large numbers.
736
mouseDataPointY = chartTop + chartHeight -
737                         (int)( (long)chartHeight * ( m_values[ index ] - m_min ) /
738                         ( m_max - m_min ) );
739
740                     // Get the average value.
741
mouseDataPointValue = m_intFormat.format( m_values[ index ] );
742
743                     // Get the time at the mouse data point
744
mouseDataPointTime = m_time - ( m_values.length - index - 1 ) *
745                         m_sampleInterval;
746
747                     showLabel = true;
748                 }
749             }
750
751             if( showLabel )
752             {
753                 paintOverlayAt( g, fontHeight, chartLeft, chartTop, chartWidth,
754                     chartHeight, mouseDataPointX, mouseDataPointY, mouseDataPointValue,
755                     mouseDataPointTime );
756             }
757         }
758     }
759     
760     /**
761      * Paints the component.
762      *
763      * @param g Graphics to paint the chart onto.
764      */

765     public synchronized void paintComponent( Graphics JavaDoc g )
766     {
767         Dimension JavaDoc size = getSize();
768         Insets JavaDoc insets = getInsets();
769         
770         // If we directly test whether g is a Graphics2D using instanceof then the class
771
// must exist. If it exists then it will be a Graphics2D.
772
if ( g.getClass().getName().indexOf( "Graphics2D" ) >= 0 )
773         {
774             Graphics2D JavaDoc g2 = (Graphics2D JavaDoc)g;
775             if ( m_antialias )
776             {
777                 g2.setRenderingHint(
778                     RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
779             }
780             else
781             {
782                 g2.setRenderingHint(
783                     RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
784             }
785         }
786
787         g.setColor( getBackground() );
788         g.fillRect( insets.left, insets.top, size.width - insets.left - insets.right,
789                     size.height - insets.top - insets.bottom );
790
791         // Resolve the vertical interval
792
int yLabelInterval = 1;
793         while( ( m_max - m_min ) / yLabelInterval > 20 )
794         {
795             yLabelInterval *= 10;
796         }
797
798         FontMetrics JavaDoc fontMetrics = g.getFontMetrics();
799         int maxYLabelWidth = fontMetrics.stringWidth( m_intFormat.format( m_max ) );
800         int fontHeight = fontMetrics.getAscent();
801         int fontHalfHeight = fontHeight / 2;
802
803         int chartLeft = insets.left + maxYLabelWidth + 5;
804         int chartTop = insets.top + 5;
805         int chartWidth = size.width - chartLeft - insets.right - 1 - 5;
806         int chartHeight = size.height - chartTop - insets.bottom - 1 - fontHeight;
807
808         // Draw the horizontal grid (Left to Right lines)
809
paintHorizontalGrid( g, yLabelInterval, fontHeight, chartLeft, chartTop,
810             chartWidth, chartHeight );
811
812         // Draw the vertical grid (Top to Bottom lines)
813
if ( m_values.length > 1 )
814         {
815             paintVerticalGrid( g, fontHeight, chartLeft, chartTop, chartWidth, chartHeight );
816         }
817
818         // Draw the frame
819
paintFrame( g, chartLeft, chartTop, chartWidth, chartHeight );
820         
821         if( ( chartWidth > 0 ) && ( chartHeight > 0 ) && ( m_values.length > 1 ) )
822         {
823             // Draw the the values that make up the data of the chart.
824
paintValues( g, chartLeft, chartTop, chartWidth, chartHeight );
825
826
827             // Make the label visible if the user tracks over any part of the chart.
828
paintOverlay( g, fontHeight, chartLeft, chartTop, chartWidth, chartHeight );
829         }
830     }
831
832     /*---------------------------------------------------------------
833      * MouseListener Methods
834      *-------------------------------------------------------------*/

835     /**
836      * Called when the mouse is clicked ont the component.
837      *
838      * @param event Event which describes the action.
839      */

840     public void mouseClicked( MouseEvent JavaDoc event )
841     {
842     }
843
844     /**
845      * Called when the mouse is pressed ont the component.
846      *
847      * @param event Event which describes the action.
848      */

849     public void mousePressed( MouseEvent JavaDoc event )
850     {
851         m_mousePressed = true;
852     }
853
854     /**
855      * Called when the mouse is released ont the component.
856      *
857      * @param event Event which describes the action.
858      */

859     public void mouseReleased( MouseEvent JavaDoc event )
860     {
861         m_mousePressed = false;
862     }
863
864     /**
865      * Called when the mouse is enters the component.
866      *
867      * @param event Event which describes the action.
868      */

869     public void mouseEntered( MouseEvent JavaDoc event )
870     {
871         m_mouseOver = true;
872         repaint();
873     }
874
875     /**
876      * Called when the mouse is exits the component.
877      *
878      * @param event Event which describes the action.
879      */

880     public void mouseExited( MouseEvent JavaDoc event )
881     {
882         m_mouseOver = false;
883         repaint();
884     }
885
886     /*---------------------------------------------------------------
887      * MouseMotionListener Methods
888      *-------------------------------------------------------------*/

889     /**
890      * Called when the mouse is dragged over the component.
891      *
892      * @param event Event which describes the motion.
893      */

894     public void mouseDragged( MouseEvent JavaDoc event )
895     {
896         m_mouseX = event.getX();
897         m_mouseY = event.getY();
898         repaint();
899     }
900
901     /**
902      * Called when the mouse is moved over the component.
903      *
904      * @param event Event which describes the motion.
905      */

906     public void mouseMoved( MouseEvent JavaDoc event )
907     {
908         m_mouseX = event.getX();
909         m_mouseY = event.getY();
910         repaint();
911     }
912 }
913
914
Popular Tags