~ubuntu-branches/ubuntu/precise/weka/precise

« back to all changes in this revision

Viewing changes to weka/gui/arffviewer/ArffViewerMainPanel.java

  • Committer: Bazaar Package Importer
  • Author(s): Soeren Sonnenburg
  • Date: 2008-02-24 09:18:45 UTC
  • Revision ID: james.westby@ubuntu.com-20080224091845-1l8zy6fm6xipbzsr
Tags: upstream-3.5.7+tut1
ImportĀ upstreamĀ versionĀ 3.5.7+tut1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 * ArffViewerMainPanel.java
 
19
 * Copyright (C) 2005 University of Waikato, Hamilton, New Zealand
 
20
 *
 
21
 */
 
22
 
 
23
package weka.gui.arffviewer;
 
24
 
 
25
import weka.core.Capabilities;
 
26
import weka.core.Instances;
 
27
import weka.core.converters.AbstractSaver;
 
28
import weka.gui.ComponentHelper;
 
29
import weka.gui.ConverterFileChooser;
 
30
import weka.gui.JTableHelper;
 
31
import weka.gui.ListSelectorDialog;
 
32
 
 
33
import java.awt.BorderLayout;
 
34
import java.awt.Container;
 
35
import java.awt.Cursor;
 
36
import java.awt.Window;
 
37
import java.awt.event.ActionEvent;
 
38
import java.awt.event.ActionListener;
 
39
import java.awt.event.KeyEvent;
 
40
import java.awt.event.WindowEvent;
 
41
import java.io.File;
 
42
import java.util.Collections;
 
43
import java.util.HashSet;
 
44
import java.util.Iterator;
 
45
import java.util.Vector;
 
46
 
 
47
import javax.swing.JComponent;
 
48
import javax.swing.JFrame;
 
49
import javax.swing.JInternalFrame;
 
50
import javax.swing.JList;
 
51
import javax.swing.JMenu;
 
52
import javax.swing.JMenuBar;
 
53
import javax.swing.JMenuItem;
 
54
import javax.swing.JOptionPane;
 
55
import javax.swing.JPanel;
 
56
import javax.swing.JTabbedPane;
 
57
import javax.swing.KeyStroke;
 
58
import javax.swing.event.ChangeEvent;
 
59
import javax.swing.event.ChangeListener;
 
60
 
 
61
/**
 
62
 * The main panel of the ArffViewer. It has a reference to the menu, that an
 
63
 * implementing JFrame only needs to add via the setJMenuBar(JMenuBar) method.
 
64
 *
 
65
 *
 
66
 * @author FracPete (fracpete at waikato dot ac dot nz)
 
67
 * @version $Revision: 1.7 $ 
 
68
 */
 
69
 
 
70
public class ArffViewerMainPanel 
 
71
  extends JPanel 
 
72
  implements ActionListener, ChangeListener {
 
73
  
 
74
  /** for serialization */
 
75
  static final long serialVersionUID = -8763161167586738753L;
 
76
  
 
77
  /** the default for width */
 
78
  public final static int    DEFAULT_WIDTH     = -1;
 
79
  /** the default for height */
 
80
  public final static int    DEFAULT_HEIGHT    = -1;
 
81
  /** the default for left */
 
82
  public final static int    DEFAULT_LEFT      = -1;
 
83
  /** the default for top */
 
84
  public final static int    DEFAULT_TOP       = -1;
 
85
  /** default width */
 
86
  public final static int    WIDTH             = 800;
 
87
  /** default height */
 
88
  public final static int    HEIGHT            = 600;
 
89
 
 
90
  protected Container             parent;
 
91
  protected JTabbedPane           tabbedPane;
 
92
  protected JMenuBar              menuBar;
 
93
  protected JMenu                 menuFile;
 
94
  protected JMenuItem             menuFileOpen;
 
95
  protected JMenuItem             menuFileSave;
 
96
  protected JMenuItem             menuFileSaveAs;
 
97
  protected JMenuItem             menuFileClose;
 
98
  protected JMenuItem             menuFileCloseAll;
 
99
  protected JMenuItem             menuFileProperties;
 
100
  protected JMenuItem             menuFileExit;
 
101
  protected JMenu                 menuEdit;
 
102
  protected JMenuItem             menuEditUndo;
 
103
  protected JMenuItem             menuEditCopy;
 
104
  protected JMenuItem             menuEditSearch;
 
105
  protected JMenuItem             menuEditClearSearch;
 
106
  protected JMenuItem             menuEditDeleteAttribute;
 
107
  protected JMenuItem             menuEditDeleteAttributes;
 
108
  protected JMenuItem             menuEditRenameAttribute;
 
109
  protected JMenuItem             menuEditAttributeAsClass;
 
110
  protected JMenuItem             menuEditDeleteInstance;
 
111
  protected JMenuItem             menuEditDeleteInstances;
 
112
  protected JMenuItem             menuEditSortInstances;
 
113
  protected JMenu                 menuView;
 
114
  protected JMenuItem             menuViewAttributes;
 
115
  protected JMenuItem             menuViewValues;
 
116
  protected JMenuItem             menuViewOptimalColWidths;
 
117
  
 
118
  protected ConverterFileChooser  fileChooser;
 
119
  protected String                frameTitle;
 
120
  protected boolean               confirmExit;
 
121
  protected int                   width;
 
122
  protected int                   height;
 
123
  protected int                   top;
 
124
  protected int                   left;
 
125
  protected boolean               exitOnClose;
 
126
  
 
127
  /**
 
128
   * initializes the object
 
129
   * 
 
130
   * @param parentFrame         the parent frame (JFrame or JInternalFrame)
 
131
   */
 
132
  public ArffViewerMainPanel(Container parentFrame) {
 
133
    parent     = parentFrame;
 
134
    frameTitle = "ARFF-Viewer"; 
 
135
    createPanel();
 
136
  }
 
137
  
 
138
  /**
 
139
   * creates all the components in the panel
 
140
   */
 
141
  protected void createPanel() {
 
142
    // basic setup
 
143
    setSize(WIDTH, HEIGHT);
 
144
    
 
145
    setConfirmExit(false);
 
146
    setLayout(new BorderLayout());
 
147
    
 
148
    // file dialog
 
149
    fileChooser = new ConverterFileChooser(new File(System.getProperty("user.dir")));
 
150
    fileChooser.setMultiSelectionEnabled(true);
 
151
    
 
152
    // menu
 
153
    menuBar        = new JMenuBar();
 
154
    menuFile       = new JMenu("File");
 
155
    menuFileOpen   = new JMenuItem("Open...", ComponentHelper.getImageIcon("open.gif"));
 
156
    menuFileOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK));
 
157
    menuFileOpen.addActionListener(this);
 
158
    menuFileSave   = new JMenuItem("Save", ComponentHelper.getImageIcon("save.gif"));
 
159
    menuFileSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK));
 
160
    menuFileSave.addActionListener(this);
 
161
    menuFileSaveAs = new JMenuItem("Save as...", ComponentHelper.getImageIcon("empty.gif"));
 
162
    menuFileSaveAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK + KeyEvent.SHIFT_MASK));
 
163
    menuFileSaveAs.addActionListener(this);
 
164
    menuFileClose  = new JMenuItem("Close", ComponentHelper.getImageIcon("empty.gif"));
 
165
    menuFileClose.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_MASK));
 
166
    menuFileClose.addActionListener(this);
 
167
    menuFileCloseAll = new JMenuItem("Close all", ComponentHelper.getImageIcon("empty.gif"));
 
168
    menuFileCloseAll.addActionListener(this);
 
169
    menuFileProperties  = new JMenuItem("Properties", ComponentHelper.getImageIcon("empty.gif"));
 
170
    menuFileProperties.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.CTRL_MASK));
 
171
    menuFileProperties.addActionListener(this);
 
172
    menuFileExit   = new JMenuItem("Exit", ComponentHelper.getImageIcon("forward.gif"));
 
173
    menuFileExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.ALT_MASK));
 
174
    menuFileExit.addActionListener(this);
 
175
    menuFile.add(menuFileOpen);
 
176
    menuFile.add(menuFileSave);
 
177
    menuFile.add(menuFileSaveAs);
 
178
    menuFile.add(menuFileClose);
 
179
    menuFile.add(menuFileCloseAll);
 
180
    menuFile.addSeparator();
 
181
    menuFile.add(menuFileProperties);
 
182
    menuFile.addSeparator();
 
183
    menuFile.add(menuFileExit);
 
184
    menuBar.add(menuFile);
 
185
    
 
186
    menuEdit       = new JMenu("Edit");
 
187
    menuEditUndo   = new JMenuItem("Undo", ComponentHelper.getImageIcon("undo.gif"));
 
188
    menuEditUndo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_MASK));
 
189
    menuEditUndo.addActionListener(this);
 
190
    menuEditCopy   = new JMenuItem("Copy", ComponentHelper.getImageIcon("copy.gif"));
 
191
    menuEditCopy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, KeyEvent.CTRL_MASK));
 
192
    menuEditCopy.addActionListener(this);
 
193
    menuEditSearch   = new JMenuItem("Search...", ComponentHelper.getImageIcon("find.gif"));
 
194
    menuEditSearch.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_MASK));
 
195
    menuEditSearch.addActionListener(this);
 
196
    menuEditClearSearch   = new JMenuItem("Clear search", ComponentHelper.getImageIcon("empty.gif"));
 
197
    menuEditClearSearch.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_MASK + KeyEvent.SHIFT_MASK));
 
198
    menuEditClearSearch.addActionListener(this);
 
199
    menuEditRenameAttribute = new JMenuItem("Rename attribute", ComponentHelper.getImageIcon("empty.gif"));
 
200
    menuEditRenameAttribute.addActionListener(this);
 
201
    menuEditAttributeAsClass = new JMenuItem("Attribute as class", ComponentHelper.getImageIcon("empty.gif"));
 
202
    menuEditAttributeAsClass.addActionListener(this);
 
203
    menuEditDeleteAttribute = new JMenuItem("Delete attribute", ComponentHelper.getImageIcon("empty.gif"));
 
204
    menuEditDeleteAttribute.addActionListener(this);
 
205
    menuEditDeleteAttributes = new JMenuItem("Delete attributes", ComponentHelper.getImageIcon("empty.gif"));
 
206
    menuEditDeleteAttributes.addActionListener(this);
 
207
    menuEditDeleteInstance = new JMenuItem("Delete instance", ComponentHelper.getImageIcon("empty.gif"));
 
208
    menuEditDeleteInstance.addActionListener(this);
 
209
    menuEditDeleteInstances = new JMenuItem("Delete instances", ComponentHelper.getImageIcon("empty.gif"));
 
210
    menuEditDeleteInstances.addActionListener(this);
 
211
    menuEditSortInstances = new JMenuItem("Sort data (ascending)", ComponentHelper.getImageIcon("sort.gif"));
 
212
    menuEditSortInstances.addActionListener(this);
 
213
    menuEdit.add(menuEditUndo);
 
214
    menuEdit.addSeparator();
 
215
    menuEdit.add(menuEditCopy);
 
216
    menuEdit.addSeparator();
 
217
    menuEdit.add(menuEditSearch);
 
218
    menuEdit.add(menuEditClearSearch);
 
219
    menuEdit.addSeparator();
 
220
    menuEdit.add(menuEditRenameAttribute);
 
221
    menuEdit.add(menuEditAttributeAsClass);
 
222
    menuEdit.add(menuEditDeleteAttribute);
 
223
    menuEdit.add(menuEditDeleteAttributes);
 
224
    menuEdit.addSeparator();
 
225
    menuEdit.add(menuEditDeleteInstance);
 
226
    menuEdit.add(menuEditDeleteInstances);
 
227
    menuEdit.add(menuEditSortInstances);
 
228
    menuBar.add(menuEdit);
 
229
    
 
230
    menuView       = new JMenu("View");
 
231
    menuViewAttributes   = new JMenuItem("Attributes...", ComponentHelper.getImageIcon("objects.gif"));
 
232
    menuViewAttributes.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK + KeyEvent.SHIFT_MASK));
 
233
    menuViewAttributes.addActionListener(this);
 
234
    menuViewValues   = new JMenuItem("Values...", ComponentHelper.getImageIcon("properties.gif"));
 
235
    menuViewValues.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_MASK + KeyEvent.SHIFT_MASK));
 
236
    menuViewValues.addActionListener(this);
 
237
    menuViewOptimalColWidths = new JMenuItem("Optimal column width (all)", ComponentHelper.getImageIcon("resize.gif"));
 
238
    menuViewOptimalColWidths.addActionListener(this);
 
239
    menuView.add(menuViewAttributes);
 
240
    menuView.add(menuViewValues);
 
241
    menuView.addSeparator();
 
242
    menuView.add(menuViewOptimalColWidths);
 
243
    menuBar.add(menuView);
 
244
    
 
245
    // tabbed pane
 
246
    tabbedPane  = new JTabbedPane();
 
247
    tabbedPane.addChangeListener(this);
 
248
    add(tabbedPane, BorderLayout.CENTER);
 
249
    
 
250
    updateMenu();
 
251
    updateFrameTitle();
 
252
  }
 
253
  
 
254
  /**
 
255
   * returns the parent frame, if it's a JFrame, otherwise null
 
256
   * 
 
257
   * @return            the parent frame
 
258
   */
 
259
  public JFrame getParentFrame() {
 
260
    if (parent instanceof JFrame)
 
261
      return (JFrame) parent;
 
262
    else
 
263
      return null;
 
264
  }
 
265
  
 
266
  /**
 
267
   * returns the parent frame, if it's a JInternalFrame, otherwise null
 
268
   * 
 
269
   * @return            the parent frame
 
270
   */
 
271
  public JInternalFrame getParentInternalFrame() {
 
272
    if (parent instanceof JInternalFrame)
 
273
      return (JInternalFrame) parent;
 
274
    else
 
275
      return null;
 
276
  }
 
277
  
 
278
  /**
 
279
   * sets the new parent frame
 
280
   * 
 
281
   * @param value       the parent frame
 
282
   */
 
283
  public void setParent(Container value) {
 
284
    parent = value;
 
285
  }
 
286
  
 
287
  /**
 
288
   * returns the menu bar to be added in a frame
 
289
   * 
 
290
   * @return            the menu bar
 
291
   */
 
292
  public JMenuBar getMenu() {
 
293
    return menuBar;
 
294
  }
 
295
  
 
296
  /**
 
297
   * returns the tabbedpane instance
 
298
   * 
 
299
   * @return            the tabbed pane
 
300
   */
 
301
  public JTabbedPane getTabbedPane() {
 
302
    return tabbedPane;
 
303
  }
 
304
  
 
305
  /**
 
306
   * whether to present a MessageBox on Exit or not
 
307
   * @param confirm           whether a MessageBox pops up or not to confirm
 
308
   *                          exit
 
309
   */
 
310
  public void setConfirmExit(boolean confirm) {
 
311
    confirmExit = confirm;
 
312
  }
 
313
  
 
314
  /**
 
315
   * returns the setting of whether to display a confirm messagebox or not
 
316
   * on exit
 
317
   * @return                  whether a messagebox is displayed or not
 
318
   */
 
319
  public boolean getConfirmExit() {
 
320
    return confirmExit;
 
321
  }
 
322
 
 
323
  /**
 
324
   * whether to do a System.exit(0) on close
 
325
   * 
 
326
   * @param value       enables/disables a System.exit(0) on close
 
327
   */
 
328
  public void setExitOnClose(boolean value) {
 
329
    exitOnClose = value;
 
330
  }
 
331
 
 
332
  /**
 
333
   * returns TRUE if a System.exit(0) is done on a close
 
334
   * 
 
335
   * @return            true if a System.exit(0) is done on close
 
336
   */
 
337
  public boolean getExitOnClose() {
 
338
    return exitOnClose;
 
339
  }
 
340
  
 
341
  /**
 
342
   * validates and repaints the frame
 
343
   */
 
344
  public void refresh() {
 
345
    validate();
 
346
    repaint();
 
347
  }
 
348
  
 
349
  /**
 
350
   * returns the title (incl. filename) for the frame
 
351
   * 
 
352
   * @return            the frame title
 
353
   */
 
354
  public String getFrameTitle() {
 
355
    if (getCurrentFilename().equals(""))
 
356
      return frameTitle;
 
357
    else
 
358
      return frameTitle + " - " + getCurrentFilename();
 
359
  }
 
360
  
 
361
  /**
 
362
   * sets the title of the parent frame, if one was provided
 
363
   */
 
364
  public void updateFrameTitle() {
 
365
    if (getParentFrame() != null)
 
366
      getParentFrame().setTitle(getFrameTitle());
 
367
    if (getParentInternalFrame() != null)
 
368
      getParentInternalFrame().setTitle(getFrameTitle());
 
369
  }
 
370
  
 
371
  /**
 
372
   * sets the enabled/disabled state of the menu 
 
373
   */
 
374
  protected void updateMenu() {
 
375
    boolean       fileOpen;
 
376
    boolean       isChanged;
 
377
    boolean       canUndo;
 
378
    
 
379
    fileOpen  = (getCurrentPanel() != null);
 
380
    isChanged = fileOpen && (getCurrentPanel().isChanged());
 
381
    canUndo   = fileOpen && (getCurrentPanel().canUndo());
 
382
    
 
383
    // File
 
384
    menuFileOpen.setEnabled(true);
 
385
    menuFileSave.setEnabled(isChanged);
 
386
    menuFileSaveAs.setEnabled(fileOpen);
 
387
    menuFileClose.setEnabled(fileOpen);
 
388
    menuFileCloseAll.setEnabled(fileOpen);
 
389
    menuFileProperties.setEnabled(fileOpen);
 
390
    menuFileExit.setEnabled(true);
 
391
    // Edit
 
392
    menuEditUndo.setEnabled(canUndo);
 
393
    menuEditCopy.setEnabled(fileOpen);
 
394
    menuEditSearch.setEnabled(fileOpen);
 
395
    menuEditClearSearch.setEnabled(fileOpen);
 
396
    menuEditAttributeAsClass.setEnabled(fileOpen);
 
397
    menuEditRenameAttribute.setEnabled(fileOpen);
 
398
    menuEditDeleteAttribute.setEnabled(fileOpen);
 
399
    menuEditDeleteAttributes.setEnabled(fileOpen);
 
400
    menuEditDeleteInstance.setEnabled(fileOpen);
 
401
    menuEditDeleteInstances.setEnabled(fileOpen);
 
402
    menuEditSortInstances.setEnabled(fileOpen);
 
403
    // View
 
404
    menuViewAttributes.setEnabled(fileOpen);
 
405
    menuViewValues.setEnabled(fileOpen);
 
406
    menuViewOptimalColWidths.setEnabled(fileOpen);
 
407
  }
 
408
  
 
409
  /**
 
410
   * sets the title of the tab that contains the given component
 
411
   * 
 
412
   * @param component           the component to set the title for
 
413
   */
 
414
  protected void setTabTitle(JComponent component) {
 
415
    int            index;
 
416
    
 
417
    if (!(component instanceof ArffPanel))
 
418
      return;
 
419
    
 
420
    index = tabbedPane.indexOfComponent(component);
 
421
    if (index == -1)
 
422
      return;
 
423
    
 
424
    tabbedPane.setTitleAt(index, ((ArffPanel) component).getTitle());
 
425
    updateFrameTitle();
 
426
  }
 
427
  
 
428
  /**
 
429
   * returns the number of panels currently open
 
430
   * 
 
431
   * @return            the number of open panels
 
432
   */
 
433
  public int getPanelCount() {
 
434
    return tabbedPane.getTabCount();
 
435
  }
 
436
  
 
437
  /**
 
438
   * returns the specified panel, <code>null</code> if index is out of bounds  
 
439
   * 
 
440
   * @param index       the index of the panel
 
441
   * @return            the panel
 
442
   */
 
443
  public ArffPanel getPanel(int index) {
 
444
    if ((index >= 0) && (index < getPanelCount()))
 
445
      return (ArffPanel) tabbedPane.getComponentAt(index);
 
446
    else
 
447
      return null;
 
448
  }
 
449
  
 
450
  /**
 
451
   * returns the currently selected tab index
 
452
   * 
 
453
   * @return            the index of the currently selected tab
 
454
   */
 
455
  public int getCurrentIndex() {
 
456
    return tabbedPane.getSelectedIndex();
 
457
  }
 
458
  
 
459
  /**
 
460
   * returns the currently selected panel
 
461
   * 
 
462
   * @return            the currently selected panel
 
463
   */
 
464
  public ArffPanel getCurrentPanel() {
 
465
    return getPanel(getCurrentIndex());
 
466
  }
 
467
  
 
468
  /**
 
469
   * checks whether a panel is currently selected
 
470
   * 
 
471
   * @return            true if a panel is currently selected
 
472
   */
 
473
  public boolean isPanelSelected() {
 
474
    return (getCurrentPanel() != null);
 
475
  }
 
476
  
 
477
  /**
 
478
   * returns the filename of the specified panel 
 
479
   * 
 
480
   * @param index       the index of the panel
 
481
   * @return            the filename for the panel
 
482
   */
 
483
  public String getFilename(int index) {
 
484
    String            result;
 
485
    ArffPanel         panel;
 
486
    
 
487
    result = "";
 
488
    panel  = getPanel(index);
 
489
    
 
490
    if (panel != null)
 
491
      result = panel.getFilename();
 
492
    
 
493
    return result;
 
494
  }
 
495
  
 
496
  /**
 
497
   * returns the filename of the current tab
 
498
   * 
 
499
   * @return            the current filename
 
500
   */
 
501
  public String getCurrentFilename() {
 
502
    return getFilename(getCurrentIndex());
 
503
  }
 
504
  
 
505
  /**
 
506
   * sets the filename of the specified panel
 
507
   * 
 
508
   * @param index       the index of the panel
 
509
   * @param filename    the new filename
 
510
   */
 
511
  public void setFilename(int index, String filename) {
 
512
    ArffPanel         panel;
 
513
    
 
514
    panel = getPanel(index);
 
515
    
 
516
    if (panel != null) {
 
517
      panel.setFilename(filename);
 
518
      setTabTitle(panel);
 
519
    }
 
520
  }
 
521
  
 
522
  /**
 
523
   * sets the filename of the current tab
 
524
   * 
 
525
   * @param filename    the new filename
 
526
   */
 
527
  public void setCurrentFilename(String filename) {
 
528
    setFilename(getCurrentIndex(), filename);
 
529
  }
 
530
  
 
531
  /**
 
532
   * if the file is changed it pops up a dialog whether to change the
 
533
   * settings. if the project wasn't changed or saved it returns TRUE
 
534
   * 
 
535
   * @return            true if project wasn't changed or saved
 
536
   */
 
537
  protected boolean saveChanges() {
 
538
    return saveChanges(true);
 
539
  }
 
540
  
 
541
  /**
 
542
   * if the file is changed it pops up a dialog whether to change the
 
543
   * settings. if the project wasn't changed or saved it returns TRUE
 
544
   * 
 
545
   * @param showCancel  whether we have YES/NO/CANCEL or only YES/NO
 
546
   * @return            true if project wasn't changed or saved
 
547
   */
 
548
  protected boolean saveChanges(boolean showCancel) {
 
549
    int            button;
 
550
    boolean        result;
 
551
    
 
552
    if (!isPanelSelected())
 
553
      return true;
 
554
    
 
555
    result = !getCurrentPanel().isChanged();
 
556
    
 
557
    if (getCurrentPanel().isChanged()) {
 
558
      try {
 
559
        if (showCancel)
 
560
          button = ComponentHelper.showMessageBox(
 
561
              this,
 
562
              "Changed",
 
563
              "The file is not saved - Do you want to save it?",
 
564
              JOptionPane.YES_NO_CANCEL_OPTION,
 
565
              JOptionPane.QUESTION_MESSAGE );
 
566
        else
 
567
          button = ComponentHelper.showMessageBox(
 
568
              this,
 
569
              "Changed",
 
570
              "The file is not saved - Do you want to save it?",
 
571
              JOptionPane.YES_NO_OPTION,
 
572
              JOptionPane.QUESTION_MESSAGE );
 
573
      }
 
574
      catch (Exception e) {
 
575
        button = JOptionPane.CANCEL_OPTION; 
 
576
      }
 
577
      
 
578
      switch (button) {
 
579
        case JOptionPane.YES_OPTION:
 
580
          saveFile();
 
581
          result = !getCurrentPanel().isChanged();
 
582
          break;
 
583
        case JOptionPane.NO_OPTION:
 
584
          result = true;
 
585
          break;
 
586
        case JOptionPane.CANCEL_OPTION: 
 
587
          result = false;
 
588
          break;
 
589
      }
 
590
    }
 
591
    
 
592
    return result;
 
593
  }
 
594
 
 
595
  /**
 
596
   * loads the specified file
 
597
   * 
 
598
   * @param filename    the file to load
 
599
   */
 
600
  public void loadFile(String filename) {
 
601
    ArffPanel         panel;
 
602
 
 
603
    panel    = new ArffPanel(filename);
 
604
    panel.addChangeListener(this);
 
605
    tabbedPane.addTab(panel.getTitle(), panel);
 
606
    tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
 
607
  }
 
608
  
 
609
  /**
 
610
   * loads the specified file into the table
 
611
   */
 
612
  public void loadFile() {
 
613
    int               retVal;
 
614
    int               i;
 
615
    String            filename;
 
616
    
 
617
    retVal = fileChooser.showOpenDialog(this);
 
618
    if (retVal != ConverterFileChooser.APPROVE_OPTION)
 
619
      return;
 
620
    
 
621
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
622
    
 
623
    for (i = 0; i< fileChooser.getSelectedFiles().length; i++) {
 
624
      filename = fileChooser.getSelectedFiles()[i].getAbsolutePath();
 
625
      loadFile(filename);
 
626
    }
 
627
    
 
628
    setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
 
629
  }
 
630
  
 
631
  /**
 
632
   * saves the current data into a file
 
633
   */
 
634
  public void saveFile() {
 
635
    ArffPanel           panel;
 
636
    String              filename;
 
637
    AbstractSaver       saver;
 
638
    
 
639
    // no panel? -> exit
 
640
    panel = getCurrentPanel();
 
641
    if (panel == null)
 
642
      return;
 
643
    
 
644
    filename = panel.getFilename();
 
645
    if (filename.equals(ArffPanel.TAB_INSTANCES)) {
 
646
      saveFileAs();
 
647
    }
 
648
    else {
 
649
      saver = fileChooser.getSaver();
 
650
      try {
 
651
        saver.setInstances(panel.getInstances());
 
652
        saver.writeBatch();
 
653
        panel.setChanged(false);
 
654
        setCurrentFilename(filename);
 
655
      }
 
656
      catch (Exception e) {
 
657
        e.printStackTrace();
 
658
      }
 
659
    }
 
660
  }
 
661
  
 
662
  /**
 
663
   * saves the current data into a new file
 
664
   */
 
665
  public void saveFileAs() {
 
666
    int                  retVal;
 
667
    ArffPanel            panel;
 
668
    
 
669
    // no panel? -> exit
 
670
    panel = getCurrentPanel();
 
671
    if (panel == null) {
 
672
      System.out.println("nothing selected!");
 
673
      return;
 
674
    }
 
675
    
 
676
    if (!getCurrentFilename().equals("")) {
 
677
      try {
 
678
        fileChooser.setSelectedFile(new File(getCurrentFilename()));
 
679
      }
 
680
      catch (Exception e) {
 
681
        // ignore
 
682
      }
 
683
    }
 
684
    
 
685
    // set filter for savers
 
686
    try {
 
687
      fileChooser.setCapabilitiesFilter(Capabilities.forInstances(panel.getInstances()));
 
688
    }
 
689
    catch (Exception e) {
 
690
      fileChooser.setCapabilitiesFilter(null);
 
691
    }
 
692
 
 
693
    retVal = fileChooser.showSaveDialog(this);
 
694
    if (retVal != ConverterFileChooser.APPROVE_OPTION)
 
695
      return;
 
696
    
 
697
    panel.setChanged(false);
 
698
    setCurrentFilename(fileChooser.getSelectedFile().getAbsolutePath());
 
699
    saveFile();
 
700
  }
 
701
  
 
702
  /**
 
703
   * closes the current tab
 
704
   */
 
705
  public void closeFile() {
 
706
    closeFile(true);
 
707
  }
 
708
  
 
709
  /**
 
710
   * closes the current tab
 
711
   * @param showCancel           whether to show an additional CANCEL button
 
712
   *                             in the "Want to save changes"-dialog
 
713
   * @see                        #saveChanges(boolean)
 
714
   */
 
715
  public void closeFile(boolean showCancel) {
 
716
    if (getCurrentIndex() == -1)
 
717
      return;
 
718
    
 
719
    if (!saveChanges(showCancel))
 
720
      return;
 
721
    
 
722
    tabbedPane.removeTabAt(getCurrentIndex());
 
723
    updateFrameTitle();
 
724
    System.gc();
 
725
  }
 
726
  
 
727
  /**
 
728
   * closes all open files
 
729
   */
 
730
  public void closeAllFiles() {
 
731
    while (tabbedPane.getTabCount() > 0) {
 
732
      if (!saveChanges(true))
 
733
        return;
 
734
      
 
735
      tabbedPane.removeTabAt(getCurrentIndex());
 
736
      updateFrameTitle();
 
737
      System.gc();
 
738
    }
 
739
  }
 
740
  
 
741
  /**
 
742
   * displays some properties of the instances
 
743
   */
 
744
  public void showProperties() {
 
745
    ArffPanel             panel;
 
746
    ListSelectorDialog    dialog;
 
747
    Vector                props;
 
748
    Instances             inst;
 
749
    
 
750
    panel = getCurrentPanel();
 
751
    if (panel == null)
 
752
      return;
 
753
    
 
754
    inst  = panel.getInstances();
 
755
    if (inst == null)
 
756
      return;
 
757
    if (inst.classIndex() < 0)
 
758
      inst.setClassIndex(inst.numAttributes() - 1);
 
759
    
 
760
    // get some data
 
761
    props = new Vector();
 
762
    props.add("Filename: " + panel.getFilename());
 
763
    props.add("Relation name: " + inst.relationName());
 
764
    props.add("# of instances: " + inst.numInstances());
 
765
    props.add("# of attributes: " + inst.numAttributes());
 
766
    props.add("Class attribute: " + inst.classAttribute().name());
 
767
    props.add("# of class labels: " + inst.numClasses());
 
768
    
 
769
    dialog = new ListSelectorDialog(getParentFrame(), new JList(props));
 
770
    dialog.showDialog();
 
771
  }
 
772
  
 
773
  /**
 
774
   * closes the window, i.e., if the parent is not null and implements
 
775
   * the WindowListener interface it calls the windowClosing method
 
776
   */
 
777
  public void close() {
 
778
    if (getParentInternalFrame() != null)
 
779
      getParentInternalFrame().doDefaultCloseAction();
 
780
    else if (getParentFrame() != null)
 
781
      ((Window) getParentFrame()).dispatchEvent(
 
782
          new WindowEvent(
 
783
              (Window) getParentFrame(), WindowEvent.WINDOW_CLOSING));
 
784
  }
 
785
  
 
786
  /**
 
787
   * undoes the last action 
 
788
   */
 
789
  public void undo() {
 
790
    if (!isPanelSelected())
 
791
      return;
 
792
    
 
793
    getCurrentPanel().undo();
 
794
  }
 
795
  
 
796
  /**
 
797
   * copies the content of the selection to the clipboard
 
798
   */
 
799
  public void copyContent() {
 
800
    if (!isPanelSelected())
 
801
      return;
 
802
    
 
803
    getCurrentPanel().copyContent();
 
804
  }
 
805
  
 
806
  /**
 
807
   * searches for a string in the cells
 
808
   */
 
809
  public void search() {
 
810
    if (!isPanelSelected())
 
811
      return;
 
812
 
 
813
    getCurrentPanel().search();
 
814
  }
 
815
  
 
816
  /**
 
817
   * clears the search, i.e. resets the found cells
 
818
   */
 
819
  public void clearSearch() {
 
820
    if (!isPanelSelected())
 
821
      return;
 
822
 
 
823
    getCurrentPanel().clearSearch();
 
824
  }
 
825
  
 
826
  /**
 
827
   * renames the current selected Attribute
 
828
   */
 
829
  public void renameAttribute() {
 
830
    if (!isPanelSelected())
 
831
      return;
 
832
    
 
833
    getCurrentPanel().renameAttribute();
 
834
  }
 
835
  
 
836
  /**
 
837
   * sets the current selected Attribute as class attribute, i.e. it moves it
 
838
   * to the end of the attributes
 
839
   */
 
840
  public void attributeAsClass() {
 
841
    if (!isPanelSelected())
 
842
      return;
 
843
    
 
844
    getCurrentPanel().attributeAsClass();
 
845
  }
 
846
  
 
847
  /**
 
848
   * deletes the current selected Attribute or several chosen ones
 
849
   * 
 
850
   * @param multiple    whether to delete myultiple attributes
 
851
   */
 
852
  public void deleteAttribute(boolean multiple) {
 
853
    if (!isPanelSelected())
 
854
      return;
 
855
    
 
856
    if (multiple)
 
857
      getCurrentPanel().deleteAttributes();
 
858
    else
 
859
      getCurrentPanel().deleteAttribute();
 
860
  }
 
861
  
 
862
  /**
 
863
   * deletes the current selected Instance or several chosen ones
 
864
   * 
 
865
   * @param multiple            whether to delete multiple instances
 
866
   */
 
867
  public void deleteInstance(boolean multiple) {
 
868
    if (!isPanelSelected())
 
869
      return;
 
870
    
 
871
    if (multiple)
 
872
      getCurrentPanel().deleteInstances();
 
873
    else
 
874
      getCurrentPanel().deleteInstance();
 
875
  }
 
876
  
 
877
  /**
 
878
   * sorts the current selected attribute
 
879
   */
 
880
  public void sortInstances() {
 
881
    if (!isPanelSelected())
 
882
      return;
 
883
    
 
884
    getCurrentPanel().sortInstances();
 
885
  }
 
886
  
 
887
  /**
 
888
   * displays all the attributes, returns the selected item or NULL if canceled
 
889
   * 
 
890
   * @return            the name of the selected attribute
 
891
   */
 
892
  public String showAttributes() {
 
893
    ArffSortedTableModel     model;
 
894
    ListSelectorDialog  dialog;
 
895
    int                 i;
 
896
    JList               list;
 
897
    String              name;
 
898
    int                 result;
 
899
    
 
900
    if (!isPanelSelected())
 
901
      return null;
 
902
    
 
903
    list   = new JList(getCurrentPanel().getAttributes());
 
904
    dialog = new ListSelectorDialog(getParentFrame(), list);
 
905
    result = dialog.showDialog();
 
906
    
 
907
    if (result == ListSelectorDialog.APPROVE_OPTION) {
 
908
      model = (ArffSortedTableModel) getCurrentPanel().getTable().getModel();
 
909
      name  = list.getSelectedValue().toString();
 
910
      i     = model.getAttributeColumn(name);
 
911
      JTableHelper.scrollToVisible(getCurrentPanel().getTable(), 0, i);
 
912
      getCurrentPanel().getTable().setSelectedColumn(i);
 
913
      return name;
 
914
    }
 
915
    else {
 
916
      return null;
 
917
    }
 
918
  }
 
919
  
 
920
  /**
 
921
   * displays all the distinct values for an attribute
 
922
   */
 
923
  public void showValues() {
 
924
    String                attribute;
 
925
    ArffSortedTableModel       model;
 
926
    ArffTable             table;
 
927
    HashSet               values;
 
928
    Vector                items;
 
929
    Iterator              iter;
 
930
    ListSelectorDialog    dialog;
 
931
    int                   i;
 
932
    int                   col;
 
933
    
 
934
    // choose attribute to retrieve values for
 
935
    attribute = showAttributes();
 
936
    if (attribute == null)
 
937
      return;
 
938
    
 
939
    table  = (ArffTable) getCurrentPanel().getTable();
 
940
    model  = (ArffSortedTableModel) table.getModel();
 
941
    
 
942
    // get column index
 
943
    col    = -1;
 
944
    for (i = 0; i < table.getColumnCount(); i++) {
 
945
      if (table.getPlainColumnName(i).equals(attribute)) {
 
946
        col = i;
 
947
        break;
 
948
      }
 
949
    }
 
950
    // not found?
 
951
    if (col == -1)
 
952
      return;
 
953
    
 
954
    // get values
 
955
    values = new HashSet();
 
956
    items  = new Vector();
 
957
    for (i = 0; i < model.getRowCount(); i++)
 
958
      values.add(model.getValueAt(i, col).toString());
 
959
    if (values.isEmpty())
 
960
      return;
 
961
    iter = values.iterator();
 
962
    while (iter.hasNext())
 
963
      items.add(iter.next());
 
964
    Collections.sort(items);
 
965
    
 
966
    dialog = new ListSelectorDialog(getParentFrame(), new JList(items));
 
967
    dialog.showDialog();
 
968
  }
 
969
  
 
970
  /**
 
971
   * sets the optimal column width for all columns
 
972
   */
 
973
  public void setOptimalColWidths() {
 
974
    if (!isPanelSelected())
 
975
      return;
 
976
    
 
977
    getCurrentPanel().setOptimalColWidths();
 
978
  }
 
979
  
 
980
  /**
 
981
   * invoked when an action occurs
 
982
   * 
 
983
   * @param e           the action event
 
984
   */
 
985
  public void actionPerformed(ActionEvent e) {
 
986
    Object          o;
 
987
    
 
988
    o = e.getSource();
 
989
    
 
990
    if (o == menuFileOpen)
 
991
      loadFile();
 
992
    else if (o == menuFileSave)
 
993
      saveFile();
 
994
    else if (o == menuFileSaveAs)
 
995
      saveFileAs();
 
996
    else if (o == menuFileClose)
 
997
      closeFile();
 
998
    else if (o == menuFileCloseAll)
 
999
      closeAllFiles();
 
1000
    else if (o == menuFileProperties)
 
1001
      showProperties();
 
1002
    else if (o == menuFileExit)
 
1003
      close();
 
1004
    else if (o == menuEditUndo)
 
1005
      undo();
 
1006
    else if (o == menuEditCopy)
 
1007
      copyContent();
 
1008
    else if (o == menuEditSearch)
 
1009
      search();
 
1010
    else if (o == menuEditClearSearch)
 
1011
      clearSearch();
 
1012
    else if (o == menuEditDeleteAttribute)
 
1013
      deleteAttribute(false);
 
1014
    else if (o == menuEditDeleteAttributes)
 
1015
      deleteAttribute(true);
 
1016
    else if (o == menuEditRenameAttribute)
 
1017
      renameAttribute();
 
1018
    else if (o == menuEditAttributeAsClass)
 
1019
      attributeAsClass();
 
1020
    else if (o == menuEditDeleteInstance)
 
1021
      deleteInstance(false);
 
1022
    else if (o == menuEditDeleteInstances)
 
1023
      deleteInstance(true);
 
1024
    else if (o == menuEditSortInstances)
 
1025
      sortInstances();
 
1026
    else if (o == menuViewAttributes)
 
1027
      showAttributes();
 
1028
    else if (o == menuViewValues)
 
1029
      showValues();
 
1030
    else if (o == menuViewOptimalColWidths)
 
1031
      setOptimalColWidths();
 
1032
    
 
1033
    updateMenu();
 
1034
  }
 
1035
  
 
1036
  /**
 
1037
   * Invoked when the target of the listener has changed its state.
 
1038
   * 
 
1039
   * @param e           the change event
 
1040
   */
 
1041
  public void stateChanged(ChangeEvent e) {
 
1042
    updateFrameTitle();
 
1043
    updateMenu();
 
1044
    
 
1045
    // did the content of panel change? -> change title of tab
 
1046
    if (e.getSource() instanceof JComponent)
 
1047
      setTabTitle((JComponent) e.getSource());
 
1048
  }
 
1049
  
 
1050
  /**
 
1051
   * returns only the classname
 
1052
   * 
 
1053
   * @return            the classname
 
1054
   */
 
1055
  public String toString() {
 
1056
    return this.getClass().getName();
 
1057
  }
 
1058
}