001    /*
002     * Copyright 2007, 2012 Stephen Fisher and Junhyong Kim, University of
003     * Pennsylvania.
004     *
005     * This file is part of Glo-DB.
006     * 
007     * Glo-DB is free software: you can redistribute it and/or modify it
008     * under the terms of the GNU General Public License as published by
009     * the Free Software Foundation, either version 3 of the License, or
010     * (at your option) any later version.
011     * 
012     * Glo-DB is distributed in the hope that it will be useful, but
013     * WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015     * General Public License for more details.
016     * 
017     * You should have received a copy of the GNU General Public License
018     * along with Glo-DB. If not, see <http://www.gnu.org/licenses/>.
019     *
020     * @(#)SequenceBrowser.java
021     */
022    
023    package edu.upenn.gloDB.gui;
024    
025    import edu.upenn.gloDB.*;
026    import java.awt.*;
027    import java.awt.event.*;
028    import javax.swing.*;
029    import javax.swing.event.*;
030    import java.util.StringTokenizer;
031    import java.util.HashMap;
032    import java.util.Set;
033    import java.util.Iterator;
034    import java.util.ArrayList;
035    
036    /**
037     * Browse existing Sequences.
038     *
039     * @author  Stephen Fisher
040     * @version $Id: SequenceBrowser.java,v 1.25.2.28 2007/03/01 21:17:33 fisher Exp $
041     */
042    
043    public class SequenceBrowser {
044             private static BrowserFrame browserFrame = null;
045    
046             public static JFrame show() {
047                      return show("");
048             }
049    
050        public static JFrame show(String id) {
051                      // only allow one instance of BrowserFrame
052                      if (browserFrame == null) browserFrame = new BrowserFrame();
053    
054                      browserFrame.selectSequence(id);
055                      browserFrame.show();
056    
057                      return browserFrame;
058             }
059                      
060             private static class BrowserFrame extends JFrame {
061                      private JComboBox sequenceCB;
062                      private JList attributeL;
063                      private JButton addAttributeB;
064                      private JButton editAttributeB;
065                      private JButton delAttributeB;
066                      private JList trackL;
067                      private JLabel statusBar;
068                      
069                      private JLabel offsetL = new JLabel("");
070                      private JLabel minL = new JLabel("");
071                      private JLabel maxL = new JLabel("");
072                      private JLabel lengthL = new JLabel("");
073                      private JLabel loadDataL = new JLabel("");
074                      
075                      private Sequence sequence;
076                      private Object[] tracks;
077                      
078                      BrowserFrame thisFrame;
079                      
080                      public BrowserFrame() {
081                                    super("Sequence Browser");
082                                    
083                                    // keep pointer to self so can 'dispose' Frame below
084                                    thisFrame = this;
085                                    
086                                    setDefaultCloseOperation(HIDE_ON_CLOSE);
087                                    
088                                    // ***** SETUP SEQUENCE INFO *****
089                                    JToolBar sequenceP = new JToolBar();
090                                    sequenceP.setFloatable(false);
091                                    sequenceP.setBorder(BorderFactory.createEtchedBorder());
092                                    // add Sequence ComboBox
093                                    sequenceCB = new JComboBox(ObjectHandles.getSequenceList());
094                                    sequenceCB.setEditable(false);
095                                    //                              selectSequence(id);
096                                    sequenceCB.addActionListener(new ActionListener() {
097                                                      public void actionPerformed(ActionEvent e) {
098                                                                    String selection = (String) ((JComboBox) e.getSource()).getSelectedItem();
099                                                                    sequenceSelected(selection);
100                                                      }
101                                             });
102                                    // add Buttons
103                                    JButton newB = new JButton(new ImageIcon("icons/new.png"));
104                                    newB.setToolTipText("New");
105                                    newB.addMouseListener(new MouseAdapter() {
106                                                      // add status bar text when mouse moves over button
107                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("New sequence"); }
108                                                      // clear status bar when mouse moves off button
109                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
110                                             });
111                                    newB.addActionListener(new ActionListener() {
112                                                      public void actionPerformed(ActionEvent e) {
113                                                                    Sequence tmp = GUISequenceIO.newSequence();
114                                                                    // if user 'cancelled' then don't do anything
115                                                                    if (tmp != null) {       
116                                                                             sequence = tmp;
117                                                                             
118                                                                             // don't use 'id' here because the actual ID
119                                                                             // might have changed when creating the
120                                                                             // Sequence
121                                                                             sequenceCB.setSelectedItem(sequence.getID());
122                                                                    }
123                                                      }
124                                             });
125                                    JButton loadB = new JButton(new ImageIcon("icons/load.png"));
126                                    loadB.setToolTipText("Load");
127                                    loadB.addMouseListener(new MouseAdapter() {
128                                                      // add status bar text when mouse moves over button
129                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Load sequence"); }
130                                                      // clear status bar when mouse moves off button
131                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
132                                             });
133                                    loadB.addActionListener(new ActionListener() {
134                                                      public void actionPerformed(ActionEvent e) {
135                                                                    Set sequences = GUISequenceIO.loadSequence();
136                                                                    if (sequences != null) {
137                                                                             Iterator i = sequences.iterator();
138                                                                             Sequence sequence = (Sequence) i.next();
139                                                                             sequenceCB.setSelectedIndex(ObjectHandles.getSequenceList().getIndexOf(sequence.getID()));
140                                                                    }
141                                                      }
142                                             });
143                                    JButton saveB = new JButton(new ImageIcon("icons/save.png"));
144                                    saveB.setToolTipText("Save");
145                                    saveB.addMouseListener(new MouseAdapter() {
146                                                      // add status bar text when mouse moves over button
147                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Save sequence"); }
148                                                      // clear status bar when mouse moves off button
149                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
150                                             });
151                                    saveB.addActionListener(new ActionListener() {
152                                                      public void actionPerformed(ActionEvent e) {
153                                                                    if (sequence == null) return;
154                                                                    GloDBUtils.printMsg("'Save' not yet implemented.");
155                                                      }
156                                             });
157                                    JButton sourceB = new JButton(new ImageIcon("icons/web.png"));
158                                    sourceB.setToolTipText("View/edit source location");
159                                    sourceB.addMouseListener(new MouseAdapter() {
160                                                      // add status bar text when mouse moves over button
161                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Edit and/or view the source location (file, URL, etc)"); }
162                                                      // clear status bar when mouse moves off button
163                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
164                                             });
165                                    sourceB.addActionListener(new ActionListener() {
166                                                      public void actionPerformed(ActionEvent e) {
167                                                                    if (sequence == null) return;
168                                                                    new EditSourcePanel();
169                                                      }
170                                             });
171                                    JButton viewB = new JButton(new ImageIcon("icons/view.png"));
172                                    viewB.setToolTipText("View Data");
173                                    viewB.addMouseListener(new MouseAdapter() {
174                                                      // add status bar text when mouse moves over button
175                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("View sequence data"); }
176                                                      // clear status bar when mouse moves off button
177                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
178                                             });
179                                    viewB.addActionListener(new ActionListener() {
180                                                      public void actionPerformed(ActionEvent e) {
181                                                                    if (sequence == null) return;
182                                                                    
183                                                                    // if user set data directly, then getDataLoader
184                                                                    // may not be set but there would still be data to
185                                                                    // view
186                                                                    if ((! sequence.isDataLoaded()) && (sequence.getDataLoader() == null)) {
187                                                                             GloDBUtils.printError("No source data associated with this sequence.");
188                                                                             return;
189                                                                    } 
190                                                                    
191                                                                    // warn user for very long sequences
192                                                                    if (sequence.length() > 100000) {
193                                                                             String msg = "The sequence is very long (" + Integer.toString(sequence.length()) + " bp).\n";
194                                                                             msg += "It may take 60sec or longer to create this display.\n";
195                                                                             msg += "Are you sure you want to continue?\n";
196                                                                             Object[] options = {"Display", "Cancel"};
197                                                                             int flag = JOptionPane.showOptionDialog(null, msg,
198                                                                                                                                                                                      "Display Confirmation",
199                                                                                                                                                                                      JOptionPane.YES_NO_OPTION,
200                                                                                                                                                                                      JOptionPane.QUESTION_MESSAGE,
201                                                                                                                                                                                      null,
202                                                                                                                                                                                      options,
203                                                                                                                                                                                      options[1]);
204                                                                             if (flag == JOptionPane.YES_OPTION) { // "Display"
205                                                                                      new ViewSequencePanel();
206                                                                             }
207                                                                    } else {
208                                                                             // short (< 100K bp) sequence so just display
209                                                                             new ViewSequencePanel();
210                                                                    }
211                                                                    
212                                                                    // if data wasn't previously loaded, it should be
213                                                                    // now so try again to set these values.
214                                                                    if (sequence.isDataLoaded()) {
215                                                                             maxL.setText(Integer.toString(sequence.getMax()));
216                                                                             lengthL.setText(Integer.toString(sequence.length()));
217                                                                    }
218                                                                    loadDataL.setText(Boolean.toString(sequence.isDataLoaded()));
219                                                      }
220                                             });
221                                    JButton deleteB= new JButton(new ImageIcon("icons/delete.png"));
222                                    deleteB.setToolTipText("Delete Sequence");
223                                    deleteB.addMouseListener(new MouseAdapter() {
224                                                      // add status bar text when mouse moves over button
225                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("THIS WILL PERMANENTLY DELETE THE SEQUENCE!"); }
226                                                      // clear status bar when mouse moves off button
227                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
228                                             });
229                                    deleteB.addActionListener(new ActionListener() {
230                                                      public void actionPerformed(ActionEvent e) {
231                                                                    if (sequence == null) return;   
232                                                                    
233                                                                    String msg = "Are you sure you want to remove this sequence?\n";
234                                                                    msg += "Sequence: " + sequence.getID();
235                                                                    Object[] options = {"Delete Sequence", "Cancel"};
236                                                                    int flag = JOptionPane.showOptionDialog(null, msg,
237                                                                                                                                                                             "Delete Confirmation",
238                                                                                                                                                                             JOptionPane.YES_NO_OPTION,
239                                                                                                                                                                             JOptionPane.QUESTION_MESSAGE,
240                                                                                                                                                                             null,
241                                                                                                                                                                             options,
242                                                                                                                                                                             options[1]);
243                                                                    if (flag == JOptionPane.YES_OPTION) { // "Delete"
244                                                                             ObjectHandles.removeSequence(sequence);
245                                                                             if (sequenceCB.getItemCount() > 0) {
246                                                                                      sequenceCB.setSelectedIndex(0);
247                                                                             } else {
248                                                                                      sequenceSelected(null);
249                                                                             }
250                                                                    }
251                                                      }
252                                             });
253                                    JButton closeB = new JButton(new ImageIcon("icons/close.png"));
254                                    closeB.setToolTipText("Close");
255                                    closeB.addMouseListener(new MouseAdapter() {
256                                                      // add status bar text when mouse moves over button
257                                                      public void mouseEntered(MouseEvent e) { statusBar.setText("Close the sequence browser"); }
258                                                      // clear status bar when mouse moves off button
259                                                      public void mouseExited(MouseEvent e) { statusBar.setText(""); }
260                                             });
261                                    closeB.addActionListener(new ActionListener() {
262                                                      public void actionPerformed(ActionEvent e) {
263                                                                    thisFrame.hide();
264                                                      }
265                                             });
266                                    // add ToolBar
267                                    sequenceP.addSeparator(new Dimension(15, 0));
268                                    sequenceP.add(newB);
269                                    sequenceP.addSeparator(new Dimension(30, 25));
270                                    sequenceP.add(loadB);
271                                    sequenceP.addSeparator(new Dimension(30, 25));
272                                    /*
273                                    sequenceP.add(saveB);
274                                    sequenceP.addSeparator(new Dimension(30, 25));
275                                    */
276                                    sequenceP.add(new JLabel("Sequence: "));
277                                    sequenceP.add(sequenceCB);
278                                    sequenceP.addSeparator(new Dimension(15, 0));
279                                    sequenceP.add(sourceB);
280                                    sequenceP.addSeparator(new Dimension(30, 25));
281                                    sequenceP.add(viewB);
282                                    sequenceP.addSeparator(new Dimension(30, 25));
283                                    sequenceP.add(deleteB);
284                                    sequenceP.addSeparator(new Dimension(30, 25));
285                                    sequenceP.add(closeB);
286                                    sequenceP.addSeparator(new Dimension(15, 0));
287                                    
288                                    // ***** SETUP ATTRIBUTE INFO *****
289                                    JPanel attributeP = new JPanel(new BorderLayout());
290                                    // add attributes List
291                                    attributeL = new JList();
292                                    //                attributeL.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
293                                    attributeL.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
294                                    attributeL.addListSelectionListener(new ListSelectionListener() {
295                                                      public void valueChanged(ListSelectionEvent e) {
296                                                                    if (e.getValueIsAdjusting()) return;
297                                                                    
298                                                                    JList list = (JList) e.getSource();
299                                                                    if (list.isSelectionEmpty()) {
300                                                                             // disable the "Delete" button if no selection
301                                                                             editAttributeB.setEnabled(false);
302                                                                             delAttributeB.setEnabled(false);
303                                                                    } else {
304                                                                             // enable the "Delete" button if something selected
305                                                                             editAttributeB.setEnabled(true);
306                                                                             delAttributeB.setEnabled(true);
307                                                                    }
308                                                      }
309                                             });
310                                    JScrollPane attributeSP = new JScrollPane(attributeL);
311                                    attributeP.add(attributeSP, BorderLayout.CENTER);
312                                    // add button sub-panel
313                                    JPanel attributeBP = new JPanel(new GridLayout(1,0,5,5));
314                                    // add attributes "add" Button
315                                    addAttributeB = new JButton(new ImageIcon("icons/new.png"));
316                                    addAttributeB.setToolTipText("Add Attribute");
317                                    addAttributeB.addActionListener(new ActionListener() {
318                                                      public void actionPerformed(ActionEvent e) {
319                                                                    if (sequence == null) return;
320                                                                    
321                                                                    String[] labels = {" Key:", " Value:"};
322                                                                    // use this to get the return value from FieldEditDialog
323                                                                    ArrayList textFields = new ArrayList();
324                                                                    textFields.add(new JTextField(20));
325                                                                    textFields.add(new JTextField(20));
326                                                                    new FieldEditDialog("Add Attribute", labels, textFields);
327                                                                    
328                                                                    // check "exit code" for FieldEditDialog, if false then exit
329                                                                    Boolean exitCode = (Boolean) textFields.get(textFields.size()-1);
330                                                                    if (! exitCode.booleanValue()) return;
331    
332                                                                    JTextField tf = (JTextField) textFields.get(0);
333                                                                    String key = tf.getText();
334                                                                    if (key.length() > 0) { // make sure a key is valid
335                                                                             tf = (JTextField) textFields.get(1);  // get value
336                                                                             String value = tf.getText();
337                                                                             String msg = "getSequence(\"" + sequence.getID() + "\")";
338                                                                             msg += ".addAttribute(\"" + key + "\", \"" + value + "\")";
339                                                                             Root.runCommand(msg, true);
340                                                                             updateAttributes();
341                                                                    }
342                                                      }
343                                             });
344                                    attributeBP.add(addAttributeB);
345                                    // add attributes "edit" Button
346                                    editAttributeB = new JButton(new ImageIcon("icons/edit.png"));
347                                    editAttributeB.setToolTipText("Edit Attribute");
348                                    editAttributeB.setEnabled(false);
349                                    editAttributeB.addActionListener(new ActionListener() {
350                                                      public void actionPerformed(ActionEvent e) {
351                                                                    StringTokenizer st = new StringTokenizer((String) 
352                                                                                                                                                                              attributeL.getSelectedValue(),
353                                                                                                                                                                              ":", true);
354                                                                    String key = st.nextToken();
355                                                                    String value = st.nextToken(); // this is the ":"
356                                                                    value = st.nextToken(); // this is the actual value
357                                                                    value = value.substring(1, value.length());  // remove leading " "
358                                                                    // add any remaining tokens
359                                                                    while (st.hasMoreTokens()) { 
360                                                                             value += st.nextToken(); 
361                                                                    }
362                                                                    
363                                                                    String[] labels = {" Key:", " Value:"};
364                                                                    // use this to get the return value from FieldEditDialog
365                                                                    ArrayList textFields = new ArrayList();
366                                                                    JTextField tf = new JTextField(20);
367                                                                    tf.setText(key);
368                                                                    tf.setEditable(false);
369                                                                    textFields.add(tf);
370                                                                    tf = new JTextField(20);
371                                                                    tf.setText(value);
372                                                                    textFields.add(tf);
373                                                                    new FieldEditDialog("Edit Attribute", labels, textFields);
374                                                                    
375                                                                    // check "exit code" for FieldEditDialog, if false then exit
376                                                                    Boolean exitCode = (Boolean) textFields.get(textFields.size()-1);
377                                                                    if (! exitCode.booleanValue()) return;
378    
379                                                                    tf = (JTextField) textFields.get(1);
380                                                                    String newValue = tf.getText();
381                                                                    if (value.compareTo(newValue) != 0) { // make sure value changed
382                                                                             String msg = "getSequence(\"" + sequence.getID() + "\")";
383                                                                             msg += ".addAttribute(\"" + key + "\", \"" + newValue + "\")";
384                                                                             Root.runCommand(msg, true);
385                                                                             updateAttributes();
386                                                                    }
387                                                      }
388                                             });
389                                    attributeBP.add(editAttributeB);
390                                    // add attributes "delete" Button
391                                    delAttributeB = new JButton(new ImageIcon("icons/delete.png"));
392                                    delAttributeB.setToolTipText("Delete Attribute");
393                                    delAttributeB.setEnabled(false);
394                                    delAttributeB.addActionListener(new ActionListener() {
395                                                      public void actionPerformed(ActionEvent e) {
396                                                                    String msg = "Are you sure you want to delete the following attribute?\n\t";
397                                                                    msg += attributeL.getSelectedValue();
398                                                                    Object[] options = {"Delete Attribute", "Cancel"};
399                                                                    int flag = JOptionPane.showOptionDialog(null, msg,
400                                                                                                                                                                             "Delete Confirmation",
401                                                                                                                                                                             JOptionPane.YES_NO_OPTION,
402                                                                                                                                                                             JOptionPane.QUESTION_MESSAGE,
403                                                                                                                                                                             null,
404                                                                                                                                                                             options,
405                                                                                                                                                                             options[1]);
406                                                                    if (flag == JOptionPane.YES_OPTION) { // "Delete"
407                                                                             StringTokenizer st = new StringTokenizer((String) 
408                                                                                                                                                                                            attributeL.getSelectedValue(),
409                                                                                                                                                                                            ":");
410                                                                             String key = st.nextToken();
411                                                                             msg = "getSequence(\"" + sequence.getID() + "\")";
412                                                                             msg += ".delAttribute(\"" + key + "\")";
413                                                                             Root.runCommand(msg, true);
414                                                                             
415                                                                             updateAttributes();
416                                                                    }
417                                                      }
418                                             });
419                                    attributeBP.add(delAttributeB);
420                                    attributeP.add(attributeBP, BorderLayout.SOUTH);
421                                    // add attributes Label
422                                    attributeP.add(new JLabel(" Attributes:"), BorderLayout.NORTH);
423                                    // provide a preferred size for attributesP
424                                    attributeP.setPreferredSize(new Dimension(300, 200));
425                                    
426                                    // ***** SETUP SEQUENCE SPECs *****
427                                    JPanel infoP = new JPanel(new BorderLayout());
428                                    // add info sub-panel
429                                    JPanel infoSP = new JPanel(new GridLayout(5,2,5,5));
430                                    infoSP.add(new JLabel(" Offset:"));
431                                    infoSP.add(offsetL);
432                                    infoSP.add(new JLabel(" Min:"));
433                                    infoSP.add(minL);
434                                    infoSP.add(new JLabel(" Max:"));
435                                    infoSP.add(maxL);
436                                    infoSP.add(new JLabel(" Length:"));
437                                    infoSP.add(lengthL);
438                                    infoSP.add(new JLabel(" Data loaded:"));
439                                    infoSP.add(loadDataL);
440                                    infoP.add(infoSP, BorderLayout.CENTER);
441                                    // add button sub-panel
442                                    JPanel infoBP = new JPanel(new GridLayout(0,1,5,5));
443                                    // add info "loadData" button
444                                    JButton loadDataB = new JButton("(Re)Load Data");
445                                    loadDataB.addActionListener(new ActionListener() {
446                                                      public void actionPerformed(ActionEvent e) {
447                                                                    String msg = "Are you sure you want to (re)load the sequence data?\n";
448                                                                    msg += "This may take a while for large data files.";
449                                                                    Object[] options = {"Load", "Cancel"};
450                                                                    int flag = JOptionPane.showOptionDialog(null, msg,
451                                                                                                                                                                             "Load Data Confirmation",
452                                                                                                                                                                             JOptionPane.YES_NO_OPTION,
453                                                                                                                                                                             JOptionPane.QUESTION_MESSAGE,
454                                                                                                                                                                             null,
455                                                                                                                                                                             options,
456                                                                                                                                                                             options[1]);
457                                                                    if (flag == JOptionPane.YES_OPTION) { // "Load"
458                                                                             if (sequence != null) {
459                                                                                      sequence.reloadData();
460                                                                                      loadDataL.setText(Boolean.toString(sequence.isDataLoaded()));
461                                                                                      if (sequence.isDataLoaded()) {
462                                                                                                    maxL.setText(Integer.toString(sequence.getMax()));
463                                                                                                    lengthL.setText(Integer.toString(sequence.length()));
464                                                                                      }
465                                                                             }
466                                                                    }
467                                                      }
468                                             });
469                                    infoBP.add(loadDataB);
470                                    infoP.add(infoBP, BorderLayout.SOUTH);
471                                    
472                                    // ***** SETUP TRACK INFO *****
473                                    JPanel trackP = new JPanel(new BorderLayout());
474                                    // setup list of Tracks for selected sequence
475                                    trackL = new JList();
476                                    trackL.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
477                                    trackL.setToolTipText("Double click on a Track name to edit the item in a Track Browser");
478                                    /*
479                                      trackL.addListSelectionListener(new ListSelectionListener() {
480                                      public void valueChanged(ListSelectionEvent e) {
481                                      if (e.getValueIsAdjusting()) return;
482                                      
483                                      JList list = (JList) e.getSource();
484                                      if (list.isSelectionEmpty()) {
485                                      statusBar.setText("");
486                                      } else {
487                                      Track track = ObjectHandles.getTrack((String) tracks[index]);
488                                      String msg = "Track ID: " + track.getID();
489                                      msg += " :: Num Features: " + track.numFeatures();
490                                      msg += " :: Length: " + track.length();
491                                      msg += " :: Attributes: " + track.getAttributes();
492                                      statusBar.setText(msg);
493                                      }
494                                      }
495                                      });
496                                    */
497                                    trackL.addMouseMotionListener(new MouseMotionListener() {
498                                                      public void mouseMoved(MouseEvent e) {
499                                                                    if (tracks.length > 0) {
500                                                                             int index = trackL.locationToIndex(e.getPoint());
501                                                                             if (index > -1) {
502                                                                                      Track track = ObjectHandles.getTrack((String) tracks[index]);
503                                                                                      String msg = "Track ID: " + track.getID();
504                                                                                      msg += " :: Num Features: " + track.numFeatures();
505                                                                                      msg += " :: Length: " + track.length();
506                                                                                      msg += " :: Attributes: " + track.getAttributes();
507                                                                                      statusBar.setText(msg);
508                                                                             }
509                                                                    } else {
510                                                                             statusBar.setText("No tracks with features on this sequence.");
511                                                                    }                                                               
512                                                      }
513                                                      public void mouseDragged(MouseEvent e) { ; }
514                                             });
515                                    trackL.addMouseListener(new MouseAdapter() {
516                                                      // clear status bar when mouse moves out of trackL
517                                                      public void mouseExited(MouseEvent e) {
518                                                                    statusBar.setText("");
519                                                      }
520                                                      
521                                                      public void mouseClicked(MouseEvent e) {
522                                                                    if (e.getClickCount() == 2) {
523                                                                             int index = trackL.locationToIndex(e.getPoint());
524                                                                             
525                                                                             if (index > -1) {    // make sure there is a valid item
526                                                                                      // launch the Track Browser through Root so
527                                                                                      // that the command gets added to the history.
528                                                                                      String id = (String) tracks[index];
529                                                                                      String cmd = "trackBrowser(\"" + id + "\")";
530                                                                                      Root.runCommand(cmd, true);
531                                                                                      
532                                                                                      /*
533                                                                                             String msg = (ObjectHandles.getTrack((String) tracks[index])).toString();
534                                                                                             JOptionPane.showMessageDialog(null, msg,
535                                                                                             "Track Viewer",
536                                                                                             JOptionPane.INFORMATION_MESSAGE);
537                                                                                      */
538                                                                             }
539                                                                    }
540                                                      }
541                                             });
542                                    JScrollPane trackSP = new JScrollPane(trackL);
543                                    trackP.add(trackSP, BorderLayout.CENTER);
544                                    // add Track Label
545                                    trackP.add(new JLabel(" Tracks:"), BorderLayout.NORTH);
546                                    trackP.add(infoP, BorderLayout.SOUTH);
547                                    
548                                    // setup split pane for Track/Feature Panels
549                                    JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, 
550                                                                                                                                      attributeP, trackP);
551                                    splitPane.setOneTouchExpandable(true);
552                                    splitPane.setDividerLocation(300);
553                                    // provide minimum sizes for the two components in the split pane
554                                    Dimension minimumSize = new Dimension(150, 200);
555                                    attributeP.setMinimumSize(minimumSize);
556                                    trackP.setMinimumSize(minimumSize);
557                                    // provide a preferred size for the split pane
558                                    splitPane.setPreferredSize(new Dimension(400, 200));
559                                    
560                                    // add status bar at bottom of window
561                                    JLabel statusBarSpacer = new JLabel(" ");
562                                    statusBar = new JLabel(" ");
563                                    JPanel statusBarP = new JPanel(false);
564                                    statusBarP.setBorder(BorderFactory.createLoweredBevelBorder());
565                                    statusBarP.setLayout(new BorderLayout());
566                                    statusBarP.add(statusBarSpacer, BorderLayout.WEST);
567                                    statusBarP.add(statusBar, BorderLayout.CENTER);
568                                    
569                                    getContentPane().add(sequenceP, BorderLayout.NORTH);
570                                    getContentPane().add(splitPane, BorderLayout.CENTER);
571                                    getContentPane().add(statusBarP, BorderLayout.SOUTH);
572                                    pack();
573                                    
574                                    // set the default window size
575                                    setSize(getSize().width + 50, getSize().height + 150);
576                                    
577                                    // initialize the browser to the current Sequence
578                                    sequenceSelected((String) sequenceCB.getSelectedItem());
579                                    
580                                    // display the window
581                                    show();
582                      }
583                      
584                      /** 
585                            * This will update the SequenceBrowser for the currently selected
586                            * Sequence.
587                            */
588                      private void sequenceSelected(String id) {
589                                    if ((id == null) || (sequenceCB.getItemCount() == 0)) {
590                                             // if null item or empty list, then clear display
591                                             tracks = new Object[0];
592                                             trackL.setListData(tracks);
593                                             attributeL.setListData(new String[0]);
594                                             
595                                             offsetL.setText("");
596                                             minL.setText("");
597                                             maxL.setText("");
598                                             lengthL.setText("");
599                                             loadDataL.setText("");
600                                             
601                                             // make sure this is reset if no items in list
602                                             sequence = null;
603                                             
604                                             return;
605                                    }
606                                    
607                                    sequence = ObjectHandles.getSequence(id);
608                                    
609                                    updateAttributes();
610                                    
611                                    // this doesn't work because the panel won't register that
612                                    // 'tracks' now points to a different list.
613                                    //                tracks = ObjectHandles.getTrackBySequenceList(sequence.getID());
614                                    Set tmpTrack = ObjectHandles.getTrackBySequenceList(sequence.getID());
615                                    if (tmpTrack != null) { tracks = tmpTrack.toArray(); }
616                                    else { tracks = new Object[0]; }
617                                    trackL.setListData(tracks);
618                                    
619                                    offsetL.setText(Integer.toString(sequence.getOffset()));
620                                    minL.setText(Integer.toString(sequence.getMin()));
621                                    if (sequence.isDataLoaded()) {
622                                             maxL.setText(Integer.toString(sequence.getMax()));
623                                             lengthL.setText(Integer.toString(sequence.length()));
624                                    } else {
625                                             // don't force the loaded of data here
626                                             maxL.setText("n/a");
627                                             lengthL.setText("n/a");
628                                    }
629                                    loadDataL.setText(Boolean.toString(sequence.isDataLoaded()));
630                      }
631                      
632                      /**
633                            * This is separate from sequenceSelected() so it can be called
634                            * separately for when the attributes are changed in the attribute
635                            * panel.
636                            */
637                      private void updateAttributes() {
638                                    // don't do anything if sequence not set
639                                    if (sequence == null) return;
640                                    
641                                    HashMap attributes = sequence.getAttributes();
642                                    if ((attributes == null) || (attributes.size() == 0)) {
643                                             attributeL.setListData(new String[0]);
644                                    } else {
645                                             String[] attributeArray = new String[attributes.size()];
646                                             Set keys = attributes.keySet();
647                                             int cnt = 0;
648                                             for (Iterator i = keys.iterator(); i.hasNext();) {
649                                                      String key = (String) i.next();
650                                                      attributeArray[cnt] = key + ": " + attributes.get(key);
651                                                      cnt++;
652                                             }
653                                             attributeL.setListData(attributeArray);
654                                    }
655                      }
656                      
657                      /** 
658                            * Displays the Sequence data. 
659                            * @XXX Should see about using FieldEditDialog here.
660                            */
661                      class EditSourcePanel extends JFrame {
662                                    EditSourcePanel thisFrame;
663    
664                                    JTextField loaderTF = new JTextField(20);
665                                    JTextField argsTF = new JTextField(20);
666    
667                                    public EditSourcePanel() {
668                                             super("Sequence Data");
669                                             
670                                             // keep pointer to self so can 'dispose' Frame below
671                                             thisFrame = this;
672                                             
673                                             setDefaultCloseOperation(DISPOSE_ON_CLOSE);
674                                             
675                                             // setup text area to display data
676                                             JPanel labelP = new JPanel(new GridLayout(0,1));
677                                             JPanel editP = new JPanel(new GridLayout(0,1));
678                                             labelP.add(new JLabel(" Source loader:"));
679                                             labelP.add(new JLabel(" Loader arguments:"));
680                                             updateValues();
681                                             editP.add(loaderTF);
682                                             editP.add(argsTF);
683                                             JPanel contentP = new JPanel(new BorderLayout());
684                                             contentP.setBorder(BorderFactory.createEmptyBorder(20, 20, 0, 20));
685                                             contentP.add(labelP, BorderLayout.WEST);
686                                             contentP.add(editP, BorderLayout.CENTER);
687                                             
688                                             // button panel
689                                             JPanel buttonP = new JPanel(new BorderLayout());
690                                             buttonP.setBorder(BorderFactory.createEmptyBorder(0, 20, 20, 20));
691                                             JButton editB = new JButton("Edit");
692                                             editB.addActionListener(new ActionListener() {
693                                                                    public void actionPerformed(ActionEvent e) {
694                                                                             if (sequence != null) {
695                                                                                      GUIUtils.newSequenceLoader(sequence.getID());
696                                                                                      updateValues();
697                                                                             }
698                                                                    }
699                                                      });
700                                             buttonP.add(editB, BorderLayout.WEST);
701                                             JButton closeB = new JButton("Close");
702                                             closeB.addActionListener(new ActionListener() {
703                                                                    public void actionPerformed(ActionEvent e) {
704                                                                             thisFrame.dispose();
705                                                                    }
706                                                      });
707                                             buttonP.add(closeB, BorderLayout.EAST);
708                                             
709                                             getContentPane().setLayout(new BorderLayout());
710                                             getContentPane().add(contentP, BorderLayout.NORTH);
711                                             getContentPane().add(buttonP, BorderLayout.SOUTH);
712                                             pack();
713                                             
714                                             // set the default window size
715                                             setSize(getSize().width + 100, getSize().height + 30);
716                                             
717                                             // display the window
718                                             //                             setVisible(true);
719                                             show();
720                                    }
721    
722                                    private void updateValues() {
723                                             SequenceLoader sl = sequence.getDataLoader();
724                                             if (sl == null) {
725                                                      loaderTF.setText("not set");
726                                             } else {
727                                                      loaderTF.setText(sl.toString());
728                                             }
729                                             loaderTF.setEditable(false);
730                                             argsTF.setText((sequence.getLoaderArgs()).toString());
731                                             argsTF.setEditable(false);
732                                    }
733                      }
734                      
735                      /** Displays the Sequence data. */
736                      class ViewSequencePanel extends JFrame {
737                                    ViewSequencePanel thisFrame;
738                                    
739                                    public ViewSequencePanel() {
740                                             super("Sequence Data");
741                                             
742                                             // keep pointer to self so can 'dispose' Frame below
743                                             thisFrame = this;
744                                             
745                                             setDefaultCloseOperation(DISPOSE_ON_CLOSE);
746                                             
747                                             // setup text area to display data
748                                             JTextArea textArea = new JTextArea(sequence.getDataFormatted());
749                                             textArea.setLineWrap(false);
750                                             textArea.setWrapStyleWord(false);
751                                             textArea.setEditable(false);
752                                             textArea.setFont(new Font("Courier", Font.PLAIN, 14));
753                                             JScrollPane areaSP = new JScrollPane(textArea);
754                                             areaSP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
755                                             areaSP.setPreferredSize(new Dimension(580, 300));
756                                             
757                                             // setup close button
758                                             JButton closeB = new JButton("Close Viewer");
759                                             closeB.addActionListener(new ActionListener() {
760                                                                    public void actionPerformed(ActionEvent e) {
761                                                                             thisFrame.dispose();
762                                                                    }
763                                                      });
764                                             
765                                             getContentPane().setLayout(new BorderLayout());
766                                             getContentPane().add(areaSP, BorderLayout.CENTER);
767                                             getContentPane().add(closeB, BorderLayout.SOUTH);
768                                             pack();
769                                             
770                                             // set the default window size
771                                             setSize(getSize().width + 100, getSize().height + 30);
772                                             
773                                             // display the window
774                                             //                             setVisible(true);
775                                             show();
776                                    }
777                      }
778                      
779                      /** Handle newSequence dialog. */
780                      class newSequencePanel extends JFrame {
781                                    JTextField idTF;
782                                    newSequencePanel thisFrame;
783                                    
784                                    public newSequencePanel() {
785                                             super("New Sequence");
786                                             
787                                             // keep pointer to self so can 'dispose' Frame below
788                                             thisFrame = this;
789                                             
790                                             setDefaultCloseOperation(DISPOSE_ON_CLOSE);
791                                             
792                                             // entry panel
793                                             JPanel labelP = new JPanel(new GridLayout(0,1));
794                                             JPanel editP = new JPanel(new GridLayout(0,1));
795                                             idTF = new JTextField(20);
796                                             labelP.add(new JLabel(" ID:"));
797                                             editP.add(idTF);
798                                             JPanel contentP = new JPanel(new BorderLayout());
799                                             contentP.setBorder(BorderFactory.createEmptyBorder(20, 20, 0, 20));
800                                             contentP.add(labelP, BorderLayout.WEST);
801                                             contentP.add(editP, BorderLayout.CENTER);
802                                             
803                                             // button panel
804                                             JPanel buttonP = new JPanel(new BorderLayout());
805                                             buttonP.setBorder(BorderFactory.createEmptyBorder(0, 20, 20, 20));
806                                             JButton addB = new JButton("Create");
807                                             addB.setActionCommand("Create");
808                                             addB.addActionListener(new ActionListener() {
809                                                                    public void actionPerformed(ActionEvent e) {
810                                                                             String id = idTF.getText().trim();
811                                                                             
812                                                                             String msg = "newSequence(\"" + id + "\")";
813                                                                             
814                                                                             // add command to history but don't run via console.
815                                                                             // instead we're running it here so we can return a
816                                                                             // reference to the Set of Sequences loaded
817                                                                             Root.runCommand(msg, false);
818                                                                             
819                                                                             // create new sequence here
820                                                                             sequence = new Sequence(id);
821                                                                             // don't use 'id' here because it will have
822                                                                             // been changed when creating the Sequence, if
823                                                                             // the ID already existed
824                                                                             sequenceCB.setSelectedItem(sequence.getID());
825                                                                             
826                                                                             thisFrame.dispose();                                                                    
827                                                                    }
828                                                      });
829                                             buttonP.add(addB, BorderLayout.WEST);
830                                             JButton cancelB = new JButton("Cancel");
831                                             cancelB.setActionCommand("Cancel");
832                                             cancelB.addActionListener(new ActionListener() {
833                                                                    public void actionPerformed(ActionEvent e) {
834                                                                             thisFrame.dispose();
835                                                                    }
836                                                      });
837                                             buttonP.add(cancelB, BorderLayout.EAST);
838                                             
839                                             getContentPane().setLayout(new BorderLayout());
840                                             getContentPane().add(contentP, BorderLayout.NORTH);
841                                             getContentPane().add(buttonP, BorderLayout.SOUTH);
842                                             pack();
843                                             
844                                             // set the default window size
845                                             setSize(getSize().width + 100, getSize().height + 30);
846                                             
847                                             // display the window
848                                             //                             setVisible(true);
849                                             show();
850                                    }
851                      }
852    
853                      public void selectSequence(String id) {
854                                    if ((id.length() == 0) || (sequenceCB.getItemCount() == 0)) return;
855                                    int index = ObjectHandles.getSequenceList().getIndexOf(id);
856                                    // only change selection if valid ID
857                                    if (index > -1) {
858                                             sequenceCB.setSelectedIndex(index);
859                                    } else {
860                                             GloDBUtils.printMsg("Invalid sequence id (\"" + id + "\").", GloDBUtils.WARNING);
861                                    }
862                      }
863             }
864    } // SequenceBrowser.java