KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > util > gui > MemoryMonitor


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

18 package org.apache.batik.util.gui;
19
20 import java.awt.BasicStroke JavaDoc;
21 import java.awt.BorderLayout JavaDoc;
22 import java.awt.Color JavaDoc;
23 import java.awt.Component JavaDoc;
24 import java.awt.Dimension JavaDoc;
25 import java.awt.FlowLayout JavaDoc;
26 import java.awt.Font JavaDoc;
27 import java.awt.Graphics JavaDoc;
28 import java.awt.Graphics2D JavaDoc;
29 import java.awt.GridBagConstraints JavaDoc;
30 import java.awt.GridBagLayout JavaDoc;
31 import java.awt.Insets JavaDoc;
32 import java.awt.RenderingHints JavaDoc;
33 import java.awt.Stroke JavaDoc;
34 import java.awt.event.ActionEvent JavaDoc;
35 import java.awt.event.WindowAdapter JavaDoc;
36 import java.awt.event.WindowEvent JavaDoc;
37 import java.awt.geom.AffineTransform JavaDoc;
38 import java.awt.geom.GeneralPath JavaDoc;
39 import java.awt.geom.Line2D JavaDoc;
40 import java.awt.geom.Rectangle2D JavaDoc;
41 import java.util.ArrayList JavaDoc;
42 import java.util.HashMap JavaDoc;
43 import java.util.Iterator JavaDoc;
44 import java.util.LinkedList JavaDoc;
45 import java.util.List JavaDoc;
46 import java.util.Locale JavaDoc;
47 import java.util.Map JavaDoc;
48 import java.util.ResourceBundle JavaDoc;
49
50 import javax.swing.AbstractAction JavaDoc;
51 import javax.swing.Action JavaDoc;
52 import javax.swing.BorderFactory JavaDoc;
53 import javax.swing.JComponent JavaDoc;
54 import javax.swing.JFrame JavaDoc;
55 import javax.swing.JPanel JavaDoc;
56
57 import org.apache.batik.util.gui.resource.ActionMap;
58 import org.apache.batik.util.gui.resource.ButtonFactory;
59 import org.apache.batik.util.gui.resource.MissingListenerException;
60 import org.apache.batik.util.gui.resource.ResourceManager;
61
62 /**
63  * This class contains a collection of components that can be used to
64  * track and display the memory usage.
65  *
66  * @author <a HREF="mailto:stephane@hillion.org">Stephane Hillion</a>
67  * @version $Id: MemoryMonitor.java,v 1.7 2004/08/18 07:15:54 vhardy Exp $
68  */

69 public class MemoryMonitor extends JFrame JavaDoc implements ActionMap {
70     /**
71      * The resource file name
72      */

73     protected final static String JavaDoc RESOURCE =
74     "org.apache.batik.util.gui.resources.MemoryMonitorMessages";
75
76     /**
77      * The resource bundle
78      */

79     protected static ResourceBundle JavaDoc bundle;
80
81     /**
82      * The resource manager
83      */

84     protected static ResourceManager resources;
85
86     static {
87     bundle = ResourceBundle.getBundle(RESOURCE, Locale.getDefault());
88     resources = new ResourceManager(bundle);
89     }
90
91     /**
92      * The map that contains the listeners
93      */

94     protected Map JavaDoc listeners = new HashMap JavaDoc();
95
96     /**
97      * The Panel instance.
98      */

99     protected Panel JavaDoc panel;
100
101     /**
102      * Creates a new memory monitor frame.
103      * The time beetween two repaints is 1s.
104      */

105     public MemoryMonitor() {
106     this(1000);
107     }
108
109     /**
110      * Creates a new memory monitor frame.
111      * @param time The time beetween two repaints in ms.
112      */

113     public MemoryMonitor(long time) {
114     super(resources.getString("Frame.title"));
115         listeners.put("CollectButtonAction", new CollectButtonAction());
116         listeners.put("CloseButtonAction", new CloseButtonAction());
117     
118     panel = new Panel JavaDoc(time);
119
120     getContentPane().add(panel);
121     panel.setBorder(BorderFactory.createTitledBorder
122             (BorderFactory.createEtchedBorder(),
123              resources.getString("Frame.border_title")));
124
125     JPanel JavaDoc p = new JPanel JavaDoc(new FlowLayout JavaDoc(FlowLayout.RIGHT));
126     ButtonFactory bf = new ButtonFactory(bundle, this);
127     p.add(bf.createJButton("CollectButton"));
128     p.add(bf.createJButton("CloseButton"));
129     getContentPane().add("South", p);
130         
131     pack();
132
133     addWindowListener(new WindowAdapter JavaDoc() {
134             public void windowActivated(WindowEvent JavaDoc e) {
135         RepaintThread t = panel.getRepaintThread();
136                 if (!t.isAlive()) {
137                     t.start();
138                 } else {
139                     t.safeResume();
140                 }
141         }
142             public void windowClosing(WindowEvent JavaDoc ev) {
143                 panel.getRepaintThread().safeSuspend();
144         }
145             public void windowDeiconified(WindowEvent JavaDoc e) {
146                 panel.getRepaintThread().safeResume();
147         }
148             public void windowIconified(WindowEvent JavaDoc e) {
149                 panel.getRepaintThread().safeSuspend();
150         }
151         });
152     }
153
154     // ActionMap implementation
155

156     /**
157      * Returns the action associated with the given string
158      * or null on error
159      * @param key the key mapped with the action to get
160      * @throws MissingListenerException if the action is not found
161      */

162     public Action JavaDoc getAction(String JavaDoc key) throws MissingListenerException {
163     return (Action JavaDoc)listeners.get(key);
164     }
165
166     /**
167      * The action associated with the 'Collect' button of the memory monitor.
168      */

169     protected class CollectButtonAction extends AbstractAction JavaDoc {
170         public void actionPerformed(ActionEvent JavaDoc e) {
171             System.gc();
172         }
173     }
174
175     /**
176      * The action associated with the 'Close' button of the memory monitor.
177      */

178     protected class CloseButtonAction extends AbstractAction JavaDoc {
179         public void actionPerformed(ActionEvent JavaDoc e) {
180             panel.getRepaintThread().safeSuspend();
181             dispose();
182         }
183     }
184
185     /**
186      * A panel composed of a Usage instance and a History instance.
187      */

188     public static class Panel extends JPanel JavaDoc {
189     /**
190      * The repaint thread.
191      */

192     protected RepaintThread repaintThread;
193
194     /**
195      * Creates a new memory monitor panel, composed of a Usage instance
196      * and a History instance.
197      * The time beetween two repaints is 1s.
198      */

199     public Panel() {
200         this(1000);
201     }
202
203     /**
204      * Creates a new memory monitor panel, composed of a Usage instance
205      * and a History instance.
206      * The repaint thread must be started by hands.
207      * @param time The time beetween two repaints in ms.
208      */

209     public Panel(long time) {
210         super(new GridBagLayout JavaDoc());
211
212         ExtendedGridBagConstraints constraints
213                 = new ExtendedGridBagConstraints();
214         constraints.insets = new Insets JavaDoc(5, 5, 5, 5);
215     
216         List JavaDoc l = new ArrayList JavaDoc();
217         JPanel JavaDoc p = new JPanel JavaDoc(new BorderLayout JavaDoc());
218         p.setBorder(BorderFactory.createLoweredBevelBorder());
219         JComponent JavaDoc c = new Usage();
220         p.add(c);
221         constraints.weightx = 0.3;
222         constraints.weighty = 1;
223         constraints.fill = GridBagConstraints.BOTH;
224         constraints.setGridBounds(0, 0, 1, 1);
225         add(p, constraints);
226         l.add(c);
227         
228         p = new JPanel JavaDoc(new BorderLayout JavaDoc());
229         p.setBorder(BorderFactory.createLoweredBevelBorder());
230         c = new MemoryMonitor.History();
231         p.add(c);
232         constraints.weightx = 0.7;
233         constraints.setGridBounds(1, 0, 1, 1);
234         add(p, constraints);
235         l.add(c);
236
237         repaintThread = new RepaintThread(time, l);
238     }
239
240     /**
241      * Returns the repaint thread.
242      */

243     public RepaintThread getRepaintThread() {
244         return repaintThread;
245     }
246     }
247
248     /**
249      * Displays the current memory usage.
250      */

251     public static class Usage extends JPanel JavaDoc implements MemoryChangeListener {
252     /**
253      * The preferred width.
254      */

255     public final static int PREFERRED_WIDTH = 90;
256
257     /**
258      * The preferred height.
259      */

260     public final static int PREFERRED_HEIGHT = 100;
261
262     /**
263      * The units string.
264      */

265     protected final static String JavaDoc UNITS
266             = resources.getString("Usage.units");
267
268     /**
269      * The total string.
270      */

271     protected final static String JavaDoc TOTAL
272             = resources.getString("Usage.total");
273
274     /**
275      * The used string.
276      */

277     protected final static String JavaDoc USED
278             = resources.getString("Usage.used");
279
280     /**
281      * The text position.
282      */

283     protected final static boolean POSTFIX
284             = resources.getBoolean("Usage.postfix");
285
286     /**
287      * The font size.
288      */

289     protected final static int FONT_SIZE = 9;
290
291     /**
292      * The blocks margin.
293      */

294     protected final static int BLOCK_MARGIN = 10;
295
296     /**
297      * The number of blocks.
298      */

299     protected final static int BLOCKS = 15;
300
301     /**
302      * The blocks width.
303      */

304     protected final static double BLOCK_WIDTH =
305         PREFERRED_WIDTH-BLOCK_MARGIN*2;
306
307     /**
308      * The blocks height.
309      */

310     protected final static double BLOCK_HEIGHT =
311         ((double)PREFERRED_HEIGHT-(3*FONT_SIZE)-BLOCKS) / BLOCKS;
312
313     /**
314      * The blocks type.
315      */

316     protected final static int[] BLOCK_TYPE =
317         { 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2 };
318
319     /**
320      * The color of the used blocks for each block type.
321      */

322     protected Color JavaDoc[] usedColors = {
323         new Color JavaDoc(255, 0, 0),
324         new Color JavaDoc(255, 165, 0),
325         new Color JavaDoc(0, 255, 0)
326     };
327
328     /**
329      * The color of the free blocks for each block type.
330      */

331     protected Color JavaDoc[] freeColors = {
332         new Color JavaDoc(130, 0, 0),
333         new Color JavaDoc(130, 90, 0),
334         new Color JavaDoc(0, 130, 0)
335     };
336
337     /**
338      * The font used to draw the strings.
339      */

340     protected Font JavaDoc font = new Font JavaDoc("SansSerif", Font.BOLD, FONT_SIZE);
341
342     /**
343      * The text color.
344      */

345     protected Color JavaDoc textColor = Color.green;
346
347     /**
348      * The total memory.
349      */

350     protected long totalMemory;
351
352     /**
353      * The free memory.
354      */

355     protected long freeMemory;
356
357     /**
358      * Creates a new Usage object.
359      */

360     public Usage() {
361         this.setBackground(Color.black);
362         setPreferredSize(new Dimension JavaDoc(PREFERRED_WIDTH, PREFERRED_HEIGHT));
363     }
364
365     /**
366      * Indicates that the memory state has changed.
367      * @param total The total amount of memory.
368      * @param free The free memory.
369      */

370     public void memoryStateChanged(long total, long free) {
371         totalMemory = total;
372         freeMemory = free;
373     }
374
375     /**
376      * Sets the text color.
377      */

378     public void setTextColor(Color JavaDoc c) {
379         textColor = c;
380     }
381
382     /**
383      * Sets the low used memory block color.
384      */

385     public void setLowUsedMemoryColor(Color JavaDoc c) {
386         usedColors[2] = c;
387     }
388     
389     /**
390      * Sets the medium used memory block color.
391      */

392     public void setMediumUsedMemoryColor(Color JavaDoc c) {
393         usedColors[1] = c;
394     }
395     
396     /**
397      * Sets the high used memory block color.
398      */

399     public void setHighUsedMemoryColor(Color JavaDoc c) {
400         usedColors[0] = c;
401     }
402     
403     /**
404      * Sets the low free memory block color.
405      */

406     public void setLowFreeMemoryColor(Color JavaDoc c) {
407         freeColors[2] = c;
408     }
409     
410     /**
411      * Sets the medium free memory block color.
412      */

413     public void setMediumFreeMemoryColor(Color JavaDoc c) {
414         freeColors[1] = c;
415     }
416     
417     /**
418      * Sets the high free memory block color.
419      */

420     public void setHighFreeMemoryColor(Color JavaDoc c) {
421         freeColors[0] = c;
422     }
423     
424     /**
425      * To paint the component.
426      */

427     protected void paintComponent(Graphics JavaDoc g) {
428         super.paintComponent(g);
429         Graphics2D JavaDoc g2d = (Graphics2D JavaDoc)g;
430
431         // Sets the transform
432
Dimension JavaDoc dim = getSize();
433         double sx = ((double)dim.width) / PREFERRED_WIDTH;
434         double sy = ((double)dim.height) / PREFERRED_HEIGHT;
435         g2d.transform(AffineTransform.getScaleInstance(sx, sy));
436         
437         // Turns the antialiasing on
438
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
439                  RenderingHints.VALUE_ANTIALIAS_ON);
440         
441         // Draw the memory blocks
442
int nfree = (int)Math.round(((double)BLOCKS)
443                                         * freeMemory / totalMemory);
444
445         for (int i = 0; i < nfree; i++) {
446         Rectangle2D JavaDoc rect = new Rectangle2D.Double JavaDoc(10,
447                            i*BLOCK_HEIGHT+i+FONT_SIZE+5,
448                               BLOCK_WIDTH,
449                               BLOCK_HEIGHT);
450         g2d.setPaint(freeColors[BLOCK_TYPE[i]]);
451         g2d.fill(rect);
452         }
453
454         for (int i = nfree; i < 15; i++) {
455         Rectangle2D JavaDoc rect = new Rectangle2D.Double JavaDoc(10,
456                            i*BLOCK_HEIGHT+i+FONT_SIZE+5,
457                               BLOCK_WIDTH,
458                               BLOCK_HEIGHT);
459         g2d.setPaint(usedColors[BLOCK_TYPE[i]]);
460         g2d.fill(rect);
461         }
462
463         // Draw the memory usage text
464
g2d.setPaint(textColor);
465         g2d.setFont(font);
466         
467         long total = totalMemory / 1024;
468         long used = (totalMemory - freeMemory) / 1024;
469         String JavaDoc totalText;
470         String JavaDoc usedText;
471         if (POSTFIX) {
472         totalText = total + UNITS + " " + TOTAL;
473         usedText = used + UNITS + " " + USED;
474         } else {
475         totalText = TOTAL + " " + total + UNITS;
476         usedText = USED + " " + used + UNITS;
477         }
478
479         g2d.drawString(totalText, 10, 10);
480         g2d.drawString(usedText, 10, PREFERRED_HEIGHT-3);
481     }
482     }
483
484     /**
485      * Displays the memory usage history in a chart.
486      */

487     public static class History extends JPanel JavaDoc implements MemoryChangeListener {
488     /**
489      * The preferred width.
490      */

491     public final static int PREFERRED_WIDTH = 200;
492
493     /**
494      * The preferred height.
495      */

496     public final static int PREFERRED_HEIGHT = 100;
497
498     /**
499      * The grid lines stroke.
500      */

501     protected final static Stroke JavaDoc GRID_LINES_STROKE = new BasicStroke JavaDoc(1);
502
503     /**
504      * The curve stroke.
505      */

506     protected final static Stroke JavaDoc CURVE_STROKE =
507         new BasicStroke JavaDoc(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
508
509     /**
510      * The border stroke.
511      */

512     protected final static Stroke JavaDoc BORDER_STROKE = new BasicStroke JavaDoc(2);
513
514     /**
515      * The grid lines color.
516      */

517     protected Color JavaDoc gridLinesColor = new Color JavaDoc(0, 130, 0);
518
519     /**
520      * The curve color.
521      */

522     protected Color JavaDoc curveColor = Color.yellow;
523
524     /**
525      * The border color.
526      */

527     protected Color JavaDoc borderColor = Color.green;
528
529     /**
530      * The data.
531      */

532     protected List JavaDoc data = new LinkedList JavaDoc();
533
534     /**
535      * The vertical lines shift.
536      */

537     protected int xShift = 0;
538
539     /**
540      * The total memory.
541      */

542     protected long totalMemory;
543
544     /**
545      * The free memory.
546      */

547     protected long freeMemory;
548
549     /**
550      * The curve representation.
551      */

552     protected GeneralPath JavaDoc path = new GeneralPath JavaDoc();
553
554     /**
555      * Creates a new History object.
556      */

557     public History() {
558         this.setBackground(Color.black);
559         setPreferredSize(new Dimension JavaDoc(PREFERRED_WIDTH, PREFERRED_HEIGHT));
560     }
561
562     /**
563      * Indicates that the memory state has changed.
564      * @param total The total amount of memory.
565      * @param free The free memory.
566      */

567     public void memoryStateChanged(long total, long free) {
568         totalMemory = total;
569         freeMemory = free;
570
571         // Add a new point to the data
572
data.add(new Long JavaDoc(totalMemory - freeMemory));
573         if (data.size() > 190) {
574         data.remove(0);
575         xShift = (xShift + 1) % 10;
576         }
577
578         // Create the path that match the data
579
Iterator JavaDoc it = data.iterator();
580         GeneralPath JavaDoc p = new GeneralPath JavaDoc();
581         long l = ((Long JavaDoc)it.next()).longValue();
582         p.moveTo(5, ((float)(totalMemory - l) / totalMemory) * 80 + 10);
583         int i = 6;
584         while (it.hasNext()) {
585         l = ((Long JavaDoc)it.next()).longValue();
586         p.lineTo(i, ((float)(totalMemory - l) / totalMemory) * 80 + 10);
587         i++;
588         }
589         path = p;
590     }
591
592     /**
593      * To paint the component.
594      */

595     protected void paintComponent(Graphics JavaDoc g) {
596         super.paintComponent(g);
597         Graphics2D JavaDoc g2d = (Graphics2D JavaDoc)g;
598
599         // Turns the antialiasing on
600
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
601                  RenderingHints.VALUE_ANTIALIAS_ON);
602         
603         // Sets the transform
604
Dimension JavaDoc dim = getSize();
605         double sx = ((double)dim.width) / PREFERRED_WIDTH;
606         double sy = ((double)dim.height) / PREFERRED_HEIGHT;
607         g2d.transform(AffineTransform.getScaleInstance(sx, sy));
608         
609         // The vertical lines
610
g2d.setPaint(gridLinesColor);
611         g2d.setStroke(GRID_LINES_STROKE);
612         for (int i = 1; i < 20; i++) {
613         int lx = i * 10 + 5 - xShift;
614         g2d.draw(new Line2D.Double JavaDoc(lx, 5, lx, PREFERRED_HEIGHT - 5));
615         }
616
617         // The horizontal lines
618
for (int i = 1; i < 9; i++) {
619         int ly = i * 10 + 5;
620         g2d.draw(new Line2D.Double JavaDoc(5, ly, PREFERRED_WIDTH - 5, ly));
621         }
622
623         // The curve.
624
g2d.setPaint(curveColor);
625         g2d.setStroke(CURVE_STROKE);
626
627         g2d.draw(path);
628
629         // The border
630
g2d.setStroke(BORDER_STROKE);
631         g2d.setPaint(borderColor);
632         g2d.draw(new Rectangle2D.Double JavaDoc(5,
633                         5,
634                         PREFERRED_WIDTH - 10,
635                         PREFERRED_HEIGHT - 10));
636
637     }
638     }
639
640     /**
641      * This interface allows the RepaintThread to notify an object that the
642      * current memory state has changed.
643      */

644     public interface MemoryChangeListener {
645     /**
646      * Indicates that the memory state has changed.
647      * @param total The total amount of memory.
648      * @param free The free memory.
649      */

650     void memoryStateChanged(long total, long free);
651     }
652
653     /**
654      * This thread repaints a list of components.
655      */

656     public static class RepaintThread extends Thread JavaDoc {
657     /**
658      * The repaint timeout
659      */

660     protected long timeout;
661
662     /**
663      * The components to repaint.
664      */

665     protected List JavaDoc components;
666
667     /**
668      * The runtime.
669      */

670     protected Runtime JavaDoc runtime = Runtime.getRuntime();
671
672         /**
673          * Whether or not the thread was supended.
674          */

675         protected boolean suspended;
676
677     /**
678      * Creates a new Thread.
679      * @param timeout The time between two repaint in ms.
680      * @param components The components to repaint.
681      */

682     public RepaintThread(long timeout, List JavaDoc components) {
683         this.timeout = timeout;
684         this.components = components;
685         setPriority(Thread.MIN_PRIORITY);
686     }
687
688     /**
689      * The thread main method.
690      */

691     public void run() {
692         for (;;) {
693         long free = runtime.freeMemory();
694         long total = runtime.totalMemory();
695         Iterator JavaDoc it = components.iterator();
696         while (it.hasNext()) {
697             Component JavaDoc c = (Component JavaDoc)it.next();
698             ((MemoryChangeListener)c).memoryStateChanged(total, free);
699             c.repaint();
700         }
701                 try {
702                     sleep(timeout);
703                     synchronized(this) {
704                         while (suspended) {
705                             wait();
706                         }
707                     }
708                 } catch (InterruptedException JavaDoc e) {}
709         }
710     }
711         
712         /**
713          * Suspends the thread.
714          */

715         public synchronized void safeSuspend() {
716             if (!suspended) {
717                 suspended = true;
718             }
719         }
720
721         /**
722          * Resumes the thread.
723          */

724         public synchronized void safeResume() {
725             if (suspended) {
726                 suspended = false;
727                 notify();
728             }
729         }
730     }
731 }
732
Popular Tags