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