KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > actions > HeapView


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.openide.actions;
21
22 import java.awt.AWTEvent JavaDoc;
23 import java.awt.AlphaComposite JavaDoc;
24 import java.awt.Color JavaDoc;
25 import java.awt.Composite JavaDoc;
26 import java.awt.Dimension JavaDoc;
27 import java.awt.Font JavaDoc;
28 import java.awt.FontMetrics JavaDoc;
29 import java.awt.GradientPaint JavaDoc;
30 import java.awt.Graphics JavaDoc;
31 import java.awt.Graphics2D JavaDoc;
32 import java.awt.Image JavaDoc;
33 import java.awt.event.ActionEvent JavaDoc;
34 import java.awt.event.ActionListener JavaDoc;
35 import java.awt.event.MouseEvent JavaDoc;
36 import java.awt.image.BufferedImage JavaDoc;
37 import java.awt.image.ConvolveOp JavaDoc;
38 import java.awt.image.Kernel JavaDoc;
39 import java.text.MessageFormat JavaDoc;
40 import javax.swing.JCheckBoxMenuItem JavaDoc;
41 import javax.swing.JComponent JavaDoc;
42 import javax.swing.JLabel JavaDoc;
43 import javax.swing.JPopupMenu JavaDoc;
44 import javax.swing.SwingUtilities JavaDoc;
45 import javax.swing.Timer JavaDoc;
46 import org.openide.util.NbBundle;
47
48 /**
49  *
50  * @author sky, radim
51  */

52 class HeapView extends JComponent JavaDoc {
53     private static final boolean AUTOMATIC_REFRESH = System.getProperty("org.netbeans.log.startup") == null;
54
55     /**
56      * Style for overlay on top of grid.
57      */

58     private static final int STYLE_DEFAULT = 0;
59     
60     /**
61      * Grid overlayed on top of heap. This is the default.
62      */

63     private static final int STYLE_OVERLAY = 1;
64     
65     /*
66      * How often the display is updated.
67      */

68     private static final int TICK = 1500;
69     
70     /**
71      * Time (in ms) to animate heap growing.
72      */

73     private static final int HEAP_GROW_ANIMATE_TIME = 1000;
74     
75     /**
76      * Width of the border.
77      */

78     private static final int BORDER_W = 2;
79     
80     /**
81      * Height of the border area.
82      */

83     private static final int BORDER_H = 4;
84     
85     /**
86      * Colors for the grid. This is alternating pairs for a linear gradient.
87      */

88     private static final Color JavaDoc[] GRID_COLORS = new Color JavaDoc[] { // FIXME
89
new Color JavaDoc(0xE3DFCF), new Color JavaDoc(0xE7E4D3),
90         new Color JavaDoc(0xDAD7C6), new Color JavaDoc(0xDFDCCB),
91         new Color JavaDoc(0xD3CFBF), new Color JavaDoc(0xD7D3C3),
92         new Color JavaDoc(0xCECABA), new Color JavaDoc(0xD0CCBC)
93     };
94     
95     /**
96      * Border color.
97      */

98     private static final Color JavaDoc BORDER1_COLOR = new Color JavaDoc(0xA6A295);
99
100     /**
101      * Border color of line below the top.
102      */

103     private static final Color JavaDoc BORDER2_COLOR = new Color JavaDoc(0xC0BCAD);
104     
105     /**
106      * Start color for the tick gradient.
107      */

108     private static final Color JavaDoc MIN_TICK_COLOR = new Color JavaDoc(0xC7D6AD);
109
110     /**
111      * End color for the tick gradient.
112      */

113     private static final Color JavaDoc MAX_TICK_COLOR = new Color JavaDoc(0x615d0f);
114
115     /**
116      * Color for the text before blurred.
117      */

118     private static final Color JavaDoc TEXT_BLUR_COLOR = Color.WHITE;
119     
120     /**
121      * Color for text drawn on top of blurred text.
122      */

123     private static final Color JavaDoc TEXT_COLOR = Color.WHITE;
124
125     /**
126      * Start color for the background gradient.
127      */

128     private static final Color JavaDoc BACKGROUND1_COLOR = new Color JavaDoc(0xD0CCBC);
129
130     /**
131      * End color for the background gradient.
132      */

133     private static final Color JavaDoc BACKGROUND2_COLOR = new Color JavaDoc(0xEAE7D7);
134     
135     /**
136      * Size used for Kernel used to generate drop shadow.
137      */

138     private static final int KERNEL_SIZE = 3;
139
140     /**
141      * Factor used for Kernel used to generate drop shadow.
142      */

143     private static final float BLUR_FACTOR = 0.1f;
144     
145     /**
146      * How far to shift the drop shadow along the horizontal axis.
147      */

148     private static final int SHIFT_X = 0;
149
150     /**
151      * How far to shift the drop shadow along the vertical axis.
152      */

153     private static final int SHIFT_Y = 1;
154     
155     /**
156      * Used to generate drop shadown.
157      */

158     private final ConvolveOp JavaDoc blur;
159     
160     /**
161      * MessageFormat used to generate text.
162      */

163     private final MessageFormat JavaDoc format;
164     
165     /**
166      * Whether or not to show a drop shadow.
167      */

168     private boolean showDropShadow;
169     
170     /**
171      * Style to render things in.
172      */

173     private int tickStyle;
174
175     /**
176      * Whether or not text is shown.
177      */

178     private boolean showText;
179
180     /**
181      * Data for the graph as a percentage of the heap used.
182      */

183     private float[] graph;
184     
185     /**
186      * Index into graph for the next tick.
187      */

188     private int graphIndex;
189     
190     /**
191      * If true, graph contains all valid data, otherwise valid data starts at
192      * 0 and ends at graphIndex - 1.
193      */

194     private boolean graphFilled;
195     
196     /**
197      * Last total heap size.
198      */

199     private long lastTotal;
200     
201     /**
202      * Timer used to update data.
203      */

204     private Timer JavaDoc updateTimer;
205     
206     /**
207      * Image containing the background gradient and tiles.
208      */

209     private Image JavaDoc bgImage;
210     
211     /**
212      * Width data is cached at.
213      */

214     private int cachedWidth;
215
216     /**
217      * Height data is cached at.
218      */

219     private int cachedHeight;
220     
221     /**
222      * Image containing text.
223      */

224     private BufferedImage JavaDoc textImage;
225     
226     /**
227      * Image containing the drop shadow.
228      */

229     private BufferedImage JavaDoc dropShadowImage;
230     
231     /**
232      * Timer used to animate heap size growing.
233      */

234     private HeapGrowTimer heapGrowTimer;
235     
236     /**
237      * Max width needed to display 999.9/999.9MB. Used to calcualte pref size.
238      */

239     private int maxTextWidth;
240     
241     /**
242      * Current text being displayed.
243      */

244     private String JavaDoc heapSizeText;
245
246     /**
247      * Image containing gradient for ticks.
248      */

249     private Image JavaDoc tickGradientImage;
250
251     /**
252      * Image drawn on top of the ticks.
253      */

254     private BufferedImage JavaDoc gridOverlayImage;
255     
256     
257     
258     public HeapView() {
259         // Configure structures needed for rendering drop shadow.
260
int kw = KERNEL_SIZE, kh = KERNEL_SIZE;
261         float blurFactor = BLUR_FACTOR;
262         float[] kernelData = new float[kw * kh];
263         for (int i = 0; i < kernelData.length; i++) {
264             kernelData[i] = blurFactor;
265         }
266         blur = new ConvolveOp JavaDoc(new Kernel JavaDoc(kw, kh, kernelData));
267         format = new MessageFormat JavaDoc("{0,number,0.0}/{1,number,0.0}MB");
268         heapSizeText = "";
269         showDropShadow = true;
270         showText = true;
271         tickStyle = STYLE_OVERLAY;
272         // Enable mouse events. This is the equivalent to adding a mouse
273
// listener.
274
enableEvents(AWTEvent.MOUSE_EVENT_MASK);
275         setToolTipText(NbBundle.getMessage(GarbageCollectAction.class, "CTL_GC"));
276         updateUI();
277     }
278     
279     /**
280      * Overriden to return true, GCComponent paints in its entire bounds in
281      * an opaque manner.
282      */

283     public boolean isOpaque() {
284         return true;
285     }
286     
287     /**
288      * Updates the look and feel for this component.
289      */

290     public void updateUI() {
291         Font JavaDoc f = new JLabel JavaDoc().getFont();
292         f = new Font JavaDoc(f.getName(), Font.BOLD, f.getSize());
293         setFont(f);
294         revalidate();
295         repaint();
296     }
297     
298     /**
299      * Sets the style used to draw the ticks. The default is
300      * STYLE_DEFAULT.
301      *
302      * @param style the tick style, one of STYLE_DEFAULT or
303      * STYLE_OVERLAY
304      */

305     public void setTickStyle(int style) {
306         tickStyle = style;
307         repaint();
308     }
309
310     /**
311      * Returns the style used to draw ticks.
312      *
313      * @return the style used to draw ticks, one of STYLE_DEFAULT or
314      * STYLE_OVERLAY
315      */

316     public int getTickStyle() {
317         return tickStyle;
318     }
319     
320     /**
321      * Sets whether the text displaying the heap size should be shown. The
322      * default is true.
323      *
324      * @param showText whether the text displaying the heap size should be
325      * shown.
326      */

327     public void setShowText(boolean showText) {
328         this.showText = showText;
329         repaint();
330     }
331     
332     /**
333      * Returns whether the text displaying the heap size should be shown.
334      *
335      * @return whether the text displaying the heap size should be shown
336      */

337     public boolean getShowText() {
338         return showText;
339     }
340
341     /**
342      * Sets whether a drop shadow should be shown around the text. The default
343      * is true.
344      *
345      * @param show whether a drop shadow should be shown around the text
346      */

347     public void setShowDropShadow(boolean show) {
348         showDropShadow = show;
349         repaint();
350     }
351
352     /**
353      * Returns whether a drop shadow should be shown around the text.
354      */

355     public boolean getShowDropShadow() {
356         return showDropShadow;
357     }
358
359     /**
360      * Sets the font used to display the heap size.
361      *
362      * @param font the font used to display the heap size
363      */

364     public void setFont(Font JavaDoc font) {
365         super.setFont(font);
366         updateTextWidth();
367     }
368     
369     Dimension JavaDoc heapViewPreferredSize() {
370         Dimension JavaDoc size = new Dimension JavaDoc(maxTextWidth + 8, getFontMetrics(
371                 getFont()).getHeight() + 8);
372         return size;
373     }
374
375     /**
376      * Recalculates the width needed to display the heap size string.
377      */

378     private void updateTextWidth() {
379         String JavaDoc maxString = format.format(new Object JavaDoc[] {
380             new Float JavaDoc(999.9f), new Float JavaDoc(999.9f) });
381         maxTextWidth = getFontMetrics(getFont()).stringWidth(maxString) + 4;
382     }
383
384     /**
385      * Processes a mouse event.
386      *
387      * @param e the MouseEvent
388      */

389     protected void processMouseEvent(MouseEvent JavaDoc e) {
390         super.processMouseEvent(e);
391         if (!e.isConsumed()) {
392             if (e.isPopupTrigger()) {
393                 // Show a popup allowing to configure the various options
394
showPopup(e.getX(), e.getY());
395             } else if (e.getID() == e.MOUSE_ENTERED) {
396                 containsMouse = true;
397                 cachedBorderVaild = false;
398                 repaint();
399             } else if (e.getID() == e.MOUSE_EXITED) {
400                 containsMouse = false;
401                 cachedBorderVaild = false;
402                 repaint();
403             }
404
405         }
406         
407         if (e.getID() == MouseEvent.MOUSE_CLICKED &&
408                 SwingUtilities.isLeftMouseButton(e) &&
409                 e.getClickCount() == 1) {
410             // Trigger a gc
411
((GarbageCollectAction)GarbageCollectAction.get(GarbageCollectAction.class)).performAction();;
412         }
413     }
414
415     /**
416      * Shows a popup at the specified location that allows you to configure
417      * the various options.
418      */

419     private void showPopup(int x, int y) {
420         JPopupMenu JavaDoc popup = new JPopupMenu JavaDoc();
421         JCheckBoxMenuItem JavaDoc cbmi = new JCheckBoxMenuItem JavaDoc(NbBundle.getMessage(HeapView.class, "LBL_ShowText"));
422         cbmi.setSelected(getShowText());
423         cbmi.addActionListener(new ActionListener JavaDoc() {
424             public void actionPerformed(ActionEvent JavaDoc e) {
425                 setShowText(((JCheckBoxMenuItem JavaDoc)e.getSource()).
426                         isSelected());
427             }
428         });
429         popup.add(cbmi);
430         cbmi = new JCheckBoxMenuItem JavaDoc(NbBundle.getMessage(HeapView.class, "LBL_DropShadow"));
431         cbmi.setSelected(getShowDropShadow());
432         cbmi.addActionListener(new ActionListener JavaDoc() {
433             public void actionPerformed(ActionEvent JavaDoc e) {
434                 setShowDropShadow(((JCheckBoxMenuItem JavaDoc)e.getSource()).
435                         isSelected());
436             }
437         });
438         popup.add(cbmi);
439         cbmi = new JCheckBoxMenuItem JavaDoc(NbBundle.getMessage(HeapView.class, "LBL_OverlayGrid"));
440         cbmi.setSelected(getTickStyle() == STYLE_OVERLAY);
441         cbmi.addActionListener(new ActionListener JavaDoc() {
442             public void actionPerformed(ActionEvent JavaDoc e) {
443                 int style = ((JCheckBoxMenuItem JavaDoc)e.getSource()).
444                         isSelected() ? STYLE_OVERLAY : STYLE_DEFAULT;
445                 setTickStyle(style);
446             }
447         });
448         popup.add(cbmi);
449         popup.show(this, x, y);
450     }
451
452     /**
453      * Returns the first index to start rendering from.
454      */

455     private int getGraphStartIndex() {
456         if (graphFilled) {
457             return graphIndex;
458         } else {
459             return 0;
460         }
461     }
462
463     /**
464      * Paints the component.
465      */

466     protected void paintComponent(Graphics JavaDoc g) {
467         Graphics2D JavaDoc g2 = (Graphics2D JavaDoc)g;
468         int width = getWidth();
469         int height = getHeight();
470         if (width - BORDER_W > 0 && height - BORDER_H > 0) {
471             startTimerIfNecessary();
472             updateCacheIfNecessary(width, height);
473             paintCachedBackground(g2, width, height);
474             g.translate(1, 2);
475             if (containsMouse) {
476                 g.clipRect(1, 0, width - 4, height - 4);
477             }
478             else {
479                 g.clipRect(0, 0, width - 2, height - 4);
480             }
481             int innerW = width - BORDER_W;
482             int innerH = height - BORDER_H;
483             if (heapGrowTimer != null) {
484                 // Render the heap growing animation.
485
Composite JavaDoc lastComposite = ((Graphics2D JavaDoc)g).getComposite();
486                 float percent = 1f - heapGrowTimer.getPercent();
487                 ((Graphics2D JavaDoc)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, percent));
488                 g.drawImage(heapGrowTimer.image, 0, 0, null);
489                 ((Graphics2D JavaDoc)g).setComposite(lastComposite);
490             }
491             paintTicks(g2, innerW, innerH);
492             if (getTickStyle() == STYLE_OVERLAY) {
493                 g2.drawImage(getGridOverlayImage(), 0, 0, null);
494             }
495             if (getShowText()) {
496                 if (getShowDropShadow()) {
497                     paintDropShadowText(g, innerW, innerH);
498                 } else {
499                     g.setColor(Color.WHITE);
500                     paintText(g, innerW, innerH);
501                 }
502             }
503             g.translate(-1, -2);
504         } else {
505             stopTimerIfNecessary();
506             // To honor opaque contract, fill in the background
507
g.setColor(getBackground());
508             g.fillRect(0, 0, width, height);
509         }
510     }
511     
512     private void paintTicks(Graphics2D JavaDoc g, int width, int height) {
513         if (graphIndex > 0 || graphFilled) {
514             int index = getGraphStartIndex();
515             int x = 0;
516             if (!graphFilled) {
517                 x = width - graphIndex;
518             }
519             float min = graph[index];
520             index = (index + 1) % graph.length;
521             while (index != graphIndex) {
522                 min = Math.min(min, graph[index]);
523                 index = (index + 1) % graph.length;
524             }
525             int minHeight = (int)(min * (float)height);
526             if (minHeight > 0) {
527                g.drawImage(tickGradientImage, x, height - minHeight, width, height,
528                         x, height - minHeight, width, height, null);
529             }
530             index = getGraphStartIndex();
531             do {
532                 int tickHeight = (int)(graph[index] * (float)height);
533                 if (tickHeight > minHeight) {
534                     g.drawImage(tickGradientImage, x, height - tickHeight, x + 1, height - minHeight,
535                             x, height - tickHeight, x + 1, height - minHeight, null);
536                 }
537                 index = (index + 1) % graph.length;
538                 x++;
539             } while (index != graphIndex);
540         }
541     }
542
543     /**
544      * Renders the text.
545      */

546     private void paintText(Graphics JavaDoc g, int w, int h) {
547         g.setFont(getFont());
548         String JavaDoc text = getHeapSizeText();
549         FontMetrics JavaDoc fm = g.getFontMetrics();
550         int textWidth = fm.stringWidth(text);
551         g.drawString(text, (w - maxTextWidth) / 2 + (maxTextWidth - textWidth),
552                 h / 2 + fm.getAscent() / 2);
553     }
554
555     /**
556      * Renders the text using a drop shadow.
557      */

558     private void paintDropShadowText(Graphics JavaDoc g, int w, int h) {
559         if (textImage == null) {
560             textImage = new BufferedImage JavaDoc(w, h, BufferedImage.TYPE_INT_ARGB);
561             dropShadowImage = new BufferedImage JavaDoc(w, h, BufferedImage.TYPE_INT_ARGB);
562         }
563         // Step 1: render the text.
564
Graphics2D JavaDoc textImageG = textImage.createGraphics();
565         textImageG.setComposite(AlphaComposite.Clear);
566         textImageG.fillRect(0, 0, w, h);
567         textImageG.setComposite(AlphaComposite.SrcOver);
568         textImageG.setColor(TEXT_BLUR_COLOR);
569         paintText(textImageG, w, h);
570         textImageG.dispose();
571         
572         // Step 2: copy the image containing the text to dropShadowImage using
573
// the blur effect, which generates a nice drop shadow.
574
Graphics2D JavaDoc blurryImageG = dropShadowImage.createGraphics();
575         blurryImageG.setComposite(AlphaComposite.Clear);
576         blurryImageG.fillRect(0, 0, w, h);
577         blurryImageG.setComposite(AlphaComposite.SrcOver);
578         blurryImageG.drawImage(textImage, blur, SHIFT_X, SHIFT_Y);
579         blurryImageG.setColor(TEXT_COLOR);
580         blurryImageG.setFont(getFont());
581         
582         // Step 3: render the text again on top.
583
paintText(blurryImageG, w, h);
584         blurryImageG.dispose();
585         
586         // And finally copy it.
587
g.drawImage(dropShadowImage, 0, 0, null);
588     }
589     
590     private String JavaDoc getHeapSizeText() {
591         return heapSizeText;
592     }
593     
594     /**
595      * Paints the grid on top of the ticks.
596      */

597     private void paintGridOverlay(Graphics2D JavaDoc g, int w, int h) {
598         int numCells = GRID_COLORS.length / 2;
599         int cellSize = (h - numCells - 1) / numCells;
600         int c1 = 0xD0CCBC;
601         int c2 = 0xEAE7D7;
602         g.setPaint(new GradientPaint JavaDoc(
603                 0, 0, new Color JavaDoc((c1 >> 16) & 0xFF, (c1 >> 8) & 0xFF, c1 & 0xFF, 0x30),
604                 0, h, new Color JavaDoc((c2 >> 16) & 0xFF, (c2 >> 8) & 0xFF, c2 & 0xFF, 0x40)));
605         for (int x = 0; x < w; x += cellSize + 1) {
606             g.fillRect(x, 0, 1, h);
607         }
608         for (int y = h - cellSize - 1; y >= 0; y -= (cellSize + 1)) {
609             g.fillRect(0, y, w, 1);
610         }
611     }
612
613     private void paintCachedBackground(Graphics2D JavaDoc g, int w, int h) {
614         if (bgImage != null) {
615             g.drawImage(bgImage, 0, 0, null);
616         }
617     }
618     
619     private void paintBackgroundTiles(Graphics2D JavaDoc g, int w, int h) {
620         g.translate(1, 2);
621         w -= BORDER_W;
622         h -= BORDER_H;
623         int numCells = GRID_COLORS.length / 2;
624         int cellSize = (h - numCells - 1) / numCells;
625         for (int i = 0; i < numCells; i++) {
626             int colorIndex = i;
627             int y = h - cellSize * (i + 1) - i;
628             int x = 1;
629             g.setPaint(new GradientPaint JavaDoc(0, y, GRID_COLORS[colorIndex * 2],
630                     0, y + cellSize - 1, GRID_COLORS[colorIndex * 2 + 1]));
631             while (x < w) {
632                 int endX = Math.min(w, x + cellSize);
633                 g.fillRect(x, y, endX - x, cellSize);
634                 x = endX + 1;
635             }
636             y += cellSize + 1;
637         }
638         g.translate(-1, -2);
639     }
640     
641     private void paintBackground(Graphics2D JavaDoc g, int w, int h) {
642         g.setPaint(new GradientPaint JavaDoc(0, 0, BACKGROUND1_COLOR,
643                 0, h, BACKGROUND2_COLOR));
644         g.fillRect(0, 0, w, h);
645     }
646     
647     private void paintBorder(Graphics JavaDoc g, int w, int h) {
648         // Draw the border
649
if (containsMouse) {
650             g.setColor(Color.WHITE);
651             g.drawRect(0, 0, w - 1, h - 1);
652             g.drawRect(1, 1, w - 3, h - 3);
653         }
654         else {
655             g.setColor(BORDER1_COLOR);
656             g.drawRect(0, 0, w - 1, h - 2);
657             g.setColor(BORDER2_COLOR);
658             g.fillRect(1, 1, w - 2, 1);
659             g.setColor(Color.WHITE);
660             g.fillRect(0, h - 1, w, 1);
661         }
662     }
663     
664     private void updateCacheIfNecessary(int w, int h) {
665         if (cachedWidth != w || cachedHeight != h || !cachedBorderVaild) {
666             cachedWidth = w;
667             cachedHeight = h;
668             cachedBorderVaild = true;
669             updateCache(w, h);
670         }
671     }
672     
673     private Image JavaDoc getGridOverlayImage() {
674         if (gridOverlayImage == null) {
675             gridOverlayImage = new BufferedImage JavaDoc(
676                     getInnerWidth(), getInnerHeight(),
677                     BufferedImage.TYPE_INT_ARGB);
678             Graphics2D JavaDoc g = gridOverlayImage.createGraphics();
679             paintGridOverlay(g, getInnerWidth(), getInnerHeight());
680             g.dispose();
681         }
682         return gridOverlayImage;
683     }
684
685     /**
686      * Recreates the various state information needed for rendering.
687      */

688     private void updateCache(int w, int h) {
689         disposeImages();
690         textImage = new BufferedImage JavaDoc(w, h, BufferedImage.TYPE_INT_ARGB);
691         dropShadowImage = new BufferedImage JavaDoc(w, h, BufferedImage.TYPE_INT_ARGB);
692         bgImage = createImage(w, h);
693         Graphics2D JavaDoc imageG = (Graphics2D JavaDoc)bgImage.getGraphics();
694         paintBackground(imageG, w, h);
695         paintBackgroundTiles(imageG, w, h);
696         paintBorder(imageG, w, h);
697         imageG.dispose();
698         w -= BORDER_W;
699         h -= BORDER_H;
700         if (graph == null || graph.length != w) {
701             graph = new float[w];
702             graphFilled = false;
703             graphIndex = 0;
704         }
705         GradientPaint JavaDoc tickGradient = new GradientPaint JavaDoc(0, h, MIN_TICK_COLOR,
706                 w, 0, MAX_TICK_COLOR);
707         tickGradientImage = createImage(w, h);
708         imageG = (Graphics2D JavaDoc)tickGradientImage.getGraphics();
709         imageG.setPaint(tickGradient);
710         imageG.fillRect(0, 0, w, h);
711         imageG.dispose();
712         if (gridOverlayImage != null) {
713             gridOverlayImage.flush();
714             gridOverlayImage = null;
715         }
716     }
717     
718     /**
719      * Invoked when component removed from a heavy weight parent. Stops the
720      * timer.
721      */

722     public void removeNotify() {
723         super.removeNotify();
724         stopTimerIfNecessary();
725     }
726     
727     /**
728      * Restarts the timer.
729      */

730     private void startTimerIfNecessary() {
731         if (!AUTOMATIC_REFRESH)
732             return;
733         
734         if (updateTimer == null) {
735             updateTimer = new Timer JavaDoc(TICK, new ActionHandler());
736             updateTimer.setRepeats(true);
737             updateTimer.start();
738         }
739     }
740     
741     /**
742      * Stops the timer.
743      */

744     private void stopTimerIfNecessary() {
745         if (updateTimer != null) {
746             graph = null;
747             graphFilled = false;
748             updateTimer.stop();
749             updateTimer = null;
750             lastTotal = 0;
751             disposeImages();
752             cachedHeight = cachedHeight = -1;
753             if (heapGrowTimer != null) {
754                 heapGrowTimer.stop();
755                 heapGrowTimer = null;
756             }
757         }
758     }
759
760     private void disposeImages() {
761         if (bgImage != null) {
762             bgImage.flush();
763             bgImage = null;
764         }
765         if (textImage != null) {
766             textImage.flush();
767             textImage = null;
768         }
769         if (dropShadowImage != null) {
770             dropShadowImage.flush();
771             dropShadowImage = null;
772         }
773         if (tickGradientImage != null) {
774             tickGradientImage.flush();
775             tickGradientImage = null;
776         }
777         if (gridOverlayImage != null) {
778             gridOverlayImage.flush();
779             gridOverlayImage = null;
780         }
781     }
782     
783     /**
784      * Invoked when the update timer fires. Updates the necessary data
785      * structures and triggers repaints.
786      */

787     private void update() {
788         if (!isShowing()) {
789             // Either we've become invisible, or one of our ancestors has.
790
// Stop the timer and bale. Next paint will trigger timer to
791
// restart.
792
stopTimerIfNecessary();
793             return;
794         }
795         Runtime JavaDoc r = Runtime.getRuntime();
796         long total = r.totalMemory();
797         if (total != lastTotal) {
798             if (lastTotal != 0) {
799                 // Total heap size has changed, start an animation.
800
startHeapAnimate();
801                 // Readjust the graph size based on the new max.
802
int index = getGraphStartIndex();
803                 do {
804                     graph[index] = (float)(((double)graph[index] *
805                             (double)lastTotal) / (double)total);
806                     index = (index + 1) % graph.length;
807                 } while (index != graphIndex);
808             }
809             lastTotal = total;
810         }
811         if (heapGrowTimer == null) {
812             // Not animating a heap size change, update the graph data and text.
813
long used = total - r.freeMemory();
814             graph[graphIndex] = (float)((double)used / (double)total);
815             graphIndex = (graphIndex + 1) % graph.length;
816             if (graphIndex == 0) {
817                 graphFilled = true;
818             }
819             heapSizeText = format.format(
820                     new Object JavaDoc[] { new Double JavaDoc((double)used / 1024 / 1024),
821                                    new Double JavaDoc((double)total / 1024 / 1024) });
822         }
823         repaint();
824     }
825     
826     private void startHeapAnimate() {
827         if (heapGrowTimer == null) {
828             heapGrowTimer = new HeapGrowTimer();
829             heapGrowTimer.start();
830         }
831     }
832     
833     private void stopHeapAnimate() {
834         if (heapGrowTimer != null) {
835             heapGrowTimer.stop();
836             heapGrowTimer = null;
837         }
838     }
839
840     private int getInnerWidth() {
841         return getWidth() - BORDER_W;
842     }
843
844     private int getInnerHeight() {
845         return getHeight() - BORDER_H;
846     }
847
848     
849     private final class ActionHandler implements ActionListener JavaDoc {
850         public void actionPerformed(ActionEvent JavaDoc e) {
851             update();
852         }
853     }
854     
855     
856     private final class HeapGrowTimer extends Timer JavaDoc {
857         private final long startTime;
858         private float percent;
859         BufferedImage JavaDoc image;
860         
861         HeapGrowTimer() {
862             super(30, null);
863             setRepeats(true);
864             startTime = System.currentTimeMillis();
865             percent = 0f;
866             int w = getWidth() - BORDER_W;
867             int h = getHeight() - BORDER_H;
868             image = new BufferedImage JavaDoc(w, h, BufferedImage.TYPE_INT_ARGB);
869             Graphics2D JavaDoc g = image.createGraphics();
870             paintTicks(g, w, h);
871             g.dispose();
872         }
873         
874         public float getPercent() {
875             return percent;
876         }
877         
878         protected void fireActionPerformed(ActionEvent JavaDoc e) {
879             long time = System.currentTimeMillis();
880             long delta = time - startTime;
881             if (delta > HEAP_GROW_ANIMATE_TIME) {
882                 stopHeapAnimate();
883             } else {
884                 percent = (float)delta / (float)HEAP_GROW_ANIMATE_TIME;
885                 repaint();
886             }
887         }
888     }
889     private boolean containsMouse;
890     private boolean cachedBorderVaild;
891 }
892
Popular Tags