001    /*
002     * CRIMSON
003     * Copyright (c) 2006, Stephen Fisher, Susan Davidson, and Junhyong Kim, 
004     * University of Pennsylvania.
005     *
006     * This program is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU General Public License as
008     * published by the Free Software Foundation; either version 2 of the
009     * License, or (at your option) any later version.
010     *
011     * This program is distributed in the hope that it will be useful, but
012     * WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * General Public License for more details.
015     *
016     * You should have received a copy of the GNU General Public License
017     * along with this program; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019     * 02110-1301 USA.
020     *
021     * @(#)TreeManager.java
022     */
023    
024    package edu.upenn.crimson.gui;
025    
026    import edu.upenn.crimson.*;
027    import edu.upenn.crimson.io.*;
028    import java.awt.*;
029    import java.awt.event.*;
030    import javax.swing.*;
031    import javax.swing.event.*;
032    import javax.swing.text.*;
033    import javax.swing.border.Border;
034    
035    /**
036     * Browse existing Trees.
037     *
038     * @author  Stephen Fisher
039     * @version $Id: TreeManager.java,v 1.38 2007/10/09 20:14:16 fisher Exp $
040     */
041    
042    public class TreeManager {
043             private static PanelFrame panelFrame = null;
044    
045             /** Only allow one instance of PanelFrame. */
046             public static JFrame show() {
047                      if (panelFrame == null) panelFrame = new PanelFrame();
048                      panelFrame.setVisible(true);
049                      return panelFrame;
050             }
051                      
052             private static class PanelFrame extends JFrame {
053                      /** List of all trees in current database. */
054                      private JTable table;
055                      private TreeTableModel tableModel;
056    
057                      /** Reference to the Tree selected. */
058                      private Tree tree = null;
059                      /** The ID for the Tree selected. */
060                      private String treeID = "";
061    
062                      /** Reference to the Partition selected. */
063                      Partition partition = null;
064                      private JList partitionsL = new JList();
065                      private JTextField pLengthTF = new JTextField();
066                      private JButton pNotesB;
067                      private JButton pExportB;
068                      private JButton pDeleteB;
069                      private JComboBox pModelCB;;
070    
071                      private JButton loadB;
072                      private JButton appendB;
073                      private JButton exportB;
074                      private JButton statsB;
075                      private JButton newickB;
076                      private JButton viewB;
077                      private JButton refreshB;
078                      private JButton notesB;
079                      private JButton queryB;
080                      private JButton deleteB;
081                      private JButton closeB;
082                      private JLabel statusBar;               
083                      
084                      PanelFrame thisFrame;
085                      
086                      public PanelFrame() {
087                                    super("Tree Manager");
088                                    
089                                    // keep pointer to self so can 'dispose' Frame below
090                                    thisFrame = this;
091                                    
092                                    setDefaultCloseOperation(HIDE_ON_CLOSE);
093                                    
094                                    // if no database connection then error
095                                    if (! Database.isOpen()) {
096                                             CrimsonUtils.printError("Must open a database before opening the tree manager.");
097                                             setVisible(false);
098                                             return;
099                                    }
100                                    
101                                    // *************************************************
102                                    // CREATE VARIOUS BORDERS
103                                    Border emptyBorder = BorderFactory.createEmptyBorder(5,5,5,5);
104                                    Border loweredBorder = BorderFactory.createLoweredBevelBorder();
105                                    //                              Border raisedBorder = BorderFactory.createRaisedBevelBorder();
106                                    Border etchedBorder = BorderFactory.createEtchedBorder();
107                                    Border etchedPadBorder5 = 
108                                             BorderFactory.createCompoundBorder(etchedBorder, emptyBorder);
109                                    //                              Border raisedPadBorder = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(1,1,2,1), raisedBorder);
110                                    
111                                    // *************************************************
112                                    // TOOLBAR SETUP
113                                    JToolBar toolbar = new JToolBar();
114                                    toolbar.setFloatable(false);
115                                    JToolBar toolbarR = new JToolBar();
116                                    toolbarR.setFloatable(false);
117                                    // add Buttons
118                                    loadB = new JButton(new ImageIcon("icons/load.png"));
119                                    loadB.setToolTipText("Load");
120                                    loadB.addMouseListener(new MouseAdapter() {
121                                                      // add status bar text when mouse moves over button
122                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Load a new tree"); }
123                                                      // clear status bar when mouse moves off button
124                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
125                                             });
126                                    loadB.addActionListener(new ActionListener() {
127                                                      public void actionPerformed(ActionEvent e) {
128                                                                    TreeUtils.loadTree();
129                                                      }
130                                             });
131                                    appendB = new JButton(new ImageIcon("icons/append.png"));
132                                    appendB.setToolTipText("Append tree");
133                                    appendB.setEnabled(false);
134                                    appendB.addMouseListener(new MouseAdapter() {
135                                                      // add status bar text when mouse moves over button
136                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Append data to the selected tree"); }
137                                                      // clear status bar when mouse moves off button
138                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
139                                             });
140                                    appendB.addActionListener(new ActionListener() {
141                                                      public void actionPerformed(ActionEvent e) {
142                                                                    if (tree == null) return;
143                                                                    TreeUtils.appendTree(treeID);
144                                                      }
145                                             });
146                                    exportB = new JButton(new ImageIcon("icons/export.png"));
147                                    exportB.setToolTipText("Export tree");
148                                    exportB.setEnabled(false);
149                                    exportB.addMouseListener(new MouseAdapter() {
150                                                      // add status bar text when mouse moves over button
151                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Export the selected tree to a NEXUS file"); }
152                                                      // clear status bar when mouse moves off button
153                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
154                                             });
155                                    exportB.addActionListener(new ActionListener() {
156                                                      public void actionPerformed(ActionEvent e) {
157                                                                    if (tree == null) return;
158                                                                    TreeUtils.exportTree(treeID);
159                                                      }
160                                             });
161                                    statsB = new JButton("Statistics");
162                                    statsB.setToolTipText("Tree statistics");
163                                    statsB.setEnabled(false);
164                                    statsB.addMouseListener(new MouseAdapter() {
165                                                      // add status bar text when mouse moves over button
166                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("View statistics for the selected tree"); }
167                                                      // clear status bar when mouse moves off button
168                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
169                                             });
170                                    statsB.addActionListener(new ActionListener() {
171                                                      public void actionPerformed(ActionEvent e) {
172                                                                    if (tree == null) return;
173                                                                    TreeUtils.statsTree(treeID);
174                                                      }
175                                             });
176                                    newickB = new JButton("Newick");
177                                    newickB.setToolTipText("Newick string");
178                                    newickB.setEnabled(false);
179                                    newickB.addMouseListener(new MouseAdapter() {
180                                                      // add status bar text when mouse moves over button
181                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("View the newick string defining the selected tree"); }
182                                                      // clear status bar when mouse moves off button
183                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
184                                             });
185                                    newickB.addActionListener(new ActionListener() {
186                                                      public void actionPerformed(ActionEvent e) {
187                                                                    if (tree == null) return;
188                                                                    TreeUtils.newickTree(treeID);
189                                                      }
190                                             });
191                                    viewB = new JButton(new ImageIcon("icons/view.png"));
192                                    viewB.setToolTipText("View tree in 3D");
193                                    viewB.setEnabled(false);
194                                    viewB.addMouseListener(new MouseAdapter() {
195                                                      // add status bar text when mouse moves over button
196                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("3D view the selected tree in Walrus"); }
197                                                      // clear status bar when mouse moves off button
198                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
199                                             });
200                                    viewB.addActionListener(new ActionListener() {
201                                                      public void actionPerformed(ActionEvent e) {
202                                                          if ((tree == null) || ! CrimsonMain.WALRUS) return;
203                                                                    TreeUtils.view3DTree(treeID);
204                                                      }
205                                             });
206                                    refreshB = new JButton(new ImageIcon("icons/refresh.png"));
207                                    refreshB.setToolTipText("Refresh tree list");
208                                    refreshB.addMouseListener(new MouseAdapter() {
209                                                      // add status bar text when mouse moves over button
210                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Refresh the list of trees"); }
211                                                      // clear status bar when mouse moves off button
212                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
213                                             });
214                                    refreshB.addActionListener(new ActionListener() {
215                                                      public void actionPerformed(ActionEvent e) {
216                                                                    Root.runCommand("loadAllTrees()");
217                                                      }
218                                             });
219                                    notesB = new JButton(new ImageIcon("icons/notes.png"));
220                                    notesB.setToolTipText("Edit/view notes");
221                                    notesB.setEnabled(false);
222                                    notesB.addMouseListener(new MouseAdapter() {
223                                                      // add status bar text when mouse moves over button
224                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Edit the notes for the selected tree"); }
225                                                      // clear status bar when mouse moves off button
226                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
227                                             });
228                                    notesB.addActionListener(new ActionListener() {
229                                                      public void actionPerformed(ActionEvent e) {
230                                                                    if (tree == null) return;
231                                                                    new NotesPanel(tree);
232                                                      }
233                                             });
234                                    queryB = new JButton(new ImageIcon("icons/search.png"));
235                                    queryB.setToolTipText("Query");
236                                    queryB.setEnabled(false);
237                                    queryB.addMouseListener(new MouseAdapter() {
238                                                      // add status bar text when mouse moves over button
239                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Query the selected tree"); }
240                                                      // clear status bar when mouse moves off button
241                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
242                                             });
243                                    queryB.addActionListener(new ActionListener() {
244                                                      public void actionPerformed(ActionEvent e) {
245                                                                    if (tree == null) return;       
246                                                                    Root.runCommand("newQuery(\"" + treeID + "\")");
247                                                                    /*                                                              QueryUtils.newQuery(treeID); */
248                                                      }
249                                             });
250                                    deleteB= new JButton(new ImageIcon("icons/delete.png"));
251                                    deleteB.setToolTipText("Delete Tree");
252                                    deleteB.setEnabled(false);
253                                    deleteB.addMouseListener(new MouseAdapter() {
254                                                      // add status bar text when mouse moves over button
255                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("PERMANENTLY DELETE THE SELECTED TREE"); }
256                                                      // clear status bar when mouse moves off button
257                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
258                                             });
259                                    deleteB.addActionListener(new ActionListener() {
260                                                      public void actionPerformed(ActionEvent e) {
261                                                                    if (tree == null) return;       
262                                                                    TreeUtils.deleteTree(treeID);
263                                                      }
264                                             });
265                                    closeB = new JButton(new ImageIcon("icons/close.png"));
266                                    closeB.setToolTipText("Close");
267                                    closeB.addMouseListener(new MouseAdapter() {
268                                                      // add status bar text when mouse moves over button
269                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Close the tree manager"); }
270                                                      // clear status bar when mouse moves off button
271                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
272                                             });
273                                    closeB.addActionListener(new ActionListener() {
274                                                      public void actionPerformed(ActionEvent e) {
275                                                                    thisFrame.setVisible(false);
276                                                      }
277                                             });
278                                    // add ToolBar
279                                    toolbar.addSeparator(new Dimension(15, 0));
280                                    toolbar.add(loadB);
281                                    toolbar.addSeparator(new Dimension(30, 25));
282                                    toolbar.add(appendB);
283                                    toolbar.addSeparator(new Dimension(30, 25));
284                                    toolbar.add(exportB);
285                                    toolbar.addSeparator(new Dimension(30, 25));
286                                    toolbar.add(statsB);
287                                    toolbar.addSeparator(new Dimension(30, 25));
288                                    toolbar.add(newickB);
289                                    toolbar.addSeparator(new Dimension(30, 25));
290                                    toolbar.add(viewB);
291                                    toolbar.addSeparator(new Dimension(30, 25));
292                                    toolbar.add(refreshB);
293                                    toolbar.addSeparator(new Dimension(30, 25));
294                                    toolbar.add(notesB);
295                                    toolbar.addSeparator(new Dimension(30, 25));
296                                    toolbar.add(queryB);
297                                    toolbar.addSeparator(new Dimension(15, 0));
298                                    toolbarR.addSeparator(new Dimension(15, 0));
299                                    toolbarR.add(deleteB);
300                                    toolbarR.addSeparator(new Dimension(30, 25));
301                                    toolbarR.add(closeB);
302                                    toolbarR.addSeparator(new Dimension(15, 0));
303                                    // END TOOLBAR SETUP
304                                    // *************************************************
305                                    
306                                    // *************************************************
307                                    // TABLE SETUP
308                                    tableModel = ObjectHandles.getTreeTableModel();
309                                    table = new JTable(tableModel);
310                                    table.setPreferredScrollableViewportSize(new Dimension(500, 70));
311                                    table.setColumnSelectionAllowed(false);
312                                    //                table.setShowGrid(true);
313                                    //                table.setShowHorizontalLines(true);
314                                    table.setShowVerticalLines(false);
315                                    // this should disallow rearranging cols 
316                                    table.setDragEnabled(false);  
317                                    // add the table to a scrollPane
318                                    JScrollPane tableSP = new JScrollPane(table);
319                                    tableSP.setBorder(etchedBorder);
320                                    /*
321                                    TableColumn column = null;
322                                    for (int i = 0; i < tableModel.getColumnCount(); i++) {
323                                             column = table.getColumnModel().getColumn(i);
324                                             // first 2 columns should be smaller
325                                             if (i < 2) column.setPreferredWidth(10); 
326                                             else column.setPreferredWidth(100); 
327                                    }
328                                    */
329    
330                                    // ***** SETUP TABLE LISTENER *****
331                                    DefaultListSelectionModel dlsm = new DefaultListSelectionModel();
332                                    table.setSelectionModel(dlsm);
333                                    // only allow single item selection
334                                    dlsm.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
335                                    dlsm.addListSelectionListener(new ListSelectionListener() {
336                                                      public void valueChanged(ListSelectionEvent e) {
337                                                                    if (e.getValueIsAdjusting()) return;
338    
339                                                                    if ((table.getRowCount() > 0)
340                                                                             && (table.getSelectedRowCount() > 0)) {
341                                                                             // an item is selected
342                                                                             tree = tableModel.getRow(table.getSelectedRow());
343                                                                             treeID = tree.getID();
344                                                                             
345                                                                             // setup partitionsL 
346                                                                             partitionsL.setListData(tree.getPartitions().toArray());
347                                                                             partitionsL.setEnabled(true);
348                                                                             
349                                                                             appendB.setEnabled(true);
350                                                                             exportB.setEnabled(true);
351                                                                             statsB.setEnabled(true);
352                                                                             newickB.setEnabled(true);
353                                                                             if (CrimsonMain.WALRUS) viewB.setEnabled(true);
354                                                                             notesB.setEnabled(true);
355                                                                             deleteB.setEnabled(true);
356                                                                             queryB.setEnabled(true);
357                                                                    } else {
358                                                                             tree = null;
359                                                                             treeID = "";
360    
361                                                                             // empty partitionsL
362                                                                             partitionsL.setListData(new Object[0]);
363                                                                             partitionsL.setEnabled(false);
364                                                                             
365                                                                             appendB.setEnabled(false);
366                                                                             exportB.setEnabled(false);
367                                                                             statsB.setEnabled(false);
368                                                                             newickB.setEnabled(false);
369                                                                             viewB.setEnabled(false);
370                                                                             notesB.setEnabled(false);
371                                                                             deleteB.setEnabled(false);
372                                                                             queryB.setEnabled(false);
373                                                                    }
374                                                      }
375                                             });
376                                    // END TABLE SETUP
377                                    // *************************************************
378    
379                                    // *************************************************
380                                    // PARTITION INFO SETUP
381                                    JPanel partitionP = new JPanel(new BorderLayout());
382                                    //                              partitionP.setBorder(BorderFactory.createTitledBorder(etchedPadBorder0, "Partitions"));
383                                    partitionP.setBorder(etchedPadBorder5);
384                                    partitionP.add(new JLabel("Partitions (length, model): "), BorderLayout.NORTH);
385    
386                                    partitionsL.setEnabled(false);
387                                    DefaultListSelectionModel partitionLSM = new DefaultListSelectionModel();
388                                    partitionsL.setSelectionModel(partitionLSM);
389                                    partitionsL.setFixedCellWidth(200);
390                                    // only allow single item selection
391                                    partitionLSM.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
392                                    partitionLSM.addListSelectionListener(new ListSelectionListener() {
393                                                      public void valueChanged(ListSelectionEvent e) {
394                                                                    if (e.getValueIsAdjusting()) return;
395                                                                    
396                                                                    if (partitionsL.isSelectionEmpty()) {
397                                                                             // nothing selected so reset partition
398                                                                             // reference and the partition's model ID
399                                                                             partition = null;
400                                                                             pModelCB.setSelectedIndex(-1);
401    
402                                                                             pNotesB.setEnabled(false);
403                                                                             pExportB.setEnabled(false);
404                                                                             pDeleteB.setEnabled(false);
405                                                                             pModelCB.setEnabled(false);
406                                                                    } else {
407                                                                             // set partition reference
408                                                                             partition = (Partition) partitionsL.getSelectedValue();
409    
410                                                                             // if the partition doesn't have a model
411                                                                             // associated with it, then clear the
412                                                                             // model combo box
413                                                                             if (CrimsonUtils.isEmpty(partition.getModelID())) {
414                                                                                      pModelCB.setSelectedIndex(-1);
415                                                                             } else {
416                                                                                      pModelCB.setSelectedItem(partition.getModelID());
417                                                                             }
418    
419                                                                             pNotesB.setEnabled(true);
420                                                                             pExportB.setEnabled(true);
421                                                                             pDeleteB.setEnabled(true);
422                                                                             pModelCB.setEnabled(true);
423                                                                    }
424                                                      }
425                                             });
426                                    JScrollPane partitionSP = new JScrollPane(partitionsL);
427                                    partitionP.add(partitionSP, BorderLayout.CENTER);
428    
429                                    JPanel partitionCtrlP = new JPanel(new BorderLayout());
430                                    pExportB = new JButton(new ImageIcon("icons/export.png"));
431                                    pExportB.setToolTipText("Export partition");
432                                    pExportB.setEnabled(false);
433                                    pExportB.addMouseListener(new MouseAdapter() {
434                                                      // add status bar text when mouse moves over button
435                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Save the selected partition as a NEXUS file"); }
436                                                      // clear status bar when mouse moves off button
437                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
438                                             });
439                                    pExportB.addActionListener(new ActionListener() {
440                                                      public void actionPerformed(ActionEvent e) {
441                                                                    if (partition == null) return;
442    
443                                                                    String cmd = "exportPartition(\"" + partition.getTreeID() + "\", \"";
444                                                                    cmd += partition.getID() + "\")";
445                                                                    Root.runCommand(cmd);
446                                                      }
447                                             });
448                                    partitionCtrlP.add(pExportB, BorderLayout.WEST);
449                                    pNotesB = new JButton(new ImageIcon("icons/notes.png"));
450                                    pNotesB.setToolTipText("Edit/view partition notes");
451                                    pNotesB.setEnabled(false);
452                                    pNotesB.addMouseListener(new MouseAdapter() {
453                                                      // add status bar text when mouse moves over button
454                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Edit the notes for the selected partition"); }
455                                                      // clear status bar when mouse moves off button
456                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
457                                             });
458                                    pNotesB.addActionListener(new ActionListener() {
459                                                      public void actionPerformed(ActionEvent e) {
460                                                                    if (partition == null) return;
461                                                                    new NotesPanel(partition);
462                                                      }
463                                             });
464                                    partitionCtrlP.add(pNotesB, BorderLayout.CENTER);
465                                    pDeleteB = new JButton(new ImageIcon("icons/delete.png"));
466                                    pDeleteB.setToolTipText("Delete");
467                                    pDeleteB.setEnabled(false);
468                                    pDeleteB.addMouseListener(new MouseAdapter() {
469                                                      // add status bar text when mouse moves over button
470                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("PERMANENTLY DELETE THE SELECTED PARTITION"); }
471                                                      // clear status bar when mouse moves off button
472                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
473                                             });
474                                    pDeleteB.addActionListener(new ActionListener() {
475                                                      public void actionPerformed(ActionEvent e) {
476                                                                    if (partition == null) return;
477    
478                                                                    String msg = "Are you sure you want to remove this partition?\n";
479                                                                    msg += "Tree: " + partition.getTreeID() + "\n";
480                                                                    msg += "Partition: " + partition.getID();
481                                                                    Object[] options = {"Delete Partition", "Cancel"};
482                                                                    int flag = JOptionPane.showOptionDialog(null, msg,
483                                                                                                                                                                             "Delete Confirmation",
484                                                                                                                                                                             JOptionPane.YES_NO_OPTION,
485                                                                                                                                                                             JOptionPane.QUESTION_MESSAGE,
486                                                                                                                                                                             null,
487                                                                                                                                                                             options,
488                                                                                                                                                                             options[1]);
489                                                                    if (flag == JOptionPane.YES_OPTION) { // "Delete"
490                                                                             msg = "deletePartition(\"" + partition.getID() + "\")";
491                                                                             Root.runCommand(msg);
492                                                                    }
493                                                      }
494                                             });
495                                    partitionCtrlP.add(pDeleteB, BorderLayout.EAST);
496                                    pModelCB = new JComboBox(ObjectHandles.getModelList());
497                                    pModelCB.setBorder(loweredBorder);
498                                    pModelCB.setEnabled(false);
499                                    pModelCB.setEditable(false);
500                                    pModelCB.setSelectedIndex(-1);
501                                    pModelCB.addActionListener(new ActionListener() {
502                                                      public void actionPerformed(ActionEvent e) {
503                                                                    if (partition == null) return;
504    
505                                                                    // get modelID and if not empty, then set the
506                                                                    // partition's modelID to this value
507                                                                    String modelID = (String) ((JComboBox) e.getSource()).getSelectedItem();
508                                                                    if ((! CrimsonUtils.isEmpty(modelID)) && 
509                                                                             (partition.getModelID().compareTo(modelID) != 0)) {
510                                                                             //                                                                      partition.setModelID(modelID);
511                                                                             String cmd = "getPartition('" + partition.getID() + "')";
512                                                                             cmd += ".setModelID(getModel('" + modelID + "'))";
513                                                                             Root.runCommand(cmd);
514                                                                    }
515                                                                    
516                                                                    // need to repaint the window to get the
517                                                                    // partition list to show the new model
518                                                                    thisFrame.repaint();
519                                                      }
520                                             });
521                                    partitionCtrlP.add(pModelCB, BorderLayout.SOUTH);
522                                    partitionP.add(partitionCtrlP, BorderLayout.SOUTH);
523                                    // END PARTITION INFO SETUP
524                                    // *************************************************
525    
526                                    // *************************************************
527                                    // STATUS BAR SETUP
528                                    JLabel statusBarSpacer = new JLabel(" ");
529                                    statusBar = new JLabel(" ");
530                                    JPanel statusBarP = new JPanel(false);
531                                    statusBarP.setBorder(loweredBorder);
532                                    statusBarP.setLayout(new BorderLayout());
533                                    statusBarP.add(statusBarSpacer, BorderLayout.WEST);
534                                    statusBarP.add(statusBar, BorderLayout.CENTER);
535                                    // END STATUS BAR SETUP
536                                    // *************************************************
537                                    
538                                    // setup main panel
539                                    JPanel listP = new JPanel(new BorderLayout());
540                                    listP.add(tableSP, BorderLayout.CENTER);
541                                    listP.add(partitionP, BorderLayout.EAST);
542    
543                                    // this will keep the toolbar on the left and right edges
544                                    Box box = Box.createHorizontalBox();
545                                    box.add(toolbar);
546                                    box.add(Box.createHorizontalGlue());
547                                    box.add(toolbarR);
548    
549                                    getContentPane().add(box, BorderLayout.NORTH);
550                                    getContentPane().add(listP, BorderLayout.CENTER);
551                                    getContentPane().add(statusBarP, BorderLayout.SOUTH);
552                                    pack();
553                                    
554                                    // set the default window size
555                                    setSize(getSize().width, getSize().height + 100);
556                                    
557                                    // display the window
558                                    setVisible(true);
559                      }
560             }
561    
562             /** Edit notes field. */
563             static class NotesPanel extends JFrame {
564                      NotesPanel thisFrame;
565                      
566                      Tree npTree;
567                      String npTreeID = "";
568                      Partition npPartition;
569                      String npPartitionID = "";
570                      JTextArea npTextArea;
571                      
572                      public NotesPanel(Tree tree) { this(tree, null); }
573    
574                      public NotesPanel(Partition partition) { this(null, partition); }
575    
576                      public NotesPanel(Tree tree, Partition partition) {
577                                    super("Notes Editor");
578                                    
579                                    // keep pointer to self so can 'dispose' Frame below
580                                    thisFrame = this;
581                                    
582                                    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
583                                    
584                                    this.npTree = tree;
585                                    this.npPartition = partition;
586    
587                                    Border emptyBorder = BorderFactory.createEmptyBorder(5,5,5,5);
588                                    Border loweredBorder = BorderFactory.createLoweredBevelBorder();
589                                    Border etchedBorder = BorderFactory.createEtchedBorder();
590                                    Border etchedPadBorder5 = 
591                                             BorderFactory.createCompoundBorder(etchedBorder, emptyBorder);
592                                    Border loweredPadBorder5 = 
593                                             BorderFactory.createCompoundBorder(loweredBorder, emptyBorder);
594                                    
595                                    // *************************************************
596                                    // SETUP BUTTONS 
597                                    JPanel buttonP = new JPanel(new BorderLayout());
598                                    JButton saveB = new JButton(new ImageIcon("icons/save.png"));
599                                    saveB.setToolTipText("Save changes");
600                                    saveB.addActionListener(new ActionListener() {
601                                                      public void actionPerformed(ActionEvent e) {
602                                                                    if (npTree == null) {
603                                                                             if (npPartition == null) {
604                                                                                      return;
605                                                                             } else {
606                                                                                      npPartition.setNotes(npTextArea.getText());
607                                                                             }
608                                                                    } else {
609                                                                             npTree.setNotes(npTextArea.getText());
610                                                                    }                                        
611                                                                    thisFrame.dispose();
612                                                      }
613                                             });
614                                    buttonP.add(saveB, BorderLayout.WEST);
615                                    JButton cancelB = new JButton(new ImageIcon("icons/close.png"));
616                                    cancelB.setToolTipText("Cancel");
617                                    cancelB.addActionListener(new ActionListener() {
618                                                      public void actionPerformed(ActionEvent e) {
619                                                                    thisFrame.dispose();
620                                                      }
621                                             });
622                                    buttonP.add(cancelB, BorderLayout.EAST);
623                                    
624                                    // *************************************************
625                                    // SETUP TEXTAREA 
626                                    PlainDocument npNotesDoc = new PlainDocument();
627                                    npNotesDoc.setDocumentFilter(GUIUtils.getDocLengthFilter());
628                                    npTextArea = new JTextArea();
629                                    npTextArea.setDocument(npNotesDoc);
630                                    if (npTree == null) {
631                                             if (npPartition == null) {
632                                                      CrimsonUtils.printMsg("Can't view notes for null object.", CrimsonUtils.ERROR);
633                                                      return;
634                                             } else {
635                                                      npTextArea.setText(npPartition.getNotes());
636                                                      npTreeID = npPartition.getTreeID();
637                                                      npPartitionID = npPartition.getID();
638                                             }
639                                    } else {
640                                             npTextArea.setText(npTree.getNotes());
641                                             npTreeID = npTree.getID();
642                                    }                                        
643                                    npTextArea.setLineWrap(true);
644                                    npTextArea.setWrapStyleWord(true);
645                                    JScrollPane areaSP = new JScrollPane(npTextArea);
646                                    areaSP.setBorder(loweredPadBorder5);
647                                    areaSP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
648                                    areaSP.setPreferredSize(new Dimension(400, 200));
649                                    
650                                    // *************************************************
651                                    // SETUP PANELS 
652                                    JPanel infoP = new JPanel(new BorderLayout());
653                                    infoP.setBorder(etchedPadBorder5);
654                                    infoP.add(new JLabel("Tree: " + npTreeID), BorderLayout.WEST);
655                                    infoP.add(new JLabel("Partition: " + npPartitionID), BorderLayout.EAST);
656                                    
657                                    getContentPane().setLayout(new BorderLayout());
658                                    getContentPane().add(infoP, BorderLayout.NORTH);
659                                    getContentPane().add(areaSP, BorderLayout.CENTER);
660                                    getContentPane().add(buttonP, BorderLayout.SOUTH);
661                                    pack();
662                                    
663                                    // set the default window size
664                                    setSize(getSize().width + 75, getSize().height + 30);
665                                    
666                                    // display the window
667                                    setVisible(true);
668                      }
669             } // NotesPanel
670    
671    } // TreeManager.java