source: src/main/java/weka/gui/MemoryUsagePanel.java @ 5

Last change on this file since 5 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 10.9 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 * MemoryUsagePanel.java
19 * Copyright (C) 2008 University of Waikato, Hamilton, New Zealand
20 */
21
22package weka.gui;
23
24import weka.core.Memory;
25import weka.core.Utils;
26import weka.gui.visualize.VisualizeUtils;
27
28import java.awt.BorderLayout;
29import java.awt.Color;
30import java.awt.Dimension;
31import java.awt.Graphics;
32import java.awt.Point;
33import java.awt.event.ActionEvent;
34import java.awt.event.ActionListener;
35import java.util.Collections;
36import java.util.Enumeration;
37import java.util.Hashtable;
38import java.util.Properties;
39import java.util.Vector;
40
41import javax.swing.JButton;
42import javax.swing.JOptionPane;
43import javax.swing.JPanel;
44import javax.swing.SwingUtilities;
45
46/**
47 * A panel for displaying the memory usage.
48 *
49 * @author  fracpete (fracpete at waikato dot ac dot nz)
50 * @version $Revision: 1.1 $
51 */
52public class MemoryUsagePanel
53  extends JPanel {
54
55  /** for serialization. */
56  private static final long serialVersionUID = -4812319791687471721L;
57
58  /**
59   * Specialized thread for monitoring the memory usage.
60   *
61   * @author  fracpete (fracpete at waikato dot ac dot nz)
62   * @version $Revision: 1.1 $
63   */
64  protected class MemoryMonitor
65    extends Thread {
66   
67    /** the refresh interval in msecs. */
68    protected int m_Interval;
69   
70    /** whether the thread is still running. */
71    protected boolean m_Monitoring;
72   
73    /**
74     * default constructor.
75     */
76    public MemoryMonitor() {
77      super();
78
79      setInterval(1000);  // TODO: via props file
80    }
81   
82    /**
83     * Returns the refresh interval in msecs.
84     *
85     * @return          returns the refresh interval
86     */
87    public int getInterval() {
88      return m_Interval;
89    }
90   
91    /**
92     * Sets the refresh interval in msecs.
93     *
94     * @param value     the refresh interval
95     */
96    public void setInterval(int value) {
97      m_Interval = value;
98    }
99   
100    /**
101     * Returns whether the thread is still running.
102     *
103     * @return          true if the thread is still running
104     */
105    public boolean isMonitoring() {
106      return m_Monitoring;
107    }
108   
109    /**
110     * stops the monitoring thread.
111     */
112    public void stopMonitoring() {
113      m_Monitoring = false;
114    }
115
116    /**
117     * The run method.
118     */
119    public void run() {
120      m_Monitoring = true;
121     
122      while (m_Monitoring) {
123        try {
124          Thread.sleep(m_Interval);
125         
126          // update GUI
127          if (m_Monitoring) {
128            Runnable doUpdate = new Runnable() {
129              public void run() {
130                update();
131              }
132            };
133            SwingUtilities.invokeLater(doUpdate);
134          }
135        } 
136        catch(InterruptedException ex) { 
137          ex.printStackTrace();
138        }
139      }
140    }
141   
142    /**
143     * Updates the GUI.
144     */
145    protected void update() {
146      double            perc;
147      Dimension         size;
148
149      // current usage
150      perc = (double) m_Memory.getCurrent() / (double) m_Memory.getMax();
151      perc = Math.round(perc * 1000) / 10;
152     
153      // tool tip
154      setToolTipText("" + perc + "% used");
155     
156      // update history
157      m_History.insertElementAt(perc, 0);
158      size = getSize();
159      while (m_History.size() > size.getWidth())
160        m_History.remove(m_History.size() - 1);
161     
162      // display history
163      repaint();
164    }
165  }
166 
167  /** The name of the properties file. */
168  protected static String PROPERTY_FILE = "weka/gui/MemoryUsage.props";
169   
170  /** Contains the properties. */
171  protected static Properties PROPERTIES;
172 
173  /** the memory usage over time. */
174  protected Vector<Double> m_History;
175
176  /** for monitoring the memory usage. */
177  protected Memory m_Memory;
178
179  /** the thread for monitoring the memory usage. */
180  protected MemoryMonitor m_Monitor;
181 
182  /** the button for running the garbage collector. */
183  protected JButton m_ButtonGC;
184
185  /** the threshold percentages to change color. */
186  protected Vector<Double> m_Percentages;
187 
188  /** the corresponding colors for the thresholds. */
189  protected Hashtable<Double,Color> m_Colors;
190 
191  /** the default color. */
192  protected Color m_DefaultColor;
193 
194  /** the background color. */
195  protected Color m_BackgroundColor;
196
197  /** the position for the dialog. */
198  protected Point m_FrameLocation;
199 
200  /**
201   * Loads the configuration property file (USE_DYNAMIC is FALSE) or determines
202   * the classes dynamically (USE_DYNAMIC is TRUE)
203   * @see #USE_DYNAMIC
204   * @see GenericPropertiesCreator
205   */
206  static {
207    // Allow a properties file in the current directory to override
208    try {
209      PROPERTIES = Utils.readProperties(PROPERTY_FILE);
210      Enumeration keys = PROPERTIES.propertyNames();
211      if (!keys.hasMoreElements())
212        throw new Exception("Failed to read a property file for the "
213            +"memory usage panel");
214    }
215    catch (Exception ex) {
216      JOptionPane.showMessageDialog(
217          null,
218          "Could not read a configuration file for the memory usage\n"
219          +"panel. An example file is included with the Weka distribution.\n"
220          +"This file should be named \"" + PROPERTY_FILE + "\" and\n"
221          +"should be placed either in your user home (which is set\n"
222          + "to \"" + System.getProperties().getProperty("user.home") + "\")\n"
223          + "or the directory that java was started from\n",
224          "MemoryUsagePanel",
225          JOptionPane.ERROR_MESSAGE);
226    }
227  }
228 
229  /**
230   * default constructor.
231   */
232  public MemoryUsagePanel() {
233    super();
234
235    // initializes members
236    m_Memory      = new Memory();
237    m_History     = new Vector<Double>();
238    m_Percentages = new Vector<Double>();
239    m_Colors      = new Hashtable<Double,Color>();
240
241    // colors and percentages
242    m_BackgroundColor = parseColor("BackgroundColor", Color.WHITE);
243    m_DefaultColor    = parseColor("DefaultColor", Color.GREEN);
244    String[] percs    = PROPERTIES.getProperty("Percentages", "70,80,90").split(",");
245    for (int i = 0; i < percs.length; i++) {
246      // do we have a color associated with percentage?
247      if (PROPERTIES.getProperty(percs[i]) != null) {
248        double perc;
249        Color color;
250       
251        // try parsing the number
252        try {
253          perc = Double.parseDouble(percs[i]);
254        }
255        catch (Exception e) {
256          System.err.println(
257              "MemoryUsagePanel: cannot parse percentage '" 
258              + percs[i] + "' - ignored!");
259          continue;
260        }
261
262        // try parsing the color
263        color = parseColor(percs[i], null);
264        if (color == null)
265          continue;
266       
267        // store color and percentage
268        m_Percentages.add(perc);
269        m_Colors.put(perc, color);
270      }
271      else {
272        System.err.println(
273            "MemoryUsagePanel: cannot find color for percentage '" 
274            + percs[i] + "' - ignored!");
275      }
276    }
277    Collections.sort(m_Percentages);
278   
279    // layout
280    setLayout(new BorderLayout());
281
282    JPanel panel = new JPanel(new BorderLayout());
283    add(panel, BorderLayout.EAST);
284   
285    m_ButtonGC = new JButton("GC");
286    m_ButtonGC.setToolTipText("Runs the garbage collector.");
287    m_ButtonGC.addActionListener(new ActionListener() {
288      public void actionPerformed(ActionEvent evt) {
289        System.gc();
290      }
291    });
292    panel.add(m_ButtonGC, BorderLayout.NORTH);
293
294    // dimensions
295    int height;
296    int width;
297    try {
298      height = Integer.parseInt(PROPERTIES.getProperty("Height", "" + (int) m_ButtonGC.getPreferredSize().getHeight()));
299      width  = Integer.parseInt(PROPERTIES.getProperty("Width", "400"));
300    }
301    catch (Exception e) {
302      System.err.println("MemoryUsagePanel: Problem parsing the dimensions - " + e);
303      height = (int) m_ButtonGC.getPreferredSize().getHeight();
304      width = 400;
305    }
306    setPreferredSize(new Dimension(width, height));
307
308    // position
309    int top;
310    int left;
311    try {
312      top  = Integer.parseInt(PROPERTIES.getProperty("Top", "0"));
313      left = Integer.parseInt(PROPERTIES.getProperty("Left", "0"));
314    }
315    catch (Exception e) {
316      System.err.println("MemoryUsagePanel: Problem parsing the position - " + e);
317      top  = 0;
318      left = 0;
319    }
320    m_FrameLocation = new Point(left, top);
321   
322    // monitoring thread
323    int interval;
324    try {
325      interval = Integer.parseInt(PROPERTIES.getProperty("Interval", "1000"));
326    }
327    catch (Exception e) {
328      System.err.println("MemoryUsagePanel: Problem parsing the refresh interval - " + e);
329      interval = 1000;
330    }
331    m_Monitor = new MemoryMonitor();
332    m_Monitor.setInterval(interval);
333    m_Monitor.setPriority(Thread.MAX_PRIORITY);
334    m_Monitor.start();
335  }
336
337  /**
338   * parses the color and returns the corresponding Color object.
339   *
340   * @param prop        the color property to read and parse
341   * @param defValue    the default color
342   * @return            the parsed color or the default color of the
343   */
344  protected Color parseColor(String prop, Color defValue) {
345    Color       result;
346    Color       color;
347    String      colorStr;
348   
349    result = defValue;
350   
351    try {
352      colorStr = PROPERTIES.getProperty(prop);
353      color    = VisualizeUtils.processColour(colorStr, result);
354      if (color == null)
355        throw new Exception(colorStr);
356      result = color;
357    }
358    catch (Exception e) {
359      System.err.println(
360          "MemoryUsagePanel: cannot parse color '" 
361          + e.getMessage() + "' - ignored!");
362    }
363   
364    return result;
365  }
366 
367  /**
368   * Returns whether the thread is still running.
369   *
370   * @return            true if the thread is still running
371   */
372  public boolean isMonitoring() {
373    return m_Monitor.isMonitoring();
374  }
375 
376  /**
377   * stops the monitoring thread.
378   */
379  public void stopMonitoring() {
380    m_Monitor.stopMonitoring();
381  }
382 
383  /**
384   * Returns the default position for the dialog.
385   *
386   * @return            the default position
387   */
388  public Point getFrameLocation() {
389    return m_FrameLocation;
390  }
391 
392  /**
393   * draws the background image.
394   *
395   * @param g           the graphics context
396   */
397  public void paintComponent(Graphics g) {
398    int         i;
399    int         n;
400    int         len;
401    double      scale;
402    double      perc;
403    Color       color;
404   
405    super.paintComponent(g);
406   
407    g.setColor(m_BackgroundColor);
408    g.fillRect(0, 0, getWidth(), getHeight());
409    scale = (double) getHeight() / 100.0;
410    for (i = 0; i < m_History.size(); i++) {
411      perc = m_History.get(i);
412     
413      // determine color
414      color = m_DefaultColor;
415      for (n = m_Percentages.size() - 1; n >= 0; n--) {
416        if (perc >= m_Percentages.get(n)) {
417          color = m_Colors.get(m_Percentages.get(n));
418          break;
419        }
420      }
421     
422      // paint line
423      g.setColor(color);
424      len = (int) Math.round(perc * scale);
425      g.drawLine(i, getHeight() - 1, i, getHeight() - len);
426    }
427  }
428}
Note: See TracBrowser for help on using the repository browser.