source: src/main/java/weka/gui/beans/StripChart.java @ 4

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

Import di weka.

File size: 23.7 KB
RevLine 
[4]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 *    StripChart.java
19 *    Copyright (C) 2002 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23package weka.gui.beans;
24
25import weka.core.Instance;
26import weka.core.Instances;
27import weka.gui.visualize.PrintableComponent;
28import weka.gui.visualize.VisualizeUtils;
29
30import java.awt.BorderLayout;
31import java.awt.Color;
32import java.awt.Dimension;
33import java.awt.Font;
34import java.awt.FontMetrics;
35import java.awt.Graphics;
36import java.awt.Image;
37import java.beans.EventSetDescriptor;
38import java.io.IOException;
39import java.io.ObjectInputStream;
40import java.util.Enumeration;
41import java.util.LinkedList;
42import java.util.Random;
43import java.util.Vector;
44
45import javax.swing.BorderFactory;
46import javax.swing.JComponent;
47import javax.swing.JFrame;
48import javax.swing.JPanel;
49import javax.swing.border.TitledBorder;
50
51/**
52 * Bean that can display a horizontally scrolling strip chart. Can
53 * display multiple plots simultaneously
54 *
55 * @author <a href="mailto:mhall@cs.waikato.ac.nz">Mark Hall</a>
56 * @version $Revision: 4806 $
57 */
58public class StripChart
59  extends JPanel
60  implements ChartListener, InstanceListener, Visible,
61             BeanCommon, UserRequestAcceptor {
62
63  /** for serialization */
64  private static final long serialVersionUID = 1483649041577695019L;
65
66  /** default colours for colouring lines */
67  protected Color [] m_colorList = {Color.green,
68                                    Color.red,
69                                    Color.blue,
70                                    Color.cyan,
71                                    Color.pink,
72                                    new Color(255, 0, 255),
73                                    Color.orange,
74                                    new Color(255, 0, 0),
75                                    new Color(0, 255, 0),
76                                    Color.white};
77
78  /** the background color. */
79  protected Color m_BackgroundColor;
80 
81  /** the color of the legend panel's border. */
82  protected Color m_LegendPanelBorderColor;
83 
84  /**
85   * Class providing a panel for the plot.
86   */
87  private class StripPlotter
88    extends JPanel {
89
90    /** for serialization. */
91    private static final long serialVersionUID = -7056271598761675879L;
92
93    public void paintComponent(Graphics g) {
94      super.paintComponent(g);
95      if (m_osi != null) {
96        g.drawImage(m_osi,0,0,this);
97      }
98    }
99  }
100
101  private transient JFrame m_outputFrame = null;
102  private transient StripPlotter m_plotPanel = null;
103
104  /**
105   * The off screen image for rendering to.
106   */
107  private transient Image m_osi = null;
108
109  /**
110   * Width and height of the off screen image.
111   */
112  private int m_iheight;
113  private int m_iwidth;
114
115  /**
116   * Max value for the y axis.
117   */
118  private double m_max = 1;
119
120  /**
121   * Min value for the y axis.
122   */
123  private double m_min = 0;
124
125  /**
126   * Scale update requested.
127   */
128  private boolean m_yScaleUpdate = false;
129  private double m_oldMax;
130  private double m_oldMin;
131
132  private Font m_labelFont = new Font("Monospaced", Font.PLAIN, 10);
133  private FontMetrics m_labelMetrics;
134
135  //  private int m_plotCount = 0;
136
137  private Vector m_legendText = new Vector();
138
139  /**
140   * Class providing a panel for displaying the y axis.
141   */
142  private class ScalePanel 
143    extends JPanel {
144
145    /** for serialization. */
146    private static final long serialVersionUID = 6416998474984829434L;
147
148    public void paintComponent(Graphics gx) {
149      super.paintComponent(gx);
150      if (m_labelMetrics == null) {
151        m_labelMetrics = gx.getFontMetrics(m_labelFont);
152      }
153      gx.setFont(m_labelFont);
154      int hf = m_labelMetrics.getAscent();
155      String temp = ""+m_max;
156      gx.setColor(m_colorList[m_colorList.length-1]);
157      gx.drawString(temp, 1, hf-2);
158      temp = ""+(m_min + ((m_max - m_min)/2.0));
159      gx.drawString(temp, 1, (this.getHeight() / 2)+(hf / 2));
160      temp = ""+m_min;
161      gx.drawString(temp, 1, this.getHeight()-1);
162    }
163  };
164 
165  /** the scale. */
166  private ScalePanel m_scalePanel = new ScalePanel();
167
168  /**
169   * Class providing a panel for the legend.
170   */
171  private class LegendPanel 
172    extends JPanel {
173
174    /** for serialization. */
175    private static final long serialVersionUID = 7713986576833797583L;
176
177    public void paintComponent(Graphics gx) {
178      super.paintComponent(gx);
179
180      if (m_labelMetrics == null) {
181        m_labelMetrics = gx.getFontMetrics(m_labelFont);
182      }
183      int hf = m_labelMetrics.getAscent();
184      int x = 10; int y = hf+15;
185      gx.setFont(m_labelFont);
186      for (int i = 0; i < m_legendText.size(); i++) {
187        String temp = (String)m_legendText.elementAt(i);
188        gx.setColor(m_colorList[(i % m_colorList.length)]);
189        gx.drawString(temp,x,y);
190        y+=hf;
191      }
192      StripChart.this.revalidate();
193    }
194  };
195 
196  /** the legend. */
197  private LegendPanel m_legendPanel = new LegendPanel();
198
199  /**
200   * Holds the data to be plotted. Entries in the list are arrays of
201   * y points.
202   */
203  private LinkedList m_dataList = new LinkedList();
204  //  private double [] m_dataPoint = new double[1];
205  private double [] m_previousY = new double[1];
206
207  private transient Thread m_updateHandler;
208
209  protected BeanVisual m_visual =
210    new BeanVisual("StripChart",
211                   BeanVisual.ICON_PATH+"StripChart.gif",
212                   BeanVisual.ICON_PATH+"StripChart_animated.gif");
213
214  private Object m_listenee = null;
215  private transient weka.gui.Logger m_log = null;
216
217  /**
218   * Print x axis labels every m_xValFreq points
219   */
220  private int m_xValFreq = 500;
221  private int m_xCount = 0;
222
223  /**
224   * Shift the plot by this many pixels every time a point is plotted
225   */
226  private int m_refreshWidth = 1;
227
228  /**
229   * Plot every m_refreshFrequency'th point
230   */
231  private int m_refreshFrequency = 5;
232
233  /** the class responsible for printing */
234  protected PrintableComponent m_Printer = null;
235
236  public StripChart() {
237
238    //    m_plotPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
239
240    setLayout(new BorderLayout());
241    add(m_visual, BorderLayout.CENTER);
242
243    // start a thread to handle plot updates
244    initPlot();
245  }
246
247  /**
248   * Set a custom (descriptive) name for this bean
249   *
250   * @param name the name to use
251   */
252  public void setCustomName(String name) {
253    m_visual.setText(name);
254  }
255
256  /**
257   * Get the custom (descriptive) name for this bean (if one has been set)
258   *
259   * @return the custom name (or the default name)
260   */
261  public String getCustomName() {
262    return m_visual.getText();
263  }
264
265  /**
266   * Global info for this bean
267   *
268   * @return a <code>String</code> value
269   */
270  public String globalInfo() {
271    return "Visualize incremental classifier performance as a scrolling plot.";
272  }
273
274  /**
275   * GUI Tip text
276   *
277   * @return a <code>String</code> value
278   */
279  public String xLabelFreqTipText() {
280    return "Show x axis labels this often";
281  }
282
283  /**
284   * Set the frequency for printing x label values
285   *
286   * @param freq an <code>int</code> value
287   */
288  public void setXLabelFreq(int freq) {
289    m_xValFreq = freq;
290    if (getGraphics() != null)
291      setRefreshWidth();
292  }
293
294  /**
295   * Get the frequency by which x axis values are printed
296   *
297   * @return an <code>int</code> value
298   */
299  public int getXLabelFreq() {
300    return m_xValFreq;
301  }
302
303  /**
304   * GUI Tip text
305   *
306   * @return a <code>String</code> value
307   */
308  public String refreshFreqTipText() {
309    return "Plot every x'th data point";
310  }
311
312  /**
313   * Set how often (in x axis points) to refresh the display
314   *
315   * @param freq an <code>int</code> value
316   */
317  public void setRefreshFreq(int freq) {
318    m_refreshFrequency = freq;
319    if (getGraphics() != null)
320      setRefreshWidth();
321  }
322
323  /**
324   * Get the refresh frequency
325   *
326   * @return an <code>int</code> value
327   */
328  public int getRefreshFreq() {
329    return m_refreshFrequency;
330  }
331
332  private void setRefreshWidth() {
333    m_refreshWidth = 1;
334    if (m_labelMetrics == null) {
335      getGraphics().setFont(m_labelFont);
336      m_labelMetrics = getGraphics().getFontMetrics(m_labelFont);
337    }
338
339    int refWidth = m_labelMetrics.stringWidth("99000");
340    // compute how often x label will be rendered
341    int z = (getXLabelFreq() / getRefreshFreq());
342    if (z < 1) {
343      z = 1;
344    }
345
346    if (z * m_refreshWidth < refWidth+5) {
347      m_refreshWidth *= (((refWidth+5) / z) + 1) ;
348    }
349  }
350
351  /**
352   * Provide some necessary initialization after object has
353   * been deserialized.
354   *
355   * @param ois an <code>ObjectInputStream</code> value
356   * @exception IOException if an error occurs
357   * @exception ClassNotFoundException if an error occurs
358   */
359  private void readObject(ObjectInputStream ois)
360    throws IOException, ClassNotFoundException {
361    try {
362      ois.defaultReadObject();
363      initPlot();
364      //      startHandler();
365    } catch (Exception ex) {
366      ex.printStackTrace();
367    }
368  }
369
370  /**
371   * Loads properties from properties file.
372   *
373   * @see       KnowledgeFlowApp#BEAN_PROPERTIES
374   */
375  private void setProperties() {
376    String      key;
377    String      color;
378
379    // background color
380    key   = this.getClass().getName() + ".backgroundColour";
381    color = KnowledgeFlowApp.BEAN_PROPERTIES.getProperty(key);
382    m_BackgroundColor = Color.BLACK;
383    if (color != null)
384      m_BackgroundColor = VisualizeUtils.processColour(color, m_BackgroundColor);
385
386    // legend color (border)
387    key   = m_legendPanel.getClass().getName() + ".borderColour";
388    color = KnowledgeFlowApp.BEAN_PROPERTIES.getProperty(key);
389    m_LegendPanelBorderColor = Color.BLUE;
390    if (color != null)
391      m_LegendPanelBorderColor = VisualizeUtils.processColour(color, m_LegendPanelBorderColor);
392  }
393
394  private void initPlot() {
395    setProperties();
396    m_plotPanel = new StripPlotter();
397    m_plotPanel.setBackground(m_BackgroundColor);
398    m_scalePanel.setBackground(m_BackgroundColor);
399    m_legendPanel.setBackground(m_BackgroundColor);
400    m_xCount = 0;
401  }
402
403  private void startHandler() {
404    if (m_updateHandler == null) {
405      m_updateHandler = new Thread() {
406          private double [] dataPoint;
407          public void run() {
408            while (true) {
409              if (m_outputFrame != null) {
410                synchronized(m_dataList) {
411                  while(m_dataList.isEmpty()) {
412                  //              while (m_dataList.empty()) {
413                    try {
414                      m_dataList.wait();
415                    } catch (InterruptedException ex) {
416                      return;
417                    }
418                  }
419                  dataPoint = (double [])m_dataList.remove(0);
420                  //dataPoint  = (double [])m_dataList.pop();
421                }
422                if (m_outputFrame != null) {
423                  StripChart.this.updateChart(dataPoint);
424                }
425              }
426            }
427          }
428        };
429      //      m_updateHandler.setPriority(Thread.MIN_PRIORITY);
430      m_updateHandler.start();
431    }
432  }
433
434  /**
435   * Popup the chart panel
436   */
437  public void showChart() {
438    if (m_outputFrame == null) {
439      m_outputFrame = new JFrame("Strip Chart");
440      m_outputFrame.getContentPane().setLayout(new BorderLayout());
441      JPanel panel = new JPanel(new BorderLayout());
442      new PrintableComponent(panel);
443      m_outputFrame.getContentPane().add(panel, BorderLayout.CENTER);
444      panel.add(m_legendPanel, BorderLayout.WEST);
445      panel.add(m_plotPanel, BorderLayout.CENTER);
446      panel.add(m_scalePanel, BorderLayout.EAST);
447      m_legendPanel.setMinimumSize(new Dimension(100,getHeight()));
448      m_legendPanel.setPreferredSize(new Dimension(100,getHeight()));
449      m_scalePanel.setMinimumSize(new Dimension(30, getHeight()));
450      m_scalePanel.setPreferredSize(new Dimension(30, getHeight()));
451      Font lf = new Font("Monospaced", Font.PLAIN, 12);
452      m_legendPanel.setBorder(BorderFactory.
453                              createTitledBorder(BorderFactory.
454                                    createEtchedBorder(Color.gray,
455                                                       Color.darkGray),
456                                    "Legend" ,
457                                    TitledBorder.CENTER,
458                                    TitledBorder.DEFAULT_POSITION, lf,
459                                    m_LegendPanelBorderColor));
460      m_outputFrame.addWindowListener(new java.awt.event.WindowAdapter() {
461          public void windowClosing(java.awt.event.WindowEvent e) {
462            if (m_updateHandler != null) {
463              System.err.println("Interrupting");
464              m_updateHandler.interrupt();
465              m_updateHandler = null;
466            }
467            synchronized (m_dataList) {
468              m_dataList = new LinkedList();
469            }
470            m_outputFrame.dispose();
471            m_outputFrame = null;
472          }
473        });
474      m_outputFrame.pack();
475      m_outputFrame.setSize(600,150);
476      m_outputFrame.setResizable(false);
477      m_outputFrame.setVisible(true);
478      int iwidth = m_plotPanel.getWidth();
479      int iheight = m_plotPanel.getHeight();
480      m_osi = m_plotPanel.createImage(iwidth, iheight);
481      Graphics m = m_osi.getGraphics();
482      m.setColor(m_BackgroundColor);
483      m.fillRect(0,0,iwidth,iheight);
484      m_previousY[0] = -1;
485      setRefreshWidth();
486      if (m_updateHandler == null) {
487        System.err.println("Starting handler");
488        startHandler();
489      }
490    } else {
491      m_outputFrame.toFront();
492    }
493  }
494
495  private int convertToPanelY(double yval) {
496    int height = m_plotPanel.getHeight();
497    double temp = (yval - m_min) / (m_max - m_min);
498    temp = temp * height;
499    temp = height - temp;
500    return (int)temp;
501  }
502
503  /**
504   * Update the plot
505   *
506   * @param dataPoint contains y values to plot
507   */
508  protected void updateChart(double [] dataPoint) {
509    if (m_previousY[0] == -1) {
510      int iw = m_plotPanel.getWidth();
511      int ih = m_plotPanel.getHeight();
512      m_osi = m_plotPanel.createImage(iw, ih);
513      Graphics m = m_osi.getGraphics();
514      m.setColor(m_BackgroundColor);
515      m.fillRect(0,0,iw,ih);
516      m_previousY[0] = convertToPanelY(0);
517      m_iheight = ih; m_iwidth = iw;
518    }
519
520    if (dataPoint.length-1 != m_previousY.length) {
521      m_previousY = new double [dataPoint.length-1];
522      //      m_plotCount = 0;
523      for (int i = 0; i < dataPoint.length-1; i++) {
524        m_previousY[i] = convertToPanelY(0);
525      }
526    }
527
528    Graphics osg = m_osi.getGraphics();
529    Graphics g = m_plotPanel.getGraphics();
530
531    osg.copyArea(m_refreshWidth,0,m_iwidth-m_refreshWidth,
532                 m_iheight,-m_refreshWidth,0);
533    osg.setColor(m_BackgroundColor);
534    osg.fillRect(m_iwidth-m_refreshWidth,0, m_iwidth, m_iheight);
535
536    // paint the old scale onto the plot if a scale update has occured
537    if (m_yScaleUpdate) {
538      String maxVal = numToString(m_oldMax);
539      String minVal = numToString(m_oldMin);
540      String midVal = numToString((m_oldMax - m_oldMin) / 2.0);
541      if (m_labelMetrics == null) {
542        m_labelMetrics = g.getFontMetrics(m_labelFont);
543      }
544      osg.setFont(m_labelFont);
545      int wmx = m_labelMetrics.stringWidth(maxVal);
546      int wmn = m_labelMetrics.stringWidth(minVal);
547      int wmd = m_labelMetrics.stringWidth(midVal);
548
549      int hf = m_labelMetrics.getAscent();
550      osg.setColor(m_colorList[m_colorList.length-1]);
551      osg.drawString(maxVal, m_iwidth-wmx, hf-2);
552      osg.drawString(midVal, m_iwidth-wmd, (m_iheight / 2)+(hf / 2));
553      osg.drawString(minVal, m_iwidth-wmn, m_iheight-1);
554      m_yScaleUpdate = false;
555    }
556
557    double pos;
558    for (int i = 0; i < dataPoint.length-1; i++) {
559      osg.setColor(m_colorList[(i % m_colorList.length)]);
560      pos = convertToPanelY(dataPoint[i]);
561      osg.drawLine(m_iwidth-m_refreshWidth, (int)m_previousY[i],
562                   m_iwidth-1, (int)pos);
563      m_previousY[i] = pos;
564      if (dataPoint[dataPoint.length-1] % m_xValFreq == 0) {
565        // draw the actual y value onto the plot for this curve
566        String val = numToString(dataPoint[i]);
567        if (m_labelMetrics == null) {
568          m_labelMetrics = g.getFontMetrics(m_labelFont);
569        }
570        int hf = m_labelMetrics.getAscent();
571        if (pos - hf < 0) {
572          pos += hf;
573        }
574        int w = m_labelMetrics.stringWidth(val);
575        osg.setFont(m_labelFont);
576        osg.drawString(val, m_iwidth-w, (int)pos);
577      }
578    }
579
580    // last element in the data point array contains the data point number
581    if (dataPoint[dataPoint.length-1] % m_xValFreq == 0) {
582
583      String xVal = ""+(int)dataPoint[dataPoint.length-1];
584      osg.setColor(m_colorList[m_colorList.length-1]);
585      int w = m_labelMetrics.stringWidth(xVal);
586      osg.setFont(m_labelFont);
587      osg.drawString(xVal, m_iwidth-w, m_iheight - 1);
588    }
589    g.drawImage(m_osi,0,0,m_plotPanel);
590    //    System.err.println("Finished");
591    //    m_plotCount++;
592  }
593
594  private static String numToString(double num) {
595    int precision = 1;
596    int whole = (int)Math.abs(num);
597    double decimal = Math.abs(num) - whole;
598    int nondecimal;
599    nondecimal = (whole > 0)
600      ? (int)(Math.log(whole) / Math.log(10))
601      : 1;
602
603    precision = (decimal > 0)
604      ? (int)Math.abs(((Math.log(Math.abs(num)) /
605                                      Math.log(10))))+2
606      : 1;
607    if (precision > 5) {
608      precision = 1;
609    }
610
611    String numString = weka.core.Utils.doubleToString(num,
612                                                      nondecimal+1+precision
613                                                      ,precision);
614
615    return numString;
616  }
617
618  ChartEvent m_ce = new ChartEvent(this);
619  double [] m_dataPoint = null;
620  public void acceptInstance(InstanceEvent e) {
621    if (e.getStatus() == InstanceEvent.FORMAT_AVAILABLE) {
622      Instances structure = e.getStructure();
623      m_legendText = new Vector();
624      m_max = 1.0;
625      m_min = 0;
626      int i = 0;
627      for (i =0; i < structure.numAttributes(); i++) {
628        if (i > 10) {
629          i--;
630          break;
631        }
632        m_legendText.addElement(structure.attribute(i).name());
633        m_legendPanel.repaint();
634        m_scalePanel.repaint();
635      }
636      m_dataPoint = new double[i];
637      m_xCount = 0;
638      return;
639    }
640
641    // process data point
642    Instance inst = e.getInstance();
643    for (int i = 0; i < m_dataPoint.length; i++) {
644      if (!inst.isMissing(i)) {
645        m_dataPoint[i] = inst.value(i);
646      }
647    }
648    acceptDataPoint(m_dataPoint);
649    m_xCount++;
650  }
651
652  /**
653   * Accept a data point (encapsulated in a chart event) to plot
654   *
655   * @param e a <code>ChartEvent</code> value
656   */
657  public void acceptDataPoint(ChartEvent e) {
658    if (e.getReset()) {
659      m_xCount = 0;
660      m_max = 1;
661      m_min = 0;
662    }
663    if (m_outputFrame != null) {
664      boolean refresh = false;
665      if (e.getLegendText() != null & e.getLegendText() != m_legendText) {
666        m_legendText = e.getLegendText();
667        refresh = true;
668      }
669
670      if (e.getMin() != m_min || e.getMax() != m_max) {
671        m_oldMax = m_max; m_oldMin = m_min;
672        m_max = e.getMax();
673        m_min = e.getMin();
674        refresh = true;
675        m_yScaleUpdate = true;
676      }
677
678      if (refresh) {
679        m_legendPanel.repaint();
680        m_scalePanel.repaint();
681      }
682
683      acceptDataPoint(e.getDataPoint());
684    }
685    m_xCount++;
686  }
687
688  /**
689   * Accept a data point to plot
690   *
691   * @param dataPoint a <code>double[]</code> value
692   */
693  public void acceptDataPoint(double [] dataPoint) {
694
695    if (m_outputFrame != null && (m_xCount % m_refreshFrequency == 0 )) {
696      double [] dp = new double[dataPoint.length+1];
697      dp[dp.length-1] = m_xCount;
698      System.arraycopy(dataPoint, 0, dp, 0, dataPoint.length);
699      // check for out of scale values
700      for (int i = 0; i < dataPoint.length; i++) {
701        if (dataPoint[i] < m_min) {
702          m_oldMin = m_min; m_min = dataPoint[i];
703          m_yScaleUpdate = true;
704        }
705
706        if (dataPoint[i] > m_max) {
707          m_oldMax = m_max; m_max = dataPoint[i];
708          m_yScaleUpdate = true;
709        }
710      }
711      if (m_yScaleUpdate) {
712        m_scalePanel.repaint();
713        m_yScaleUpdate = false;
714      }
715      synchronized(m_dataList) {
716        m_dataList.add(m_dataList.size(), dp);
717        //      m_dataList.push(dp);
718        m_dataList.notifyAll();
719        /*      if (m_dataList.size() != 0) {
720          System.err.println("***** "+m_dataList.size());
721          } */
722
723        //      System.err.println(m_xCount);
724      }
725    }
726  }
727
728  /**
729   * Set the visual appearance of this bean
730   *
731   * @param newVisual a <code>BeanVisual</code> value
732   */
733  public void setVisual(BeanVisual newVisual) {
734    m_visual = newVisual;
735  }
736
737  /**
738   * Get the visual appearance of this bean
739   */
740  public BeanVisual getVisual() {
741    return m_visual;
742  }
743
744  /**
745   * Use the default visual appearance for this bean
746   */
747  public void useDefaultVisual() {
748    m_visual.loadIcons(BeanVisual.ICON_PATH+"StripChart.gif",
749                       BeanVisual.ICON_PATH+"StripChart_animated.gif");
750  }
751
752  /**
753   * Stop any processing that the bean might be doing.
754   */
755  public void stop() {
756    // tell the listenee (upstream bean) to stop
757    if (m_listenee instanceof BeanCommon) {
758      ((BeanCommon)m_listenee).stop();
759    }
760  }
761 
762  /**
763   * Returns true if. at this time, the bean is busy with some
764   * (i.e. perhaps a worker thread is performing some calculation).
765   *
766   * @return true if the bean is busy.
767   */
768  public boolean isBusy() {
769    return (m_updateHandler != null);
770  }
771
772  /**
773   * Set a logger
774   *
775   * @param logger a <code>weka.gui.Logger</code> value
776   */
777  public void setLog(weka.gui.Logger logger) {
778    m_log = logger;
779  }
780
781  /**
782   * Returns true if, at this time,
783   * the object will accept a connection via the named event
784   *
785   * @param eventName the name of the event
786   * @return true if the object will accept a connection
787   */
788  public boolean connectionAllowed(String eventName) {
789    if (m_listenee == null) {
790      return true;
791    }
792    return false;
793  }
794
795  /**
796   * Returns true if, at this time,
797   * the object will accept a connection according to the supplied
798   * EventSetDescriptor
799   *
800   * @param esd the EventSetDescriptor
801   * @return true if the object will accept a connection
802   */
803  public boolean connectionAllowed(EventSetDescriptor esd) {
804    return connectionAllowed(esd.getName());
805  }
806
807  /**
808   * Notify this object that it has been registered as a listener with
809   * a source for recieving events described by the named event
810   * This object is responsible for recording this fact.
811   *
812   * @param eventName the event
813   * @param source the source with which this object has been registered as
814   * a listener
815   */
816  public void connectionNotification(String eventName, Object source) {
817    if (connectionAllowed(eventName)) {
818      m_listenee = source;
819    }
820  }
821
822  /**
823   * Notify this object that it has been deregistered as a listener with
824   * a source for named event. This object is responsible
825   * for recording this fact.
826   *
827   * @param eventName the event
828   * @param source the source with which this object has been registered as
829   * a listener
830   */
831  public void disconnectionNotification(String eventName, Object source) {
832    m_listenee = null;
833  }
834
835  /**
836   * Describe <code>enumerateRequests</code> method here.
837   *
838   * @return an <code>Enumeration</code> value
839   */
840  public Enumeration enumerateRequests() {
841    Vector newVector = new Vector(0);
842    newVector.addElement("Show chart");
843    return newVector.elements();
844  }
845
846  /**
847   * Describe <code>performRequest</code> method here.
848   *
849   * @param request a <code>String</code> value
850   * @exception IllegalArgumentException if an error occurs
851   */
852  public void performRequest(String request) {
853    if (request.compareTo("Show chart") == 0) {
854      showChart();
855    } else {
856      throw new
857        IllegalArgumentException(request
858                                 + " not supported (StripChart)");
859    }
860  }
861
862  /**
863   * Tests out the StripChart from the command line
864   *
865   * @param args ignored
866   */
867  public static void main(String [] args) {
868
869    try {
870      final javax.swing.JFrame jf =
871        new javax.swing.JFrame("Weka Knowledge Flow : StipChart");
872      jf.getContentPane().setLayout(new BorderLayout());
873      final StripChart jd = new StripChart();
874      jf.getContentPane().add(jd, BorderLayout.CENTER);
875      jf.addWindowListener(new java.awt.event.WindowAdapter() {
876        public void windowClosing(java.awt.event.WindowEvent e) {
877          jf.dispose();
878          System.exit(0);
879        }
880      });
881      jf.pack();
882      jf.setVisible(true);
883      jd.showChart();
884      Random r = new Random(1);
885      for (int i = 0; i < 1020; i++) {
886        double [] pos = new double[1];
887        pos[0] = r.nextDouble();
888        jd.acceptDataPoint(pos);
889      }
890      System.err.println("Done sending data");
891    } catch (Exception ex) {
892      ex.printStackTrace();
893      System.err.println(ex.getMessage());
894    }
895  }
896}
Note: See TracBrowser for help on using the repository browser.