1 /* $RCSfile$ 2 * $Author: hansonr $ 3 * $Date: 2009-06-26 23:35:44 -0500 (Fri, 26 Jun 2009) $ 4 * $Revision: 11131 $ 5 * 6 * Copyright (C) 2000-2005 The Jmol Development Team 7 * 8 * Contact: jmol-developers@lists.sf.net 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23 */ 24 package org.openscience.jmol.app.janocchio; 25 26 import java.awt.BorderLayout; 27 import java.awt.Color; 28 import java.awt.Component; 29 import java.awt.Container; 30 import java.awt.Dimension; 31 import java.awt.Image; 32 import java.awt.Point; 33 import java.awt.event.ActionEvent; 34 import java.beans.PropertyChangeEvent; 35 import java.beans.PropertyChangeListener; 36 import java.io.BufferedReader; 37 import java.io.File; 38 import java.io.FileReader; 39 import java.io.FileWriter; 40 import java.io.IOException; 41 import java.io.PrintWriter; 42 import java.util.ArrayList; 43 import java.util.HashSet; 44 import java.util.Hashtable; 45 import java.util.List; 46 import java.util.Map; 47 import java.util.Set; 48 import java.util.StringTokenizer; 49 50 import javajs.util.BS; 51 import javajs.util.JSJSONParser; 52 53 import javax.swing.AbstractAction; 54 import javax.swing.Action; 55 import javax.swing.Box; 56 import javax.swing.BoxLayout; 57 import javax.swing.ImageIcon; 58 import javax.swing.JCheckBoxMenuItem; 59 import javax.swing.JFileChooser; 60 import javax.swing.JFrame; 61 import javax.swing.JLabel; 62 import javax.swing.JMenuItem; 63 import javax.swing.JOptionPane; 64 import javax.swing.JPanel; 65 import javax.swing.JSplitPane; 66 import javax.swing.JToolBar; 67 import javax.swing.SwingConstants; 68 69 import org.jmol.c.CBK; 70 import org.jmol.dialog.FileChooser; 71 import org.jmol.i18n.GT; 72 import org.jmol.modelset.Atom; 73 import org.jmol.quantum.NMRCalculation; 74 import org.openscience.jmol.app.Jmol; 75 import org.openscience.jmol.app.JmolApp; 76 import org.openscience.jmol.app.jmolpanel.DisplayPanel; 77 import org.openscience.jmol.app.jmolpanel.GuiMap; 78 import org.openscience.jmol.app.jmolpanel.JmolPanel; 79 import org.openscience.jmol.app.jmolpanel.JmolResourceHandler; 80 import org.openscience.jmol.app.jmolpanel.Splash; 81 import org.openscience.jmol.app.jmolpanel.StatusBar; 82 import org.openscience.jmol.app.jmolpanel.StatusListener; 83 84 public class NMR_JmolPanel extends JmolPanel { 85 86 final static int MIN_SIZE = 600; 87 88 private NMR_DisplayPanel nmrDisplay; 89 90 public JSplitPane mainSplitPane; 91 public NoeTable noeTable; 92 public CoupleTable coupleTable; 93 public FrameCounter frameCounter; 94 public LabelSetter labelSetter; 95 public PopulationDisplay populationDisplay; 96 public FrameDeltaDisplay frameDeltaDisplay; 97 98 protected static File currentDir; 99 100 FileChooser openChooser; 101 JFileChooser exportChooser; 102 JFileChooser saveNmrChooser; 103 JFileChooser readNmrChooser; 104 JFileChooser saveNamfisChooser; 105 JFileChooser readNamfisChooser; 106 107 NmrApplet nmrApplet; 108 boolean isApplet; 109 // private CDKPluginManager pluginManager; 110 111 private NmrGuiMap nmrguimap; // ha ha! Can't initialize this if superclass is also initializing! 112 113 @Override getMenuItem(String name)114 public JMenuItem getMenuItem(String name) { 115 return (JMenuItem) nmrguimap.get(name); 116 } 117 118 static Point border; 119 static Boolean haveBorder = Boolean.FALSE; 120 121 static Set<String> htGuiChanges; 122 123 static { 124 htGuiChanges = new HashSet<String>(); 125 String[] changes = tokenize(NmrResourceHandler.getStringX("changes")); 126 for (int i = changes.length; --i >= 0;) 127 htGuiChanges.add(changes[i]); 128 } 129 NMR_JmolPanel(JmolApp jmolApp, Splash splash, JFrame frame, Jmol parent, int startupWidth, int startupHeight, Map<String, Object> vwrOptions, Point loc)130 public NMR_JmolPanel(JmolApp jmolApp, Splash splash, JFrame frame, 131 Jmol parent, int startupWidth, int startupHeight, 132 Map<String, Object> vwrOptions, Point loc) { 133 super(jmolApp, splash, frame, parent, startupWidth, startupHeight, 134 vwrOptions, loc); 135 } 136 getDistanceJMolecule(BS mol, String[] labelArray, boolean forNOE)137 NmrMolecule getDistanceJMolecule(BS mol, String[] labelArray, boolean forNOE) { 138 return new NmrMolecule(this, (mol == null ? vwr.getFrameAtoms() 139 : mol), labelArray, forNOE); 140 } 141 getAllMolecules()142 BS[] getAllMolecules() { 143 BS[] mols; 144 int mc = ((NMR_Viewer) vwr).getModelCount(); 145 mols = new BS[mc]; 146 for (int i = mc; --i >= 0;) { 147 mols[i] = vwr.getModelUndeletedAtomsBitSet(i); 148 } 149 return mols; 150 } 151 152 @Override getWindowName()153 protected String getWindowName() { 154 return "Janocchio"; 155 } 156 157 /** 158 * @return A list of Actions that is understood by the upper level application 159 */ 160 @Override getFrameActions()161 protected List<Action> getFrameActions() { 162 List<Action> actions = super.getFrameActions(); 163 Action[] a = { 164 //new PdfAction(), 165 new ReadNmrAction(), new SaveNmrAction(), new DetachAppletAction(), 166 new ReattachAppletAction(), new WriteNamfisAction(), 167 new ReadNamfisAction(), new LabelNmrAction(), 168 new JumpBestFrameAction(), new ViewNoeTableAction(), 169 new ViewCoupleTableAction() }; 170 for (int i = a.length; --i >= 0;) 171 actions.add(a[i]); 172 return actions; 173 } 174 175 @Override getStringX(String cmd)176 protected String getStringX(String cmd) { 177 return (cmd.indexOf("NMR.") == 0 ? NmrResourceHandler.getStringX(cmd) 178 : JmolResourceHandler.getStringX(cmd)); 179 } 180 181 @Override getIconX(String img)182 protected ImageIcon getIconX(String img) { 183 return (img.indexOf("NMR.") == 0 ? NmrResourceHandler.getIconX(img) 184 : JmolResourceHandler.getIconX(img)); 185 } 186 187 @Override createGuiMap()188 protected GuiMap createGuiMap() { 189 return nmrguimap = new NmrGuiMap(); 190 } 191 192 @Override createStatusBar()193 protected StatusBar createStatusBar() { 194 return super.createStatusBar(); 195 } 196 197 @Override createToolBar()198 protected JToolBar createToolBar() { 199 JToolBar toolbar = newToolbar(tokenize(NmrResourceHandler 200 .getStringX("toolbar"))); 201 //DAE add extra label 202 frameCounter = new FrameCounter((NMR_Viewer) vwr); 203 toolbar.add(frameCounter, BorderLayout.EAST); 204 say(GT.$("Initializing Noes...")); 205 noeTable = new NoeTable(this, frame); 206 say(GT.$("Initializing Couples...")); 207 coupleTable = new CoupleTable(this, frame); 208 labelSetter = new LabelSetter((NMR_Viewer) vwr, noeTable, coupleTable); 209 toolbar.add(labelSetter, BorderLayout.EAST); 210 //Action handler implementation would go here. 211 toolbar.add(Box.createHorizontalGlue()); 212 return toolbar; 213 } 214 215 @Override createDisplayAndAddStatusListener()216 protected void createDisplayAndAddStatusListener() { 217 isPlugin = ((Nmr) jmolApp).isPlugin(); 218 say(GT.$("Initializing 3D display...")); 219 display = nmrDisplay = new NMR_DisplayPanel(this); 220 vwrOptions.put("display", display); 221 myStatusListener = new MyStatusListener(this, display); 222 vwrOptions.put("statusListener", myStatusListener); 223 } 224 225 @Override setupModelAdapterAndViewer()226 protected void setupModelAdapterAndViewer() { 227 if (JmolResourceHandler.codePath != null) 228 vwrOptions.put("codePath", JmolResourceHandler.codePath); 229 if (modelAdapter != null) 230 vwrOptions.put("modelAdapter", modelAdapter); 231 say(GT.$("Initializing 3D display...4")); 232 vwr = new NMR_Viewer(vwrOptions); 233 say(GT.$("Initializing 3D display...5")); 234 nmrDisplay.setViewer(vwr); 235 myStatusListener.setViewer(vwr); 236 237 } 238 239 @Override getDialogs()240 protected void getDialogs() { 241 super.getDialogs(); 242 } 243 244 @Override getMeasurementTable()245 protected void getMeasurementTable() { 246 super.getMeasurementTable(); 247 } 248 249 @Override setupDisplay()250 protected void setupDisplay() { 251 super.setupDisplay(); 252 } 253 254 @Override setFrameLocation(Point loc, JmolPanel parent)255 protected void setFrameLocation(Point loc, JmolPanel parent) { 256 super.setFrameLocation(loc, parent); 257 } 258 259 @Override setIntoFrame()260 protected void setIntoFrame() { 261 262 frame.setTitle("Janocchio"); 263 frame.setBackground(Color.lightGray); 264 frame.setLayout(new BorderLayout()); 265 frame.setBounds(0, 0, startupWidth, startupHeight); 266 Container contentPane = frame.getContentPane(); 267 // contentPane.setPreferredSize(new Dimension(500, 500)); 268 // display.setPreferredSize(new Dimension(500, 500)); 269 270 mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, null, null); 271 mainSplitPane.setOneTouchExpandable(true); 272 mainSplitPane.setContinuousLayout(true); 273 mainSplitPane.setLeftComponent(this); 274 // setMinimumSize(new Dimension(MIN_SIZE, MIN_SIZE)); 275 frame.setMinimumSize(new Dimension(startupWidth + 400, 100)); 276 277 JSplitPane splitPaneRight = new JSplitPane(JSplitPane.VERTICAL_SPLIT, null, 278 null); 279 splitPaneRight.setOneTouchExpandable(true); 280 //splitPaneRight.setDividerLocation(0.5); Doesn't do anything here 281 //splitPaneRight.setContinuousLayout(true); 282 JPanel noePanel = new JPanel(); 283 noePanel.setLayout(new BoxLayout(noePanel, BoxLayout.PAGE_AXIS)); 284 285 JLabel label = new JLabel("NOE Table", null, SwingConstants.CENTER); 286 label.setAlignmentX(Component.CENTER_ALIGNMENT); 287 288 noePanel.add(label); 289 noePanel.add(noeTable); 290 291 JPanel couplePanel = new JPanel(); 292 couplePanel.setLayout(new BoxLayout(couplePanel, BoxLayout.PAGE_AXIS)); 293 294 JLabel label1 = new JLabel("Couple Table", null, SwingConstants.CENTER); 295 label1.setAlignmentX(Component.CENTER_ALIGNMENT); 296 297 populationDisplay = new PopulationDisplay(((NMR_Viewer) vwr)); 298 frameDeltaDisplay = new FrameDeltaDisplay(((NMR_Viewer) vwr)); 299 300 nmrDisplay.setPopulationDisplay(populationDisplay); 301 nmrDisplay.setFrameDeltaDisplay(frameDeltaDisplay); 302 303 noeTable.setFrameDeltaDisplay(frameDeltaDisplay); 304 coupleTable.setFrameDeltaDisplay(frameDeltaDisplay); 305 306 couplePanel.add(label1, BorderLayout.PAGE_START); 307 couplePanel.add(coupleTable, BorderLayout.CENTER); 308 309 couplePanel.add(populationDisplay, BorderLayout.PAGE_END); 310 couplePanel.add(frameDeltaDisplay, BorderLayout.PAGE_END); 311 312 splitPaneRight.setTopComponent(couplePanel); 313 splitPaneRight.setBottomComponent(noePanel); 314 315 mainSplitPane.setRightComponent(splitPaneRight); 316 splitPaneRight.setMinimumSize(new Dimension(300, 500)); 317 318 //noeTable.setMinimumSize(new Dimension(0,0)); 319 contentPane.add(mainSplitPane, BorderLayout.CENTER); 320 321 contentPane.setPreferredSize(new Dimension(startupWidth, startupHeight)); 322 //dumpContainer(frame, ""); 323 frame.pack(); 324 //dumpContainer(frame, ""); 325 // dumpContainer(frame, ""); 326 327 ImageIcon jmolIcon = JmolResourceHandler.getIconX("icon"); 328 Image iconImage = jmolIcon.getImage(); 329 frame.setIconImage(iconImage); 330 if (!((Nmr) jmolApp).isPlugin()) 331 frame.addWindowListener(new AppCloser()); 332 333 } 334 335 @Override setupConsole()336 protected void setupConsole() { 337 super.setupConsole(); 338 } 339 340 @Override setupDnD()341 protected void setupDnD() { 342 super.setupDnD(); 343 } 344 345 @Override setAtomChooser()346 protected void setAtomChooser() { 347 super.setAtomChooser(); 348 } 349 350 @Override launchMainFrame()351 protected void launchMainFrame() { 352 say(GT.$("Launching main frame...")); 353 } 354 355 @Override saveWindowSizes()356 protected void saveWindowSizes() { 357 super.saveWindowSizes(); 358 } 359 360 @Override getJavaConsole()361 public void getJavaConsole() { 362 super.getJavaConsole(); 363 } 364 365 @Override setMenuKeys(String key, String tokens)366 protected String setMenuKeys(String key, String tokens) { 367 if (htGuiChanges.contains(key)) { 368 String s = NmrResourceHandler.getStringX(key); 369 if (s == null) { 370 System.err.println("Replacement for " + key + " not found; using " 371 + tokens); 372 } else { 373 // insert at end or prior to last - 374 if (s.startsWith("+")) { 375 s = s.substring(1); 376 int pt = tokens.lastIndexOf(" - "); 377 if (pt < 0) { 378 // menubar, toolbar will not hvae - s 379 tokens += (key.endsWith("bar") ? " " : " - ") + s; 380 } else { 381 tokens = tokens.substring(0, pt + 3) + s + tokens.substring(pt); 382 } 383 } else { 384 tokens = s; 385 } 386 System.out.println("Replacement for " + key + " = " + tokens); 387 } 388 } 389 return tokens; 390 } 391 392 @Override doClose(boolean saveSize)393 protected boolean doClose(boolean saveSize) { 394 if (isPlugin) { 395 frame.setVisible(false); 396 ((Nmr) jmolApp).plugin.setVisible(false); 397 } else { 398 super.doClose(saveSize); 399 } 400 return true; 401 402 } 403 setCurrentDirectoryAll(File cDir)404 void setCurrentDirectoryAll(File cDir) { 405 openChooser.setCurrentDirectory(cDir); 406 saveNmrChooser.setCurrentDirectory(cDir); 407 saveNamfisChooser.setCurrentDirectory(cDir); 408 409 readNmrChooser.setCurrentDirectory(cDir); 410 readNamfisChooser.setCurrentDirectory(cDir); 411 } 412 getMinindex()413 public int getMinindex() { 414 return labelSetter.getMinindex(); 415 } 416 getCurrentStructureFile()417 public String getCurrentStructureFile() { 418 return vwr.getModelSetPathName(); 419 } 420 421 /** 422 * Returns a new File referenced by the property 'user.dir', or null if the 423 * property is not defined. 424 * 425 * @return a File to the user directory 426 */ getUserDirectory()427 public static File getUserDirectory() { 428 if (System.getProperty("user.dir") == null) { 429 return null; 430 } 431 return new File(System.getProperty("user.dir")); 432 } 433 dumpContainer(Container c, String s)434 protected static void dumpContainer(Container c, String s) { 435 if (c == null) 436 return; 437 for (int i = c.getComponentCount(); --i >= 0;) { 438 Container c1 = (Container) c.getComponent(i); 439 System.out.println(s + c1); 440 dumpContainer(c1, s + " "); 441 } 442 } 443 444 /** 445 * Take the given string and chop it up into a series of strings on whitespace 446 * boundries. This is useful for trying to get an array of strings out of the 447 * resource file. 448 * 449 * @param input 450 * String to chop 451 * @return Strings chopped on whitespace boundries 452 */ tokenize(String input)453 protected static String[] tokenize(String input) { 454 455 List<String> v = new ArrayList<String>(); 456 StringTokenizer t = new StringTokenizer(input); 457 String cmd[]; 458 459 while (t.hasMoreTokens()) { 460 v.add(t.nextToken()); 461 } 462 cmd = new String[v.size()]; 463 for (int i = 0; i < cmd.length; i++) { 464 cmd[i] = v.get(i); 465 } 466 return cmd; 467 } 468 469 // these correlate with items in NMR_GuiMap.java 470 471 // private static final String pdfActionProperty = "NMR.pdf"; 472 private static final String saveNmrAction = "NMR.saveNmr"; 473 private static final String readNmrAction = "NMR.readNmr"; 474 private static final String detachAppletAction = "NMR.detachApplet"; 475 private static final String reattachAppletAction = "NMR.reattachApplet"; 476 private static final String writeNamfisAction = "NMR.writeNamfis"; 477 private static final String readNamfisAction = "NMR.readNamfis"; 478 private static final String jumpBestFrameAction = "NMR.jumpBestFrame"; 479 private static final String labelNmrAction = "NMR.labelNmr"; 480 481 // --- action implementations ----------------------------------- 482 483 // private PdfAction pdfAction; 484 // private ViewNoeTableAction viewNoeTableAction; 485 // private ViewCoupleTableAction viewCoupleTableAction; 486 487 class SaveNmrAction extends AbstractAction { 488 SaveNmrAction()489 public SaveNmrAction() { 490 super(saveNmrAction); 491 } 492 493 @Override actionPerformed(ActionEvent e)494 public void actionPerformed(ActionEvent e) { 495 NmrSaver nmrSaver = new NmrSaver(saveNmrChooser); 496 497 saveNmrChooser.setAccessory(nmrSaver); 498 499 int retval = saveNmrChooser.showSaveDialog(NMR_JmolPanel.this); 500 File cDir = saveNmrChooser.getCurrentDirectory(); 501 setCurrentDirectoryAll(cDir); 502 if (retval == 0) { 503 File file = saveNmrChooser.getSelectedFile(); 504 MyFileFilter filter = new MyFileFilter("jsn", "NMR Data files"); 505 506 if (file != null) { 507 if (!filter.checkExtension(file)) { 508 String name = file.getAbsolutePath(); 509 // name = name + ".jnc"; 510 // file = new File(name); 511 name = name + ".jsn"; 512 file = new File(name); 513 } 514 515 try { 516 new LoadMeasureThreadJSON(NMR_JmolPanel.this, null) 517 .writeNmrDataJSON(file); 518 } catch (Exception exc) { 519 // Help 520 } 521 } 522 // 523 } 524 525 } 526 527 } 528 writeNmrData(File file)529 public void writeNmrData(File file) throws IOException { 530 PrintWriter out = new PrintWriter(new FileWriter(file)); 531 532 String structurefile = vwr.getModelSetPathName(); 533 out.println(structurefile); 534 535 String[] labelArray = labelSetter.getLabelArray(); 536 for (int i = 0; i < labelArray.length; i++) { 537 if (labelArray[i] != null) { 538 out.println(String.valueOf(i + 1) + " " + labelArray[i]); 539 } 540 } 541 out.println(""); 542 int noeCount = noeTable.getRowCount(); 543 for (int i = 0; i < noeCount; i++) { 544 int[] atomIndices = noeTable.getMeasurementCountPlusIndices(i); 545 out.println(String.valueOf(atomIndices[1] + 1) + " " 546 + String.valueOf(atomIndices[2] + 1) + " " 547 + noeTable.getExpNoe(atomIndices[1], atomIndices[2])); 548 } 549 out.println(""); 550 551 int coupleCount = coupleTable.getRowCount(); 552 for (int i = 0; i < coupleCount; i++) { 553 int[] atomIndices = coupleTable.getMeasurementCountPlusIndices(i); 554 out.println(String.valueOf(atomIndices[1] + 1) + " " 555 + String.valueOf(atomIndices[2] + 1) + " " 556 + String.valueOf(atomIndices[3] + 1) + " " 557 + String.valueOf(atomIndices[4] + 1) + " " 558 + coupleTable.getExpCouple(atomIndices[1], atomIndices[4])); 559 } 560 561 out.flush(); 562 out.close(); 563 } 564 565 public class ReadNmrAction extends AbstractAction { 566 ReadNmrAction()567 public ReadNmrAction() { 568 super(readNmrAction); 569 } 570 571 @Override actionPerformed(ActionEvent e)572 public void actionPerformed(ActionEvent e) { 573 NmrReader nmrReader = new NmrReader(readNmrChooser); 574 575 readNmrChooser.setAccessory(nmrReader); 576 577 int retval = readNmrChooser.showOpenDialog(NMR_JmolPanel.this); 578 File cDir = readNmrChooser.getCurrentDirectory(); 579 setCurrentDirectoryAll(cDir); 580 if (retval == 0) { 581 File file = readNmrChooser.getSelectedFile(); 582 if (file != null) { 583 try { 584 MyFileFilter filter = new MyFileFilter("jnc", "NMR Data files"); 585 if (filter.checkExtension(file)) { 586 readNmrData(file); 587 } else { 588 readNmrDataJSON(file); 589 } 590 591 } catch (Exception exc) { 592 // Help 593 } 594 } 595 // 596 } 597 598 } 599 600 } 601 readNmrData(File file)602 public void readNmrData(File file) throws Exception { 603 // Structure File 604 String fileData = vwr.getFileAsString(file.getAbsolutePath()); 605 String structureFile = firstLineOf(fileData); 606 fileData = fileData.substring(structureFile.length()).trim(); 607 checkLoadAndRun(structureFile, fileData, "jnc"); 608 } 609 readNmrDataJSON(File file)610 public void readNmrDataJSON(File file) throws Exception { 611 String json = vwr.getFileAsString(file.getAbsolutePath()); 612 Map<String, Object> jsonData = new JSJSONParser().parseMap(json, true); 613 String structureFile = (String) jsonData.get("StructureFile"); 614 checkLoadAndRun(structureFile, jsonData, "json"); 615 } 616 checkLoadAndRun(String structureFile, Object fileData, String fileType)617 private void checkLoadAndRun(String structureFile, Object fileData, String fileType) { 618 String currentStructureFile = getCurrentStructureFile(); 619 if (currentStructureFile == null) { 620 int opt = JOptionPane.showConfirmDialog(this, 621 "No Structure File currently loaded.\nLoad Structure File " + structureFile 622 + "\ndefined in this NMR Data File?", "No Structure Warning", 623 JOptionPane.YES_NO_OPTION); 624 if (opt != JOptionPane.YES_OPTION) 625 return; 626 } else if (!currentStructureFile.equals(structureFile)) { 627 int opt = JOptionPane 628 .showConfirmDialog( 629 NMR_JmolPanel.this, 630 "This NMR Data file was saved from a different structure file from that currently loaded.\nContinue Reading Data?", 631 "Read NMR Data Warning", JOptionPane.YES_NO_OPTION); 632 if (opt != JOptionPane.YES_OPTION) { 633 return; 634 } 635 structureFile = null; 636 } 637 @SuppressWarnings("unchecked") 638 LoadMeasureThread thread = ("jnc".equals(fileType) ? new LoadMeasureThread(this, (String) fileData) : 639 new LoadMeasureThreadJSON(this, (Map<String, Object>)fileData)); 640 if (structureFile == null) { 641 thread.start(); 642 } else { 643 thread.loadAndRun(structureFile); 644 } 645 } 646 firstLineOf(String s)647 private static String firstLineOf(String s) { 648 int pt; 649 if ((pt = s.indexOf("\n")) < 0 && (pt = s.indexOf("\r")) < 0) 650 pt = s.length(); 651 return s.substring(0, pt).trim(); 652 } 653 654 public class LabelNmrAction extends AbstractAction { LabelNmrAction()655 public LabelNmrAction() { 656 super(labelNmrAction); 657 } 658 659 @Override actionPerformed(ActionEvent e)660 public void actionPerformed(ActionEvent e) { 661 String[] labelArray = labelSetter.getLabelArray(); 662 String command = new String(); 663 // int minindex = labelSetter.getMinindex(); 664 for (int i = 0; i < labelArray.length; i++) { 665 // if (labelArray[i] != null) { 666 command = command + labelSetter.setLabelString(i, labelArray[i]); 667 // } 668 } 669 vwr.script(command); 670 } 671 } 672 673 public class DetachAppletAction extends AbstractAction { 674 DetachAppletAction()675 public DetachAppletAction() { 676 super(detachAppletAction); 677 } 678 679 @Override actionPerformed(ActionEvent e)680 public void actionPerformed(ActionEvent e) { 681 // ?? 682 // nmrApplet.detach(); 683 } 684 685 } 686 687 public class ReattachAppletAction extends AbstractAction { 688 ReattachAppletAction()689 public ReattachAppletAction() { 690 super(reattachAppletAction); 691 } 692 693 @Override actionPerformed(ActionEvent e)694 public void actionPerformed(ActionEvent e) { 695 // nmrApplet.reattach(); 696 } 697 698 } 699 700 public class ReadNamfisAction extends AbstractAction { 701 ReadNamfisAction()702 public ReadNamfisAction() { 703 super(readNamfisAction); 704 } 705 706 @Override actionPerformed(ActionEvent e)707 public void actionPerformed(ActionEvent e) { 708 709 NamfisReader namfisReader = new NamfisReader(readNamfisChooser); 710 711 readNamfisChooser.setAccessory(namfisReader); 712 713 int retval = readNamfisChooser.showOpenDialog(NMR_JmolPanel.this); 714 File cDir = readNamfisChooser.getCurrentDirectory(); 715 setCurrentDirectoryAll(cDir); 716 if (retval == 0) { 717 File file = readNamfisChooser.getSelectedFile(); 718 // MyFileFilter filter = new MyFileFilter("in1"); 719 720 if (file != null) { 721 722 try { 723 readNamfisOutput(file); 724 } catch (Exception exc) { 725 // Help 726 } 727 } 728 // 729 } 730 731 } 732 readNamfisOutput(File file)733 private boolean readNamfisOutput(File file) throws IOException { 734 BufferedReader inp = new BufferedReader(new FileReader(file)); 735 String line; 736 737 // NAMFIS often fails to fit the data 738 // Indicated by first line 739 740 line = inp.readLine(); 741 if (line.matches("No feasible solution")) { 742 inp.close(); 743 return false; 744 } 745 inp.readLine(); 746 inp.readLine(); 747 inp.readLine(); 748 int nmodel = ((NMR_Viewer) vwr).getModelCount(); 749 double[] population = new double[nmodel + 1]; 750 for (int i = 0; i <= nmodel; i++) { 751 population[i] = 0.0; 752 } 753 754 while ((line = inp.readLine()).trim().length() != 0) { 755 String[] l = line.split("[()=\\s]+"); 756 757 int i = (new Integer(l[1])).intValue(); 758 double p = (new Double(l[2])).doubleValue(); 759 760 population[i] = p; 761 } 762 populationDisplay.addPopulation(population); 763 frameDeltaDisplay.setVisible(false); 764 JCheckBoxMenuItem mi = (JCheckBoxMenuItem) getMenuItem("NMR.populationDisplayCheck"); 765 mi.setSelected(true); 766 767 inp.close(); 768 return true; 769 } 770 } 771 772 public class WriteNamfisAction extends AbstractAction { 773 WriteNamfisAction()774 public WriteNamfisAction() { 775 super(writeNamfisAction); 776 } 777 778 @Override actionPerformed(ActionEvent e)779 public void actionPerformed(ActionEvent e) { 780 // nmrApplet.reattach(); 781 NamfisSaver namfisSaver = new NamfisSaver(saveNamfisChooser); 782 783 saveNamfisChooser.setAccessory(namfisSaver); 784 785 int retval = saveNamfisChooser.showSaveDialog(NMR_JmolPanel.this); 786 File cDir = saveNamfisChooser.getCurrentDirectory(); 787 setCurrentDirectoryAll(cDir); 788 if (retval == 0) { 789 File file = saveNamfisChooser.getSelectedFile(); 790 // MyFileFilter filter = new MyFileFilter("in1"); 791 792 if (file != null) { 793 String name = file.getAbsolutePath(); 794 String[] exts = { "in1", "in2", "in3" }; 795 MyFileFilter filter = new MyFileFilter(exts, ""); 796 if (filter.checkExtension(file)) { 797 // Pattern p = Pattern.compile(".in[0-9]$"); 798 name = name.replaceFirst(".in[0-9]$", ""); 799 800 } 801 802 try { 803 new LoadMeasureThreadJSON(NMR_JmolPanel.this, null) 804 .writeNamfisFiles(name); 805 } catch (Exception exc) { 806 // Help 807 } 808 } 809 // 810 } 811 812 } 813 814 } 815 816 public class JumpBestFrameAction extends AbstractAction { 817 JumpBestFrameAction()818 public JumpBestFrameAction() { 819 super(jumpBestFrameAction); 820 } 821 822 @Override actionPerformed(ActionEvent e)823 public void actionPerformed(ActionEvent e) { 824 int frame = new LoadMeasureThreadJSON(NMR_JmolPanel.this, null) 825 .jumpBestFrame(); 826 if (frame >= 0) 827 frameCounter.setFrameNumberChangeViewer(frame); 828 829 } 830 831 } 832 833 class AtomSetChooserAction extends AbstractAction { AtomSetChooserAction()834 public AtomSetChooserAction() { 835 super(atomsetchooserAction); 836 } 837 838 @Override actionPerformed(ActionEvent e)839 public void actionPerformed(ActionEvent e) { 840 atomSetChooser.setVisible(true); 841 } 842 } 843 844 // public class PdfAction extends MoleculeDependentAction { 845 // 846 // public PdfAction() { 847 // super(pdfActionProperty); 848 // } 849 // 850 // @Override 851 // public void actionPerformed(ActionEvent e) { 852 // 853 // exportChooser.setAccessory(null); 854 // 855 // int retval = exportChooser.showSaveDialog(NMR_JmolPanel.this); 856 // File cDir = exportChooser.getCurrentDirectory(); 857 // setCurrentDirectoryAll(cDir); 858 // if (retval == JFileChooser.APPROVE_OPTION) { 859 // File file = exportChooser.getSelectedFile(); 860 // 861 // if (file != null) { 862 // Document document = new Document(); 863 // 864 // try { 865 // PdfWriter writer = PdfWriter.getInstance(document, 866 // new FileOutputStream(file)); 867 // 868 // document.open(); 869 // 870 // int w = display.getWidth(); 871 // int h = display.getHeight(); 872 // PdfContentByte cb = writer.getDirectContent(); 873 // PdfTemplate tp = cb.createTemplate(w, h); 874 // Graphics2D g2 = tp.createGraphics(w, h); 875 // g2.setStroke(new BasicStroke(0.1f)); 876 // tp.setWidth(w); 877 // tp.setHeight(h); 878 // 879 // display.print(g2); 880 // g2.dispose(); 881 // cb.addTemplate(tp, 72, 720 - h); 882 // } catch (DocumentException de) { 883 // System.err.println(de.getMessage()); 884 // } catch (IOException ioe) { 885 // System.err.println(ioe.getMessage()); 886 // } 887 // 888 // document.close(); 889 // } 890 // } 891 // } 892 // 893 // } 894 895 public class ViewNoeTableAction extends MoleculeDependentAction { 896 ViewNoeTableAction()897 public ViewNoeTableAction() { 898 super("viewNoeTable"); 899 } 900 901 @Override actionPerformed(ActionEvent e)902 public void actionPerformed(ActionEvent e) { 903 noeTable.activate(); 904 } 905 } 906 907 public class ViewCoupleTableAction extends MoleculeDependentAction { 908 ViewCoupleTableAction()909 public ViewCoupleTableAction() { 910 super("viewCoupleTable"); 911 } 912 913 @Override actionPerformed(ActionEvent e)914 public void actionPerformed(ActionEvent e) { 915 coupleTable.activate(); 916 } 917 } 918 919 public static final String chemFileProperty = "chemFile"; 920 921 private abstract class MoleculeDependentAction extends AbstractAction 922 implements PropertyChangeListener { 923 MoleculeDependentAction(String name)924 public MoleculeDependentAction(String name) { 925 super(name); 926 setEnabled(false); 927 } 928 929 @Override propertyChange(PropertyChangeEvent event)930 public void propertyChange(PropertyChangeEvent event) { 931 932 if (event.getPropertyName().equals(chemFileProperty)) { 933 if (event.getNewValue() != null) { 934 setEnabled(true); 935 } else { 936 setEnabled(false); 937 } 938 } 939 } 940 } 941 942 protected Map<String, Thread> htMessageCallbacks = new Hashtable<String, Thread>(); 943 runScriptWithCallback(Thread t, String command)944 void runScriptWithCallback(Thread t, String command) { 945 String key = "NMR:" + t.getClass().getName(); 946 htMessageCallbacks.put(key, t); 947 vwr.script(command); 948 vwr.script("#>NMR>" + key + "<NMR<"); 949 } 950 notifyScriptCallback(String script)951 void notifyScriptCallback(String script) { 952 int pt = (script.startsWith("#>NMR>") ? script.indexOf("<NMR<") : -1); 953 if (pt < 0) 954 return; 955 String key = script.substring(6, pt); 956 Thread t = htMessageCallbacks.remove(key); 957 if (t != null) 958 t.start(); 959 } 960 961 class MyStatusListener extends StatusListener { 962 963 private String defaultFormat = "set measurementUnits noe_hz"; 964 MyStatusListener(JmolPanel jmol, DisplayPanel display)965 MyStatusListener(JmolPanel jmol, DisplayPanel display) { 966 super(jmol, display); 967 } 968 969 /** 970 * @param fullPathName 971 * @param fileName 972 * @param modelName 973 * @param errorMsg 974 * @param isAsync 975 */ notifyFileLoaded(String fullPathName, String fileName, String modelName, String errorMsg, Boolean isAsync)976 private void notifyFileLoaded(String fullPathName, String fileName, 977 String modelName, String errorMsg, 978 Boolean isAsync) { 979 if (errorMsg != null) { 980 return; 981 } 982 if (jmolApp.haveDisplay) 983 pcs.firePropertyChange(chemFileProperty, null, fullPathName); 984 985 int nmodel = ((NMR_Viewer) vwr).getModelCount(); 986 987 frameCounter.setFrameCount(nmodel); 988 989 populationDisplay.setVisible(false); 990 frameDeltaDisplay.setVisible(true); 991 JCheckBoxMenuItem mi = (JCheckBoxMenuItem) getMenuItem("NMR.frameDeltaDisplayCheck"); 992 mi.setSelected(true); 993 if (defaultFormat != null) 994 vwr.script(defaultFormat); 995 } 996 notifyFrameChanged(int modelIndex)997 public void notifyFrameChanged(int modelIndex) { 998 if (vwr == null || modelIndex < 0) 999 return; 1000 if (modelIndex == Integer.MIN_VALUE) 1001 modelIndex = ((NMR_Viewer) vwr).getCurrentModelIndex(); 1002 int modelAtomCount = getFrameAtomCount(); 1003 if (labelSetter.getLabelArray() == null || modelAtomCount != labelSetter.getLabelArray().length) { 1004 labelSetter.allocateLabelArray(modelAtomCount); 1005 1006 noeTable.allocateLabelArray(modelAtomCount); 1007 noeTable.allocateExpNoes(modelAtomCount); 1008 coupleTable.allocateLabelArray(modelAtomCount); 1009 coupleTable.allocateExpCouples(modelAtomCount); 1010 } 1011 1012 frameCounter.setFrameNumberFromViewer(modelIndex + 1); 1013 populationDisplay.setFrameNumberFromViewer(modelIndex + 1); 1014 1015 coupleTable.setmolCDKuptodate(false); 1016 noeTable.setmolCDKuptodate(false); 1017 noeTable.addMol(); 1018 1019 coupleTable.updateTables(); 1020 noeTable.updateTables(); 1021 } 1022 1023 /** 1024 * @param atomIndex 1025 * @param strInfo 1026 */ notifyAtomPicked(int atomIndex, String strInfo)1027 public void notifyAtomPicked(int atomIndex, String strInfo) { 1028 if (atomIndex < 0) { 1029 // bond picked; 1030 return; 1031 } 1032 int atomNo = ((NMR_Viewer) vwr).getAtomNumber(atomIndex); 1033 labelSetter.setSelectedAtomIndex(atomNo - 1); 1034 String command = "set display SELECTED; select (atomindex=" 1035 + atomIndex + ")"; 1036 vwr.script(command); 1037 } 1038 1039 @Override notifyCallback(CBK type, Object[] data)1040 public void notifyCallback(CBK type, Object[] data) { 1041 String strInfo = (data == null || data[1] == null ? null : data[1] 1042 .toString()); 1043 1044 // System.out.println("NMR_JmolPanel notifyCallback "+type + " " + strInfo + " " + data[2]); 1045 super.notifyCallback(type, data); 1046 switch (type) { 1047 case LOADSTRUCT: 1048 notifyFileLoaded(strInfo, (String) data[2], (String) data[3], 1049 (String) data[4], (Boolean) data[8]); 1050 break; 1051 case ANIMFRAME: 1052 int[] iData = (int[]) data[1]; 1053 int modelIndex = iData[0]; 1054 notifyFrameChanged(modelIndex); 1055 break; 1056 case PICK: 1057 int atomIndex = ((Integer) data[2]).intValue(); 1058 notifyAtomPicked(atomIndex, strInfo); 1059 break; 1060 case MEASURE: 1061 String mystatus = (String) data[3]; 1062 if (defaultFormat != null) { 1063 vwr.script(defaultFormat); 1064 defaultFormat = null; 1065 } 1066 if (mystatus.equals("measurePending") 1067 || mystatus.equals("measureDeleted")) 1068 return; 1069 if (mystatus.indexOf("Sequence") < 0) { 1070 if (mystatus.indexOf("Picked") >= 0) { 1071 // picking mode 1072 Integer picked = (Integer) vwr.getPOrNull("_picked"); 1073 if (picked != null) 1074 notifyAtomPicked(picked.intValue(), strInfo); 1075 } 1076 } 1077 int n = vwr.getMeasurementCount() - 1; 1078 System.out.println("checking for measurement " + n); 1079 if (getViewerMeasurement(n, NMRCalculation.MODE_CALC_J) == null 1080 && getViewerMeasurement(n, NMRCalculation.MODE_CALC_NOE) == null) { 1081 vwr.deleteMeasurement(n); 1082 return; 1083 } 1084 System.out.println("updating for measurement " + n); 1085 noeTable.updateTables(); 1086 coupleTable.updateTables(); 1087 break; 1088 case MESSAGE: 1089 // this one is totally not helpful. Why doesn't MESSAGE fire this?? 1090 break; 1091 case APPLETREADY: 1092 break; 1093 case ATOMMOVED: 1094 break; 1095 case AUDIO: 1096 break; 1097 case CLICK: 1098 break; 1099 case DRAGDROP: 1100 break; 1101 case ECHO: 1102 break; 1103 case ERROR: 1104 break; 1105 case EVAL: 1106 break; 1107 case HOVER: 1108 break; 1109 case IMAGE: 1110 break; 1111 case MINIMIZATION: 1112 break; 1113 case RESIZE: 1114 break; 1115 case SCRIPT: 1116 // looking for the script started, which has the script as data[2] 1117 // We make sure the script we send is a separate script that is just 1118 // the message. 1119 Integer status = (Integer) data[3]; 1120 if (status.intValue() < -1) 1121 notifyScriptCallback(data[2].toString()); 1122 break; 1123 case SERVICE: 1124 break; 1125 case STRUCTUREMODIFIED: 1126 notifyStructureModified(); 1127 break; 1128 case SYNC: 1129 break; 1130 default: 1131 break; 1132 } 1133 1134 } 1135 notifyStructureModified()1136 public void notifyStructureModified() { 1137 vwr.deleteMeasurement(vwr.getMeasurementCount() - 1); 1138 notifyFrameChanged(Integer.MIN_VALUE); 1139 } 1140 1141 1142 } 1143 getFrameAtomCount()1144 public int getFrameAtomCount() { 1145 return vwr.getFrameAtoms().cardinality(); 1146 } 1147 getViewerMeasurement(int vRow, int type)1148 Atom[] getViewerMeasurement(int vRow, int type) { 1149 int[] m = vwr.getMeasurementCountPlusIndices(vRow); 1150 if (m[0] != 2) 1151 return null; 1152 Atom[] atoms = new Atom[] { ((NMR_Viewer)vwr).getAtomAt(m[1]), null, null, 1153 ((NMR_Viewer)vwr).getAtomAt(m[2]) }; 1154 return (NMRCalculation.getCalcType(atoms, null, type) == NMRCalculation.MODE_CALC_INVALID ? null 1155 : atoms); 1156 } 1157 getViewerRow(int row, int type)1158 int getViewerRow(int row, int type) { 1159 for (int j = -1, i = 0; i < vwr.getMeasurementCount(); i++) { 1160 if (getViewerMeasurement(i, type) == null) 1161 continue; 1162 if (++j == row) { 1163 return i; 1164 } 1165 } 1166 return -1; 1167 } 1168 clearViewerSelection()1169 void clearViewerSelection() { 1170 vwr.script("select none"); 1171 } 1172 1173 1174 1175 } 1176