Java tutorial
/** * Title: Force Field X. * * Description: Force Field X - Software for Molecular Biophysics. * * Copyright: Copyright (c) Michael J. Schnieders 2001-2017. * * This file is part of Force Field X. * * Force Field X is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 as published by * the Free Software Foundation. * * Force Field X is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA * * Linking this library statically or dynamically with other modules is making a * combined work based on this library. Thus, the terms and conditions of the * GNU General Public License cover the whole combination. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent modules, and * to copy and distribute the resulting executable under terms of your choice, * provided that you also meet, for each linked independent module, the terms * and conditions of the license of that module. An independent module is a * module which is not derived from or based on this library. If you modify this * library, you may extend this exception to your version of the library, but * you are not obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package ffx.ui; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import java.util.prefs.Preferences; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextArea; import javax.swing.JToolBar; import javax.swing.border.Border; import javax.swing.border.EtchedBorder; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.configuration.CompositeConfiguration; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.PropertiesConfiguration; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import ffx.potential.parsers.KeyFileFilter; import ffx.potential.parsers.KeyFilter; import ffx.ui.commands.DTDResolver; import ffx.utilities.Keyword; /** * The KeywordPanel class provides a View and Control of TINKER Keyword (*.KEY) * files. * * @author Michael J. Schnieders * */ public final class KeywordPanel extends JPanel implements ActionListener { private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(KeywordPanel.class.getName()); private static final Preferences preferences = Preferences.userNodeForPackage(KeywordPanel.class); /** * True if a Key File is open. */ private boolean fileOpen = false; /** * Currently open Keywords. */ private Hashtable<String, Keyword> currentKeys; /** * Currently open Key File. */ private File currentKeyFile; /** * FFXSystem associated with currently open Key File (if any). */ private FFXSystem currentSystem; /** * The MainPanel has references to many things the KeywordPanel uses. */ private final MainPanel mainPanel; /** * HashMap for Keyword GUI Components. */ private LinkedHashMap<String, KeywordComponent> keywordHashMap; /** * HashMap for Keyword Groups. */ private LinkedHashMap<String, String> groupHashMap; /** * JComboBox with Keyword Groups, plus a few special cases (Active, * FlatFile). */ private JComboBox<String> groupComboBox; /** * The editPanel holds the toolBar (north), splitPane (center) and * statusLabel (south). */ private JPanel editPanel; private JToolBar toolBar; /** * The splitPane holds the editScrollPane (top) and descriptScrollPane * (bottom). */ private JSplitPane splitPane; private final JLabel statusLabel = new JLabel(" "); /** * The editScrollPane holds the gridPanel, where KeywordComponents actually * live. */ private JScrollPane editScrollPane; /** * The descriptScrollPane holds the descriptTextArea for Keyword * Descriptions. */ private JScrollPane descriptScrollPane; /** * The descriptTextArea actually holds Keyword Descriptions. */ private JTextArea descriptTextArea; /** * Allow the user to show/hide Keyword Descriptions. */ private JCheckBoxMenuItem descriptCheckBox; private final GridBagLayout gridBagLayout = new GridBagLayout(); private final GridBagConstraints gridBagConstraints = new GridBagConstraints(); /** * The gridPanel holds an array of KeywordComponents. */ private final JPanel gridPanel = new JPanel(gridBagLayout); /** * Lines in Keyword files that are comments, unrecognized keywords, or * keywords where editing is not supported are stored in a big * StringBuilder. */ private StringBuilder commentStringBuffer = new StringBuilder(); /** * This component shows what the saved Key file will look like (WYSIWYG). */ private JTextArea flatfileTextArea; /** * A simple label if no Keyword File is open. */ private final JLabel noSystemLabel = new JLabel("Keywords for the active system are edited here. "); // A simple label if no Keyword Description is available. private final JLabel noKeywordLabel = new JLabel("Keyword desciptions are displayed here."); private final JPanel noKeywordPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5)); private final FlowLayout flowLayout = new FlowLayout(FlowLayout.LEFT, 5, 5); private final BorderLayout borderLayout = new BorderLayout(); // Location of TINKER parameter files private File paramDir = null; private File paramFiles[] = null; private String paramNames[] = null; private LinkedHashMap<String, String> paramHashtable = null; /** * Default Construtor where parent is the tinker Window Frame object. * * @param f a {@link ffx.ui.MainPanel} object. */ public KeywordPanel(MainPanel f) { super(); mainPanel = f; initialize(); } /** * Handles input from KeywordPanel ToolBar buttons. * * {@inheritDoc} */ @Override public void actionPerformed(ActionEvent evt) { String arg = evt.getActionCommand(); switch (arg) { case "Open...": keyOpen(); break; case "Close": keyClose(); break; case "Save": keySave(currentKeyFile); break; case "Save As...": keySaveAs(); break; case "Description": JCheckBoxMenuItem box = (JCheckBoxMenuItem) evt.getSource(); setDivider(box.isSelected()); break; } if (evt.getSource() instanceof JComboBox) { loadKeywordGroup(); } } /** * <p> * getKeyword</p> * * @param key a {@link java.lang.String} object. * @return a {@link java.lang.String} object. */ public String getKeyword(String key) { if (key == null) { return null; } synchronized (this) { KeywordComponent keyword = keywordHashMap.get(key.toUpperCase()); if (keyword == null) { return null; } return keyword.toString(); } } /** * <p> * getKeywordDescription</p> * * @param key a {@link java.lang.String} object. * @return a {@link java.lang.String} object. */ public String getKeywordDescription(String key) { if (key == null) { return null; } synchronized (this) { KeywordComponent keyword = keywordHashMap.get(key.toUpperCase()); if (keyword == null) { return null; } return keyword.getKeywordDescription(); } } /** * <p> * getKeywordValue</p> * * @param key a {@link java.lang.String} object. * @return a {@link java.lang.String} object. */ public String getKeywordValue(String key) { if (key == null) { return null; } synchronized (this) { KeywordComponent keyword = keywordHashMap.get(key.toUpperCase()); if (keyword == null) { return null; } String value = keyword.toString().trim(); if (value == null) { return null; } int firstSpace = value.indexOf(" "); if (firstSpace < 1) { return value; } return value.substring(firstSpace, value.length()); } } /** * <p> * Getter for the field <code>paramFiles</code>.</p> * * @return an array of {@link java.lang.String} objects. */ public String[] getParamFiles() { return paramNames; } /** * <p> * getParamPath</p> * * @param key a {@link java.lang.String} object. * @return a {@link java.lang.String} object. */ public String getParamPath(String key) { return paramHashtable.get(key); } private void initialize() { // Load the Keyword Definitions loadXML(); // TextAreas flatfileTextArea = new JTextArea(); flatfileTextArea.setEditable(false); flatfileTextArea.setFont(Font.decode("monospaced plain 12")); Insets insets = flatfileTextArea.getInsets(); insets.set(5, 5, 5, 5); flatfileTextArea.setMargin(insets); // Keyword Edit Panel editPanel = new JPanel(flowLayout); ClassLoader loader = getClass().getClassLoader(); ImageIcon icKeyPanel = new ImageIcon(loader.getResource("ffx/ui/icons/page_key.png")); noSystemLabel.setIcon(icKeyPanel); ImageIcon icon = new ImageIcon(loader.getResource("ffx/ui/icons/information.png")); noKeywordLabel.setIcon(icon); noKeywordPanel.add(noKeywordLabel); editScrollPane = new JScrollPane(editPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); descriptScrollPane = new JScrollPane(descriptTextArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); Border eb = BorderFactory.createEtchedBorder(EtchedBorder.RAISED); descriptScrollPane.setBorder(eb); // Add the Keyword Group Panel and Decription Panel to a JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, editScrollPane, descriptScrollPane); splitPane.setResizeWeight(1.0); splitPane.setOneTouchExpandable(true); statusLabel.setBorder(eb); // Add the main pieces to the overall KeywordPanel (except the ToolBar) setLayout(new BorderLayout()); add(splitPane, BorderLayout.CENTER); add(statusLabel, BorderLayout.SOUTH); // Init the GridBagContraints gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = GridBagConstraints.WEST; gridBagConstraints.gridheight = 1; gridBagConstraints.gridwidth = 1; gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; initToolBar(); add(toolBar, BorderLayout.NORTH); setParamPath(); loadPrefs(); loadKeywordGroup(); } /** * <p> * initToolBar</p> */ public void initToolBar() { toolBar = new JToolBar("Keyword Editor"); toolBar.setLayout(flowLayout); ClassLoader loader = getClass().getClassLoader(); JButton jbopen = new JButton(new ImageIcon(loader.getResource("ffx/ui/icons/folder_page.png"))); jbopen.setActionCommand("Open..."); jbopen.setToolTipText("Open a *.KEY File for Editing"); jbopen.addActionListener(this); Insets insets = jbopen.getInsets(); insets.top = 2; insets.bottom = 2; insets.left = 2; insets.right = 2; jbopen.setMargin(insets); //toolBar.add(jbopen); JButton jbsave = new JButton(new ImageIcon(loader.getResource("ffx/ui/icons/disk.png"))); jbsave.setActionCommand("Save"); jbsave.setToolTipText("Save the Active *.KEY File"); jbsave.addActionListener(this); jbsave.setMargin(insets); toolBar.add(jbsave); JButton jbsaveas = new JButton(new ImageIcon(loader.getResource("ffx/ui/icons/page_save.png"))); jbsaveas.setActionCommand("Save As..."); jbsaveas.setToolTipText("Save the Active *.KEY File Under a New Name"); jbsaveas.addActionListener(this); jbsaveas.setMargin(insets); toolBar.add(jbsaveas); JButton jbclose = new JButton(new ImageIcon(loader.getResource("ffx/ui/icons/cancel.png"))); jbclose.setActionCommand("Close"); jbclose.setToolTipText("Close the Active *.KEY File"); jbclose.addActionListener(this); jbclose.setMargin(insets); //toolBar.add(jbclose); toolBar.addSeparator(); groupComboBox.setMaximumSize(groupComboBox.getPreferredSize()); groupComboBox.addActionListener(this); groupComboBox.setEditable(false); toolBar.add(groupComboBox); toolBar.addSeparator(); ImageIcon icinfo = new ImageIcon(loader.getResource("ffx/ui/icons/information.png")); descriptCheckBox = new JCheckBoxMenuItem(icinfo); descriptCheckBox.setActionCommand("Description"); descriptCheckBox.setToolTipText("Show/Hide Keyword Descriptions"); descriptCheckBox.addActionListener(this); descriptCheckBox.setMargin(insets); toolBar.add(descriptCheckBox); toolBar.add(new JLabel("")); toolBar.setBorderPainted(false); toolBar.setFloatable(false); toolBar.setRollover(true); toolBar.setOrientation(JToolBar.HORIZONTAL); } /** * <p> * isFileOpen</p> * * @return a boolean. */ public boolean isFileOpen() { return fileOpen; } /** * <p> * isKeyword</p> * * @param key a {@link java.lang.String} object. * @return a boolean. */ public boolean isKeyword(String key) { synchronized (this) { KeywordComponent keyword = keywordHashMap.get(key.toUpperCase()); return keyword != null; } } /** * <p> * keyClear</p> */ public void keyClear() { synchronized (this) { // Clear each KeywordComponent for (KeywordComponent kw : keywordHashMap.values()) { kw.clearKeywordComponent(); } KeywordComponent.setKeywordModified(false); // Reset internal variables fileOpen = false; currentKeys = null; currentSystem = null; currentKeyFile = null; // Reset the View commentStringBuffer = new StringBuilder(); statusLabel.setText(" "); loadKeywordGroup(); } } /** * <p> * keyClose</p> * * @return a boolean. */ public boolean keyClose() { if (KeywordComponent.isKeywordModified()) { return false; } keyClear(); return true; } /** * Give the user a File Dialog Box so they can select a key file. */ public void keyOpen() { if (fileOpen && KeywordComponent.isKeywordModified()) { int option = JOptionPane.showConfirmDialog(this, "Save Changes First", "Opening New File", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE); if (option == JOptionPane.CANCEL_OPTION) { return; } else if (option == JOptionPane.YES_OPTION) { keySave(currentKeyFile); } keyClear(); } JFileChooser d = MainPanel.resetFileChooser(); if (currentSystem != null) { File cwd = currentSystem.getFile(); if (cwd != null && cwd.getParentFile() != null) { d.setCurrentDirectory(cwd.getParentFile()); } } d.setAcceptAllFileFilterUsed(false); d.setFileFilter(MainPanel.keyFileFilter); d.setDialogTitle("Open KEY File"); int result = d.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { File newKeyFile = d.getSelectedFile(); if (newKeyFile != null && newKeyFile.exists() && newKeyFile.canRead()) { keyOpen(newKeyFile); } } } /** * <p> * keyOpen</p> * * @param newKeyFile a {@link java.io.File} object. * @return a boolean. */ public boolean keyOpen(File newKeyFile) { if (newKeyFile != null && newKeyFile.exists() && newKeyFile.canRead()) { Hashtable<String, Keyword> newKeys = KeyFilter.open(newKeyFile); if (newKeys != null && newKeys.size() > 0) { if (currentSystem != null) { currentSystem.setKeyFile(currentKeyFile); currentSystem.setKeywords(currentKeys); } loadActive(currentSystem, newKeys, newKeyFile); return true; } } return false; } /** * <p> * keySave</p> * * @param f a {@link java.io.File} object. */ public void keySave(File f) { if (f != null) { currentKeyFile = f; } if (!fileOpen || currentKeyFile == null) { return; } storeActive(); saveKeywords(currentKeyFile, keywordHashMap, commentStringBuffer); } /** * <p> * keySaveAs</p> */ public void keySaveAs() { if (!fileOpen) { return; } JFileChooser d = MainPanel.resetFileChooser(); d.setDialogTitle("Save KEY File"); d.setAcceptAllFileFilterUsed(false); if (currentKeyFile != null) { d.setCurrentDirectory(currentKeyFile.getParentFile()); d.setSelectedFile(currentKeyFile); } d.setFileFilter(new KeyFileFilter()); int result = d.showSaveDialog(this); if (result == JFileChooser.APPROVE_OPTION) { currentKeyFile = d.getSelectedFile(); keySave(currentKeyFile); } } /** * <p> * loadActive</p> * * @param newSystem a {@link ffx.ui.FFXSystem} object. * @return a boolean. */ public boolean loadActive(FFXSystem newSystem) { synchronized (this) { if (newSystem == null) { keyClear(); return false; } configToKeywords(newSystem); File newKeyFile = newSystem.getKeyFile(); if (newKeyFile != null) { //logger.info(String.format("Key File %s.", newKeyFile.getAbsolutePath())); } Hashtable<String, Keyword> newKeys = newSystem.getKeywords(); if (newKeyFile == null && newKeys == null) { logger.info(String.format("Loaded %s with no keywords.", newSystem.toString())); return false; } //logger.info(String.format("Loading %s with %d keywords.", newSystem.toString(), newKeys.size())); return loadActive(newSystem, newKeys, newKeyFile); } } private void configToKeywords(FFXSystem newSystem) { CompositeConfiguration properties = newSystem.getProperties(); Hashtable<String, Keyword> keywordHash = new Hashtable<>(); // Create the "Comments" property. Keyword keyword = new Keyword("COMMENTS"); keywordHash.put("COMMENTS", keyword); // Loop over properties from the keyword file. Configuration config = properties.getConfiguration(0); if (config instanceof PropertiesConfiguration) { PropertiesConfiguration prop = (PropertiesConfiguration) config; Iterator<String> keys = prop.getKeys(); while (keys.hasNext()) { String key = keys.next(); if (keywordHash.contains(key)) { keyword = keywordHash.get(key); keyword.append(prop.getStringArray(key)); } else { String[] values = prop.getStringArray(key); keyword = new Keyword(key, values); keywordHash.put(key, keyword); } } } newSystem.setKeywords(keywordHash); } /** * <p> * loadActive</p> * * @param newSystem a {@link ffx.ui.FFXSystem} object. * @param newKeys a {@link java.util.Hashtable} object. * @param newKeyFile a {@link java.io.File} object. * @return a boolean. */ public boolean loadActive(FFXSystem newSystem, Hashtable<String, Keyword> newKeys, File newKeyFile) { synchronized (this) { // Store changes made to the current system (if any) first. if (currentKeys != null && KeywordComponent.isKeywordModified()) { if (currentSystem != null && currentSystem != newSystem) { storeActive(); } else { saveChanges(); } } // Clear previous values keyClear(); // No keywords to load if (newKeys == null || newKeys.size() == 0) { return false; } currentSystem = newSystem; currentKeyFile = newKeyFile; currentKeys = newKeys; fileOpen = true; /* * Keys to remove are those entries not recognized by the FFX * Keyword Editor These keys are removed from the active System's * keyword Hashtable and appended to the generic "Comments" * KeywordData instance. */ ArrayList<String> keysToRemove = new ArrayList<>(); Keyword comments = currentKeys.get("COMMENTS"); for (Keyword keyword : currentKeys.values()) { String label = keyword.getKeyword(); Vector<String> data = keyword.getEntries(); if (label.equals("COMMENTS")) { continue; } KeywordComponent tk = keywordHashMap.get(label.toUpperCase()); // If the keyword label isn't recognized, preserve the line // as a Comment if (tk == null) { keysToRemove.add(keyword.getKeyword()); if (data.isEmpty()) { comments.append(label); } else if (label.equalsIgnoreCase("MULTIPOLE")) { int count = 5; for (String entry : data) { count++; if (count > 5) { comments.append(label + " " + entry); count = 1; } else { comments.append(entry); } } } else if (label.equalsIgnoreCase("TORTORS")) { int points = 0; int count = 0; for (String entry : data) { count++; if (count > points) { String res[] = entry.split(" +"); int xres = Integer.parseInt(res[5]); int yres = Integer.parseInt(res[5]); points = xres * yres; comments.append(label + " " + entry); count = 0; } else { comments.append(entry); } } } else { for (String entry : data) { comments.append(label + " " + entry); } } continue; } // No data for this keyword (something like "verbose" that // doesn't have modifiers) if (data.isEmpty()) { tk.loadKeywordEntry(label); } // One to many data entries (something "atom" or "bond" that // can be repeated) for (String s : data) { tk.loadKeywordEntry(s); } } // Load up the Comments Vector<String> entries = comments.getEntries(); if (entries != null) { for (String s : entries) { if (s.length() > 1) { if (!groupHashMap.containsKey(s.substring(1).toUpperCase().trim())) { commentStringBuffer.append(s).append("\n"); } } else { commentStringBuffer.append(s).append("\n"); } } } // Keywords that aren't recognized have been turned into Comments for (String k : keysToRemove) { currentKeys.remove(k); } if (currentSystem != null) { currentSystem.setKeywords(currentKeys); currentSystem.setKeyFile(currentKeyFile); } loadKeywordGroup(); return true; } } private void loadKeywordGroup() { synchronized (this) { editPanel.removeAll(); String selectedGroup = (String) groupComboBox.getSelectedItem(); if (currentKeys == null) { editPanel.setLayout(flowLayout); editPanel.add(noSystemLabel); int temp = splitPane.getDividerLocation(); splitPane.setBottomComponent(noKeywordPanel); splitPane.setDividerLocation(temp); } else if (selectedGroup.equalsIgnoreCase("Flat File View")) { editPanel.setLayout(borderLayout); publishKeywords(); editPanel.add(flatfileTextArea, BorderLayout.CENTER); int temp = splitPane.getDividerLocation(); splitPane.setBottomComponent(noKeywordPanel); splitPane.setDividerLocation(temp); } else if (selectedGroup.equalsIgnoreCase("Active Keywords")) { gridPanel.removeAll(); gridBagConstraints.gridy = 0; gridBagConstraints.anchor = GridBagConstraints.WEST; gridBagConstraints.gridheight = 1; gridBagConstraints.gridwidth = 1; gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; for (KeywordComponent keywordComponent : keywordHashMap.values()) { if (keywordComponent.isActive() == true) { JPanel jptemp = keywordComponent.getKeywordGUI(); gridBagLayout.setConstraints(jptemp, gridBagConstraints); gridPanel.add(jptemp); gridBagConstraints.gridy++; } } KeywordComponent.fillPanel(gridPanel, gridBagLayout, gridBagConstraints); editPanel.setLayout(flowLayout); editPanel.add(gridPanel); int temp = splitPane.getDividerLocation(); splitPane.setBottomComponent(descriptScrollPane); splitPane.setDividerLocation(temp); } else { gridPanel.removeAll(); gridBagConstraints.gridy = 0; gridBagConstraints.gridx = 0; gridBagConstraints.anchor = GridBagConstraints.WEST; gridBagConstraints.gridheight = 1; gridBagConstraints.gridwidth = 1; gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; for (KeywordComponent keywordComponent : keywordHashMap.values()) { if (keywordComponent.getKeywordGroup().equalsIgnoreCase(selectedGroup)) { JPanel jptemp = keywordComponent.getKeywordGUI(); gridBagLayout.setConstraints(jptemp, gridBagConstraints); gridPanel.add(jptemp); gridBagConstraints.gridy++; } } KeywordComponent.fillPanel(gridPanel, gridBagLayout, gridBagConstraints); editPanel.setLayout(flowLayout); editPanel.add(gridPanel); int temp = splitPane.getDividerLocation(); splitPane.setBottomComponent(descriptScrollPane); splitPane.setDividerLocation(temp); } if (currentKeyFile != null) { statusLabel.setText(" " + currentKeyFile.toString()); } else { statusLabel.setText(" "); } editScrollPane.validate(); editScrollPane.repaint(); } } /** * <p> * loadPrefs</p> */ public void loadPrefs() { String c = KeywordPanel.class.getName(); descriptCheckBox.setSelected(!preferences.getBoolean(c + ".description", true)); descriptCheckBox.doClick(); } /** * Load up the Force Field X Keyword Definitions */ private void loadXML() { NodeList groups, keywords, values; Element group, keyword, value; String groupName; String keywordName, keywordDescription, keywordGUI; groups = null; try { // Build the Document from the keywords.xml file DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); db.setEntityResolver(new DTDResolver()); URL keyURL = getClass().getClassLoader().getResource("ffx/ui/commands/keywords.xml"); Document doc = db.parse(keyURL.openStream()); Element document = doc.getDocumentElement(); Element body = (Element) document.getElementsByTagName("body").item(0); groups = body.getElementsByTagName("section"); } catch (ParserConfigurationException | SAXException | IOException e) { logger.warning(e.toString()); } keywordHashMap = new LinkedHashMap<>(); groupHashMap = new LinkedHashMap<>(); groupHashMap.put("ACTIVE KEYWORDS", "Active Keywords"); groupHashMap.put("FLAT FILE VIEW", "Flat File View"); groupComboBox = new JComboBox<>(); groupComboBox.addItem("Active Keywords"); groupComboBox.addItem("Flat File View"); descriptTextArea = new JTextArea(); descriptTextArea.setLineWrap(true); descriptTextArea.setWrapStyleWord(true); Insets insets = descriptTextArea.getInsets(); insets.set(5, 5, 5, 5); descriptTextArea.setMargin(insets); int length = groups.getLength(); // Iterate through the Keyword Groups for (int i = 0; i < length; i++) { group = (Element) groups.item(i); groupName = group.getAttribute("name"); groupComboBox.addItem(groupName); keywords = group.getElementsByTagName("subsection"); int klength = keywords.getLength(); for (int j = 0; j < klength; j++) { keyword = (Element) keywords.item(j); keywordName = keyword.getAttribute("name"); Node text = keyword.getFirstChild(); keywordDescription = text.getNodeValue().replace('\n', ' '); keywordDescription = keywordDescription.replaceAll(" +", " "); keywordGUI = keyword.getAttribute("rep"); KeywordComponent.SwingRepresentation type; try { type = KeywordComponent.SwingRepresentation.valueOf(keywordGUI.toUpperCase()); } catch (Exception e) { type = null; logger.log(Level.WARNING, "{0}: Unknown GUI Component - {1}", new Object[] { keywordName, type }); System.exit(-1); } KeywordComponent key; if (type == KeywordComponent.SwingRepresentation.CHECKBOXES || type == KeywordComponent.SwingRepresentation.COMBOBOX) { values = keyword.getElementsByTagName("Value"); String labels[] = new String[values.getLength()]; for (int k = 0; k < values.getLength(); k++) { value = (Element) values.item(k); labels[k] = value.getAttribute("name"); } key = new KeywordComponent(keywordName, groupName, type, keywordDescription, descriptTextArea, labels); } else { key = new KeywordComponent(keywordName, groupName, type, keywordDescription, descriptTextArea); } keywordHashMap.put(keywordName.toUpperCase(), key); groupHashMap.put(groupName.toUpperCase(), groupName); } } groupComboBox.setSelectedIndex(0); } /** * <p> * publishKeywords</p> */ public void publishKeywords() { synchronized (this) { flatfileTextArea.setText(""); boolean writegroup = false; String pgroup = null; // Write out keywords in groups for (KeywordComponent keyword : keywordHashMap.values()) { String group = keyword.getKeywordGroup(); if (pgroup == null || !group.equalsIgnoreCase(pgroup)) { writegroup = true; pgroup = group; } String line = keyword.toString(); if (line != null) { if (writegroup == true) { flatfileTextArea.append("\n"); flatfileTextArea.append("# " + group); flatfileTextArea.append("\n"); writegroup = false; } flatfileTextArea.append(line); flatfileTextArea.append("\n"); } } flatfileTextArea.append("\n"); String s = commentStringBuffer.toString(); if (s != null && !s.trim().equals("")) { flatfileTextArea.append(s.trim()); } flatfileTextArea.append("\n"); } } /** * <p> * saveChanges</p> * * @return a boolean. */ public boolean saveChanges() { if (KeywordComponent.isKeywordModified() && currentKeyFile != null) { keySave(currentKeyFile); return true; } return false; } /** * <p> * saveKeywords</p> * * @param keyFile a {@link java.io.File} object. * @param keywordHashMap a {@link java.util.LinkedHashMap} object. * @param comments a {@link java.lang.StringBuilder} object. * @return a boolean. */ public boolean saveKeywords(File keyFile, LinkedHashMap<String, KeywordComponent> keywordHashMap, StringBuilder comments) { synchronized (this) { FileWriter fw = null; BufferedWriter bw = null; try { fw = new FileWriter(keyFile); bw = new BufferedWriter(fw); boolean writegroup = false; String pgroup = null; // Write out keywords in groups for (KeywordComponent keyword : keywordHashMap.values()) { String group = keyword.getKeywordGroup(); if (pgroup == null || !group.equalsIgnoreCase(pgroup)) { writegroup = true; pgroup = group; } String line = keyword.toString(); if (line != null) { if (writegroup == true) { bw.newLine(); bw.write("# " + group); bw.newLine(); writegroup = false; } bw.write(line); bw.newLine(); } } bw.newLine(); String s = comments.toString(); if (s != null && !s.trim().equals("")) { bw.write(s.trim()); } bw.newLine(); bw.flush(); KeywordComponent.setKeywordModified(false); } catch (FileNotFoundException e) { logger.warning(e.toString()); return false; } catch (IOException e) { logger.warning(e.toString()); return false; } finally { try { if (bw != null) { bw.close(); } if (fw != null) { fw.close(); } } catch (Exception e) { logger.warning(e.toString()); } } return true; } } /** * <p> * savePrefs</p> */ public void savePrefs() { String c = KeywordPanel.class.getName(); preferences.putInt(c + ".divider", splitPane.getDividerLocation()); preferences.putBoolean(c + ".description", descriptCheckBox.isSelected()); } /** * <p> * selected</p> */ public void selected() { setDivider(descriptCheckBox.isSelected()); validate(); repaint(); } /** * <p> * setDivider</p> * * @param b a boolean. */ public void setDivider(boolean b) { if (b) { descriptCheckBox.setSelected(b); int spDivider = (int) (this.getHeight() * (3.0f / 5.0f)); splitPane.setDividerLocation(spDivider); } else { splitPane.setDividerLocation(1.0); } } /** * Make the passed Keyword Group active in the editor. * * @param keygroup String */ public void setKeywordGroup(String keygroup) { synchronized (this) { keygroup = groupHashMap.get(keygroup.toUpperCase()); if (keygroup == null) { return; } if (!groupComboBox.getSelectedItem().equals(keygroup)) { groupComboBox.setSelectedItem(keygroup); loadKeywordGroup(); } } } /** * Load a value into a KeywordComponent. Value is equivalent to one line in * a TINKER key file, except without the keyword at the beginning. Value * should be null to just indicate the Keyword is present (active). If this * Keyword can apprear many times, value will be appended to the list. * * @param key String * @param value String */ public void setKeywordValue(String key, String value) { synchronized (this) { KeywordComponent keyword = keywordHashMap.get(key.toUpperCase()); if (keyword == null) { return; } keyword.loadKeywordEntry(value); String keygroup = keyword.getKeywordGroup(); if (!groupComboBox.getSelectedItem().equals(keygroup)) { groupComboBox.setSelectedItem(keygroup); loadKeywordGroup(); } mainPanel.setPanel(MainPanel.KEYWORDS); } } /** * <p> * setParamPath</p> */ public void setParamPath() { paramDir = new File(MainPanel.ffxDir.getAbsolutePath() + File.separator + "params"); if (paramDir != null && paramDir.exists()) { paramFiles = paramDir.listFiles(); paramHashtable = new LinkedHashMap<>(); for (File f : paramFiles) { if (f.exists() && f.canRead() && MainPanel.forceFieldFileFilter.accept(f)) { paramHashtable.put(f.getName(), f.getAbsolutePath()); } } int num = paramHashtable.size(); paramNames = new String[num + 1]; int i = 1; for (String name : paramHashtable.keySet()) { paramNames[i] = name; i++; } paramNames[0] = "AAA"; java.util.Arrays.sort(paramNames); paramNames[0] = "Use an existing TINKER Key file".intern(); } } /** * Store the KeywordPanel's current keyword content into sys. * * @param sys FFXSystem */ public void store(FFXSystem sys) { synchronized (this) { FFXSystem back = currentSystem; currentSystem = sys; storeActive(); currentSystem = back; } } /** * Store the KeywordPanel's current keyword content in the activeSystem. */ public void storeActive() { synchronized (this) { if (currentSystem == null) { return; } // No changes if (!KeywordComponent.isKeywordModified()) { return; } Hashtable<String, Keyword> currentKeys = currentSystem.getKeywords(); Hashtable<String, Keyword> newKeys = new Hashtable<String, Keyword>(); for (KeywordComponent kc : keywordHashMap.values()) { if (kc.isActive() == true) { Keyword keywordData = null; if (currentKeys != null) { keywordData = currentKeys.get(kc.getKeyword()); } if (keywordData == null) { keywordData = new Keyword(kc.getKeyword()); } else { keywordData.clear(); } kc.getKeywordData(keywordData); newKeys.put(kc.getKeyword(), keywordData); } } Keyword comments = new Keyword("COMMENTS", commentStringBuffer.toString()); newKeys.put("COMMENTS", comments); currentSystem.setKeywords(newKeys); } } /** * {@inheritDoc} */ @Override public String toString() { return "Keyword Editor"; } }