source: src/main/java/weka/gui/explorer/PreprocessPanel.java @ 15

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

Import di weka.

File size: 45.0 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 *    PreprocessPanel.java
19 *    Copyright (C) 2003 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23package weka.gui.explorer;
24
25import weka.core.Capabilities;
26import weka.core.CapabilitiesHandler;
27import weka.core.Instances;
28import weka.core.OptionHandler;
29import weka.core.Utils;
30import weka.core.converters.AbstractFileLoader;
31import weka.core.converters.AbstractFileSaver;
32import weka.core.converters.ConverterUtils;
33import weka.core.converters.Loader;
34import weka.core.converters.SerializedInstancesLoader;
35import weka.core.converters.URLSourcedLoader;
36import weka.datagenerators.DataGenerator;
37import weka.experiment.InstanceQuery;
38import weka.filters.Filter;
39import weka.filters.SupervisedFilter;
40import weka.filters.unsupervised.attribute.Remove;
41import weka.gui.AttributeSelectionPanel;
42import weka.gui.AttributeSummaryPanel;
43import weka.gui.AttributeVisualizationPanel;
44import weka.gui.ConverterFileChooser;
45import weka.gui.GenericObjectEditor;
46import weka.gui.InstancesSummaryPanel;
47import weka.gui.Logger;
48import weka.gui.PropertyDialog;
49import weka.gui.PropertyPanel;
50import weka.gui.SysErrLog;
51import weka.gui.TaskLogger;
52import weka.gui.ViewerDialog;
53import weka.gui.explorer.Explorer.CapabilitiesFilterChangeEvent;
54import weka.gui.explorer.Explorer.CapabilitiesFilterChangeListener;
55import weka.gui.explorer.Explorer.ExplorerPanel;
56import weka.gui.explorer.Explorer.LogHandler;
57import weka.gui.sql.SqlViewerDialog;
58
59import java.awt.BorderLayout;
60import java.awt.Dimension;
61import java.awt.FlowLayout;
62import java.awt.Font;
63import java.awt.GridLayout;
64import java.awt.Toolkit;
65import java.awt.event.ActionEvent;
66import java.awt.event.ActionListener;
67import java.awt.event.ItemEvent;
68import java.awt.event.ItemListener;
69import java.awt.event.WindowAdapter;
70import java.awt.event.WindowEvent;
71import java.beans.PropertyChangeEvent;
72import java.beans.PropertyChangeListener;
73import java.beans.PropertyChangeSupport;
74import java.io.BufferedOutputStream;
75import java.io.BufferedWriter;
76import java.io.File;
77import java.io.FileOutputStream;
78import java.io.FileWriter;
79import java.io.ObjectOutputStream;
80import java.net.URL;
81
82import javax.swing.BorderFactory;
83import javax.swing.JButton;
84import javax.swing.JCheckBox;
85import javax.swing.JComboBox;
86import javax.swing.JDialog;
87import javax.swing.JFileChooser;
88import javax.swing.JFrame;
89import javax.swing.JOptionPane;
90import javax.swing.JPanel;
91import javax.swing.JScrollPane;
92import javax.swing.JTextArea;
93import javax.swing.ListSelectionModel;
94import javax.swing.SwingUtilities;
95import javax.swing.event.ListSelectionEvent;
96import javax.swing.event.ListSelectionListener;
97import javax.swing.filechooser.FileFilter;
98
99/**
100 * This panel controls simple preprocessing of instances. Summary
101 * information on instances and attributes is shown. Filters may be
102 * configured to alter the set of instances. Altered instances may
103 * also be saved.
104 *
105 * @author Richard Kirkby (rkirkby@cs.waikato.ac.nz)
106 * @author Len Trigg (trigg@cs.waikato.ac.nz)
107 * @version $Revision: 5508 $
108 */
109public class PreprocessPanel
110  extends JPanel
111  implements CapabilitiesFilterChangeListener, ExplorerPanel, LogHandler {
112
113  /** for serialization */
114  private static final long serialVersionUID = 6764850273874813049L;
115 
116  /** Displays simple stats on the working instances */
117  protected InstancesSummaryPanel m_InstSummaryPanel =
118    new InstancesSummaryPanel();
119
120  /** Click to load base instances from a file */
121  protected JButton m_OpenFileBut = new JButton("Open file...");
122
123  /** Click to load base instances from a URL */
124  protected JButton m_OpenURLBut = new JButton("Open URL...");
125
126  /** Click to load base instances from a Database */
127  protected JButton m_OpenDBBut = new JButton("Open DB...");
128
129  /** Click to generate artificial data */
130  protected JButton m_GenerateBut = new JButton("Generate...");
131
132  /** Click to revert back to the last saved point */
133  protected JButton m_UndoBut = new JButton("Undo");
134
135  /** Click to open the current instances in a viewer */
136  protected JButton m_EditBut = new JButton("Edit...");
137
138  /** Click to apply filters and save the results */
139  protected JButton m_SaveBut = new JButton("Save...");
140 
141  /** Panel to let the user toggle attributes */
142  protected AttributeSelectionPanel m_AttPanel = new AttributeSelectionPanel();
143
144  /** Button for removing attributes */
145  protected JButton m_RemoveButton = new JButton("Remove");
146
147  /** Displays summary stats on the selected attribute */
148  protected AttributeSummaryPanel m_AttSummaryPanel =
149    new AttributeSummaryPanel();
150
151  /** Lets the user configure the filter */
152  protected GenericObjectEditor m_FilterEditor =
153    new GenericObjectEditor();
154
155  /** Filter configuration */
156  protected PropertyPanel m_FilterPanel = new PropertyPanel(m_FilterEditor);
157
158  /** Click to apply filters and save the results */
159  protected JButton m_ApplyFilterBut = new JButton("Apply");
160
161  /** The file chooser for selecting data files */
162  protected ConverterFileChooser m_FileChooser
163    = new ConverterFileChooser(new File(ExplorerDefaults.getInitialDirectory()));
164
165  /** Stores the last URL that instances were loaded from */
166  protected String m_LastURL = "http://";
167 
168  /** Stores the last sql query executed */
169  protected String m_SQLQ = new String("SELECT * FROM ?");
170 
171  /** The working instances */
172  protected Instances m_Instances;
173
174  /** The last generator that was selected */
175  protected DataGenerator m_DataGenerator = null;
176
177  /** The visualization of the attribute values */
178  protected AttributeVisualizationPanel m_AttVisualizePanel = 
179    new AttributeVisualizationPanel();
180
181  /** Keeps track of undo points */
182  protected File[] m_tempUndoFiles = new File[20]; // set number of undo ops here
183
184  /** The next available slot for an undo point */
185  protected int m_tempUndoIndex = 0;
186 
187  /**
188   * Manages sending notifications to people when we change the set of
189   * working instances.
190   */
191  protected PropertyChangeSupport m_Support = new PropertyChangeSupport(this);
192
193  /** A thread for loading/saving instances from a file or URL */
194  protected Thread m_IOThread;
195
196  /** The message logger */
197  protected Logger m_Log = new SysErrLog();
198
199  /** the parent frame */
200  protected Explorer m_Explorer = null;
201 
202  static {
203     GenericObjectEditor.registerEditors();
204  }
205 
206  /**
207   * Creates the instances panel with no initial instances.
208   */
209  public PreprocessPanel() {
210
211    // Create/Configure/Connect components
212    m_FilterEditor.setClassType(weka.filters.Filter.class);
213    if (ExplorerDefaults.getFilter() != null)
214      m_FilterEditor.setValue(ExplorerDefaults.getFilter());
215   
216    m_FilterEditor.addPropertyChangeListener(new PropertyChangeListener() {
217      public void propertyChange(PropertyChangeEvent e) {
218        m_ApplyFilterBut.setEnabled(true);
219        Capabilities currentCapabilitiesFilter = m_FilterEditor.getCapabilitiesFilter();
220        Filter filter = (Filter) m_FilterEditor.getValue();
221        Capabilities currentFilterCapabilities = null;
222        if (filter != null && currentCapabilitiesFilter != null &&
223            (filter instanceof CapabilitiesHandler)) {
224          currentFilterCapabilities = ((CapabilitiesHandler)filter).getCapabilities();
225         
226          if (!currentFilterCapabilities.supportsMaybe(currentCapabilitiesFilter) &&
227              !currentFilterCapabilities.supports(currentCapabilitiesFilter)) {
228            m_ApplyFilterBut.setEnabled(false);
229          }
230        }
231      }
232    });
233    m_OpenFileBut.setToolTipText("Open a set of instances from a file");
234    m_OpenURLBut.setToolTipText("Open a set of instances from a URL");
235    m_OpenDBBut.setToolTipText("Open a set of instances from a database");
236    m_GenerateBut.setToolTipText("Generates artificial data");
237    m_UndoBut.setToolTipText("Undo the last change to the dataset");
238    m_EditBut.setToolTipText("Open the current dataset in a Viewer for editing");
239    m_SaveBut.setToolTipText("Save the working relation to a file");
240    m_ApplyFilterBut.setToolTipText("Apply the current filter to the data");
241
242    m_FileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
243    m_OpenURLBut.addActionListener(new ActionListener() {
244      public void actionPerformed(ActionEvent e) {
245        setInstancesFromURLQ();
246      }
247    });
248    m_OpenDBBut.addActionListener(new ActionListener() {
249      public void actionPerformed(ActionEvent e) {
250        SqlViewerDialog dialog = new SqlViewerDialog(null);
251        dialog.setVisible(true);
252        if (dialog.getReturnValue() == JOptionPane.OK_OPTION)
253          setInstancesFromDBQ(dialog.getURL(), dialog.getUser(),
254                              dialog.getPassword(), dialog.getQuery(),
255                              dialog.getGenerateSparseData());
256      }
257    });
258    m_OpenFileBut.addActionListener(new ActionListener() {
259      public void actionPerformed(ActionEvent e) {
260        setInstancesFromFileQ();
261      }
262    });
263    m_GenerateBut.addActionListener(new ActionListener() {
264      public void actionPerformed(ActionEvent e) {
265        generateInstances();
266      }
267    });
268    m_UndoBut.addActionListener(new ActionListener() {
269      public void actionPerformed(ActionEvent e) {
270        undo();
271      }
272    });
273    m_EditBut.addActionListener(new ActionListener() {
274      public void actionPerformed(ActionEvent e) {
275        edit();
276      }
277    });
278    m_SaveBut.addActionListener(new ActionListener() {
279      public void actionPerformed(ActionEvent e) {
280        saveWorkingInstancesToFileQ();
281      }
282    });
283    m_ApplyFilterBut.addActionListener(new ActionListener() {
284        public void actionPerformed(ActionEvent e) {
285          applyFilter((Filter) m_FilterEditor.getValue());
286        }
287      });
288    m_AttPanel.getSelectionModel()
289      .addListSelectionListener(new ListSelectionListener() {
290        public void valueChanged(ListSelectionEvent e) {
291          if (!e.getValueIsAdjusting()) {         
292            ListSelectionModel lm = (ListSelectionModel) e.getSource();
293            for (int i = e.getFirstIndex(); i <= e.getLastIndex(); i++) {
294              if (lm.isSelectedIndex(i)) {
295                m_AttSummaryPanel.setAttribute(i);
296                m_AttVisualizePanel.setAttribute(i);
297                break;
298              }
299            }
300          }
301        }
302    });
303
304
305    m_InstSummaryPanel.setBorder(BorderFactory
306                                 .createTitledBorder("Current relation"));
307    JPanel attStuffHolderPanel = new JPanel();
308    attStuffHolderPanel.setBorder(BorderFactory
309                                  .createTitledBorder("Attributes"));
310    attStuffHolderPanel.setLayout(new BorderLayout());
311    attStuffHolderPanel.add(m_AttPanel, BorderLayout.CENTER);
312    m_RemoveButton.setEnabled(false);
313    m_RemoveButton.setToolTipText("Remove selected attributes.");
314    m_RemoveButton.addActionListener(new ActionListener() {
315        public void actionPerformed(ActionEvent e) {
316          try {
317            Remove r = new Remove();
318            int [] selected = m_AttPanel.getSelectedAttributes();
319            if (selected.length == 0) {
320              return;
321            }
322            if (selected.length == m_Instances.numAttributes()) {
323              // Pop up an error optionpane
324              JOptionPane.showMessageDialog(PreprocessPanel.this,
325                                            "Can't remove all attributes from data!\n",
326                                            "Remove Attributes",
327                                            JOptionPane.ERROR_MESSAGE);
328              m_Log.logMessage("Can't remove all attributes from data!");
329              m_Log.statusMessage("Problem removing attributes");
330              return;
331            }
332            r.setAttributeIndicesArray(selected);
333            applyFilter(r);
334          } catch (Exception ex) {
335            if (m_Log instanceof TaskLogger) {
336              ((TaskLogger)m_Log).taskFinished();
337            }
338            // Pop up an error optionpane
339            JOptionPane.showMessageDialog(PreprocessPanel.this,
340                                          "Problem filtering instances:\n"
341                                          + ex.getMessage(),
342                                          "Remove Attributes",
343                                          JOptionPane.ERROR_MESSAGE);
344            m_Log.logMessage("Problem removing attributes: " + ex.getMessage());
345            m_Log.statusMessage("Problem removing attributes");
346          }
347        }
348      });
349
350    JPanel p1 = new JPanel();
351    p1.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
352    p1.setLayout(new BorderLayout());
353    p1.add(m_RemoveButton, BorderLayout.CENTER);
354    attStuffHolderPanel.add(p1, BorderLayout.SOUTH);
355    m_AttSummaryPanel.setBorder(BorderFactory
356                    .createTitledBorder("Selected attribute"));
357    m_UndoBut.setEnabled(false);
358    m_EditBut.setEnabled(false);
359    m_SaveBut.setEnabled(false);
360    m_ApplyFilterBut.setEnabled(false);
361   
362    // Set up the GUI layout
363    JPanel buttons = new JPanel();
364    buttons.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
365    buttons.setLayout(new GridLayout(1, 6, 5, 5));
366    buttons.add(m_OpenFileBut);
367    buttons.add(m_OpenURLBut);
368    buttons.add(m_OpenDBBut);
369    buttons.add(m_GenerateBut);
370    buttons.add(m_UndoBut);
371    buttons.add(m_EditBut);
372    buttons.add(m_SaveBut);
373
374    JPanel attInfo = new JPanel();
375
376    attInfo.setLayout(new BorderLayout());
377    attInfo.add(attStuffHolderPanel, BorderLayout.CENTER);
378
379    JPanel filter = new JPanel();
380    filter.setBorder(BorderFactory
381                    .createTitledBorder("Filter"));
382    filter.setLayout(new BorderLayout());
383    filter.add(m_FilterPanel, BorderLayout.CENTER);
384    filter.add(m_ApplyFilterBut, BorderLayout.EAST); 
385
386    JPanel attVis = new JPanel();
387    attVis.setLayout( new GridLayout(2,1) );
388    attVis.add(m_AttSummaryPanel);
389
390    JComboBox colorBox = m_AttVisualizePanel.getColorBox();
391    colorBox.setToolTipText("The chosen attribute will also be used as the " +
392                            "class attribute when a filter is applied.");
393    colorBox.addItemListener(new ItemListener() {
394      public void itemStateChanged(ItemEvent ie) {
395        if (ie.getStateChange() == ItemEvent.SELECTED) {
396          updateCapabilitiesFilter(m_FilterEditor.getCapabilitiesFilter());
397        }
398      }
399    });
400    final JButton visAllBut = new JButton("Visualize All");
401    visAllBut.addActionListener(new ActionListener() {
402        public void actionPerformed(ActionEvent ae) {
403          if (m_Instances != null) {
404            try {
405              final weka.gui.beans.AttributeSummarizer as = 
406                new weka.gui.beans.AttributeSummarizer();
407              as.setColoringIndex(m_AttVisualizePanel.getColoringIndex());
408              as.setInstances(m_Instances);
409             
410              final javax.swing.JFrame jf = new javax.swing.JFrame();
411              jf.getContentPane().setLayout(new java.awt.BorderLayout());
412             
413              jf.getContentPane().add(as, java.awt.BorderLayout.CENTER);
414              jf.addWindowListener(new java.awt.event.WindowAdapter() {
415                  public void windowClosing(java.awt.event.WindowEvent e) {
416                    visAllBut.setEnabled(true);
417                    jf.dispose();
418                  }
419                });
420              jf.setSize(830,600);
421              jf.setVisible(true);
422            } catch (Exception ex) {
423              ex.printStackTrace();
424            }
425          }
426        }
427      });
428    JPanel histoHolder = new JPanel();
429    histoHolder.setLayout(new BorderLayout());
430    histoHolder.add(m_AttVisualizePanel, BorderLayout.CENTER);
431    JPanel histoControls = new JPanel();
432    histoControls.setLayout(new BorderLayout());
433    histoControls.add(colorBox, BorderLayout.CENTER);
434    histoControls.add(visAllBut, BorderLayout.EAST);
435    histoHolder.add(histoControls, BorderLayout.NORTH);
436    attVis.add(histoHolder);
437
438    JPanel lhs = new JPanel();
439    lhs.setLayout(new BorderLayout());
440    lhs.add(m_InstSummaryPanel, BorderLayout.NORTH);
441    lhs.add(attInfo, BorderLayout.CENTER);
442
443    JPanel rhs = new JPanel();
444    rhs.setLayout(new BorderLayout());
445    rhs.add(attVis, BorderLayout.CENTER);
446
447    JPanel relation = new JPanel();
448    relation.setLayout(new GridLayout(1, 2));
449    relation.add(lhs);
450    relation.add(rhs);
451
452    JPanel middle = new JPanel();
453    middle.setLayout(new BorderLayout());
454    middle.add(filter, BorderLayout.NORTH);
455    middle.add(relation, BorderLayout.CENTER);
456
457    setLayout(new BorderLayout());
458    add(buttons, BorderLayout.NORTH);
459    add(middle, BorderLayout.CENTER);
460  }
461
462  /**
463   * Sets the Logger to receive informational messages
464   *
465   * @param newLog the Logger that will now get info messages
466   */
467  public void setLog(Logger newLog) {
468
469    m_Log = newLog;
470  }
471 
472  /**
473   * Tells the panel to use a new base set of instances.
474   *
475   * @param inst a set of Instances
476   */
477  public void setInstances(Instances inst) {
478
479    m_Instances = inst;
480    try {
481      Runnable r = new Runnable() {
482        public void run() {
483          m_InstSummaryPanel.setInstances(m_Instances);
484          m_AttPanel.setInstances(m_Instances);
485          m_RemoveButton.setEnabled(true);
486          m_AttSummaryPanel.setInstances(m_Instances);
487          m_AttVisualizePanel.setInstances(m_Instances);
488
489          // select the first attribute in the list
490          m_AttPanel.getSelectionModel().setSelectionInterval(0, 0);
491          m_AttSummaryPanel.setAttribute(0);
492          m_AttVisualizePanel.setAttribute(0);
493
494          m_ApplyFilterBut.setEnabled(true);
495
496          m_Log.logMessage("Base relation is now "
497                           + m_Instances.relationName()
498                           + " (" + m_Instances.numInstances()
499                           + " instances)");
500          m_SaveBut.setEnabled(true);
501          m_EditBut.setEnabled(true);
502          m_Log.statusMessage("OK");
503          // Fire a propertychange event
504          m_Support.firePropertyChange("", null, null);
505         
506          // notify GOEs about change
507          try {
508            // get rid of old filter settings
509            getExplorer().notifyCapabilitiesFilterListener(null);
510
511            int oldIndex = m_Instances.classIndex();
512            m_Instances.setClassIndex(m_AttVisualizePanel.getColorBox().getSelectedIndex() - 1);
513           
514            // send new ones
515            if (ExplorerDefaults.getInitGenericObjectEditorFilter())
516              getExplorer().notifyCapabilitiesFilterListener(
517                  Capabilities.forInstances(m_Instances));
518            else
519              getExplorer().notifyCapabilitiesFilterListener(
520                  Capabilities.forInstances(new Instances(m_Instances, 0)));
521
522            m_Instances.setClassIndex(oldIndex);
523          }
524          catch (Exception e) {
525            e.printStackTrace();
526            m_Log.logMessage(e.toString());
527          }
528        }
529      };
530      if (SwingUtilities.isEventDispatchThread()) {
531        r.run();
532      } else {
533        SwingUtilities.invokeAndWait(r);
534      }
535    } catch (Exception ex) {
536      ex.printStackTrace();
537      JOptionPane.showMessageDialog(this,
538                                    "Problem setting base instances:\n"
539                                    + ex,
540                                    "Instances",
541                                    JOptionPane.ERROR_MESSAGE);
542    }
543  }
544
545  /**
546   * Gets the working set of instances.
547   *
548   * @return the working instances
549   */
550  public Instances getInstances() {
551
552    return m_Instances;
553  }
554 
555  /**
556   * Adds a PropertyChangeListener who will be notified of value changes.
557   *
558   * @param l a value of type 'PropertyChangeListener'
559   */
560  public void addPropertyChangeListener(PropertyChangeListener l) {
561
562    m_Support.addPropertyChangeListener(l);
563  }
564
565  /**
566   * Removes a PropertyChangeListener.
567   *
568   * @param l a value of type 'PropertyChangeListener'
569   */
570  public void removePropertyChangeListener(PropertyChangeListener l) {
571
572    m_Support.removePropertyChangeListener(l);
573  }
574 
575  /**
576   * Passes the dataset through the filter that has been configured for use.
577   *
578   * @param filter      the filter to apply
579   */
580  protected void applyFilter(final Filter filter) {
581
582    if (m_IOThread == null) {
583      m_IOThread = new Thread() {
584        public void run() {
585          try {
586
587            if (filter != null) {
588           
589              if (m_Log instanceof TaskLogger) {
590                ((TaskLogger)m_Log).taskStarted();
591              }
592              m_Log.statusMessage("Passing dataset through filter "
593                  + filter.getClass().getName());
594              String cmd = filter.getClass().getName();
595              if (filter instanceof OptionHandler)
596                cmd += " " + Utils.joinOptions(((OptionHandler) filter).getOptions());
597              m_Log.logMessage("Command: " + cmd);
598              int classIndex = m_AttVisualizePanel.getColoringIndex();
599              if ((classIndex < 0) && (filter instanceof SupervisedFilter)) {
600                throw new IllegalArgumentException("Class (colour) needs to " +
601                                                   "be set for supervised " +
602                                                   "filter.");
603              }
604              Instances copy = new Instances(m_Instances);
605              copy.setClassIndex(classIndex);
606              filter.setInputFormat(copy);
607              Instances newInstances = Filter.useFilter(copy, filter);
608              if (newInstances == null || newInstances.numAttributes() < 1) {
609                throw new Exception("Dataset is empty.");
610              }
611              m_Log.statusMessage("Saving undo information");
612              addUndoPoint();
613              m_AttVisualizePanel.setColoringIndex(copy.classIndex());
614              // if class was not set before, reset it again after use of filter
615              if (m_Instances.classIndex() < 0)
616                newInstances.setClassIndex(-1);
617              m_Instances = newInstances;
618              setInstances(m_Instances);
619              if (m_Log instanceof TaskLogger) {
620                ((TaskLogger)m_Log).taskFinished();
621              }
622            }
623           
624          } catch (Exception ex) {
625       
626            if (m_Log instanceof TaskLogger) {
627              ((TaskLogger)m_Log).taskFinished();
628            }
629            // Pop up an error optionpane
630            JOptionPane.showMessageDialog(PreprocessPanel.this,
631                                          "Problem filtering instances:\n"
632                                          + ex.getMessage(),
633                                          "Apply Filter",
634                                          JOptionPane.ERROR_MESSAGE);
635            m_Log.logMessage("Problem filtering instances: " + ex.getMessage());
636            m_Log.statusMessage("Problem filtering instances");
637          }
638          m_IOThread = null;
639        }
640      };
641      m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
642      m_IOThread.start();
643    } else {
644      JOptionPane.showMessageDialog(this,
645                                    "Can't apply filter at this time,\n"
646                                    + "currently busy with other IO",
647                                    "Apply Filter",
648                                    JOptionPane.WARNING_MESSAGE);
649    }
650  }
651
652  /**
653   * Queries the user for a file to save instances as, then saves the
654   * instances in a background process. This is done in the IO
655   * thread, and an error message is popped up if the IO thread is busy.
656   */
657  public void saveWorkingInstancesToFileQ() {
658   
659    if (m_IOThread == null) {
660      m_FileChooser.setCapabilitiesFilter(m_FilterEditor.getCapabilitiesFilter());
661      m_FileChooser.setAcceptAllFileFilterUsed(false);
662      int returnVal = m_FileChooser.showSaveDialog(this);
663      if (returnVal == JFileChooser.APPROVE_OPTION) {
664        Instances inst = new Instances(m_Instances);
665        inst.setClassIndex(m_AttVisualizePanel.getColoringIndex());
666        saveInstancesToFile(m_FileChooser.getSaver(), inst);
667      }
668      FileFilter temp = m_FileChooser.getFileFilter();
669      m_FileChooser.setAcceptAllFileFilterUsed(true);
670      m_FileChooser.setFileFilter(temp);
671    }
672    else {
673      JOptionPane.showMessageDialog(this,
674                                    "Can't save at this time,\n"
675                                    + "currently busy with other IO",
676                                    "Save Instances",
677                                    JOptionPane.WARNING_MESSAGE);
678    }
679  }
680 
681  /**
682   * saves the data with the specified saver
683   *
684   * @param saver       the saver to use for storing the data
685   * @param inst        the data to save
686   */
687  public void saveInstancesToFile(final AbstractFileSaver saver, final Instances inst) {
688    if (m_IOThread == null) {
689      m_IOThread = new Thread() {
690          public void run() {
691            try {
692              m_Log.statusMessage("Saving to file...");
693
694              saver.setInstances(inst);
695              saver.writeBatch();
696             
697              m_Log.statusMessage("OK");
698            }
699            catch (Exception ex) {
700              ex.printStackTrace();
701              m_Log.logMessage(ex.getMessage());
702            }
703            m_IOThread = null;
704          }
705        };
706      m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
707      m_IOThread.start();
708    }
709    else {
710      JOptionPane.showMessageDialog(this,
711                                    "Can't save at this time,\n"
712                                    + "currently busy with other IO",
713                                    "Saving instances",
714                                    JOptionPane.WARNING_MESSAGE);
715    } 
716  }
717 
718  /**
719   * Queries the user for a file to load instances from, then loads the
720   * instances in a background process. This is done in the IO
721   * thread, and an error message is popped up if the IO thread is busy.
722   */
723  public void setInstancesFromFileQ() {
724   
725    if (m_IOThread == null) {
726      int returnVal = m_FileChooser.showOpenDialog(this);
727      if (returnVal == JFileChooser.APPROVE_OPTION) {
728        try {
729          addUndoPoint();
730        }
731        catch (Exception ignored) {
732          // ignored
733        }
734
735        if (m_FileChooser.getLoader() == null) {
736          JOptionPane.showMessageDialog(this,
737              "Cannot determine file loader automatically, please choose one.",
738              "Load Instances",
739              JOptionPane.ERROR_MESSAGE);
740          converterQuery(m_FileChooser.getSelectedFile());
741        }
742        else {
743          setInstancesFromFile(m_FileChooser.getLoader());
744        }
745           
746      }
747    } else {
748      JOptionPane.showMessageDialog(this,
749                                    "Can't load at this time,\n"
750                                    + "currently busy with other IO",
751                                    "Load Instances",
752                                    JOptionPane.WARNING_MESSAGE);
753    }
754  }
755
756  /**
757   * Loads (non-sparse) instances from an SQL query the user provided with the
758   * SqlViewerDialog, then loads the instances in a background process. This is
759   * done in the IO thread, and an error message is popped up if the IO thread
760   * is busy.
761   *
762   * @param url           the database URL
763   * @param user          the user to connect as
764   * @param pw            the password of the user
765   * @param query         the query for retrieving instances from
766   */
767  public void setInstancesFromDBQ(String url, String user, 
768                                  String pw, String query) {
769    setInstancesFromDBQ(url, user, pw, query, false);
770  }
771
772  /**
773   * Loads instances from an SQL query the user provided with the
774   * SqlViewerDialog, then loads the instances in a background process. This is
775   * done in the IO thread, and an error message is popped up if the IO thread
776   * is busy.
777   *
778   * @param url         the database URL
779   * @param user        the user to connect as
780   * @param pw          the password of the user
781   * @param query       the query for retrieving instances from
782   * @param sparse      whether to create sparse or non-sparse instances
783   */
784  public void setInstancesFromDBQ(String url, String user, 
785                                  String pw, String query,
786                                  boolean sparse) {
787    if (m_IOThread == null) {
788      try {
789        InstanceQuery InstQ = new InstanceQuery();
790        InstQ.setDatabaseURL(url);
791        InstQ.setUsername(user);
792        InstQ.setPassword(pw);
793        InstQ.setQuery(query);
794        InstQ.setSparseData(sparse);
795       
796        // we have to disconnect, otherwise we can't change the DB!
797        if (InstQ.isConnected())
798          InstQ.disconnectFromDatabase();
799
800        InstQ.connectToDatabase();     
801        try {
802          addUndoPoint();
803        } catch (Exception ignored) {}
804        setInstancesFromDB(InstQ);
805      } catch (Exception ex) {
806        JOptionPane.showMessageDialog(this,
807                                      "Problem connecting to database:\n"
808                                      + ex.getMessage(),
809                                      "Load Instances",
810                                      JOptionPane.ERROR_MESSAGE);
811      }
812     
813    } else {
814      JOptionPane.showMessageDialog(this,
815                                     "Can't load at this time,\n"
816                                    + "currently busy with other IO",
817                                    "Load Instances",
818                                    JOptionPane.WARNING_MESSAGE);
819    }
820  }
821   
822  /**
823   * Queries the user for a URL to load instances from, then loads the
824   * instances in a background process. This is done in the IO
825   * thread, and an error message is popped up if the IO thread is busy.
826   */
827  public void setInstancesFromURLQ() {
828   
829    if (m_IOThread == null) {
830      try {
831        String urlName = (String) JOptionPane.showInputDialog(this,
832                        "Enter the source URL",
833                        "Load Instances",
834                        JOptionPane.QUESTION_MESSAGE,
835                        null,
836                        null,
837                        m_LastURL);
838        if (urlName != null) {
839          m_LastURL = urlName;
840          URL url = new URL(urlName);
841          try {
842            addUndoPoint();
843          } catch (Exception ignored) {}
844          setInstancesFromURL(url);
845        }
846      } catch (Exception ex) {
847        ex.printStackTrace();
848        JOptionPane.showMessageDialog(this,
849                                      "Problem with URL:\n"
850                                      + ex.getMessage(),
851                                      "Load Instances",
852                                      JOptionPane.ERROR_MESSAGE);
853      }
854    } else {
855      JOptionPane.showMessageDialog(this,
856                                    "Can't load at this time,\n"
857                                    + "currently busy with other IO",
858                                    "Load Instances",
859                                    JOptionPane.WARNING_MESSAGE);
860    }
861  }
862 
863  /**
864   * sets Instances generated via DataGenerators (pops up a Dialog)
865   */
866  public void generateInstances() {
867    if (m_IOThread == null) {
868      m_IOThread = new Thread() {
869          public void run() {
870            try {
871              // create dialog
872              final DataGeneratorPanel generatorPanel = new DataGeneratorPanel();
873              final JDialog dialog = new JDialog();
874              final JButton generateButton = new JButton("Generate");
875              final JCheckBox showOutputCheckBox = 
876                                  new JCheckBox("Show generated data as text, incl. comments");
877
878              showOutputCheckBox.setMnemonic('S');
879              generatorPanel.setLog(m_Log);
880              generatorPanel.setGenerator(m_DataGenerator);
881              generatorPanel.setPreferredSize(
882                  new Dimension(
883                        300, 
884                        (int) generatorPanel.getPreferredSize().getHeight()));
885              generateButton.setMnemonic('G');
886              generateButton.setToolTipText("Generates the dataset according the settings.");
887              generateButton.addActionListener(new ActionListener(){
888                  public void actionPerformed(ActionEvent evt){
889                    // generate
890                    generatorPanel.execute();
891                    boolean generated = (generatorPanel.getInstances() != null);
892                    if (generated)
893                      setInstances(generatorPanel.getInstances());
894
895                    // close dialog
896                    dialog.dispose();
897
898                    // get last generator
899                    m_DataGenerator = generatorPanel.getGenerator();
900
901                    // display output?
902                    if ( (generated) && (showOutputCheckBox.isSelected()) )
903                      showGeneratedInstances(generatorPanel.getOutput());
904                }
905              });
906              dialog.setTitle("DataGenerator");
907              dialog.getContentPane().add(generatorPanel, BorderLayout.CENTER);
908              dialog.getContentPane().add(generateButton, BorderLayout.EAST);
909              dialog.getContentPane().add(showOutputCheckBox, BorderLayout.SOUTH);
910              dialog.pack();
911             
912              // display dialog
913              dialog.setVisible(true);
914            } 
915            catch (Exception ex) {
916              ex.printStackTrace();
917              m_Log.logMessage(ex.getMessage());
918            }
919            m_IOThread = null;
920          }
921        };
922      m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
923      m_IOThread.start();
924    } 
925    else {
926      JOptionPane.showMessageDialog(this,
927                                    "Can't generate data at this time,\n"
928                                    + "currently busy with other IO",
929                                    "Generate Data",
930                                    JOptionPane.WARNING_MESSAGE);
931    }
932  }
933 
934  /**
935   * displays a dialog with the generated instances from the DataGenerator
936   *
937   * @param data        the data to display
938   */
939  protected void showGeneratedInstances(String data) {
940    final JDialog dialog = new JDialog();
941    final JButton saveButton = new JButton("Save");
942    final JButton closeButton = new JButton("Close");
943    final JTextArea textData = new JTextArea(data);
944    final JPanel panel = new JPanel();
945    panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
946    textData.setEditable(false);
947    textData.setFont(
948        new Font("Monospaced", Font.PLAIN, textData.getFont().getSize()));
949
950    saveButton.setMnemonic('S');
951    saveButton.setToolTipText("Saves the output to a file");
952    saveButton.addActionListener(new ActionListener(){
953      public void actionPerformed(ActionEvent evt){
954        JFileChooser filechooser = new JFileChooser();
955        int result = filechooser.showSaveDialog(dialog);
956        if (result == JFileChooser.APPROVE_OPTION) {
957          try {
958            BufferedWriter writer = new BufferedWriter(
959                                      new FileWriter(
960                                        filechooser.getSelectedFile()));
961            writer.write(textData.getText());
962            writer.flush();
963            writer.close();
964            JOptionPane.showMessageDialog(
965              dialog, 
966              "Output successfully saved to file '" 
967              + filechooser.getSelectedFile() + "'!",
968              "Information",
969              JOptionPane.INFORMATION_MESSAGE);
970          }
971          catch (Exception e) {
972            e.printStackTrace();
973          }
974          dialog.dispose();
975        }
976      }
977    });
978    closeButton.setMnemonic('C');
979    closeButton.setToolTipText("Closes the dialog");
980    closeButton.addActionListener(new ActionListener(){
981      public void actionPerformed(ActionEvent evt){
982        dialog.dispose();
983      }
984    });
985    panel.add(saveButton);
986    panel.add(closeButton);
987    dialog.setTitle("Generated Instances (incl. comments)");
988    dialog.getContentPane().add(new JScrollPane(textData), BorderLayout.CENTER);
989    dialog.getContentPane().add(panel, BorderLayout.SOUTH);
990    dialog.pack();
991
992    // make sure, it's not bigger than 80% of the screen
993    Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
994    int width  = dialog.getWidth() > screen.getWidth()*0.8
995                    ? (int) (screen.getWidth()*0.8) : dialog.getWidth();
996    int height = dialog.getHeight() > screen.getHeight()*0.8 
997                    ? (int) (screen.getHeight()*0.8) : dialog.getHeight();
998    dialog.setSize(width, height);
999   
1000    // display dialog
1001    dialog.setVisible(true);
1002  }
1003
1004  /**
1005   * Pops up generic object editor with list of conversion filters
1006   *
1007   * @param f the File
1008   */
1009  private void converterQuery(final File f) {
1010    final GenericObjectEditor convEd = new GenericObjectEditor(true);
1011
1012    try {
1013      convEd.setClassType(weka.core.converters.Loader.class);
1014      convEd.setValue(new weka.core.converters.CSVLoader());
1015      ((GenericObjectEditor.GOEPanel)convEd.getCustomEditor())
1016        .addOkListener(new ActionListener() {
1017            public void actionPerformed(ActionEvent e) {
1018              tryConverter((Loader)convEd.getValue(), f);
1019            }
1020          });
1021    } catch (Exception ex) {
1022    }
1023
1024    PropertyDialog pd;
1025    if (PropertyDialog.getParentDialog(this) != null)
1026      pd = new PropertyDialog(PropertyDialog.getParentDialog(this), convEd, 100, 100);
1027    else
1028      pd = new PropertyDialog(PropertyDialog.getParentFrame(this), convEd, 100, 100);
1029    pd.setVisible(true);
1030  }
1031
1032  /**
1033   * Applies the selected converter
1034   *
1035   * @param cnv the converter to apply to the input file
1036   * @param f the input file
1037   */
1038  private void tryConverter(final Loader cnv, final File f) {
1039
1040    if (m_IOThread == null) {
1041      m_IOThread = new Thread() {
1042          public void run() {
1043            try {
1044              cnv.setSource(f);
1045              Instances inst = cnv.getDataSet();
1046              setInstances(inst);
1047            } catch (Exception ex) {
1048              m_Log.statusMessage(cnv.getClass().getName()+" failed to load "
1049                                 +f.getName());
1050              JOptionPane.showMessageDialog(PreprocessPanel.this,
1051                                            cnv.getClass().getName()+" failed to load '"
1052                                            + f.getName() + "'.\n"
1053                                            + "Reason:\n" + ex.getMessage(),
1054                                            "Convert File",
1055                                            JOptionPane.ERROR_MESSAGE);
1056              m_IOThread = null;
1057              converterQuery(f);
1058            }
1059            m_IOThread = null;
1060          }
1061        };
1062      m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
1063      m_IOThread.start();
1064    }
1065  }
1066
1067  /**
1068   * Loads results from a set of instances retrieved with the supplied loader.
1069   * This is started in the IO thread, and a dialog is popped up
1070   * if there's a problem.
1071   *
1072   * @param loader      the loader to use
1073   */
1074  public void setInstancesFromFile(final AbstractFileLoader loader) {
1075     
1076    if (m_IOThread == null) {
1077      m_IOThread = new Thread() {
1078        public void run() {
1079          try {
1080            m_Log.statusMessage("Reading from file...");
1081            Instances inst = loader.getDataSet();
1082            setInstances(inst);
1083          }
1084          catch (Exception ex) {
1085            m_Log.statusMessage(
1086                "File '" + loader.retrieveFile() + "' not recognised as an '"
1087                + loader.getFileDescription() + "' file.");
1088            m_IOThread = null;
1089            if (JOptionPane.showOptionDialog(PreprocessPanel.this,
1090                                             "File '" + loader.retrieveFile()
1091                                             + "' not recognised as an '"
1092                                             + loader.getFileDescription() 
1093                                             + "' file.\n"
1094                                             + "Reason:\n" + ex.getMessage(),
1095                                             "Load Instances",
1096                                             0,
1097                                             JOptionPane.ERROR_MESSAGE,
1098                                             null,
1099                                             new String[] {"OK", "Use Converter"},
1100                                             null) == 1) {
1101           
1102              converterQuery(loader.retrieveFile());
1103            }
1104          }
1105          m_IOThread = null;
1106        }
1107      };
1108      m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
1109      m_IOThread.start();
1110    } else {
1111      JOptionPane.showMessageDialog(this,
1112                                    "Can't load at this time,\n"
1113                                    + "currently busy with other IO",
1114                                    "Load Instances",
1115                                    JOptionPane.WARNING_MESSAGE);
1116    }
1117  }
1118 
1119  /**
1120   * Loads instances from a database
1121   *
1122   * @param iq the InstanceQuery object to load from (this is assumed
1123   * to have been already connected to a valid database).
1124   */
1125  public void setInstancesFromDB(final InstanceQuery iq) {
1126    if (m_IOThread == null) {
1127      m_IOThread = new Thread() {
1128        public void run() {
1129         
1130          try {
1131            m_Log.statusMessage("Reading from database...");
1132            final Instances i = iq.retrieveInstances();
1133            SwingUtilities.invokeAndWait(new Runnable() {
1134              public void run() {
1135                setInstances(new Instances(i));
1136              }
1137            });
1138            iq.disconnectFromDatabase();
1139          } catch (Exception ex) {
1140            m_Log.statusMessage("Problem executing DB query "+m_SQLQ);
1141            JOptionPane.showMessageDialog(PreprocessPanel.this,
1142                                          "Couldn't read from database:\n"
1143                                          + ex.getMessage(),
1144                                          "Load Instances",
1145                                          JOptionPane.ERROR_MESSAGE);
1146          }
1147
1148           m_IOThread = null;
1149        }
1150      };
1151
1152      m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
1153      m_IOThread.start();
1154    } else {
1155       JOptionPane.showMessageDialog(this,
1156                                    "Can't load at this time,\n"
1157                                    + "currently busy with other IO",
1158                                    "Load Instances",
1159                                    JOptionPane.WARNING_MESSAGE);
1160    }
1161  }
1162
1163  /**
1164   * Loads instances from a URL.
1165   *
1166   * @param u the URL to load from.
1167   */
1168  public void setInstancesFromURL(final URL u) {
1169
1170    if (m_IOThread == null) {
1171      m_IOThread = new Thread() {
1172        public void run() {
1173
1174          try {
1175            m_Log.statusMessage("Reading from URL...");
1176            AbstractFileLoader loader = ConverterUtils.getURLLoaderForFile(u.toString());
1177            if (loader == null)
1178              throw new Exception("No suitable URLSourcedLoader found for URL!\n" + u);
1179            ((URLSourcedLoader) loader).setURL(u.toString());
1180            setInstances(loader.getDataSet());
1181          } catch (Exception ex) {
1182            ex.printStackTrace();
1183            m_Log.statusMessage("Problem reading " + u);
1184            JOptionPane.showMessageDialog(PreprocessPanel.this,
1185                                          "Couldn't read from URL:\n"
1186                                          + u + "\n"
1187                                          + ex.getMessage(),
1188                                          "Load Instances",
1189                                          JOptionPane.ERROR_MESSAGE);
1190          }
1191
1192          m_IOThread = null;
1193        }
1194      };
1195      m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
1196      m_IOThread.start();
1197    } else {
1198      JOptionPane.showMessageDialog(this,
1199                                    "Can't load at this time,\n"
1200                                    + "currently busy with other IO",
1201                                    "Load Instances",
1202                                    JOptionPane.WARNING_MESSAGE);
1203    }
1204  }
1205
1206  /**
1207   * Backs up the current state of the dataset, so the changes can be undone.
1208   *
1209   * @throws Exception  if an error occurs
1210   */
1211  public void addUndoPoint() throws Exception {
1212   
1213    if (m_Instances != null) {
1214      // create temporary file
1215      File tempFile = File.createTempFile("weka", SerializedInstancesLoader.FILE_EXTENSION);
1216      tempFile.deleteOnExit();
1217
1218      ObjectOutputStream oos = 
1219        new ObjectOutputStream(
1220        new BufferedOutputStream(
1221        new FileOutputStream(tempFile)));
1222   
1223      oos.writeObject(m_Instances);
1224      oos.flush();
1225      oos.close();
1226
1227      // update undo file list
1228      if (m_tempUndoFiles[m_tempUndoIndex] != null) {
1229        // remove undo points that are too old
1230        m_tempUndoFiles[m_tempUndoIndex].delete();
1231      }
1232      m_tempUndoFiles[m_tempUndoIndex] = tempFile;
1233      if (++m_tempUndoIndex >= m_tempUndoFiles.length) {
1234        // wrap pointer around
1235        m_tempUndoIndex = 0;
1236      }
1237
1238      m_UndoBut.setEnabled(true);
1239    }
1240  }
1241
1242  /**
1243   * Reverts to the last backed up version of the dataset.
1244   */
1245  public void undo() {
1246
1247    if (--m_tempUndoIndex < 0) {
1248      // wrap pointer around
1249      m_tempUndoIndex = m_tempUndoFiles.length-1;
1250    }
1251   
1252    if (m_tempUndoFiles[m_tempUndoIndex] != null) {
1253      // load instances from the temporary file
1254      AbstractFileLoader loader = ConverterUtils.getLoaderForFile(m_tempUndoFiles[m_tempUndoIndex]);
1255      try {
1256        loader.setFile(m_tempUndoFiles[m_tempUndoIndex]);
1257        setInstancesFromFile(loader);
1258      }
1259      catch (Exception e) {
1260        e.printStackTrace();
1261        m_Log.logMessage(e.toString());
1262        JOptionPane.showMessageDialog(PreprocessPanel.this,
1263            "Cannot perform undo operation!\n" + e.toString(),
1264            "Undo",
1265            JOptionPane.ERROR_MESSAGE);
1266      }
1267
1268      // update undo file list
1269      m_tempUndoFiles[m_tempUndoIndex] = null;
1270    }
1271   
1272    // update undo button
1273    int temp = m_tempUndoIndex-1;
1274    if (temp < 0) {
1275      temp = m_tempUndoFiles.length-1;
1276    }
1277    m_UndoBut.setEnabled(m_tempUndoFiles[temp] != null);
1278  }
1279 
1280  /**
1281   * edits the current instances object in the viewer
1282   */
1283  public void edit() {
1284    ViewerDialog        dialog;
1285    int                 result;
1286    Instances           copy;
1287    Instances           newInstances;
1288   
1289    final int classIndex = m_AttVisualizePanel.getColoringIndex();
1290    copy   = new Instances(m_Instances);
1291    copy.setClassIndex(classIndex);
1292    dialog = new ViewerDialog(null);
1293    result = dialog.showDialog(copy);
1294    if (result == ViewerDialog.APPROVE_OPTION) {
1295      try {
1296        addUndoPoint();
1297      }
1298      catch (Exception e) {
1299        e.printStackTrace();
1300      }
1301      // if class was not set before, reset it again after use of filter
1302      newInstances = dialog.getInstances();
1303      if (m_Instances.classIndex() < 0)
1304        newInstances.setClassIndex(-1);
1305      setInstances(newInstances);
1306    }
1307  }
1308
1309  /**
1310   * Sets the Explorer to use as parent frame (used for sending notifications
1311   * about changes in the data)
1312   *
1313   * @param parent      the parent frame
1314   */
1315  public void setExplorer(Explorer parent) {
1316    m_Explorer = parent;
1317  }
1318 
1319  /**
1320   * returns the parent Explorer frame
1321   *
1322   * @return            the parent
1323   */
1324  public Explorer getExplorer() {
1325    return m_Explorer;
1326  }
1327 
1328  /**
1329   * updates the capabilities filter of the GOE
1330   *
1331   * @param filter      the new filter to use
1332   */
1333  protected void updateCapabilitiesFilter(Capabilities filter) {
1334    Instances           tempInst;
1335    Capabilities        filterClass;
1336
1337    if (filter == null) {
1338      m_FilterEditor.setCapabilitiesFilter(new Capabilities(null));
1339      return;
1340    }
1341   
1342    if (!ExplorerDefaults.getInitGenericObjectEditorFilter())
1343      tempInst = new Instances(m_Instances, 0);
1344    else
1345      tempInst = new Instances(m_Instances);
1346    tempInst.setClassIndex(m_AttVisualizePanel.getColorBox().getSelectedIndex() - 1);
1347
1348    try {
1349      filterClass = Capabilities.forInstances(tempInst);
1350    }
1351    catch (Exception e) {
1352      filterClass = new Capabilities(null);
1353    }
1354   
1355    // set new filter
1356    m_FilterEditor.setCapabilitiesFilter(filterClass);
1357   
1358    // check capabilities
1359    m_ApplyFilterBut.setEnabled(true);
1360    Capabilities currentCapabilitiesFilter = m_FilterEditor.getCapabilitiesFilter();
1361    Filter currentFilter = (Filter) m_FilterEditor.getValue();
1362    Capabilities currentFilterCapabilities = null;
1363    if (currentFilter != null && currentCapabilitiesFilter != null &&
1364        (currentFilter instanceof CapabilitiesHandler)) {
1365      currentFilterCapabilities = ((CapabilitiesHandler)currentFilter).getCapabilities();
1366     
1367      if (!currentFilterCapabilities.supportsMaybe(currentCapabilitiesFilter) &&
1368          !currentFilterCapabilities.supports(currentCapabilitiesFilter)) {
1369        m_ApplyFilterBut.setEnabled(false);
1370      }
1371    }
1372  }
1373 
1374  /**
1375   * method gets called in case of a change event
1376   *
1377   * @param e           the associated change event
1378   */
1379  public void capabilitiesFilterChanged(CapabilitiesFilterChangeEvent e) {
1380    if (e.getFilter() == null)
1381      updateCapabilitiesFilter(null);
1382    else
1383      updateCapabilitiesFilter((Capabilities) e.getFilter().clone());
1384  }
1385 
1386  /**
1387   * Returns the title for the tab in the Explorer
1388   *
1389   * @return            the title of this tab
1390   */
1391  public String getTabTitle() {
1392    return "Preprocess";
1393  }
1394 
1395  /**
1396   * Returns the tooltip for the tab in the Explorer
1397   *
1398   * @return            the tooltip of this tab
1399   */
1400  public String getTabTitleToolTip() {
1401    return "Open/Edit/Save instances";
1402  }
1403 
1404  /**
1405   * Tests out the instance-preprocessing panel from the command line.
1406   *
1407   * @param args ignored
1408   */
1409  public static void main(String [] args) {
1410
1411    try {
1412      final JFrame jf = new JFrame("Weka Explorer: Preprocess");
1413      jf.getContentPane().setLayout(new BorderLayout());
1414      final PreprocessPanel sp = new PreprocessPanel();
1415      jf.getContentPane().add(sp, BorderLayout.CENTER);
1416      weka.gui.LogPanel lp = new weka.gui.LogPanel();
1417      sp.setLog(lp);
1418      jf.getContentPane().add(lp, BorderLayout.SOUTH);
1419      jf.addWindowListener(new WindowAdapter() {
1420        public void windowClosing(WindowEvent e) {
1421          jf.dispose();
1422          System.exit(0);
1423        }
1424      });
1425      jf.pack();
1426      jf.setSize(800, 600);
1427      jf.setVisible(true);
1428    } catch (Exception ex) {
1429      ex.printStackTrace();
1430      System.err.println(ex.getMessage());
1431    }
1432  }
1433}
Note: See TracBrowser for help on using the repository browser.