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     * @(#)QueryManager.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.border.Border;
033    import java.io.File;
034    
035    /**
036     * Browse existing Queries.
037     *
038     * @author  Stephen Fisher
039     * @version $Id: QueryManager.java,v 1.44 2007/06/14 19:48:42 fisher Exp $
040     */
041    
042    public class QueryManager {
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 queries in current database. */
054                      private JTable table;
055                      private QueryTableModel tableModel;
056                      
057                      /** Reference to the selected query. */
058                      private Query query = null;
059                      private String treeID = "";
060                      private JLabel notesL = new JLabel("");
061    
062                      private JTextField fileNameTF = new JTextField(10);
063                      private JButton fileBrowseB;
064                      private JCheckBox fileIntSeqCB = new JCheckBox("Include Internal Sequence");
065                      // start = 1, min = 1, max = 100, step = 1
066                      private JSpinner fileRepeatS = new JSpinner(new SpinnerNumberModel(1, 1, 100, 1));
067                      
068                      private JButton newB;
069                      private JButton copyB;
070                      private JButton loadB;
071                      private JButton publishB;
072                      private JButton importB;
073                      private JButton exportB;
074                      private JButton viewB;
075                      private JButton editB;
076                      private JButton runB;
077                      private JButton deleteB;
078                      private JButton closeB;
079                      private JLabel statusBar;               
080                      
081                      PanelFrame thisFrame;
082                      
083                      public PanelFrame() {
084                                    super("Query Manager");
085    
086                                    // keep pointer to self so can 'dispose' Frame below
087                                    thisFrame = this;
088                                    
089                                    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
090                                    
091                                    // if no database connection then error
092                                    if (! Database.isOpen()) {
093                                             CrimsonUtils.printError("Must open a database before opening the query manager.");
094                                             setVisible(false);
095                                             return;
096                                    }
097                                    
098                                    // *************************************************
099                                    // CREATE VARIOUS BORDERS
100                                    Border emptyBorder = BorderFactory.createEmptyBorder(5,5,5,5);
101                                    Border loweredBorder = BorderFactory.createLoweredBevelBorder();
102                                    Border raisedBorder = BorderFactory.createRaisedBevelBorder();
103                                    Border etchedBorder = BorderFactory.createEtchedBorder();
104                                    Border etchedPadBorder5 = 
105                                             BorderFactory.createCompoundBorder(etchedBorder, emptyBorder);
106                                    Border loweredPadBorder5 = 
107                                             BorderFactory.createCompoundBorder(loweredBorder, emptyBorder);
108                                    Border etchedPadBorder10 = 
109                                             BorderFactory.createCompoundBorder(etchedBorder, 
110                                                                                                                                            BorderFactory.createEmptyBorder(0,10,10,10));
111                                    Border raisedPadBorder = 
112                                             BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(1,1,2,1), 
113                                                                                                                                            raisedBorder);
114                                    
115                                    // *************************************************
116                                    // TOOLBAR SETUP
117                                    JToolBar toolBar = new JToolBar();
118                                    toolBar.setFloatable(false);
119                                    JToolBar toolBarR = new JToolBar();
120                                    toolBarR.setFloatable(false);
121                                    // add Buttons
122                                    newB = new JButton(new ImageIcon("icons/new.png"));
123                                    newB.setToolTipText("New");
124                                    newB.addMouseListener(new MouseAdapter() {
125                                                      // add status bar text when mouse moves over button
126                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Create a new query"); }
127                                                      // clear status bar when mouse moves off button
128                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
129                                             });
130                                    newB.addActionListener(new ActionListener() {
131                                                      public void actionPerformed(ActionEvent e) {
132                                                                    QueryUtils.newQuery();
133                                                      }
134                                             });
135                                    loadB = new JButton(new ImageIcon("icons/load.png"));
136                                    loadB.setToolTipText("Load");
137                                    loadB.addMouseListener(new MouseAdapter() {
138                                                      // add status bar text when mouse moves over button
139                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Load specified query from the database."); }
140                                                      // clear status bar when mouse moves off button
141                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
142                                             });
143                                    loadB.addActionListener(new ActionListener() {
144                                                      public void actionPerformed(ActionEvent e) {
145                                                                    QueryUtils.loadQuery();
146                                                      }
147                                             });
148                                    publishB = new JButton(new ImageIcon("icons/publish.png"));
149                                    publishB.setToolTipText("Publish");
150                                    publishB.setEnabled(false);
151                                    publishB.addMouseListener(new MouseAdapter() {
152                                                      // add status bar text when mouse moves over button
153                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Save the selected query to the database."); }
154                                                      // clear status bar when mouse moves off button
155                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
156                                             });
157                                    publishB.addActionListener(new ActionListener() {
158                                                      public void actionPerformed(ActionEvent e) {
159                                                                    if (query == null) return;
160                                                                    QueryUtils.publishQuery(query.getID());
161                                                      }
162                                             });
163                                    importB = new JButton(new ImageIcon("icons/import.png"));
164                                    importB.setToolTipText("Import");
165                                    importB.addMouseListener(new MouseAdapter() {
166                                                      // add status bar text when mouse moves over button
167                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Import a query from a text file."); }
168                                                      // clear status bar when mouse moves off button
169                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
170                                             });
171                                    importB.addActionListener(new ActionListener() {
172                                                      public void actionPerformed(ActionEvent e) {
173                                                                    QueryUtils.importQuery();
174                                                      }
175                                             });
176                                    exportB = new JButton(new ImageIcon("icons/export.png"));
177                                    exportB.setToolTipText("Export");
178                                    exportB.setEnabled(false);
179                                    exportB.addMouseListener(new MouseAdapter() {
180                                                      // add status bar text when mouse moves over button
181                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Export the selected query to a text file."); }
182                                                      // clear status bar when mouse moves off button
183                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
184                                             });
185                                    exportB.addActionListener(new ActionListener() {
186                                                      public void actionPerformed(ActionEvent e) {
187                                                                    if (query == null) return;
188                                                                    QueryUtils.exportQuery(query.getID());
189                                                      }
190                                             });
191                                    viewB = new JButton(new ImageIcon("icons/view.png"));
192                                    viewB.setToolTipText("View");
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("View the selected query."); }
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 (query == null) return;
203                                                                    Root.runCommand("viewQuery(\"" + query.getID() + "\")");
204                                                      }
205                                             });
206                                    copyB = new JButton(new ImageIcon("icons/copy.png"));
207                                    copyB.setToolTipText("Duplicate");
208                                    copyB.setEnabled(false);
209                                    copyB.addMouseListener(new MouseAdapter() {
210                                                      // add status bar text when mouse moves over button
211                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Duplicate the selected query"); }
212                                                      // clear status bar when mouse moves off button
213                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
214                                             });
215                                    copyB.addActionListener(new ActionListener() {
216                                                      public void actionPerformed(ActionEvent e) {
217                                                                    // clone the query and then open in edit window
218                                                                    if (query == null) return;
219                                                                    String id = QueryUtils.getQueryID(ObjectHandles.randomQueryID(query.getID() + "_"));
220                                                                    if (! CrimsonUtils.isEmpty(id)) query.clone(id);
221                                                      }
222                                             });
223                                    editB = new JButton(new ImageIcon("icons/edit.png"));
224                                    editB.setToolTipText("Edit");
225                                    editB.setEnabled(false);
226                                    editB.addMouseListener(new MouseAdapter() {
227                                                      // add status bar text when mouse moves over button
228                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Edit the selected query"); }
229                                                      // clear status bar when mouse moves off button
230                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
231                                             });
232                                    editB.addActionListener(new ActionListener() {
233                                                      public void actionPerformed(ActionEvent e) {
234                                                                    if (query == null) return;
235                                                                    //                                                              QueryUtils.editQuery(query.getID());
236                                                                    Root.runCommand("editQuery(\"" + query.getID() + "\")", false);
237                                                                    new QueryEditor(query, fileNameTF.getText(),
238                                                                                                             fileIntSeqCB.isSelected(), 
239                                                                                                             ((Integer) fileRepeatS.getValue()).intValue());
240                                                      }
241                                             });
242                                    runB = new JButton(new ImageIcon("icons/run.png"));
243                                    runB.setToolTipText("Run query");
244                                    runB.addMouseListener(new MouseAdapter() {
245                                                      // add status bar text when mouse moves over button
246                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Run the selected query"); }
247                                                      // clear status bar when mouse moves off button
248                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
249                                             });
250                                    runB.addActionListener(new ActionListener() {
251                                                      public void actionPerformed(ActionEvent e) {
252                                                                    if (query == null) return;
253    
254                                                                    QueryUtils.runQuery(query.getID(), fileNameTF.getText(),
255                                                                                                                      fileIntSeqCB.isSelected(), 
256                                                                                                                      ((Integer) fileRepeatS.getValue()).intValue());
257                                                                    /*
258                                                                    String cmd = "runQuery(\"" + query.getID() + "\", \"";
259                                                                    cmd += fileNameTF.getText() + "\", ";
260                                                                    cmd += (fileIntSeqCB.isSelected()) ? "1, " : "0, ";
261                                                                    cmd += ((Integer) fileRepeatS.getValue()).toString() + ")";
262                                                                    Root.runCommand(cmd);
263                                                                    */
264                                                      }
265                                             });
266                                    deleteB= new JButton(new ImageIcon("icons/delete.png"));
267                                    deleteB.setToolTipText("Delete Tree");
268                                    deleteB.setEnabled(false);
269                                    deleteB.addMouseListener(new MouseAdapter() {
270                                                      // add status bar text when mouse moves over button
271                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("PERMANENTLY DELETE THE SELECTED QUERY"); }
272                                                      // clear status bar when mouse moves off button
273                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
274                                             });
275                                    deleteB.addActionListener(new ActionListener() {
276                                                      public void actionPerformed(ActionEvent e) {
277                                                                    if (query == null) return;      
278                                                                    QueryUtils.deleteQuery(query.getID());
279                                                      }
280                                             });
281                                    closeB = new JButton(new ImageIcon("icons/close.png"));
282                                    closeB.setToolTipText("Close");
283                                    closeB.addMouseListener(new MouseAdapter() {
284                                                      // add status bar text when mouse moves over button
285                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Close the query manager"); }
286                                                      // clear status bar when mouse moves off button
287                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
288                                             });
289                                    closeB.addActionListener(new ActionListener() {
290                                                      public void actionPerformed(ActionEvent e) {
291                                                                    thisFrame.setVisible(false);
292                                                      }
293                                             });
294                                    // add ToolBar
295                                    toolBar.addSeparator(new Dimension(15, 0));
296                                    toolBar.add(newB);
297                                    toolBar.addSeparator(new Dimension(30, 25));
298                                    toolBar.add(copyB);
299                                    toolBar.addSeparator(new Dimension(30, 25));
300                                    toolBar.add(loadB);
301                                    toolBar.addSeparator(new Dimension(30, 25));
302                                    toolBar.add(publishB);
303                                    toolBar.addSeparator(new Dimension(30, 25));
304                                    toolBar.add(importB);
305                                    toolBar.addSeparator(new Dimension(30, 25));
306                                    toolBar.add(exportB);
307                                    toolBar.addSeparator(new Dimension(30, 25));
308                                    toolBar.add(viewB);
309                                    toolBar.addSeparator(new Dimension(30, 25));
310                                    toolBar.add(editB);
311                                    toolBar.addSeparator(new Dimension(30, 25));
312                                    toolBar.add(runB);
313                                    toolBar.addSeparator(new Dimension(15, 0));
314                                    toolBarR.addSeparator(new Dimension(15, 0));
315                                    toolBarR.add(deleteB);
316                                    toolBarR.addSeparator(new Dimension(30, 25));
317                                    toolBarR.add(closeB);
318                                    toolBarR.addSeparator(new Dimension(15, 0));
319                                    // END TOOLBAR SETUP
320                                    // *************************************************
321                                    
322                                    // *************************************************
323                                    // TABLE SETUP
324                                    tableModel = ObjectHandles.getQueryTableModel();
325                                    table = new JTable(tableModel);
326                                    table.setPreferredScrollableViewportSize(new Dimension(500, 70));
327                                    table.setColumnSelectionAllowed(false);
328                                    //                table.setShowGrid(true);
329                                    //                table.setShowHorizontalLines(true);
330                                    table.setShowVerticalLines(false);
331                                    // this should disallow rearranging cols 
332                                    table.setDragEnabled(false);  
333                                    // add the table to a scrollPane
334                                    JScrollPane tableSP = new JScrollPane(table);
335                                    tableSP.setBorder(etchedBorder);
336                                    /*
337                                    TableColumn column = null;
338                                    for (int i = 0; i < tableModel.getColumnCount(); i++) {
339                                             column = table.getColumnModel().getColumn(i);
340                                             // first 2 columns should be smaller
341                                             if (i < 2) column.setPreferredWidth(10); 
342                                             else column.setPreferredWidth(100); 
343                                    }
344                                    */
345    
346                                    // ***** SETUP TABLE LISTENER *****
347                                    DefaultListSelectionModel dlsm = new DefaultListSelectionModel();
348                                    table.setSelectionModel(dlsm);
349                                    // only allow single item selection
350                                    dlsm.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
351                                    dlsm.addListSelectionListener(new ListSelectionListener() {
352                                                      public void valueChanged(ListSelectionEvent e) {
353                                                                    if (e.getValueIsAdjusting()) return;
354    
355                                                                    if ((table.getRowCount() > 0)
356                                                                             && (table.getSelectedRowCount() > 0)) {
357                                                                             // an item is selected
358                                                                             query = tableModel.getRow(table.getSelectedRow());
359                                                                             treeID = query.getTreeID();
360    
361                                                                             // setup notesL
362                                                                             notesL.setText(" " + query.getNotes());
363                                                                             //                                                                      notesL.setCaretPosition(0); // move cursor to begin of field
364                                                                             
365                                                                             publishB.setEnabled(true);
366                                                                             exportB.setEnabled(true);
367                                                                             copyB.setEnabled(true);
368                                                                             viewB.setEnabled(true);
369                                                                             editB.setEnabled(true);
370                                                                             deleteB.setEnabled(true);
371                                                                             runB.setEnabled(true);
372                                                                    } else {
373                                                                             query = null;
374                                                                             treeID = "";
375                                                                             
376                                                                             // empty notesTF
377                                                                             notesL.setText("");
378    
379                                                                             publishB.setEnabled(false);
380                                                                             exportB.setEnabled(false);
381                                                                             copyB.setEnabled(false);
382                                                                             viewB.setEnabled(false);
383                                                                             editB.setEnabled(false);
384                                                                             deleteB.setEnabled(false);
385                                                                             runB.setEnabled(false);
386                                                                    }
387                                                      }
388                                             });
389                                    // END TABLE SETUP
390                                    // *************************************************
391    
392                                    // *************************************************
393                                    // QUERY NOTES INFO SETUP
394                                    JPanel notesP = new JPanel(new BorderLayout());
395                                    notesP.setBorder(etchedPadBorder5);
396                                    notesP.add(new JLabel("Notes: "), BorderLayout.WEST);
397                                    notesL.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0,0,0,5), 
398                                                                                                                                                                              loweredBorder));
399                                    notesP.add(notesL, BorderLayout.CENTER);
400                                    // END QUERY NOTES INFO SETUP
401                                    // *************************************************
402                      
403                                    // *************************************************
404                                    // FILE INFO SETUP
405                                    JPanel fileInfoP = new JPanel(new BorderLayout());
406                                    fileInfoP.setBorder(emptyBorder);
407                                    
408                                    // file browse button
409                                    fileBrowseB = new JButton("Browse...");
410                                    fileBrowseB.addMouseListener(new MouseAdapter() {
411                                                      // add status bar text when mouse moves over button
412                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Browse the operating system for a file to store the query."); }
413                                                      // clear status bar when mouse moves off button
414                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
415                                             });
416                                    fileBrowseB.addActionListener(new ActionListener() {
417                                                      public void actionPerformed(ActionEvent e) {
418                                                                    String name = fileNameTF.getText();
419                                                                    
420                                                                    if (CrimsonUtils.isEmpty(name)) {
421                                                                             // no current name so use queryID and
422                                                                             // treeID to create a default name
423                                                                             if (query != null) {
424                                                                                      name = query.getID();
425                                                                                      if (! CrimsonUtils.isEmpty(query.getTreeID())) {
426                                                                                                    name += "_" + query.getTreeID();
427                                                                                      }
428                                                                             }
429                                                                    }
430                                                                    File file = GUIUtils.saveFileChooser("Select Output NEXUS File", name, null);
431                                                                    fileNameTF.setText(GUIUtils.getFilename(file));
432                                                      }
433                                             });
434    
435                                    // Output filename
436                                    JPanel fileP = new JPanel(new GridLayout(0,1,0,5));
437                                    fileP.setBorder(BorderFactory.createTitledBorder(etchedBorder, "Output File"));
438                                    fileNameTF.setBorder(loweredBorder);
439                                    fileP.add(fileNameTF);
440                                    fileP.add(fileBrowseB);
441                                    fileInfoP.add(fileP, BorderLayout.NORTH);
442    
443                                    // Number of Repeats
444                                    JPanel fileRepeatP = new JPanel(new GridLayout(0,1,0,5));
445                                    fileRepeatP.setBorder(BorderFactory.createTitledBorder(etchedBorder, "Number of Query Runs"));
446                                    fileRepeatS.setBorder(loweredBorder);
447                                    fileRepeatP.add(fileRepeatS);
448    
449                                    JPanel fileCtrlP = new JPanel(new GridLayout(0,1,0,5));
450                                    fileCtrlP.add(fileIntSeqCB);
451                                    fileCtrlP.add(fileRepeatP);
452                                    fileInfoP.add(fileCtrlP, BorderLayout.SOUTH);
453                                    // END FILE INFO SETUP
454                                    // *************************************************
455    
456                                    // *************************************************
457                                    // STATUS BAR SETUP
458                                    JLabel statusBarSpacer = new JLabel(" ");
459                                    statusBar = new JLabel(" ");
460                                    JPanel statusBarP = new JPanel(false);
461                                    statusBarP.setBorder(loweredBorder);
462                                    statusBarP.setLayout(new BorderLayout());
463                                    statusBarP.add(statusBarSpacer, BorderLayout.WEST);
464                                    statusBarP.add(statusBar, BorderLayout.CENTER);
465                                    // END STATUS BAR SETUP
466                                    // *************************************************
467    
468                                    // setup options panel
469                                    JPanel optionsP = new JPanel(new BorderLayout());
470                                    optionsP.setBorder(etchedPadBorder5);
471                                    optionsP.add(fileInfoP, BorderLayout.CENTER);
472    
473                                    // setup main panel
474                                    JPanel listP = new JPanel(new BorderLayout());
475                                    listP.add(tableSP, BorderLayout.CENTER);
476                                    listP.add(optionsP, BorderLayout.EAST);
477                                    listP.add(notesP, BorderLayout.SOUTH);
478    
479                                    // this will keep the toolbar on the left and right edges
480                                    Box box = Box.createHorizontalBox();
481                                    box.add(toolBar);
482                                    box.add(Box.createHorizontalGlue());
483                                    box.add(toolBarR);
484    
485                                    getContentPane().add(box, BorderLayout.NORTH);
486                                    getContentPane().add(listP, BorderLayout.CENTER);
487                                    getContentPane().add(statusBarP, BorderLayout.SOUTH);
488                                    pack();
489                                    
490                                    // set the default window size
491                                    setSize(getSize().width, getSize().height + 100);
492                                    
493                                    // display the window
494                                    setVisible(true);
495                      }
496             }
497    } // QueryManager.java
498