package beast.app.beauti; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.Cursor; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.UIManager; import javax.swing.WindowConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import beast.app.BEASTVersion2; import beast.app.beauti.BeautiDoc.ActionOnExit; import beast.app.beauti.BeautiDoc.DOC_STATUS; import beast.app.draw.BEASTObjectPanel; import beast.app.draw.HelpBrowser; import beast.app.draw.ModelBuilder; import beast.app.draw.MyAction; import beast.app.tools.AppStore; import beast.app.util.Utils; import beast.core.BEASTInterface; import beast.core.util.Log; import beast.evolution.alignment.Alignment; import beast.math.distributions.MRCAPrior; import beast.util.AddOnManager; import jam.framework.DocumentFrame; public class Beauti extends JTabbedPane implements BeautiDocListener { private static final long serialVersionUID = 1L; static final String BEAUTI_ICON = "beast/app/draw/icons/beauti.png"; // ExtensionFileFilter ef0 = new ExtensionFileFilter(".nex", "Nexus files"); // ExtensionFileFilter ef1 = new ExtensionFileFilter(".xml", "BEAST files"); /** * current directory for opening files * */ public static String g_sDir = System.getProperty("user.dir"); /** * File extension for Beast specifications */ static public final String FILE_EXT = ".xml"; static public final String FILE_EXT2 = ".json"; static final String fileSep = System.getProperty("file.separator"); /** * document in document-view pattern. BTW this class is the view */ public BeautiDoc doc; public JFrame frame; /** * currently selected tab * */ public BeautiPanel currentTab; public boolean[] isPaneIsVisible; public BeautiPanel[] panels; /** * menu for file handling, importing partitions, etc. */ JMenu fileMenu; /** * menu for switching templates * */ JMenu templateMenu; /** * menu for making showing/hiding tabs * */ JMenu viewMenu; JCheckBoxMenuItem autoSetClockRate; JCheckBoxMenuItem allowLinking; JCheckBoxMenuItem autoUpdateFixMeanSubstRate; /** * flag indicating beauti is in the process of being set up and panels * should not sync with current model * */ public boolean isInitialising = true; public Beauti(BeautiDoc doc) { isPaneIsVisible = new boolean[doc.beautiConfig.panels.size()]; Arrays.fill(isPaneIsVisible, true); // m_panels = new BeautiPanel[NR_OF_PANELS]; this.doc = doc; this.doc.addBeautiDocListener(this); doc.setBeauti(this); } void setTitle() { frame.setTitle("BEAUti 2: " + this.doc.getTemplateName() + " " + doc.getFileName()); } void toggleVisible(int panelNr) { if (isPaneIsVisible[panelNr]) { isPaneIsVisible[panelNr] = false; int tabNr = tabNrForPanel(panelNr); removeTabAt(tabNr); } else { isPaneIsVisible[panelNr] = true; int tabNr = tabNrForPanel(panelNr); BeautiPanelConfig panel = doc.beautiConfig.panels.get(panelNr); insertTab( doc.beautiConfig.getButtonLabel(this, panel.nameInput.get()), null, panels[panelNr], panel.tipTextInput.get(), tabNr); // } setSelectedIndex(tabNr); } } int tabNrForPanel(int panelNr) { int k = 0; for (int i = 0; i < panelNr; i++) { if (isPaneIsVisible[i]) { k++; } } return k; } Action a_new = new ActionNew(); public Action a_load = new ActionLoad(); Action a_template = new ActionTemplate(); Action a_addOn = new ActionAddOn(); Action a_appLauncher = new ActionAppLauncher(); // public Action a_import = new ActionImport(); public Action a_save = new ActionSave(); Action a_saveas = new ActionSaveAs(); Action a_close = new ActionClose(); Action a_quit = new ActionQuit(); Action a_viewall = new ActionViewAllPanels(); Action a_help = new ActionHelp(); Action a_msgs = new ActionMsgs(); Action a_citation = new ActionCitation(); Action a_about = new ActionAbout(); Action a_viewModel = new ActionViewModel(); @Override public void docHasChanged() throws NoSuchMethodException, SecurityException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { setUpPanels(); setUpViewMenu(); setTitle(); } class ActionSave extends MyAction { private static final long serialVersionUID = 1; public ActionSave() { super("Save", "Save Model", "save", KeyEvent.VK_S); setEnabled(false); } // c'tor public ActionSave(String name, String toolTipText, String icon, int acceleratorKey) { super(name, toolTipText, icon, acceleratorKey); } // c'tor @Override public void actionPerformed(ActionEvent ae) { DOC_STATUS docStatus = doc.validateModel(); if (docStatus != DOC_STATUS.DIRTY) { if (docStatus == DOC_STATUS.NO_DOCUMENT) JOptionPane.showMessageDialog(null, "There is no data to save to file"); return; } if (!doc.getFileName().equals("")) { saveFile(doc.getFileName()); // m_doc.isSaved(); } else { if (saveAs()) { // m_doc.isSaved(); } } } // actionPerformed } // class ActionSave class ActionSaveAs extends ActionSave { /** * for serialisation */ private static final long serialVersionUID = -20389110859354L; public ActionSaveAs() { super("Save As", "Save Model As", "saveas", -1); setEnabled(false); } // c'tor @Override public void actionPerformed(ActionEvent ae) { saveAs(); } // actionPerformed } // class ActionSaveAs boolean saveAs() { if (doc.validateModel() == DOC_STATUS.NO_DOCUMENT) { JOptionPane.showMessageDialog(null, "There is no data to save to file"); return false; } String fileSep = System.getProperty("file.separator"); if (fileSep.equals("\\")) { fileSep = "\\\\"; } String defaultFile = g_sDir + (doc.getFileName().equals("") ? "" : fileSep + new File(doc.getFileName()).getName()); File file = beast.app.util.Utils.getSaveFile("Save Model As", new File( defaultFile), null, FILE_EXT, FILE_EXT2); if (file != null) { if (file.exists() && !Utils.isMac()) { if (JOptionPane.showConfirmDialog(null, "File " + file.getName() + " already exists. Do you want to overwrite?", "Overwrite file?", JOptionPane.YES_NO_CANCEL_OPTION) != JOptionPane.YES_OPTION) { return false; } } // System.out.println("Saving to file \""+ // f.getAbsoluteFile().toString()+"\""); doc.setFileName(file.getAbsolutePath());// fc.getSelectedFile().toString(); if (doc.getFileName().lastIndexOf(fileSep) > 0) { g_sDir = doc.getFileName().substring(0, doc.getFileName().lastIndexOf(fileSep)); } if (!doc.getFileName().toLowerCase().endsWith(FILE_EXT) && !doc.getFileName().toLowerCase().endsWith(FILE_EXT2)) doc.setFileName(doc.getFileName().concat(FILE_EXT)); saveFile(doc.getFileName()); setTitle(); return true; } return false; } // saveAs public void saveFile(String fileName) { try { if (currentTab != null) { currentTab.config.sync(currentTab.partitionIndex); } else { panels[0].config.sync(0); } doc.save(fileName); } catch (Exception e) { e.printStackTrace(); } } // saveFile class ActionNew extends MyAction { private static final long serialVersionUID = 1; public ActionNew() { super("New", "Start new analysis", "new", KeyEvent.VK_N); } // c'tor @Override public void actionPerformed(ActionEvent ae) { main2(new String[0]); // doc.newAnalysis(); // a_save.setEnabled(false); // a_saveas.setEnabled(false); // setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } } class ActionLoad extends MyAction { private static final long serialVersionUID = 1; public ActionLoad() { super("Load", "Load Beast File", "open", KeyEvent.VK_O); } public ActionLoad(String name, String toolTipText, String icon, int acceleratorKey) { super(name, toolTipText, icon, acceleratorKey); } @Override public void actionPerformed(ActionEvent ae) { File file = beast.app.util.Utils.getLoadFile("Load Beast XML File", new File(g_sDir), "Beast XML files", "xml");//, "BEAST json file", "json"); // JFileChooser fileChooser = new JFileChooser(g_sDir); // fileChooser.addChoosableFileFilter(ef1); // fileChooser.setDialogTitle("Load Beast XML File"); // if (fileChooser.showOpenDialog(null) == // JFileChooser.APPROVE_OPTION) { // fileName = fileChooser.getSelectedFile().toString(); if (file != null) { setCursor(new Cursor(Cursor.WAIT_CURSOR)); doc.newAnalysis(); doc.setFileName(file.getAbsolutePath()); String fileSep = System.getProperty("file.separator"); if (fileSep.equals("\\")) { fileSep = "\\\\"; } if (doc.getFileName().lastIndexOf(fileSep) > 0) { g_sDir = doc.getFileName().substring(0, doc.getFileName().lastIndexOf(fileSep)); } try { // TODO: deal with json files doc.loadXML(new File(doc.getFileName())); a_save.setEnabled(true); a_saveas.setEnabled(true); setTitle(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog( null, "Something went wrong loading the file: " + e.getMessage()); } } setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } // actionPerformed } class ActionTemplate extends MyAction { private static final long serialVersionUID = 1; public ActionTemplate() { super("Other Template", "Load Beast Analysis Template From File", "template", -1); } // c'tor @Override public void actionPerformed(ActionEvent ae) { setCursor(new Cursor(Cursor.WAIT_CURSOR)); File file = beast.app.util.Utils .getLoadFile("Load Template XML File"); // JFileChooser fileChooser = new // JFileChooser(System.getProperty("user.dir")+"/templates"); // fileChooser.addChoosableFileFilter(ef1); // fileChooser.setDialogTitle("Load Template XML File"); // if (fileChooser.showOpenDialog(null) == // JFileChooser.APPROVE_OPTION) { // String fileName = fileChooser.getSelectedFile().toString(); if (file != null) { String fileName = file.getAbsolutePath(); try { doc.loadNewTemplate(fileName); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog( null, "Something went wrong loading the template: " + e.getMessage()); } } createFileMenu(); setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } // actionPerformed } // ActionTemplate class ActionAddOn extends MyAction { private static final long serialVersionUID = 1; public ActionAddOn() { super("Manage Packages", "Manage Packages", "package", -1); } // c'tor @Override public void actionPerformed(ActionEvent ae) { JPackageDialog panel = new JPackageDialog(); JDialog dlg = panel.asDialog(frame); dlg.setVisible(true); // refresh template menu item templateMenu.removeAll(); List<AbstractAction> templateActions = getTemplateActions(); for (AbstractAction a : templateActions) { templateMenu.add(a); } templateMenu.addSeparator(); templateMenu.add(a_template); setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } // actionPerformed } class ActionAppLauncher extends MyAction { private static final long serialVersionUID = 1; public ActionAppLauncher() { super("Launch Apps", "Launch BEAST Apps supplied by packages", "launch", -1); } // c'tor @Override public void actionPerformed(ActionEvent ae) { AppStore.main(new String[]{}); } // actionPerformed } // class ActionImport extends MyAction { // private static final long serialVersionUID = 1; // // public ActionImport() { // super("Import Alignment", "Import Alignment File", "import", // KeyEvent.VK_I); // } // // public ActionImport(String name, String toolTipText, String icon, // int acceleratorKey) { // super(name, toolTipText, icon, acceleratorKey); // } // // public void actionPerformed(ActionEvent ae) { // // try { // setCursor(new Cursor(Cursor.WAIT_CURSOR)); // // // get user-specified alignments // doc.beautiConfig.selectAlignments(doc,Beauti.this); // // doc.connectModel(); // doc.fireDocHasChanged(); // a_save.setEnabled(true); // a_saveas.setEnabled(true); // } catch (Exception e) { // e.printStackTrace(); // // String text = "Something went wrong importing the alignment:\n"; // JTextArea textArea = new JTextArea(text); // textArea.setColumns(30); // textArea.setLineWrap(true); // textArea.setWrapStyleWord(true); // textArea.append(e.getMessage()); // textArea.setSize(textArea.getPreferredSize().width, 1); // textArea.setOpaque(false); // JOptionPane.showMessageDialog(null, textArea, // "Error importing alignment", // JOptionPane.WARNING_MESSAGE); // } // setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); // // } // } // actionPerformed // } class ActionClose extends ActionSave { /** * for serialisation */ private static final long serialVersionUID = -2038911085935515L; public ActionClose() { super("Close", "Close Window", "close", KeyEvent.VK_W); } // c'tor @Override public void actionPerformed(ActionEvent ae) { // if (!m_doc.m_bIsSaved) { if (!quit()) { return; } JMenuItem menuItem = (JMenuItem) ae.getSource(); JPopupMenu popupMenu = (JPopupMenu) menuItem.getParent(); Component invoker = popupMenu.getInvoker(); JComponent invokerAsJComponent = (JComponent) invoker; Container topLevel = invokerAsJComponent.getTopLevelAncestor(); if (topLevel != null) { ((JFrame) topLevel).dispose(); } } } // class ActionClose class ActionQuit extends ActionSave { /** * for serialisation */ private static final long serialVersionUID = -2038911085935515L; public ActionQuit() { super("Exit", "Exit Program", "exit", KeyEvent.VK_F4); putValue(Action.MNEMONIC_KEY, new Integer('x')); } // c'tor @Override public void actionPerformed(ActionEvent ae) { // if (!m_doc.m_bIsSaved) { if (!quit()) { return; } System.exit(0); } } // class ActionQuit boolean quit() { if (doc.validateModel() == DOC_STATUS.DIRTY) { int result = JOptionPane.showConfirmDialog(null, "Do you want to save the Beast specification?", "Save before closing?", JOptionPane.YES_NO_CANCEL_OPTION); Log.err.println("result=" + result); if (result == JOptionPane.CANCEL_OPTION) { return false; } if (result == JOptionPane.YES_OPTION) { if (!saveAs()) { return false; } } } return true; } ViewPanelCheckBoxMenuItem[] m_viewPanelCheckBoxMenuItems; class ViewPanelCheckBoxMenuItem extends JCheckBoxMenuItem { private static final long serialVersionUID = 1L; int m_iPanel; ViewPanelCheckBoxMenuItem(int panelIndex) { super("Show " + doc.beautiConfig.panels.get(panelIndex).nameInput.get() + " panel", doc.beautiConfig.panels.get(panelIndex).isVisibleInput.get()); m_iPanel = panelIndex; if (m_viewPanelCheckBoxMenuItems == null) { m_viewPanelCheckBoxMenuItems = new ViewPanelCheckBoxMenuItem[doc.beautiConfig.panels .size()]; } m_viewPanelCheckBoxMenuItems[panelIndex] = this; } // c'tor void doAction() { toggleVisible(m_iPanel); } } ; /** * makes all panels visible * */ class ActionViewAllPanels extends MyAction { private static final long serialVersionUID = -1; public ActionViewAllPanels() { super("View all", "View all panels", "viewall", -1); } // c'tor @Override public void actionPerformed(ActionEvent ae) { for (int panelNr = 0; panelNr < isPaneIsVisible.length; panelNr++) { if (!isPaneIsVisible[panelNr]) { toggleVisible(panelNr); m_viewPanelCheckBoxMenuItems[panelNr].setState(true); } } } // actionPerformed } // class ActionViewAllPanels class ActionAbout extends MyAction { private static final long serialVersionUID = -1; public ActionAbout() { super("About", "Help about", "about", -1); } // c'tor @Override public void actionPerformed(ActionEvent ae) { BEASTVersion2 version = new BEASTVersion2(); JOptionPane.showMessageDialog(null, version.getCredits(), "About Beauti " + version.getVersionString(), JOptionPane.PLAIN_MESSAGE, Utils.getIcon(BEAUTI_ICON)); } } // class ActionAbout class ActionHelp extends MyAction { private static final long serialVersionUID = -1; public ActionHelp() { super("Help", "Help on current panel", "help", -1); } // c'tor @Override public void actionPerformed(ActionEvent ae) { setCursor(new Cursor(Cursor.WAIT_CURSOR)); HelpBrowser b = new HelpBrowser(currentTab.config.getType()); int size = UIManager.getFont("Label.font").getSize(); b.setSize(800 * size / 13, 800 * size / 13); b.setVisible(true); b.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } } // class ActionHelp class ActionMsgs extends MyAction { private static final long serialVersionUID = -1; public ActionMsgs() { super("Messages", "Show information, warning and error messages", "msgs", -1); } // c'tor @Override public void actionPerformed(ActionEvent ae) { if (BeautiDoc.baos == null) { JOptionPane.showMessageDialog(frame, "<html>Error and warning messages are printed to Stdout and Stderr<br>" + "To show them here, start BEAUti with the -capture argument.</html>"); } else { String msgs = BeautiDoc.baos.toString(); JTextArea textArea = new JTextArea(msgs); textArea.setRows(40); textArea.setColumns(50); textArea.setEditable(true); JScrollPane scroller = new JScrollPane(textArea); JOptionPane.showMessageDialog(frame, scroller); } } } class ActionCitation extends MyAction implements ClipboardOwner { private static final long serialVersionUID = -1; public ActionCitation() { super("Citation", "Show appropriate citations and copy to clipboard", "citation", -1); } // c'tor @Override public void actionPerformed(ActionEvent ae) { String citations = doc.mcmc.get().getCitations(); try { StringSelection stringSelection = new StringSelection( citations); Clipboard clipboard = Toolkit.getDefaultToolkit() .getSystemClipboard(); clipboard.setContents(stringSelection, this); } catch (Exception e) { e.printStackTrace(); } JOptionPane.showMessageDialog(null, citations + "\nCitations copied to clipboard", "Citation(s) applicable to this model:", JOptionPane.INFORMATION_MESSAGE); } // getCitations @Override public void lostOwnership(Clipboard clipboard, Transferable contents) { // do nothing } } // class ActionAbout class ActionViewModel extends MyAction { private static final long serialVersionUID = -1; public ActionViewModel() { super("View model", "View model graph", "model", -1); } // c'tor @Override public void actionPerformed(ActionEvent ae) { JFrame frame = new JFrame("Model Builder"); ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.init(); frame.add(modelBuilder, BorderLayout.CENTER); frame.add(modelBuilder.m_jTbTools2, BorderLayout.NORTH); modelBuilder.setEditable(false); modelBuilder.m_doc.init(doc.mcmc.get()); modelBuilder.setDrawingFlag(); frame.setSize(600, 800); frame.setVisible(true); } } // class ActionViewModel public void refreshPanel() { try { BeautiPanel panel = (BeautiPanel) getSelectedComponent(); if (panel != null) { this.doc.determinePartitions(); panel.updateList(); panel.refreshPanel(); } requestFocus(); } catch (Exception ex) { ex.printStackTrace(); } } public JMenuBar makeMenuBar() { JMenuBar menuBar = new JMenuBar(); fileMenu = new JMenu("File"); fileMenu.setMnemonic('F'); menuBar.add(fileMenu); createFileMenu(); JMenu modeMenu = new JMenu("Mode"); menuBar.add(modeMenu); modeMenu.setMnemonic('M'); autoSetClockRate = new JCheckBoxMenuItem( "Automatic set clock rate", this.doc.autoSetClockRate); autoSetClockRate.addActionListener(ae -> { doc.autoSetClockRate = autoSetClockRate.getState(); refreshPanel(); }); modeMenu.add(autoSetClockRate); allowLinking = new JCheckBoxMenuItem( "Allow parameter linking", this.doc.allowLinking); allowLinking.addActionListener(ae -> { doc.allowLinking = allowLinking.getState(); doc.determineLinks(); refreshPanel(); }); modeMenu.add(allowLinking); autoUpdateFixMeanSubstRate = new JCheckBoxMenuItem( "Automatic set fix mean substitution rate flag", this.doc.autoUpdateFixMeanSubstRate); autoUpdateFixMeanSubstRate.addActionListener(ae -> { doc.autoUpdateFixMeanSubstRate = autoUpdateFixMeanSubstRate.getState(); refreshPanel(); }); modeMenu.add(autoUpdateFixMeanSubstRate); // final JCheckBoxMenuItem muteSound = new // JCheckBoxMenuItem("Mute sound", false); // muteSound.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent ae) { // BeautiPanel.soundIsPlaying = !muteSound.getState(); // refreshPanel(); // } // }); // modeMenu.add(muteSound); viewMenu = new JMenu("View"); menuBar.add(viewMenu); viewMenu.setMnemonic('V'); setUpViewMenu(); JMenu helpMenu = new JMenu("Help"); menuBar.add(helpMenu); helpMenu.setMnemonic('H'); helpMenu.add(a_help); helpMenu.add(a_msgs); helpMenu.add(a_citation); helpMenu.add(a_viewModel); if (!Utils.isMac()) { helpMenu.add(a_about); } setMenuVisibiliy("", menuBar); return menuBar; } // makeMenuBar private void createFileMenu() { // first clear menu fileMenu.removeAll(); fileMenu.add(a_new); fileMenu.add(a_load); fileMenu.addSeparator(); addAlignmentProviderMenus(fileMenu); fileMenu.addSeparator(); templateMenu = new JMenu("Template"); fileMenu.add(templateMenu); List<AbstractAction> templateActions = getTemplateActions(); for (AbstractAction a : templateActions) { templateMenu.add(a); } JMenu workDirMenu = new JMenu("Set working dir"); fileMenu.add(workDirMenu); List<AbstractAction> workDirMenuActions = getWorkDirActions(); for (AbstractAction a : workDirMenuActions) { workDirMenu.add(a); } templateMenu.addSeparator(); templateMenu.add(a_template); fileMenu.add(a_addOn); fileMenu.add(a_appLauncher); fileMenu.addSeparator(); fileMenu.add(a_save); fileMenu.add(a_saveas); if (!Utils.isMac()) { fileMenu.addSeparator(); fileMenu.add(a_close); fileMenu.add(a_quit); } } private void addAlignmentProviderMenus(JMenu fileMenu) { List<BeautiAlignmentProvider> providers = doc.beautiConfig.alignmentProvider; for (BeautiAlignmentProvider provider : providers) { AbstractAction action = new AbstractAction() { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { try { setCursor(new Cursor(Cursor.WAIT_CURSOR)); // get user-specified alignments List<BEASTInterface> beastObjects = provider.getAlignments(doc); if (beastObjects != null) { for (BEASTInterface o : beastObjects) { if (o instanceof Alignment) { try { BeautiDoc.createTaxonSet((Alignment) o, doc); } catch(Exception ex) { ex.printStackTrace(); } } } } doc.connectModel(); doc.fireDocHasChanged(); if (beastObjects != null) { for (BEASTInterface o : beastObjects) { if (o instanceof MRCAPrior) { doc.addMRCAPrior((MRCAPrior) o); } } } a_save.setEnabled(true); a_saveas.setEnabled(true); } catch (Exception exx) { exx.printStackTrace(); String text = "Something went wrong importing the alignment:\n"; JTextArea textArea = new JTextArea(text); textArea.setColumns(30); textArea.setLineWrap(true); textArea.setWrapStyleWord(true); textArea.append(exx.getMessage()); textArea.setSize(textArea.getPreferredSize().width, 1); textArea.setOpaque(false); JOptionPane.showMessageDialog(null, textArea, "Error importing alignment", JOptionPane.WARNING_MESSAGE); } setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } }; String providerInfo = provider.toString().replaceAll("Add ", "Add partition for "); action.putValue(Action.SHORT_DESCRIPTION, providerInfo); action.putValue(Action.LONG_DESCRIPTION, providerInfo); action.putValue(Action.NAME, provider.toString()); fileMenu.add(action); } } void setUpViewMenu() { m_viewPanelCheckBoxMenuItems = null; viewMenu.removeAll(); for (int panelIndex = 0; panelIndex < doc.beautiConfig.panels.size(); panelIndex++) { final ViewPanelCheckBoxMenuItem viewPanelAction = new ViewPanelCheckBoxMenuItem( panelIndex); viewPanelAction.addActionListener(ae -> { viewPanelAction.doAction(); }); viewMenu.add(viewPanelAction); } viewMenu.addSeparator(); viewMenu.add(a_viewall); viewMenu.addSeparator(); MyAction zoomIn = new MyAction("Zoom in", "Increase font size of all components", null, KeyEvent.VK_EQUALS) { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent ae) { int size = UIManager.getFont("Label.font").getSize(); Utils.setFontSize(size + 1); Utils.saveBeautiProperty("fontsize", (size + 1) + ""); refreshPanel(); repaint(); } }; MyAction zoomOut = new MyAction("Zoom out", "Decrease font size of all components", null, KeyEvent.VK_MINUS) { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent ae) { int size = UIManager.getFont("Label.font").getSize(); Utils.setFontSize(Math.max(size - 1, 4)); Utils.saveBeautiProperty("fontsize", Math.max(size - 1, 4) + ""); refreshPanel(); repaint(); } }; viewMenu.add(zoomIn); viewMenu.add(zoomOut); } class TemplateAction extends AbstractAction { private static final long serialVersionUID = 1L; String m_sFileName; String templateInfo; public TemplateAction(File file) { super("xx"); m_sFileName = file.getAbsolutePath(); String fileSep = System.getProperty("file.separator"); if (fileSep.equals("\\")) { fileSep = "\\"; } int i = m_sFileName.lastIndexOf(fileSep) + 1; String name = m_sFileName.substring( i, m_sFileName.length() - 4); putValue(Action.NAME, name); try { DocumentBuilderFactory factory = DocumentBuilderFactory .newInstance(); Document doc = factory.newDocumentBuilder().parse(file); doc.normalize(); // get name and version of add-on Element template = doc.getDocumentElement(); templateInfo = template.getAttribute("templateinfo"); if (templateInfo == null || templateInfo.length() == 0) { templateInfo = "switch to " + name + " template"; } //templateInfo = "<html>" + templateInfo + "</html>"; putValue(Action.SHORT_DESCRIPTION, templateInfo); putValue(Action.LONG_DESCRIPTION, templateInfo); } catch (Exception e) { // ignore } } @Override public void actionPerformed(ActionEvent e) { try { if (doc.validateModel() == DOC_STATUS.NO_DOCUMENT) { doc.loadNewTemplate(m_sFileName); } else if (JOptionPane.showConfirmDialog(frame, "Changing templates means the information input so far will be lost. " + "Are you sure you want to change templates?", "Are you sure?", JOptionPane.YES_NO_CANCEL_OPTION) == JOptionPane.YES_OPTION) { doc.loadNewTemplate(m_sFileName); } createFileMenu(); } catch (Exception ex) { ex.printStackTrace(); JOptionPane.showMessageDialog( null, "Something went wrong loading the template: " + ex.getMessage()); } } } private List<AbstractAction> getTemplateActions() { List<AbstractAction> actions = new ArrayList<>(); List<String> beastDirectories = AddOnManager.getBeastDirectories(); for (String dirName : beastDirectories) { File dir = new File(dirName + "/templates"); getTemplateActionForDir(dir, actions); } return actions; } private void getTemplateActionForDir(File dir, List<AbstractAction> actions) { if (dir.exists() && dir.isDirectory()) { File[] files = dir.listFiles(); if (files != null) { for (File template : files) { if (template.getName().toLowerCase().endsWith(".xml")) { try { String xml2 = BeautiDoc.load(template.getAbsolutePath()); if (xml2.contains("templateinfo=")) { String fileName = template.getName(); fileName = fileName.substring(0, fileName.length() - 4); boolean duplicate = false; for (AbstractAction action : actions) { String name = action.getValue(Action.NAME).toString(); if (name.equals(fileName)) { duplicate = true; } } if (!duplicate) { actions.add(new TemplateAction(template)); } } } catch (Exception e) { Log.warning.println(e.getMessage()); } } } } } } private List<AbstractAction> getWorkDirActions() { List<AbstractAction> actions = new ArrayList<>(); List<String> beastDirectories = AddOnManager.getBeastDirectories(); Set<String> doneDirs = new HashSet<>(); for (String dir : beastDirectories) { if (!doneDirs.contains(dir)) { doneDirs.add(dir); String exampledir = dir + File.separator+ "examples"; if (new File(exampledir).exists()) { AbstractAction action = new AbstractAction() { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { g_sDir = dir; } }; String workDirInfo = "Set working directory to " + dir; String name = dir; if (name.indexOf(File.separator) >= 0) { name = dir.substring(dir.lastIndexOf(File.separator) + 1); } action.putValue(Action.SHORT_DESCRIPTION, workDirInfo); action.putValue(Action.LONG_DESCRIPTION, workDirInfo); action.putValue(Action.NAME, name); actions.add(action); } } } return actions; } void setMenuVisibiliy(String parentName, Component c) { String name = ""; if (c instanceof JMenu) { name = ((JMenu) c).getText(); } else if (c instanceof JMenuItem) { name = ((JMenuItem) c).getText(); } if (name.length() > 0 && doc.beautiConfig.menuIsInvisible(parentName + name)) { c.setVisible(false); } if (c instanceof JMenu) { for (Component x : ((JMenu) c).getMenuComponents()) { setMenuVisibiliy(parentName + name + (name.length() > 0 ? "." : ""), x); } } else if (c instanceof Container) { for (int i = 0; i < ((Container) c).getComponentCount(); i++) { setMenuVisibiliy(parentName, ((Container) c).getComponent(i)); } } } // hide panels as indicated in the hidepanels attribute in the XML template, // or use default tabs to hide otherwise. public void hidePanels() { // for (int panelIndex = 0; panelIndex < BeautiConfig.g_panels.size(); panelIndex++) // { // BeautiPanelConfig panelConfig = BeautiConfig.g_panels.get(panelIndex); // if (!panelConfig.m_bIsVisibleInput.get()) { // toggleVisible(panelIndex); // } // } } // hidePanels public void setUpPanels() throws NoSuchMethodException, SecurityException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { isInitialising = true; // remove any existing tabs if (getTabCount() > 0) { while (getTabCount() > 0) { removeTabAt(0); } isPaneIsVisible = new boolean[doc.beautiConfig.panels.size()]; Arrays.fill(isPaneIsVisible, true); } for (int panelIndex = 0; panelIndex < doc.beautiConfig.panels.size(); panelIndex++) { BeautiPanelConfig panelConfig = doc.beautiConfig.panels.get(panelIndex); isPaneIsVisible[panelIndex] = panelConfig.isVisibleInput.get(); } // add panels according to BeautiConfig panels = new BeautiPanel[doc.beautiConfig.panels.size()]; for (int panelIndex = 0; panelIndex < doc.beautiConfig.panels.size(); panelIndex++) { BeautiPanelConfig panelConfig = doc.beautiConfig.panels.get(panelIndex); panels[panelIndex] = new BeautiPanel(panelIndex, this.doc, panelConfig); addTab(doc.beautiConfig.getButtonLabel(this, panelConfig.getName()), null, panels[panelIndex], panelConfig.getTipText()); } for (int panelIndex = doc.beautiConfig.panels.size() - 1; panelIndex >= 0; panelIndex--) { if (!isPaneIsVisible[panelIndex]) { removeTabAt(panelIndex); } } isInitialising = false; } /** * record number of frames. If the last frame is closed, exit the app. * */ static int BEAUtiIntances = 0; static public boolean isInBeauti() { return BEAUtiIntances > 0; } private static String usage() { return "java Beauti [options]\n" + "where options can be one of the following:\n" + "-template [template file] : BEAUti template to be used. Default templates/Standard.xml\n" + "-nex [nexus data file] : nexus file to be read using template, multiple -nex arguments are allowed\n" + "-xmldat [beast xml file] : as -nex but with BEAST 1 or 2 xml file instead of nexus file\n" + "-xml [beast file] : BEAST 2 XML file to be loaded\n" + "-exitaction [writexml|usetemplate|usexml] : what to do after processing arguments\n" + "-out [output file name] : file to be written\n" + "-capture : captures stdout and stderr and make them available under Help/Messages menu\n" + "-v, -version : print version\n" + "-h, -help : print this help message\n"; } public static Beauti main2(String[] args) { try { ByteArrayOutputStream baos = null; for (String arg : args) { if (arg.equals("-v") || arg.equals("-version")) { System.out.println((new BEASTVersion2()).getVersionString()); System.exit(0); } if (arg.equals("-h") || arg.equals("-help")) { System.out.println(usage()); System.exit(0); } if (arg.equals("-capture")) { final PrintStream beautiLog = System.err; baos = new ByteArrayOutputStream() { @Override public synchronized void write(byte[] b, int off, int len) { super.write(b, off, len); beautiLog.write(b, off, len); }; @Override public synchronized void write(int b) { super.write(b); beautiLog.write(b); }; @Override public void write(byte[] b) throws java.io.IOException { super.write(b); beautiLog.write(b); }; @Override public void flush() throws java.io.IOException { super.flush(); beautiLog.flush(); }; @Override public void close() throws IOException { super.close(); beautiLog.close(); } }; PrintStream p = new PrintStream(baos); System.setOut(p); System.setErr(p); Log.err = p; Log.warning = p; Log.info = p; Log.debug = p; Log.trace = p; } } AddOnManager.loadExternalJars(); //if (!Utils.isMac()) { Utils.loadUIManager(); //} BEASTObjectPanel.init(); BeautiDoc doc = new BeautiDoc(); BeautiDoc.baos = baos; if (doc.parseArgs(args) == ActionOnExit.WRITE_XML) { return null; } final Beauti beauti = new Beauti(doc); if (Utils.isMac()) { // set up application about-menu for Mac // Mac-only stuff try { URL url = ClassLoader.getSystemResource(ModelBuilder.ICONPATH + "beauti.png"); Icon icon = null; if (url != null) { icon = new ImageIcon(url); } else { Log.warning.println("Unable to find image: " + ModelBuilder.ICONPATH + "beauti.png"); } jam.framework.Application application = new jam.framework.MultiDocApplication(null, "BEAUti", "about", icon) { @Override protected JFrame getDefaultFrame() { return null; } @Override public void doQuit() { beauti.a_quit.actionPerformed(null); } @Override public void doAbout() { beauti.a_about.actionPerformed(null); } @Override public DocumentFrame doOpenFile(File file) { return null; } @Override public DocumentFrame doNew() { return null; } }; jam.mac.Utils.macOSXRegistration(application); } catch (Exception e) { // ignore } try { Class<?> class_ = Class.forName("jam.maconly.OSXAdapter"); Method method = class_.getMethod("enablePrefs", boolean.class); method.invoke(null, false); } catch (java.lang.NoSuchMethodException e) { // ignore } } beauti.setUpPanels(); beauti.currentTab = beauti.panels[0]; beauti.hidePanels(); beauti.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { if (beauti.currentTab == null) { beauti.currentTab = beauti.panels[0]; } if (beauti.currentTab != null) { if (!beauti.isInitialising) { beauti.currentTab.config .sync(beauti.currentTab.partitionIndex); } BeautiPanel panel = (BeautiPanel) beauti .getSelectedComponent(); beauti.currentTab = panel; beauti.refreshPanel(); } } }); beauti.setVisible(true); beauti.refreshPanel(); JFrame frame = new JFrame("BEAUti 2: " + doc.getTemplateName() + " " + doc.getFileName()); beauti.frame = frame; ImageIcon icon = Utils.getIcon(BEAUTI_ICON); if (icon != null) { frame.setIconImage(icon.getImage()); } JMenuBar menuBar = beauti.makeMenuBar(); frame.setJMenuBar(menuBar); if (doc.getFileName() != null || doc.alignments.size() > 0) { beauti.a_save.setEnabled(true); beauti.a_saveas.setEnabled(true); } frame.add(beauti); int size = UIManager.getFont("Label.font").getSize(); frame.setSize(1024 * size / 13, 768 * size / 13); frame.setLocation(BEAUtiIntances * 10, BEAUtiIntances * 10); frame.setVisible(true); // check file needs to be save on closing main frame frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); BEAUtiIntances++; frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { if (!beauti.quit()) { return; } JFrame frame = (JFrame) e.getSource(); frame.dispose(); BEAUtiIntances--; if (BEAUtiIntances == 0) { System.exit(0); } } }); // Toolkit toolkit = Toolkit.getDefaultToolkit(); // // PropertyChangeListener plistener = new // PropertyChangeListener() { // // @Override // // public void propertyChange(PropertyChangeEvent event) { // // Object o = event.getSource(); // // Object o2 = event.getNewValue(); // // event.getPropertyName(); // // System.err.println(">>> " + event.getPropertyName() + " " + // o.getClass().getName() + "\n" + o2.getClass().getName()); // // } // // }; // AWTEventListener listener = new AWTEventListener() { // @Override // public void eventDispatched(AWTEvent event) { // Object o = event.getSource(); // String label = ""; // try { // Method method = o.getClass().getMethod("getText", Object.class); // label = (String) method.invoke(o); // } catch (Exception e) { // // TODO: handle exception // } // if (event.paramString().matches(".*\\([0-9]*,[0-9]*\\).*")) { // String s = event.paramString(); // String sx = s.substring(s.indexOf('(') + 1); // String sy = sx; // sx = sx.substring(0, sx.indexOf(',')); // sy = sy.substring(sy.indexOf(',') + 1, sy.indexOf(')')); // int x = Integer.parseInt(sx); // int y = Integer.parseInt(sy); // Component c = beauti.findComponentAt(x, y); // if (c != null) { // System.err.println(c.getClass().getName()); // } // } // // System.err.println(label + " " + event.paramString() + " " + // o.getClass().getName()); // // } // }; // toolkit.addAWTEventListener(listener, // AWTEvent.ACTION_EVENT_MASK|AWTEvent.ITEM_EVENT_MASK|AWTEvent.MOUSE_EVENT_MASK); // // beauti.addPropertyChangeListener(plistener); return beauti; } catch (Exception e) { e.printStackTrace(); } return null; } // main2 public static void main(String[] args) { main2(args); } } // class Beauti