1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package ffx.ui;
39
40 import static ffx.utilities.FileUtils.copyInputStreamToTmpFile;
41 import static ffx.utilities.StringUtils.pdbForID;
42 import static java.lang.String.format;
43 import static java.lang.System.arraycopy;
44
45 import ffx.crystal.Crystal;
46 import ffx.crystal.ReplicatesCrystal;
47 import ffx.potential.MolecularAssembly;
48 import ffx.potential.bonded.Atom;
49 import ffx.potential.bonded.Bond;
50 import ffx.potential.bonded.MSNode;
51 import ffx.potential.bonded.MSRoot;
52 import ffx.potential.bonded.RendererCache;
53 import ffx.potential.bonded.RotamerLibrary;
54 import ffx.potential.parameters.ForceField;
55 import ffx.potential.parsers.ARCFileFilter;
56 import ffx.potential.parsers.FFXFileFilter;
57 import ffx.potential.parsers.ForceFieldFileFilter;
58 import ffx.potential.parsers.ForceFieldFilter;
59 import ffx.potential.parsers.INTFileFilter;
60 import ffx.potential.parsers.INTFilter;
61 import ffx.potential.parsers.InducedFileFilter;
62 import ffx.potential.parsers.InducedFilter;
63 import ffx.potential.parsers.KeyFileFilter;
64 import ffx.potential.parsers.KeyFilter;
65 import ffx.potential.parsers.MergeFilter;
66 import ffx.potential.parsers.PDBFileFilter;
67 import ffx.potential.parsers.PDBFilter;
68 import ffx.potential.parsers.SystemFilter;
69 import ffx.potential.parsers.XYZFileFilter;
70 import ffx.potential.parsers.XYZFilter;
71 import ffx.ui.properties.FFXLocale;
72 import ffx.utilities.Keyword;
73 import ffx.utilities.Resources;
74
75 import java.awt.BorderLayout;
76 import java.awt.Container;
77 import java.awt.Cursor;
78 import java.awt.Dimension;
79 import java.awt.Font;
80 import java.awt.Frame;
81 import java.awt.GraphicsConfiguration;
82 import java.awt.GraphicsEnvironment;
83 import java.awt.GridLayout;
84 import java.awt.Toolkit;
85 import java.awt.event.ActionEvent;
86 import java.awt.event.ActionListener;
87 import java.io.*;
88 import java.net.InetAddress;
89 import java.net.InetSocketAddress;
90 import java.net.MalformedURLException;
91 import java.net.URI;
92 import java.net.URISyntaxException;
93 import java.net.URL;
94 import java.time.Month;
95 import java.util.ArrayList;
96 import java.util.Arrays;
97 import java.util.Hashtable;
98 import java.util.List;
99 import java.util.logging.Level;
100 import java.util.logging.Logger;
101 import java.util.prefs.Preferences;
102 import javax.swing.BorderFactory;
103 import javax.swing.ImageIcon;
104 import javax.swing.JCheckBoxMenuItem;
105 import javax.swing.JDialog;
106 import javax.swing.JFileChooser;
107 import javax.swing.JFrame;
108 import javax.swing.JLabel;
109 import javax.swing.JOptionPane;
110 import javax.swing.JPanel;
111 import javax.swing.JScrollPane;
112 import javax.swing.JSplitPane;
113 import javax.swing.JTabbedPane;
114 import javax.swing.JTextArea;
115 import javax.swing.SwingUtilities;
116 import javax.swing.UIManager;
117 import javax.swing.UnsupportedLookAndFeelException;
118 import javax.swing.border.Border;
119 import javax.swing.border.EtchedBorder;
120 import javax.swing.event.ChangeEvent;
121 import javax.swing.event.ChangeListener;
122 import javax.swing.filechooser.FileSystemView;
123
124 import org.apache.commons.configuration2.CompositeConfiguration;
125 import org.apache.commons.io.FileUtils;
126 import org.apache.commons.io.FilenameUtils;
127 import org.apache.commons.lang3.SystemUtils;
128 import org.jogamp.java3d.GraphicsConfigTemplate3D;
129 import org.jogamp.java3d.Transform3D;
130 import org.jogamp.java3d.TransformGroup;
131 import org.jogamp.vecmath.Vector3d;
132
133
134
135
136
137
138
139 public final class MainPanel extends JPanel implements ActionListener, ChangeListener {
140
141 @Serial
142 private static final long serialVersionUID = 1L;
143
144
145
146
147 public static final String version = "1.0.0-BETA";
148
149
150
151 public static final String date = "February 2024";
152
153
154
155 public static final String border =
156 " _________________________________________________________________________\n";
157
158
159
160 public static final String title = " FORCE FIELD X - Polyglot Software for Molecular Biophysics \n";
161
162 public static final String aboutString;
163
164
165
166 static final int KEYWORDS = 1;
167
168
169
170 static final int MODELING = 2;
171
172
173
174 static final ForceFieldFileFilter forceFieldFileFilter = new ForceFieldFileFilter();
175
176
177
178 static final KeyFileFilter keyFileFilter = new KeyFileFilter();
179
180 private static final Logger logger = Logger.getLogger(MainPanel.class.getName());
181
182
183
184 private static final int GRAPHICS = 0;
185
186
187
188 private static final XYZFileFilter xyzFileFilter = new XYZFileFilter();
189
190
191
192 private static final ARCFileFilter arcFileFilter = new ARCFileFilter();
193
194
195
196 private static final INTFileFilter intFileFilter = new INTFileFilter();
197
198
199
200 private static final InducedFileFilter indFileFilter = new InducedFileFilter();
201
202
203
204 private static final PDBFileFilter pdbFileFilter = new PDBFileFilter();
205
206
207
208 private static final FFXFileFilter ffxFileFilter = new FFXFileFilter();
209
210 private static final Preferences preferences = Preferences.userNodeForPackage(MainPanel.class);
211
212
213
214 static String classpath;
215
216
217
218 static File ffxDir;
219
220
221
222 private static File pwd;
223
224
225
226 private static JFileChooser fileChooser = null;
227
228 static {
229 var basedir = System.getProperty("basedir");
230 var mvnProps = new File(basedir + "/bin/build.properties");
231 var commitVersion = version + "-unknown";
232 var commitDate = date;
233 var commitSCM = "";
234 if (mvnProps.exists()) {
235 try (BufferedReader br = new BufferedReader(new FileReader(mvnProps))) {
236 var ffxVersion = "1.0.0-BETA";
237 var ffxVersionProp = "ffx.version=";
238 var gitCommitsCount = "";
239 var gitCommitsCountProp = "git.total.commit.count=";
240 var timestampProp = "timestamp=";
241 var gitRevisionProp = "git.commit.id.full=";
242 var line = br.readLine();
243 while (line != null) {
244 line = line.trim();
245 if (line.startsWith(ffxVersionProp)) {
246 ffxVersion = line.replaceFirst(ffxVersionProp, "");
247 } else if (line.startsWith(gitCommitsCountProp)) {
248 gitCommitsCount = line.replaceFirst(gitCommitsCountProp, "");
249 } else if (line.startsWith(timestampProp)) {
250 var timeStr = line.replaceFirst(timestampProp, "");
251
252 var timeToks = timeStr.split("-");
253 try {
254 var year = timeToks[2];
255 int mon = Integer.parseInt(timeToks[0]);
256 Month month = Month.of(mon);
257 var mstr = month.toString();
258 commitDate = format("%c%s %s", mstr.charAt(0), mstr.substring(1).toLowerCase(), year);
259 } catch (Exception ex) {
260 commitDate = date;
261 }
262 } else if (line.startsWith(gitRevisionProp) && !line.contains("UNKNOWN_REVISION")) {
263 var scm = line.replaceFirst(gitRevisionProp, "");
264 commitSCM = format(" %s %s \n", "Git Revision ", scm);
265 }
266 line = br.readLine();
267 }
268 var sb = new StringBuilder(ffxVersion).append("-");
269 if (!gitCommitsCount.isEmpty()) {
270 sb.append(gitCommitsCount);
271 } else {
272 sb.append("unknown");
273 }
274 commitVersion = sb.toString();
275 } catch (Exception ex) {
276
277 }
278 }
279 aboutString = " Version "
280 + commitVersion
281 + " "
282 + commitDate
283 + " \n"
284 + commitSCM
285 + " \n"
286 + """
287 Copyright (c) Michael J. Schnieders 2001-2024
288 Portions Copyright (c):
289 Timothy D. Fenn 2009-2024
290 Jacob M. Litman 2015-2024
291 Rae A. Corrigan 2019-2024
292 Guowei Qi 2019-2024
293 Mallory R. Tollefson 2019-2024
294 Aaron J. Nessler 2021-2024
295 Andrew C. Thiel 2021-2024
296
297 All Rights Reserved
298
299 Force Field X is distributed under the GPL v. 3 license
300 with linking exception and is hosted by the Schnieders Lab
301 at The University of Iowa.
302
303 User Manual: https:
304 Publications: https:
305 License: https:
306 """;
307
308 try {
309 String ffxString = System.getProperty("ffx.dir", ".");
310 ffxDir = new File(ffxString);
311 classpath = System.getProperty("java.class.path");
312 pwd = MainPanel.getPWD();
313 } catch (Exception e) {
314 logger.severe(" FFX directory could not be found.\n" + e);
315 }
316 }
317
318
319
320
321 private final JFrame frame;
322
323
324
325 private int fileOpenerThreads = -1;
326
327
328
329 private MSRoot dataRoot;
330
331
332
333 private Hierarchy hierarchy;
334
335
336
337 private MainMenu mainMenu;
338
339
340
341 private GraphicsPanel graphicsPanel;
342
343
344
345 private ModelingPanel modelingPanel;
346
347
348
349 private KeywordPanel keywordPanel;
350
351
352
353 private ModelingShell modelingShell = null;
354
355
356
357 private GraphicsCanvas graphicsCanvas;
358
359
360
361 private JSplitPane splitPane;
362
363
364
365 private int splitPaneDivider;
366
367
368
369 private JLabel statusLabel;
370
371
372
373 private ForceFieldFilter forceFieldFilter;
374
375
376
377 private FFXLocale locale = null;
378
379
380
381 private JDialog aboutDialog = null;
382
383
384
385 private JTextArea aboutTextArea = null;
386
387
388
389 private Thread openThread = null;
390
391
392
393 private SystemFilter activeFilter = null;
394
395
396
397 private boolean oscillate = false;
398
399
400
401 private SimulationLoader simulation;
402
403
404
405 private String ip = "";
406
407
408
409 private int port = 2000;
410
411
412
413 private InetAddress address = null;
414
415
416
417 private InetSocketAddress socketAddress = new InetSocketAddress(port);
418
419
420
421 private boolean init = false;
422
423
424
425 private ExitStatus exitType = ExitStatus.NORMAL;
426
427
428
429
430
431
432 public MainPanel(JFrame f) {
433 frame = f;
434 }
435
436
437
438
439 public MainPanel() {
440 frame = null;
441 }
442
443
444
445
446
447
448 static File getPWD() {
449 if (pwd == null) {
450 pwd =
451 new File(
452 System.getProperty(
453 "user.dir",
454 FileSystemView.getFileSystemView().getDefaultDirectory().getAbsolutePath()));
455 }
456 return pwd;
457 }
458
459
460
461
462
463
464 static JFileChooser resetFileChooser() {
465 if (fileChooser == null) {
466 fileChooser = new JFileChooser();
467 }
468 fileChooser.resetChoosableFileFilters();
469 fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
470 fileChooser.setFileHidingEnabled(false);
471 fileChooser.setAcceptAllFileFilterUsed(true);
472 fileChooser.setCurrentDirectory(getPWD());
473 fileChooser.setMultiSelectionEnabled(false);
474 fileChooser.setSelectedFile(null);
475 return fileChooser;
476 }
477
478
479
480
481 public void about() {
482 if (aboutDialog == null) {
483 aboutDialog = new JDialog(frame, "About... ", true);
484 URL ffxURL = getClass().getClassLoader().getResource("ffx/ui/icons/splash.png");
485 ImageIcon logoIcon = new ImageIcon(ffxURL);
486 JLabel logoLabel = new JLabel(logoIcon);
487 logoLabel.setSize(600, 600);
488 logoLabel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
489 Container contentpane = aboutDialog.getContentPane();
490 contentpane.setLayout(new BorderLayout());
491 initAbout();
492 contentpane.add(aboutTextArea, BorderLayout.SOUTH);
493 contentpane.add(logoLabel, BorderLayout.CENTER);
494 aboutDialog.pack();
495 Dimension dim = getToolkit().getScreenSize();
496 Dimension ddim = aboutDialog.getSize();
497 aboutDialog.setLocation((dim.width - ddim.width) / 2, (dim.height - ddim.height) / 2);
498 aboutDialog.setResizable(false);
499 }
500 aboutDialog.setVisible(true);
501 }
502
503
504
505
506
507
508
509 @Override
510 public void actionPerformed(ActionEvent evt) {
511 String arg = evt.getActionCommand();
512 if (logger.isLoggable(Level.FINEST)) {
513 logger.finest(" Action: " + arg);
514 }
515
516 switch (arg) {
517 case "Open" -> open();
518 case "DownloadFromPDB" -> openFromPDB();
519 case "SaveAs" -> saveAsXYZ(null);
520 case "Close" -> close();
521 case "CloseAll" -> closeAll();
522 case "ChooseKeyFile" -> chooseKey();
523 case "ChooseLogFile" -> chooseLog();
524 case "LoadInducedData" -> openInduced();
525
526
527 case "SelectAll" -> selectAll();
528 case "MergeSelections" -> merge();
529 case "HighlightSelections" -> highlightSelections(evt);
530
531
532 case "Play" -> play();
533 case "Stop" -> stop();
534 case "StepForward" -> stepForward();
535 case "StepBack" -> stepBack();
536 case "Reset" -> reset();
537 case "Oscillate" -> oscillate(evt);
538 case "Frame" -> frame();
539 case "Speed" -> speed();
540 case "Skip" -> skip();
541
542
543 case "ConnectToLocalJob" -> connectToTINKER(null, null);
544 case "ConnectToRemoteJob" -> connect();
545 case "ReleaseJob" -> release();
546 case "SetPort" -> setPort();
547 case "SetRemoteJobAddress" -> setRemoteJobAddress();
548
549
550 case "ShowToolBar" -> showToolBar(evt);
551 case "ShowTree" -> showTree(evt);
552 case "ShowGlobalAxes" -> showGlobalAxes(evt);
553 case "ResetPanes" -> resetPanes();
554 case "ResetConsole" -> resetShell();
555 case "OceanLookAndFeel" -> oceanLookAndFeel();
556 case "WindowsLookAndFeel", "MacOSXLookAndFeel", "MotifLookAndFeel" -> platformLookAndFeel();
557 case "ShrinkGraphicsWindow" -> resizePanes(20);
558 case "ExpandGraphicsWindow" -> resizePanes(-20);
559 case "About" -> about();
560
561
562 case "GarbageCollect" -> Runtime.getRuntime().gc();
563 case "Exit" -> exit();
564 default -> {
565 try {
566 ClassLoader cl = MainPanel.class.getClassLoader();
567 URL url = cl.getResource(arg);
568 logger.info(url.toString());
569 File structureFile = new File(url.getFile());
570 logger.info(structureFile.toString());
571 String tempFile =
572 copyInputStreamToTmpFile(url.openStream(), "ffx", structureFile.getName(), "pdb");
573 open(tempFile);
574 } catch (Exception e) {
575 System.err.println("MainPanel - Menu command not found: " + arg);
576 }
577 }
578 }
579 }
580
581
582
583
584
585
586 public Thread close() {
587 FFXSystem m = hierarchy.getActive();
588 return close(m);
589 }
590
591
592
593
594
595
596
597 public Thread close(FFXSystem closedModel) {
598 if (closedModel.getParent() != null) {
599 Trajectory traj = closedModel.getTrajectory();
600 if (traj != null) {
601 traj.stop();
602 }
603 if (simulation != null && simulation.getFSystem() == closedModel) {
604 release();
605 }
606 hierarchy.removeTreeNode(closedModel);
607 closedModel.setView(RendererCache.ViewModel.DESTROY, null);
608 Thread thread = new Thread(new UIFileCloser(closedModel));
609 thread.start();
610 return thread;
611 }
612 return null;
613 }
614
615
616
617
618 public void exit() {
619 exit(exitType);
620 }
621
622
623
624
625 public void frame() {
626 Trajectory trajectory = getTrajectory();
627 if (trajectory == null) {
628 return;
629 }
630 String frameNumber = "" + trajectory.getFrame();
631 frameNumber = JOptionPane.showInputDialog("Enter the Frame Number", frameNumber);
632 try {
633 int f = Integer.parseInt(frameNumber);
634 trajectory.setFrame(f);
635 } catch (NumberFormatException e) {
636
637 }
638 }
639
640
641
642
643
644
645 public SystemFilter getFilter() {
646 return activeFilter;
647 }
648
649
650
651
652
653
654 public Frame getFrame() {
655 return frame;
656 }
657
658
659
660
661
662
663 public Hierarchy getHierarchy() {
664 return hierarchy;
665 }
666
667
668
669
670
671
672 public MainMenu getMainMenu() {
673 return mainMenu;
674 }
675
676
677
678
679
680
681 public ModelingShell getModelingShell() {
682 if (modelingShell == null) {
683 modelingShell = new ModelingShell(this);
684 modelingShell.run();
685 }
686 return modelingShell;
687 }
688
689
690
691
692 public void initialize() {
693 if (init) {
694 return;
695 }
696 init = true;
697
698 String dir =
699 System.getProperty(
700 "user.dir", FileSystemView.getFileSystemView().getDefaultDirectory().getAbsolutePath());
701 setCWD(new File(dir));
702 locale = new FFXLocale("en", "US");
703
704
705 dataRoot = new MSRoot();
706 Border bb = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
707 statusLabel = new JLabel(" ");
708 JLabel stepLabel = new JLabel(" ");
709 stepLabel.setHorizontalAlignment(JLabel.RIGHT);
710 JLabel energyLabel = new JLabel(" ");
711 energyLabel.setHorizontalAlignment(JLabel.RIGHT);
712 JPanel statusPanel = new JPanel(new GridLayout(1, 3));
713 statusPanel.setBorder(bb);
714 statusPanel.add(statusLabel);
715 statusPanel.add(stepLabel);
716 statusPanel.add(energyLabel);
717
718
719 setLayout(new BorderLayout());
720 hierarchy = new Hierarchy(this);
721 hierarchy.setStatus(statusLabel, stepLabel, energyLabel);
722 keywordPanel = new KeywordPanel(this);
723 modelingPanel = new ModelingPanel(this);
724
725 JPanel treePane = new JPanel(new BorderLayout());
726 JScrollPane scrollPane =
727 new JScrollPane(
728 hierarchy,
729 JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
730 JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
731 treePane.add(scrollPane, BorderLayout.CENTER);
732
733 if (!GraphicsEnvironment.isHeadless()) {
734 GraphicsConfigTemplate3D template3D = new GraphicsConfigTemplate3D();
735
736 GraphicsConfiguration gc = null;
737 try {
738 gc =
739 GraphicsEnvironment.getLocalGraphicsEnvironment()
740 .getDefaultScreenDevice()
741 .getBestConfiguration(template3D);
742
743
744 } catch (Exception e) {
745 logger.log(Level.SEVERE, " Exception encountered when trying to get the best GraphicsConfiguration", e);
746 }
747 try {
748 graphicsCanvas = new GraphicsCanvas(gc, this);
749 } catch (Exception e) {
750 logger.log(Level.SEVERE, " Exception encountered when trying to create the GraphicsCanvas", e);
751 }
752 graphicsPanel = new GraphicsPanel(graphicsCanvas, statusPanel);
753 }
754
755
756
757
758
759
760
761
762
763
764
765
766
767 splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, false, treePane, graphicsPanel);
768 splitPane.setResizeWeight(0.25);
769 splitPane.setOneTouchExpandable(true);
770 add(splitPane, BorderLayout.CENTER);
771
772 if (!GraphicsEnvironment.isHeadless()) {
773 mainMenu = new MainMenu(this);
774 add(mainMenu.getToolBar(), BorderLayout.NORTH);
775 getModelingShell();
776 loadPrefs();
777 }
778 }
779
780
781
782
783
784
785 public void merge(MSNode[] nodesToMerge) {
786 ArrayList<MSNode> activeNodes = new ArrayList<>();
787 for (MSNode node : nodesToMerge) {
788 if (node != null) {
789 activeNodes.add(node);
790 }
791 }
792 if (activeNodes.size() > 1) {
793 merge(activeNodes);
794 }
795 }
796
797 public Thread open(File file, String commandDescription) {
798 UIFileOpener opener = openInit(file, commandDescription);
799 openThread = new Thread(opener);
800 openThread.start();
801 setPanel(GRAPHICS);
802 return openThread;
803 }
804
805 public Thread open(List<File> files, String commandDescription) {
806 UIFileOpener openFile = openInit(files, commandDescription);
807 openThread = new Thread(openFile);
808 openThread.start();
809 setPanel(GRAPHICS);
810 return openThread;
811 }
812
813
814
815
816
817
818
819 public Thread open(String name) {
820 File file = resolveName(name);
821 if (file == null) {
822 logger.log(Level.WARNING, "{0}: could not be found.", name);
823 return null;
824 }
825 return open(file, null);
826 }
827
828
829
830
831
832
833
834 public Thread open(String[] names) {
835 if (names == null) {
836 return null;
837 }
838 List<File> files = new ArrayList<>();
839
840 for (String name : names) {
841 File file = resolveName(name);
842 if (file == null || !file.exists()) {
843 return null;
844 }
845 files.add(file);
846 }
847 return open(files, null);
848 }
849
850 public synchronized MolecularAssembly[] openWaitUtils(String file) {
851 UIFileOpener opener = openFromUtils(file);
852 Thread thread = new Thread(opener);
853 while (thread.isAlive()) {
854 try {
855 wait(1);
856 } catch (InterruptedException e) {
857 String message = "Exception waiting for " + file + " to open.";
858 logger.log(Level.WARNING, message, e);
859 return null;
860 }
861 }
862
863 MolecularAssembly[] systems = activeFilter.getMolecularAssemblyArray();
864 if (systems != null) {
865 int n = systems.length;
866 FFXSystem[] ffxSystems = new FFXSystem[n];
867 FFXSystem[] allSystems = getHierarchy().getSystems();
868 int total = allSystems.length;
869 System.arraycopy(allSystems, total - n, ffxSystems, 0, n);
870 return ffxSystems;
871 } else {
872 return null;
873 }
874 }
875
876
877
878
879 public void reset() {
880 Trajectory trajectory = getTrajectory();
881 if (trajectory == null) {
882 return;
883 }
884 trajectory.stop();
885 trajectory.rewind();
886 }
887
888 public void saveKeywordFile(File file) {
889 keywordPanel.keySave(file);
890 }
891
892
893
894
895 @Override
896 public void stateChanged(ChangeEvent evt) {
897 JTabbedPane jtp = (JTabbedPane) evt.getSource();
898 int index = jtp.getSelectedIndex();
899 if (index == 0) {
900 graphicsCanvas.selected();
901 } else if (index == 1) {
902 keywordPanel.selected();
903 } else if (index == 2) {
904 modelingPanel.selected();
905 }
906 }
907
908
909
910
911 public void stop() {
912 Trajectory trajectory = getTrajectory();
913 if (trajectory == null) {
914 return;
915 }
916 trajectory.stop();
917 }
918
919
920
921
922 @Override
923 public String toString() {
924 return "Program Control";
925 }
926
927
928
929
930 private void chooseKey() {
931 JFileChooser d = MainPanel.resetFileChooser();
932 d.setFileFilter(new KeyFileFilter());
933 d.setAcceptAllFileFilterUsed(false);
934 FFXSystem sys = getHierarchy().getActive();
935 if (sys != null) {
936 File newCWD = sys.getFile();
937 if (newCWD != null && newCWD.getParentFile() != null) {
938 d.setCurrentDirectory(newCWD.getParentFile());
939 }
940 } else {
941 return;
942 }
943 int result = d.showOpenDialog(this);
944 if (result == JFileChooser.APPROVE_OPTION) {
945 File f = d.getSelectedFile();
946 sys.setKeyFile(f);
947 sys.setKeywords(KeyFilter.open(f));
948 getKeywordPanel().loadActive(sys);
949 }
950 }
951
952
953
954
955 private void chooseLog() {
956 JFileChooser d = resetFileChooser();
957 FFXSystem sys = getHierarchy().getActive();
958 if (sys != null) {
959 File newCWD = sys.getFile();
960 if (newCWD != null && newCWD.getParentFile() != null) {
961 d.setCurrentDirectory(newCWD.getParentFile());
962 }
963 } else {
964 return;
965 }
966 d.setDialogTitle("Select a log file");
967 d.setAcceptAllFileFilterUsed(true);
968 int result = d.showOpenDialog(this);
969 if (result == JFileChooser.APPROVE_OPTION) {
970 File f = d.getSelectedFile();
971 if (f != null) {
972 sys.setLogFile(f);
973 setCWD(d.getCurrentDirectory());
974
975 }
976 }
977 }
978
979
980
981
982 synchronized void closeWait() {
983 FFXSystem active = hierarchy.getActive();
984 if (active == null) {
985 logger.log(Level.INFO, " No active system to close.");
986 return;
987 }
988 Thread thread = close(active);
989 while (thread != null && thread.isAlive()) {
990 try {
991 wait(1);
992 } catch (InterruptedException e) {
993 String message = "Exception waiting for " + active + " to close.";
994 logger.log(Level.WARNING, message, e);
995 }
996 }
997 }
998
999
1000
1001
1002 synchronized void closeAll() {
1003 while (hierarchy.getActive() != null) {
1004 closeWait();
1005 }
1006 }
1007
1008
1009
1010
1011 private void connect() {
1012 if (simulation == null || simulation.isFinished()) {
1013 if (simulation != null) {
1014 simulation.release();
1015 }
1016 simulation = new SimulationLoader(null, null, this, socketAddress);
1017 simulation.connect();
1018 mainMenu.setConnect(false);
1019 setPanel(GRAPHICS);
1020 }
1021 }
1022
1023
1024
1025
1026
1027
1028
1029 void connectToTINKER(FFXSystem system, Thread modelingThread) {
1030 if (simulation == null || simulation.isFinished()) {
1031 if (simulation != null) {
1032 simulation.release();
1033 }
1034 InetSocketAddress tempAddress;
1035 try {
1036 tempAddress = new InetSocketAddress(InetAddress.getLocalHost(), port);
1037 } catch (Exception e) {
1038 try {
1039 tempAddress = new InetSocketAddress(InetAddress.getByName(null), port);
1040 } catch (Exception ex) {
1041 System.err.println("Could not determine Local Host: " + ex);
1042 return;
1043 }
1044 }
1045 simulation = new SimulationLoader(system, modelingThread, this, tempAddress);
1046 if (modelingThread != null) {
1047 modelingThread.start();
1048 }
1049 simulation.connect();
1050 mainMenu.setConnect(false);
1051 setPanel(GRAPHICS);
1052 }
1053 }
1054
1055
1056
1057
1058
1059
1060
1061 boolean createKeyFile(FFXSystem system) {
1062 String message = "Please select a parameter file " + "and a TINKER Key file will be created.";
1063 String params = (String) JOptionPane.showInputDialog(this, message, "Parameter File",
1064 JOptionPane.QUESTION_MESSAGE, null, keywordPanel.getParamFiles(), null);
1065 if (params != null) {
1066 if (params.equalsIgnoreCase("Use an existing TINKER Key file")) {
1067 JFileChooser fc = resetFileChooser();
1068 fc.setDialogTitle("Choose a KEY File");
1069 fc.setCurrentDirectory(pwd);
1070 fc.setSelectedFile(null);
1071 fc.setFileFilter(keyFileFilter);
1072 int result = fc.showOpenDialog(this);
1073 if (result == JFileChooser.APPROVE_OPTION) {
1074 File keyfile = fc.getSelectedFile();
1075 if (keyfile.exists()) {
1076 Hashtable<String, Keyword> keywordHash = KeyFilter.open(keyfile);
1077 if (keywordHash != null) {
1078 system.setKeywords(keywordHash);
1079 } else {
1080 return false;
1081 }
1082 system.setKeyFile(keyfile);
1083 system.setForceField(null);
1084 return true;
1085 }
1086 }
1087 } else {
1088 File tempFile = system.getFile();
1089 if (tempFile.getParentFile().canWrite()) {
1090 String path = system.getFile().getParent() + File.separatorChar;
1091 String keyFileName = system.getName() + ".key";
1092 File keyfile = new File(path + keyFileName);
1093 try {
1094 FileWriter fw = new FileWriter(keyfile);
1095 BufferedWriter bw = new BufferedWriter(fw);
1096 bw.write("\n");
1097 bw.write("# Force Field Selection\n");
1098 String tempParm = keywordPanel.getParamPath(params);
1099 if (tempParm.indexOf(" ") > 0) {
1100 tempParm = "\"" + keywordPanel.getParamPath(params) + "\"";
1101 }
1102 bw.write("PARAMETERS " + tempParm + "\n");
1103 bw.close();
1104 fw.close();
1105 Hashtable<String, Keyword> keywordHash = KeyFilter.open(keyfile);
1106 if (keywordHash != null) {
1107 system.setKeywords(keywordHash);
1108 } else {
1109 return false;
1110 }
1111 system.setKeyFile(keyfile);
1112 system.setForceField(null);
1113 return true;
1114 } catch (Exception e) {
1115 logger.warning("" + e);
1116 message = "There was an error creating " + keyfile.getAbsolutePath();
1117 JOptionPane.showMessageDialog(this, message);
1118 }
1119 } else {
1120 message =
1121 "Could not create a Key file because " + pwd.getAbsolutePath() + " is not writable";
1122 JOptionPane.showMessageDialog(this, message);
1123 }
1124 }
1125 }
1126 return false;
1127 }
1128
1129
1130
1131
1132
1133
1134 void exit(ExitStatus exitStatus) {
1135
1136 savePrefs();
1137
1138 Resources.logResources();
1139
1140 System.exit(exitStatus.getExitCode());
1141 }
1142
1143
1144
1145
1146
1147
1148 void setExitType(ExitStatus exitType) {
1149
1150 this.exitType = exitType;
1151 }
1152
1153
1154
1155
1156
1157
1158 MSRoot getDataRoot() {
1159 return dataRoot;
1160 }
1161
1162
1163
1164
1165
1166
1167 FFXLocale getFFXLocale() {
1168 return locale;
1169 }
1170
1171
1172
1173
1174
1175
1176 GraphicsCanvas getGraphics3D() {
1177 return graphicsCanvas;
1178 }
1179
1180
1181
1182
1183
1184
1185 KeywordPanel getKeywordPanel() {
1186 return keywordPanel;
1187 }
1188
1189 ModelingPanel getModelingPanel() {
1190 return modelingPanel;
1191 }
1192
1193
1194
1195
1196
1197
1198 JLabel getStatusBar() {
1199 return statusLabel;
1200 }
1201
1202
1203
1204
1205
1206
1207 private Trajectory getTrajectory() {
1208 FFXSystem system = hierarchy.getActive();
1209 if (system == null) {
1210 return null;
1211 }
1212 Trajectory trajectory = system.getTrajectory();
1213 if (trajectory != null) {
1214 return trajectory;
1215 }
1216 trajectory = new Trajectory(system, this);
1217 trajectory.setOscillate(oscillate);
1218 system.setTrajectory(trajectory);
1219 return trajectory;
1220 }
1221
1222
1223
1224
1225
1226
1227 private void highlightSelections(ActionEvent evt) {
1228 if (evt.getSource() instanceof JCheckBoxMenuItem jcb) {
1229 hierarchy.setHighlighting(jcb.isSelected());
1230 } else {
1231 boolean highlighting = RendererCache.highlightSelections;
1232 if (highlighting) {
1233 hierarchy.setHighlighting(false);
1234 mainMenu.setHighlighting(false);
1235 } else {
1236 hierarchy.setHighlighting(true);
1237 mainMenu.setHighlighting(true);
1238 }
1239 }
1240 }
1241
1242 private void initAbout() {
1243 aboutTextArea = new JTextArea();
1244 Font font = Font.decode(Font.MONOSPACED);
1245 aboutTextArea.setFont(font);
1246 aboutTextArea.setText(aboutString);
1247 aboutTextArea.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
1248 aboutTextArea.setEditable(false);
1249 }
1250
1251
1252
1253
1254
1255
1256 boolean isOpening() {
1257 return (openThread != null && openThread.isAlive());
1258 }
1259
1260
1261
1262
1263 private void loadPrefs() {
1264 String c = MainPanel.class.getName();
1265 JFrame frame1 = (JFrame) SwingUtilities.getRoot(this);
1266 Toolkit toolkit = getToolkit();
1267 Dimension screenSize = toolkit.getScreenSize();
1268 int x = preferences.getInt(c + ".x", screenSize.width / 8);
1269 int y = preferences.getInt(c + ".y", screenSize.height / 8);
1270 int width = preferences.getInt(c + ".width", screenSize.width * 3 / 4);
1271 int height = preferences.getInt(c + ".height", screenSize.height * 3 / 4);
1272 if (width > screenSize.width * 0.4
1273 && width < screenSize.width * 0.8
1274 && height > screenSize.height * 0.4
1275 && height < screenSize.height * 0.8) {
1276 frame1.setSize(width, height);
1277 } else {
1278 frame1.setSize(screenSize.width * 4 / 5, screenSize.height * 4 / 5);
1279 }
1280 if (x > 0 && x < screenSize.width / 2 && y > 0 && y < screenSize.height / 2) {
1281 frame1.setLocation(x, y);
1282 } else {
1283 frame1.setLocation(screenSize.width / 8, screenSize.height / 8);
1284 }
1285 splitPaneDivider = preferences.getInt(c + ".divider", 200);
1286 if (splitPaneDivider < frame1.getWidth() * (1.0f / 4.0f)) {
1287 splitPaneDivider = (int) (frame1.getWidth() * (1.0f / 4.0f));
1288 }
1289 splitPane.setDividerLocation(splitPaneDivider);
1290 if (!preferences.getBoolean(c + ".system", true)) {
1291 mainMenu.setSystemShowing(false);
1292 splitPane.setDividerLocation(0);
1293 } else {
1294 mainMenu.setSystemShowing(true);
1295 }
1296 if (!preferences.getBoolean(c + ".menu", true)) {
1297 remove(mainMenu.getToolBar());
1298 mainMenu.setMenuShowing(false);
1299 validate();
1300 } else {
1301 mainMenu.setMenuShowing(true);
1302 }
1303 try {
1304 port = preferences.getInt(c + ".port", 2000);
1305 ip = preferences.get(c + ".ip", InetAddress.getLocalHost().getHostAddress());
1306 if (ip != null) {
1307 address = InetAddress.getByName(ip);
1308 socketAddress = new InetSocketAddress(address, port);
1309 } else {
1310 socketAddress = new InetSocketAddress(port);
1311 }
1312 } catch (Exception e) {
1313 logger.log(Level.WARNING, e.toString());
1314 }
1315 if (graphicsCanvas != null) {
1316 graphicsCanvas.loadPrefs();
1317 }
1318 }
1319
1320
1321
1322
1323 private void merge() {
1324 ArrayList<MSNode> activeNodes = hierarchy.getActiveNodes();
1325 if (activeNodes.size() >= 2) {
1326 merge(activeNodes);
1327 }
1328 }
1329
1330
1331
1332
1333
1334
1335
1336 private void merge(ArrayList<MSNode> nodesToMerge) {
1337 ArrayList<MSNode> activeNodes = new ArrayList<>();
1338 for (MSNode node : nodesToMerge) {
1339 if (node != null && !(node instanceof MSRoot)) {
1340 activeNodes.add(node);
1341 }
1342 }
1343 if (activeNodes.size() <= 1) {
1344 return;
1345 }
1346
1347 FFXSystem active = hierarchy.getActive();
1348 File file = SystemFilter.version(hierarchy.getActive().getFile());
1349 FFXSystem system = new FFXSystem(file, "Merge Result", active.getProperties());
1350 system.setKeyFile(active.getKeyFile());
1351 system.setKeywords(KeyFilter.open(active.getKeyFile()));
1352
1353 ArrayList<Atom> mergedAtoms = new ArrayList<>();
1354 ArrayList<Bond> mergedBonds = new ArrayList<>();
1355 ArrayList<FFXSystem> systems = new ArrayList<>();
1356 TransformGroup parentTransformGroup;
1357 FFXSystem parentSystem;
1358 Transform3D parentTransform3D = new Transform3D();
1359 Vector3d parentPosition = new Vector3d();
1360 Vector3d atomPosition = new Vector3d();
1361
1362 int atomNum = 1;
1363 Vector3d zero = new Vector3d(0.0, 0.0, 0.0);
1364 for (MSNode m : activeNodes) {
1365 parentSystem = m.getMSNode(FFXSystem.class);
1366 if (parentSystem == null) {
1367 return;
1368 }
1369 if (!systems.contains(parentSystem)) {
1370 graphicsCanvas.updateSceneWait(
1371 parentSystem, false, true, RendererCache.ViewModel.WIREFRAME, false, null);
1372 systems.add(parentSystem);
1373 }
1374
1375
1376
1377 parentTransformGroup = parentSystem.getOriginToRot();
1378 parentTransformGroup.getTransform(parentTransform3D);
1379 parentTransform3D.get(parentPosition);
1380 parentTransform3D.setTranslation(zero);
1381
1382 for (Atom atom : m.getAtomList()) {
1383 atom.removeFromParent();
1384 atom.setXyzIndex(atomNum++);
1385 mergedAtoms.add(atom);
1386 atom.getV3D(atomPosition);
1387 parentTransform3D.transform(atomPosition);
1388 atomPosition.add(parentPosition);
1389 atom.moveTo(atomPosition);
1390 }
1391 for (Bond bond : m.getBondList()) {
1392 bond.removeFromParent();
1393 mergedBonds.add(bond);
1394 }
1395 }
1396 for (FFXSystem sys : systems) {
1397 close(sys);
1398 }
1399 MergeFilter mergeFilter = new MergeFilter(system, mergedAtoms, mergedBonds);
1400 UIFileOpener fileOpener = new UIFileOpener(mergeFilter, this);
1401 if (fileOpenerThreads > 0) {
1402 fileOpener.setNThreads(fileOpenerThreads);
1403 }
1404 Thread thread = new Thread(fileOpener);
1405 thread.start();
1406 }
1407
1408
1409
1410
1411 private void oceanLookAndFeel() {
1412 try {
1413 UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
1414 SwingUtilities.updateComponentTreeUI(SwingUtilities.getRoot(this));
1415 } catch (Exception e) {
1416
1417 }
1418 }
1419
1420
1421
1422
1423 private Thread open() {
1424 if (openThread != null && openThread.isAlive()) {
1425 return null;
1426 }
1427 JFileChooser fc = resetFileChooser();
1428 fc.setDialogTitle("Choose FFX, PDB, XYZ or ARC");
1429 fc.addChoosableFileFilter(xyzFileFilter);
1430 fc.addChoosableFileFilter(pdbFileFilter);
1431 fc.addChoosableFileFilter(intFileFilter);
1432 fc.addChoosableFileFilter(arcFileFilter);
1433 fc.addChoosableFileFilter(ffxFileFilter);
1434 fc.setAcceptAllFileFilterUsed(true);
1435 int result = fc.showOpenDialog(this);
1436 if (result == JFileChooser.APPROVE_OPTION) {
1437 File file = fc.getSelectedFile();
1438 return open(file, null);
1439 }
1440 return null;
1441 }
1442
1443 private UIFileOpener openFromUtils(File file, String commandDescription) {
1444 UIFileOpener opener = openInit(file, commandDescription);
1445 openThread = new Thread(opener);
1446 openThread.start();
1447 setPanel(GRAPHICS);
1448 return opener;
1449 }
1450
1451
1452
1453
1454
1455
1456
1457
1458 private UIFileOpener openInit(File file, String commandDescription) {
1459 if (file == null || !file.isFile() || !file.canRead()) {
1460 return null;
1461 }
1462 file = new File(FilenameUtils.normalize(file.getAbsolutePath()));
1463
1464 setCWD(file.getParentFile());
1465
1466
1467 CompositeConfiguration properties = Keyword.loadProperties(file);
1468
1469 FFXSystem newSystem = new FFXSystem(file, commandDescription, properties);
1470
1471 forceFieldFilter = new ForceFieldFilter(properties);
1472 ForceField forceField = forceFieldFilter.parse();
1473 String[] patches = properties.getStringArray("patch");
1474 for (String patch : patches) {
1475 logger.info(" Attempting to read force field patch from " + patch + ".");
1476 CompositeConfiguration patchConfiguration = new CompositeConfiguration();
1477 patchConfiguration.addProperty("parameters", patch);
1478 forceFieldFilter = new ForceFieldFilter(patchConfiguration);
1479 ForceField patchForceField = forceFieldFilter.parse();
1480 forceField.append(patchForceField);
1481 if (RotamerLibrary.addRotPatch(patch)) {
1482 logger.info(format(" Loaded rotamer definitions from patch %s.", patch));
1483 }
1484 }
1485 newSystem.setForceField(forceField);
1486 SystemFilter systemFilter;
1487
1488
1489 if (xyzFileFilter.acceptDeep(file)) {
1490
1491 systemFilter = new XYZFilter(file, newSystem, forceField, properties);
1492 } else if (intFileFilter.acceptDeep(file)) {
1493
1494 systemFilter = new INTFilter(file, newSystem, forceField, properties);
1495 } else {
1496
1497 systemFilter = new PDBFilter(file, newSystem, forceField, properties);
1498 }
1499
1500 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1501 activeFilter = systemFilter;
1502 UIFileOpener fileOpener = new UIFileOpener(systemFilter, this);
1503 if (fileOpenerThreads > 0) {
1504 fileOpener.setNThreads(fileOpenerThreads);
1505 }
1506 return fileOpener;
1507 }
1508
1509 private UIFileOpener openFromUtils(List<File> files, String commandDescription) {
1510 UIFileOpener openFile = openInit(files, commandDescription);
1511 openThread = new Thread(openFile);
1512 openThread.start();
1513 setPanel(GRAPHICS);
1514 return openFile;
1515 }
1516
1517
1518
1519
1520
1521
1522
1523
1524 private UIFileOpener openInit(List<File> files, String commandDescription) {
1525 if (files == null) {
1526 return null;
1527 }
1528 File file = new File(FilenameUtils.normalize(files.get(0).getAbsolutePath()));
1529
1530 setCWD(file.getParentFile());
1531
1532
1533 CompositeConfiguration properties = Keyword.loadProperties(file);
1534 forceFieldFilter = new ForceFieldFilter(properties);
1535 ForceField forceField = forceFieldFilter.parse();
1536
1537
1538 FFXSystem newSystem = new FFXSystem(file, commandDescription, properties);
1539 String[] patches = properties.getStringArray("patch");
1540 for (String patch : patches) {
1541 logger.info(" Attempting to read force field patch from " + patch + ".");
1542 CompositeConfiguration patchConfiguration = new CompositeConfiguration();
1543 patchConfiguration.addProperty("parameters", patch);
1544 forceFieldFilter = new ForceFieldFilter(patchConfiguration);
1545 ForceField patchForceField = forceFieldFilter.parse();
1546 forceField.append(patchForceField);
1547 if (RotamerLibrary.addRotPatch(patch)) {
1548 logger.info(format(" Loaded rotamer definitions from patch %s.", patch));
1549 }
1550 }
1551 newSystem.setForceField(forceField);
1552
1553 SystemFilter systemFilter;
1554 if (xyzFileFilter.acceptDeep(file)) {
1555
1556 systemFilter = new XYZFilter(files, newSystem, forceField, properties);
1557 } else if (intFileFilter.acceptDeep(file)) {
1558
1559 systemFilter = new INTFilter(files, newSystem, forceField, properties);
1560 } else {
1561
1562 systemFilter = new PDBFilter(files, newSystem, forceField, properties);
1563 }
1564
1565 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1566 activeFilter = systemFilter;
1567
1568 UIFileOpener fileOpener = new UIFileOpener(systemFilter, this);
1569 if (fileOpenerThreads > 0) {
1570 fileOpener.setNThreads(fileOpenerThreads);
1571 }
1572 return fileOpener;
1573 }
1574
1575
1576
1577
1578
1579
1580
1581 synchronized FFXSystem[] openWait(String file) {
1582 Thread thread = open(file);
1583 while (thread != null && thread.isAlive()) {
1584 try {
1585 wait(1);
1586 } catch (InterruptedException e) {
1587 String message = "Exception waiting for " + file + " to open.";
1588 logger.log(Level.WARNING, message, e);
1589 return null;
1590 }
1591 }
1592
1593 MolecularAssembly[] systems = activeFilter.getMolecularAssemblyArray();
1594 if (systems != null) {
1595 int n = systems.length;
1596 FFXSystem[] ffxSystems = new FFXSystem[n];
1597 FFXSystem[] allSystems = getHierarchy().getSystems();
1598 int total = allSystems.length;
1599 arraycopy(allSystems, total - n, ffxSystems, 0, n);
1600 return ffxSystems;
1601 } else {
1602 return null;
1603 }
1604 }
1605
1606
1607
1608
1609
1610
1611
1612
1613 synchronized FFXSystem[] openWait(String file, int nThreads) {
1614 fileOpenerThreads = nThreads;
1615 FFXSystem[] systs = openWait(file);
1616 fileOpenerThreads = -1;
1617 return systs;
1618 }
1619
1620
1621
1622
1623
1624
1625
1626 synchronized FFXSystem[] openWait(String[] files) {
1627 Thread thread = open(files);
1628 while (thread != null && thread.isAlive()) {
1629 try {
1630 wait(1);
1631 } catch (InterruptedException e) {
1632 String message = "Exception waiting for " + files[0] + " to open.";
1633 logger.log(Level.WARNING, message, e);
1634 return null;
1635 }
1636 }
1637
1638 MolecularAssembly[] systems = activeFilter.getMolecularAssemblyArray();
1639 if (systems != null) {
1640 int n = systems.length;
1641 FFXSystem[] ffxSystems = new FFXSystem[n];
1642 FFXSystem[] allSystems = getHierarchy().getSystems();
1643 int total = allSystems.length;
1644 arraycopy(allSystems, total - n, ffxSystems, 0, n);
1645 return ffxSystems;
1646 } else {
1647 return null;
1648 }
1649 }
1650
1651
1652
1653
1654
1655
1656
1657
1658 synchronized FFXSystem[] openWait(String[] files, int nThreads) {
1659 fileOpenerThreads = nThreads;
1660 FFXSystem[] systs = openWait(files);
1661 fileOpenerThreads = -1;
1662 return systs;
1663 }
1664
1665 private UIFileOpener openFromUtils(String name) {
1666 File file = resolveName(name);
1667 if (file == null) {
1668 logger.log(Level.WARNING, "{0}: could not be found.", name);
1669 return null;
1670 }
1671 return openFromUtils(file, null);
1672 }
1673
1674 private File resolveName(String name) {
1675
1676 if (name == null) {
1677 return null;
1678 }
1679 File file = new File(name);
1680
1681 if (file.exists()) {
1682 return file;
1683 }
1684
1685 file = new File(pwd + File.separator + name);
1686 if (file.exists()) {
1687 return file;
1688 }
1689
1690 if (name.startsWith("http://")) {
1691 String fileName = FilenameUtils.getName(name);
1692 if (fileName == null) {
1693 return null;
1694 }
1695 return downloadURL(name);
1696 }
1697
1698 if (name.length() == 4) {
1699 String fileName = name + ".pdb";
1700 String path = getPWD().getAbsolutePath();
1701 File pdbFile = new File(path + File.separatorChar + fileName);
1702 if (!pdbFile.exists()) {
1703 String fromURL = pdbForID(name);
1704 return downloadURL(fromURL);
1705 } else {
1706 return pdbFile;
1707 }
1708 }
1709 return null;
1710 }
1711
1712 private UIFileOpener openFromUtils(String[] names) {
1713 if (names == null) {
1714 return null;
1715 }
1716 List<File> files = new ArrayList<>();
1717
1718 for (String name : names) {
1719 File file = resolveName(name);
1720 if (file == null || !file.exists()) {
1721 return null;
1722 }
1723 files.add(file);
1724 }
1725 return openFromUtils(files, null);
1726 }
1727
1728
1729
1730
1731 private void openFromPDB() {
1732 if (openThread != null && openThread.isAlive()) {
1733 return;
1734 }
1735 String code = JOptionPane.showInputDialog("Enter the PDB Identifier (4 characters)", "");
1736 if (code == null) {
1737 return;
1738 }
1739 code = code.toLowerCase().trim();
1740 if (code.length() != 4) {
1741 return;
1742 }
1743 String fileName = code + ".pdb";
1744 String path = getPWD().getAbsolutePath();
1745 File pdbFile = new File(path + File.separatorChar + fileName);
1746 CompositeConfiguration properties = Keyword.loadProperties(pdbFile);
1747 forceFieldFilter = new ForceFieldFilter(properties);
1748 ForceField forceField = forceFieldFilter.parse();
1749 FFXSystem newSystem = new FFXSystem(pdbFile, "PDB", properties);
1750 newSystem.setForceField(forceField);
1751 if (!pdbFile.exists()) {
1752 String fromURL = pdbForID(code);
1753 pdbFile = downloadURL(fromURL);
1754 if (pdbFile == null || !pdbFile.exists()) {
1755 return;
1756 }
1757 } else {
1758 String message = format(" Reading the local copy of the PDB file %s.", pdbFile);
1759 logger.info(message);
1760 }
1761 PDBFilter pdbFilter = new PDBFilter(pdbFile, newSystem, forceField, properties);
1762 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1763 UIFileOpener openFile = new UIFileOpener(pdbFilter, this);
1764 if (fileOpenerThreads > 0) {
1765 openFile.setNThreads(fileOpenerThreads);
1766 }
1767 openThread = new Thread(openFile);
1768 openThread.start();
1769 setPanel(GRAPHICS);
1770 }
1771
1772 private File downloadURL(String fromString) {
1773
1774 if (fromString == null) {
1775 return null;
1776 }
1777
1778
1779 URL fromURL;
1780 try {
1781 URI uri = new URI(fromString);
1782 fromURL = uri.toURL();
1783 } catch (MalformedURLException | URISyntaxException e) {
1784 String message = format(" URL incorrectly formatted %s.", fromString);
1785 logger.log(Level.INFO, message, e);
1786 return null;
1787 }
1788
1789
1790 logger.info(format(" Downloading %s", fromString));
1791 try {
1792 File toFile = new File(FilenameUtils.getName(fromURL.getPath()));
1793 FileUtils.copyURLToFile(fromURL, toFile, 1000, 1000);
1794 logger.info(format(" Saved to %s\n", toFile.getPath()));
1795 return toFile;
1796 } catch (IOException ex) {
1797 logger.log(Level.INFO, " Failed to read URL " + fromURL.getPath(), ex);
1798 return null;
1799 }
1800 }
1801
1802 private void openInduced() {
1803 FFXSystem active = hierarchy.getActive();
1804 resetFileChooser();
1805 fileChooser.setCurrentDirectory(pwd);
1806 fileChooser.setSelectedFile(active.getFile());
1807 fileChooser.setDialogTitle("Choose Induced Dipole File");
1808 fileChooser.addChoosableFileFilter(indFileFilter);
1809 fileChooser.setAcceptAllFileFilterUsed(true);
1810 fileChooser.setFileFilter(indFileFilter);
1811 int result = fileChooser.showOpenDialog(this);
1812 if (result == JFileChooser.APPROVE_OPTION) {
1813 File f = fileChooser.getSelectedFile();
1814 InducedFilter indFilter = new InducedFilter(active, f);
1815 indFilter.read();
1816 }
1817 }
1818
1819
1820
1821
1822
1823
1824
1825
1826 boolean openKey(FFXSystem newSystem, boolean createKey) {
1827 String keyFileName;
1828 String temp = newSystem.getFile().getName();
1829 int dot = temp.lastIndexOf(".");
1830 if (dot > 0) {
1831 keyFileName = temp.substring(0, dot) + ".key";
1832 } else {
1833 keyFileName = temp + ".key";
1834 }
1835 String path = newSystem.getFile().getParent() + File.separator;
1836 File keyfile = new File(path + keyFileName);
1837 if (keyfile.exists()) {
1838 Hashtable<String, Keyword> keywordHash = KeyFilter.open(keyfile);
1839 if (keywordHash != null) {
1840 newSystem.setKeywords(keywordHash);
1841 } else {
1842 return false;
1843 }
1844 newSystem.setKeyFile(keyfile);
1845 newSystem.setForceField(null);
1846 return true;
1847 }
1848 keyfile = new File(path + "tinker.key");
1849 if (keyfile.exists()) {
1850 logger.info("Using tinker.key: " + keyfile);
1851 Hashtable<String, Keyword> keywordHash = KeyFilter.open(keyfile);
1852 if (keywordHash != null) {
1853 newSystem.setKeywords(keywordHash);
1854 } else {
1855 return false;
1856 }
1857 newSystem.setKeyFile(keyfile);
1858 newSystem.setForceField(null);
1859 return true;
1860 }
1861 if (createKey) {
1862 return createKeyFile(newSystem);
1863 }
1864 return false;
1865 }
1866
1867
1868
1869
1870
1871
1872
1873
1874 void openOn(File f, FFXSystem oldSystem, String command) {
1875 XYZFilter.readOnto(f, oldSystem);
1876 oldSystem.setCommandDescription(command);
1877 graphicsCanvas.updateScene(oldSystem, true, false, null, false, null);
1878 getHierarchy().updateStatus();
1879 getHierarchy().repaint();
1880 }
1881
1882
1883
1884
1885
1886
1887 private void oscillate(ActionEvent evt) {
1888 oscillate = ((JCheckBoxMenuItem) evt.getSource()).isSelected();
1889 FFXSystem[] systems = getHierarchy().getSystems();
1890
1891 if (systems == null) {
1892 return;
1893 }
1894
1895 for (FFXSystem system : systems) {
1896 Trajectory trajectory = system.getTrajectory();
1897 if (trajectory != null) {
1898 trajectory.setOscillate(oscillate);
1899 }
1900 }
1901 }
1902
1903
1904
1905
1906 private void platformLookAndFeel() {
1907 try {
1908 if (SystemUtils.IS_OS_LINUX) {
1909 UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
1910 } else {
1911 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1912 }
1913 SwingUtilities.updateComponentTreeUI(SwingUtilities.getRoot(this));
1914 } catch (ClassNotFoundException
1915 | InstantiationException
1916 | IllegalAccessException
1917 | UnsupportedLookAndFeelException e) {
1918 logger.log(Level.WARNING, "Can''t set look and feel: {0}", e);
1919 }
1920 }
1921
1922
1923
1924
1925 private void play() {
1926 Trajectory trajectory = getTrajectory();
1927 if (trajectory == null) {
1928 return;
1929 }
1930 trajectory.start();
1931 }
1932
1933
1934
1935
1936 private void release() {
1937 if (simulation != null) {
1938 simulation.release();
1939 simulation = null;
1940 mainMenu.setConnect(true);
1941 }
1942 }
1943
1944
1945
1946
1947 private void resetPanes() {
1948 resizePanes(0);
1949 }
1950
1951
1952
1953
1954 void resetShell() {
1955 if (!GraphicsEnvironment.isHeadless()) {
1956 modelingShell = getModelingShell();
1957 try {
1958 modelingShell.exit();
1959 } catch (NullPointerException e) {
1960
1961 } finally {
1962 modelingShell = null;
1963 }
1964 modelingShell = getModelingShell();
1965 }
1966 }
1967
1968
1969
1970
1971
1972
1973 private void resizePanes(int move) {
1974 if (move == 0) {
1975 splitPaneDivider = 0;
1976 mainMenu.setMenuShowing(false);
1977 mainMenu.toggleToolBarShowing();
1978 mainMenu.setSystemShowing(false);
1979 mainMenu.systemClick();
1980 } else {
1981 splitPane.setDividerLocation(splitPane.getDividerLocation() + move);
1982 }
1983 }
1984
1985
1986
1987
1988
1989
1990
1991 void saveAsXYZ(File file) {
1992 FFXSystem system = hierarchy.getActive();
1993 if (system != null && !system.isClosing()) {
1994 File saveFile = file;
1995 if (saveFile == null) {
1996 resetFileChooser();
1997 fileChooser.setCurrentDirectory(pwd);
1998 fileChooser.setFileFilter(xyzFileFilter);
1999 fileChooser.setAcceptAllFileFilterUsed(false);
2000 int result = fileChooser.showSaveDialog(this);
2001 if (result == JFileChooser.APPROVE_OPTION) {
2002 saveFile = fileChooser.getSelectedFile();
2003 pwd = saveFile.getParentFile();
2004 }
2005 }
2006 if (saveFile != null) {
2007 SystemFilter filter = new XYZFilter(saveFile, system, null, null);
2008 if (filter.writeFile(saveFile, false)) {
2009
2010 hierarchy.setActive(system);
2011 activeFilter = filter;
2012 }
2013 }
2014 }
2015 }
2016
2017
2018
2019
2020
2021
2022
2023 void saveAsP1(File file) {
2024 FFXSystem system = hierarchy.getActive();
2025 if (system != null && !system.isClosing()) {
2026 File saveFile = file;
2027 if (saveFile == null) {
2028 resetFileChooser();
2029 fileChooser.setCurrentDirectory(pwd);
2030 fileChooser.setFileFilter(xyzFileFilter);
2031 fileChooser.setAcceptAllFileFilterUsed(false);
2032 int result = fileChooser.showSaveDialog(this);
2033 if (result == JFileChooser.APPROVE_OPTION) {
2034 saveFile = fileChooser.getSelectedFile();
2035 pwd = saveFile.getParentFile();
2036 }
2037 }
2038 if (saveFile != null) {
2039 XYZFilter filter = new XYZFilter(saveFile, system, null, null);
2040 Crystal crystal = system.getCrystal().getUnitCell();
2041 if (crystal instanceof ReplicatesCrystal) {
2042 crystal = crystal.getUnitCell();
2043 }
2044 if (filter.writeFileAsP1(saveFile, false, crystal)) {
2045
2046 hierarchy.setActive(system);
2047 }
2048 activeFilter = filter;
2049 }
2050 }
2051 }
2052
2053
2054
2055
2056
2057
2058
2059 void saveAsPDB(File file) {
2060 saveAsPDB(file, true);
2061 }
2062
2063
2064
2065
2066
2067
2068
2069
2070 private void saveAsPDB(File file, boolean writeEnd) {
2071 saveAsPDB(file, writeEnd, false);
2072 }
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082 void saveAsPDB(File file, boolean writeEnd, boolean append) {
2083 FFXSystem system = hierarchy.getActive();
2084 if (system == null) {
2085 logger.log(Level.INFO, " No active system to save.");
2086 return;
2087 }
2088 if (system.isClosing()) {
2089 logger.log(Level.INFO, " {0} is being closed and can no longer be saved.", system);
2090 return;
2091 }
2092 File saveFile = file;
2093 if (saveFile == null) {
2094 resetFileChooser();
2095 fileChooser.setCurrentDirectory(pwd);
2096 fileChooser.setFileFilter(pdbFileFilter);
2097 fileChooser.setAcceptAllFileFilterUsed(false);
2098 int result = fileChooser.showSaveDialog(this);
2099 if (result == JFileChooser.APPROVE_OPTION) {
2100 saveFile = fileChooser.getSelectedFile();
2101 pwd = saveFile.getParentFile();
2102 }
2103 }
2104 if (saveFile == null) {
2105 logger.log(Level.INFO, " No filename is defined for {0}.", system);
2106 return;
2107 }
2108 PDBFilter pdbFilter = new PDBFilter(saveFile, system, null, null);
2109 if (pdbFilter.writeFile(saveFile, append, false, writeEnd)) {
2110
2111 hierarchy.setActive(system);
2112 activeFilter = pdbFilter;
2113 } else {
2114 logger.log(Level.INFO, " Save failed for: {0}", system);
2115 }
2116 }
2117
2118 void savePDBasP1(File file) {
2119 FFXSystem system = hierarchy.getActive();
2120 if (system == null) {
2121 logger.log(Level.INFO, " No active system to save.");
2122 return;
2123 }
2124 if (system.isClosing()) {
2125 logger.log(Level.INFO, " {0} is being closed and can no longer be saved.", system);
2126 return;
2127 }
2128 File saveFile = file;
2129 if (saveFile == null) {
2130 resetFileChooser();
2131 fileChooser.setCurrentDirectory(pwd);
2132 fileChooser.setFileFilter(pdbFileFilter);
2133 fileChooser.setAcceptAllFileFilterUsed(false);
2134 int result = fileChooser.showSaveDialog(this);
2135 if (result == JFileChooser.APPROVE_OPTION) {
2136 saveFile = fileChooser.getSelectedFile();
2137 pwd = saveFile.getParentFile();
2138 }
2139 }
2140 if (saveFile == null) {
2141 logger.log(Level.INFO, " No filename is defined for {0}.", system);
2142 return;
2143 }
2144
2145 PDBFilter pdbFilter = new PDBFilter(saveFile, system, null, null);
2146 pdbFilter.writeFileAsP1(saveFile);
2147 }
2148
2149
2150
2151
2152
2153
2154
2155 void saveAsPDB(MolecularAssembly[] activeSystems, File file) {
2156 File saveFile = file;
2157 if (saveFile == null) {
2158 resetFileChooser();
2159 fileChooser.setCurrentDirectory(pwd);
2160 fileChooser.setFileFilter(pdbFileFilter);
2161 fileChooser.setAcceptAllFileFilterUsed(false);
2162 int result = fileChooser.showSaveDialog(this);
2163 if (result == JFileChooser.APPROVE_OPTION) {
2164 saveFile = fileChooser.getSelectedFile();
2165 pwd = saveFile.getParentFile();
2166 }
2167 }
2168 if (saveFile != null) {
2169 PDBFilter pdbFilter = new PDBFilter(saveFile, Arrays.asList(activeSystems), null, null);
2170 pdbFilter.writeFile(saveFile, false);
2171 activeFilter = pdbFilter;
2172 }
2173 }
2174
2175
2176
2177
2178 private void savePrefs() {
2179 String c = MainPanel.class.getName();
2180 if (!GraphicsEnvironment.isHeadless()) {
2181 preferences.putInt(c + ".x", frame.getLocation().x);
2182 preferences.putInt(c + ".y", frame.getLocation().y);
2183 preferences.putInt(c + ".width", frame.getWidth());
2184 preferences.putInt(c + ".height", frame.getHeight());
2185 preferences.putBoolean(c + ".system", mainMenu.isSystemShowing());
2186 preferences.putInt(c + ".divider", splitPane.getDividerLocation());
2187 preferences.putBoolean(c + ".menu", mainMenu.isMenuShowing());
2188 preferences.putBoolean(c + ".axis", mainMenu.isAxisShowing());
2189 }
2190 if (ip == null) {
2191 ip = "";
2192 }
2193 if (address != null) {
2194 String s = address.getHostAddress();
2195 if (s != null) {
2196 preferences.put(c + ".ip", s);
2197 }
2198 preferences.putInt(c + ".port", socketAddress.getPort());
2199 }
2200 preferences.put(c + ".cwd", pwd.toString());
2201
2202 if (modelingPanel != null) {
2203 modelingPanel.savePrefs();
2204 }
2205 if (keywordPanel != null) {
2206 keywordPanel.savePrefs();
2207 }
2208 if (graphicsCanvas != null) {
2209 graphicsCanvas.savePrefs();
2210 }
2211 }
2212
2213
2214
2215
2216 private void selectAll() {
2217 if (dataRoot.getChildCount() == 0) {
2218 return;
2219 }
2220 hierarchy.selectAll();
2221 }
2222
2223
2224
2225
2226
2227
2228 void setCWD(File file) {
2229 if ((file == null) || (!file.exists())) {
2230 return;
2231 }
2232 pwd = file;
2233 }
2234
2235
2236
2237
2238
2239
2240 void setPanel(int panel) {
2241
2242 }
2243
2244
2245
2246
2247 private void setPort() {
2248 String s = "" + port;
2249 s = JOptionPane.showInputDialog("Enter a port number", s);
2250 if (s == null) {
2251 return;
2252 }
2253 int temp;
2254 try {
2255 temp = Integer.parseInt(s);
2256 } catch (NumberFormatException e) {
2257 return;
2258 }
2259 port = temp;
2260 socketAddress = new InetSocketAddress(address, port);
2261 }
2262
2263
2264
2265
2266 private void setRemoteJobAddress() {
2267 if (address == null) {
2268 try {
2269 address = InetAddress.getLocalHost();
2270 } catch (Exception e) {
2271 try {
2272 address = InetAddress.getByName(null);
2273 } catch (Exception ex) {
2274 return;
2275 }
2276 }
2277 }
2278 String s = address.getHostAddress();
2279 s = JOptionPane.showInputDialog("Enter an IP Address (XXX.XXX.XXX.XXX)", s);
2280 if (s == null) {
2281 return;
2282 }
2283 InetAddress newAddress;
2284 InetSocketAddress newSocketAddress;
2285 try {
2286 newAddress = InetAddress.getByName(s);
2287 newSocketAddress = new InetSocketAddress(newAddress, port);
2288 } catch (Exception e) {
2289 return;
2290 }
2291 address = newAddress;
2292 socketAddress = newSocketAddress;
2293 }
2294
2295
2296
2297
2298
2299
2300 private void showGlobalAxes(ActionEvent evt) {
2301 JCheckBoxMenuItem showAxesCheckBox = (JCheckBoxMenuItem) evt.getSource();
2302 graphicsCanvas.setAxisShowing(showAxesCheckBox.isSelected());
2303 }
2304
2305
2306
2307
2308
2309
2310 private void showToolBar(ActionEvent evt) {
2311 JCheckBoxMenuItem toolBarCheckBox = (JCheckBoxMenuItem) evt.getSource();
2312 if (toolBarCheckBox.isSelected()) {
2313 add(mainMenu.getToolBar(), BorderLayout.NORTH);
2314 frame.validate();
2315 } else {
2316 remove(mainMenu.getToolBar());
2317 frame.validate();
2318 }
2319 }
2320
2321
2322
2323
2324
2325
2326 private void showTree(ActionEvent evt) {
2327 JCheckBoxMenuItem treeCheckBox = (JCheckBoxMenuItem) evt.getSource();
2328 if (treeCheckBox.isSelected()) {
2329 if (splitPaneDivider < frame.getWidth() * (1.0f / 4.0f)) {
2330 splitPaneDivider = (int) (frame.getWidth() * (1.0f / 4.0f));
2331 }
2332 splitPane.setDividerLocation(splitPaneDivider);
2333 } else {
2334 splitPaneDivider = splitPane.getDividerLocation();
2335 splitPane.setDividerLocation(0.0);
2336 }
2337 }
2338
2339
2340
2341
2342 private void skip() {
2343 Trajectory trajectory = getTrajectory();
2344 if (trajectory == null) {
2345 return;
2346 }
2347 String skip = "" + trajectory.getSkip();
2348 skip = JOptionPane.showInputDialog("Enter the Number of Frames to Skip", skip);
2349 try {
2350 int f = Integer.parseInt(skip);
2351 trajectory.setSkip(f);
2352 } catch (NumberFormatException e) {
2353
2354 }
2355 }
2356
2357
2358
2359
2360 private void speed() {
2361 Trajectory trajectory = getTrajectory();
2362 if (trajectory == null) {
2363 return;
2364 }
2365 String rate = "" + trajectory.getRate();
2366 rate = JOptionPane.showInputDialog("Enter the Frame Rate (1-100)", rate);
2367 try {
2368 int f = Integer.parseInt(rate);
2369 trajectory.setRate(f);
2370 } catch (NumberFormatException e) {
2371
2372 }
2373 }
2374
2375
2376
2377
2378 private void stepBack() {
2379 Trajectory trajectory = getTrajectory();
2380 if (trajectory == null) {
2381 return;
2382 }
2383 trajectory.stop();
2384 trajectory.back();
2385 }
2386
2387
2388
2389
2390 private void stepForward() {
2391 Trajectory trajectory = getTrajectory();
2392 if (trajectory == null) {
2393 return;
2394 }
2395 trajectory.stop();
2396 trajectory.forward();
2397 }
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408 enum ExitStatus {
2409
2410 NORMAL(0),
2411
2412
2413
2414 EXCEPTION(1),
2415
2416 SEVERE(3),
2417
2418
2419 ALGORITHM_FAILURE(100),
2420
2421 OTHER(200);
2422
2423
2424 private final int exitCode;
2425
2426 ExitStatus(int exitCode) {
2427 this.exitCode = exitCode;
2428 }
2429
2430
2431
2432
2433
2434
2435 int getExitCode() {
2436 return exitCode;
2437 }
2438 }
2439 }