2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.awt.Color;
24 import java.io.BufferedReader;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.io.OutputStreamWriter;
30 import java.io.PrintWriter;
31 import java.net.MalformedURLException;
33 import java.net.URISyntaxException;
35 import java.security.AllPermission;
36 import java.security.CodeSource;
37 import java.security.PermissionCollection;
38 import java.security.Permissions;
39 import java.security.Policy;
40 import java.util.HashMap;
41 import java.util.Locale;
43 import java.util.Vector;
44 import java.util.logging.ConsoleHandler;
45 import java.util.logging.Level;
46 import java.util.logging.Logger;
48 import javax.swing.JOptionPane;
49 import javax.swing.SwingUtilities;
50 import javax.swing.UIManager;
51 import javax.swing.UIManager.LookAndFeelInfo;
53 import com.formdev.flatlaf.FlatLightLaf;
54 import com.formdev.flatlaf.util.SystemInfo;
55 import com.threerings.getdown.util.LaunchUtil;
57 //import edu.stanford.ejalbert.launching.IBrowserLaunching;
58 import groovy.lang.Binding;
59 import groovy.util.GroovyScriptEngine;
60 import jalview.bin.ArgParser.Arg;
61 import jalview.ext.so.SequenceOntology;
62 import jalview.gui.AlignFrame;
63 import jalview.gui.Desktop;
64 import jalview.gui.PromptUserConfig;
65 import jalview.io.AppletFormatAdapter;
66 import jalview.io.BioJsHTMLOutput;
67 import jalview.io.DataSourceType;
68 import jalview.io.FileFormat;
69 import jalview.io.FileFormatException;
70 import jalview.io.FileFormatI;
71 import jalview.io.FileFormats;
72 import jalview.io.FileLoader;
73 import jalview.io.HtmlSvgOutput;
74 import jalview.io.IdentifyFile;
75 import jalview.io.NewickFile;
76 import jalview.io.gff.SequenceOntologyFactory;
77 import jalview.schemes.ColourSchemeI;
78 import jalview.schemes.ColourSchemeProperty;
79 import jalview.util.ChannelProperties;
80 import jalview.util.HttpUtils;
81 import jalview.util.LaunchUtils;
82 import jalview.util.MessageManager;
83 import jalview.util.Platform;
84 import jalview.ws.jws2.Jws2Discoverer;
87 * Main class for Jalview Application <br>
89 * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
92 * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
93 * jalview.bin.Jalview jalview.bin.Jalview
95 * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
96 * embellish '*' to e.g. '*.jar')
105 Platform.getURLCommandArguments();
106 Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
107 Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
108 Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
109 Platform.addJ2SDirectDatabaseCall("https://www.compbio.dundee.ac.uk");
113 * singleton instance of this class
115 private static Jalview instance;
117 private Desktop desktop;
119 public static AlignFrame currentAlignFrame;
123 if (!Platform.isJS())
130 // grab all the rights we can for the JVM
131 Policy.setPolicy(new Policy()
134 public PermissionCollection getPermissions(CodeSource codesource)
136 Permissions perms = new Permissions();
137 perms.add(new AllPermission());
142 public void refresh()
150 * keep track of feature fetching tasks.
158 * TODO: generalise to track all jalview events to orchestrate batch processing
162 private int queued = 0;
164 private int running = 0;
166 public FeatureFetcher()
171 public void addFetcher(final AlignFrame af,
172 final Vector<String> dasSources)
174 final long id = System.currentTimeMillis();
176 final FeatureFetcher us = this;
177 new Thread(new Runnable()
189 af.setProgressBar(MessageManager
190 .getString("status.das_features_being_retrived"), id);
191 af.featureSettings_actionPerformed(null);
192 af.setProgressBar(null, id);
201 public synchronized boolean allFinished()
203 return queued == 0 && running == 0;
208 public static Jalview getInstance()
214 * main class for Jalview application
217 * open <em>filename</em>
219 public static void main(String[] args)
221 // setLogging(); // BH - for event debugging in JavaScript
222 instance = new Jalview();
223 instance.doMain(args);
226 private static void logClass(String name)
228 // BH - for event debugging in JavaScript
229 ConsoleHandler consoleHandler = new ConsoleHandler();
230 consoleHandler.setLevel(Level.ALL);
231 Logger logger = Logger.getLogger(name);
232 logger.setLevel(Level.ALL);
233 logger.addHandler(consoleHandler);
236 @SuppressWarnings("unused")
237 private static void setLogging()
245 System.out.println("not in js");
248 // BH - for event debugging in JavaScript (Java mode only)
249 if (!Platform.isJS())
256 Logger.getLogger("").setLevel(Level.ALL);
257 logClass("java.awt.EventDispatchThread");
258 logClass("java.awt.EventQueue");
259 logClass("java.awt.Component");
260 logClass("java.awt.focus.Component");
261 logClass("java.awt.focus.DefaultKeyboardFocusManager");
269 void doMain(String[] args)
272 if (!Platform.isJS())
274 System.setSecurityManager(null);
278 .println("Java version: " + System.getProperty("java.version"));
279 System.out.println("Java Home: " + System.getProperty("java.home"));
280 System.out.println(System.getProperty("os.arch") + " "
281 + System.getProperty("os.name") + " "
282 + System.getProperty("os.version"));
283 String val = System.getProperty("sys.install4jVersion");
286 System.out.println("Install4j version: " + val);
288 val = System.getProperty("installer_template_version");
291 System.out.println("Install4j template version: " + val);
293 val = System.getProperty("launcher_version");
296 System.out.println("Launcher version: " + val);
299 // report Jalview version
300 Cache.loadBuildProperties(true);
303 ArgsParser aparser = new ArgsParser(args);
305 ArgParser argparser = new ArgParser(args);
306 boolean headless = false;
308 String usrPropsFile = aparser.getValue("props");
309 Cache.loadProperties(usrPropsFile); // must do this before
310 if (usrPropsFile != null)
313 "CMD [-props " + usrPropsFile + "] executed successfully!");
316 if (!Platform.isJS())
323 if (argparser.isSet(Arg.HEADLESS))
325 headless = argparser.getBool(Arg.HEADLESS);
328 if (aparser.contains("help") || aparser.contains("h"))
333 if (headless || aparser.contains("nodisplay")
334 || aparser.contains("nogui") || aparser.contains("headless"))
336 System.setProperty("java.awt.headless", "true");
341 // allow https handshakes to download intermediate certs if necessary
342 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
344 final String jabawsUrl = aparser.getValue("jabaws");
345 if (jabawsUrl != null)
349 Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
351 "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
352 } catch (MalformedURLException e)
355 "Invalid jabaws parameter: " + jabawsUrl + " ignored");
360 String defs = aparser.getValue("setprop");
363 int p = defs.indexOf('=');
366 System.err.println("Ignoring invalid setprop argument : " + defs);
370 System.out.println("Executing setprop argument: " + defs);
373 Cache.setProperty(defs.substring(0, p), defs.substring(p + 1));
375 // DISABLED FOR SECURITY REASONS
376 // TODO: add a property to allow properties to be overriden by cli args
377 // Cache.setProperty(defs.substring(0,p), defs.substring(p+1));
379 defs = aparser.getValue("setprop");
381 if (System.getProperty("java.awt.headless") != null
382 && System.getProperty("java.awt.headless").equals("true"))
386 System.setProperty("http.agent",
387 "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
391 Console.initLogger();
392 } catch (NoClassDefFoundError error)
394 error.printStackTrace();
395 System.out.println("\nEssential logging libraries not found."
396 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview");
405 * configure 'full' SO model if preferences say to, else use the default (full SO)
406 * - as JS currently doesn't have OBO parsing, it must use 'Lite' version
408 boolean soDefault = !Platform.isJS();
409 if (Cache.getDefault("USE_FULL_SO", soDefault))
411 SequenceOntologyFactory.setInstance(new SequenceOntology());
416 Desktop.nosplash = aparser.contains("nosplash");
417 desktop = new Desktop();
418 desktop.setInBatchMode(true); // indicate we are starting up
422 JalviewTaskbar.setTaskbar(this);
423 } catch (Exception e)
425 Console.info("Cannot set Taskbar");
426 Console.error(e.getMessage());
427 // e.printStackTrace();
428 } catch (Throwable t)
430 Console.info("Cannot set Taskbar");
431 Console.error(t.getMessage());
432 // t.printStackTrace();
435 // set Proxy settings before all the internet calls
436 Cache.setProxyPropertiesFromPreferences();
438 desktop.setVisible(true);
440 if (!Platform.isJS())
449 * Check to see that the JVM version being run is suitable for the Java
450 * version this Jalview was compiled for. Popup a warning if not.
452 if (!LaunchUtils.checkJavaVersion())
454 Console.warn("The Java version being used (Java "
455 + LaunchUtils.getJavaVersion()
456 + ") may lead to problems. This installation of Jalview should be used with Java "
457 + LaunchUtils.getJavaCompileVersion() + ".");
460 .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
463 MessageManager.getString("label.continue") };
464 JOptionPane.showOptionDialog(null,
465 MessageManager.formatMessage(
466 "warning.wrong_jvm_version_message",
467 LaunchUtils.getJavaVersion(),
468 LaunchUtils.getJavaCompileVersion()),
470 .getString("warning.wrong_jvm_version_title"),
471 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
472 null, options, options[0]);
476 if (!aparser.contains("nowebservicediscovery"))
478 desktop.startServiceDiscovery();
480 if (!aparser.contains("nousagestats"))
482 startUsageStats(desktop);
486 System.err.println("CMD [-nousagestats] executed successfully!");
489 if (!aparser.contains("noquestionnaire"))
491 String url = aparser.getValue("questionnaire");
494 // Start the desktop questionnaire prompter with the specified
496 Console.debug("Starting questionnaire url at " + url);
497 desktop.checkForQuestionnaire(url);
498 System.out.println("CMD questionnaire[-" + url
499 + "] executed successfully!");
503 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
505 // Start the desktop questionnaire prompter with the specified
508 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
510 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
512 "Starting questionnaire with default url: " + defurl);
513 desktop.checkForQuestionnaire(defurl);
520 .println("CMD [-noquestionnaire] executed successfully!");
523 if (!aparser.contains("nonews")
524 || Cache.getProperty("NONEWS") == null)
526 desktop.checkForNews();
529 if (!aparser.contains("nohtmltemplates")
530 || Cache.getProperty("NOHTMLTEMPLATES") == null)
532 BioJsHTMLOutput.updateBioJS();
537 // Check if JVM and compile version might cause problems and log if it
539 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
541 Console.warn("The Java version being used (Java "
542 + LaunchUtils.getJavaVersion()
543 + ") may lead to problems. This installation of Jalview should be used with Java "
544 + LaunchUtils.getJavaCompileVersion() + ".");
547 // Move any new getdown-launcher-new.jar into place over old
548 // getdown-launcher.jar
549 String appdirString = System.getProperty("getdownappdir");
550 if (appdirString != null && appdirString.length() > 0)
552 final File appdir = new File(appdirString);
558 LaunchUtil.upgradeGetdown(
559 new File(appdir, "getdown-launcher-old.jar"),
560 new File(appdir, "getdown-launcher.jar"),
561 new File(appdir, "getdown-launcher-new.jar"));
566 if (argparser.isSet(Arg.HEADLESS))
567 headless = argparser.getBool(Arg.HEADLESS);
568 if (Commands.processArgs(argparser, headless))
573 String file = null, data = null;
574 FileFormatI format = null;
575 DataSourceType protocol = null;
576 FileLoader fileLoader = new FileLoader(!headless);
578 String groovyscript = null; // script to execute after all loading is
579 // completed one way or another
580 // extract groovy argument and execute if necessary
581 groovyscript = aparser.getValue("groovy", true);
582 file = aparser.getValue("open", true);
584 if (file == null && desktop == null)
586 System.out.println("No files to open!");
590 // Finally, deal with the remaining input data.
595 desktop.setProgressBar(
597 .getString("status.processing_commandline_args"),
598 progress = System.currentTimeMillis());
600 System.out.println("CMD [-open " + file + "] executed successfully!");
602 if (!Platform.isJS())
604 * ignore in JavaScript -- can't just file existence - could load it?
609 if (!HttpUtils.startsWithHttpOrHttps(file))
611 if (!(new File(file)).exists())
613 System.out.println("Can't find " + file);
622 protocol = AppletFormatAdapter.checkProtocol(file);
626 format = new IdentifyFile().identify(file, protocol);
627 } catch (FileFormatException e1)
632 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
636 System.out.println("error");
640 setCurrentAlignFrame(af);
641 data = aparser.getValue("colour", true);
644 data.replaceAll("%20", " ");
646 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
647 af.getViewport(), af.getViewport().getAlignment(), data);
652 "CMD [-color " + data + "] executed successfully!");
657 // Must maintain ability to use the groups flag
658 data = aparser.getValue("groups", true);
661 af.parseFeaturesFile(data,
662 AppletFormatAdapter.checkProtocol(data));
663 // System.out.println("Added " + data);
665 "CMD groups[-" + data + "] executed successfully!");
667 data = aparser.getValue("features", true);
670 af.parseFeaturesFile(data,
671 AppletFormatAdapter.checkProtocol(data));
672 // System.out.println("Added " + data);
674 "CMD [-features " + data + "] executed successfully!");
677 data = aparser.getValue("annotations", true);
680 af.loadJalviewDataFile(data, null, null, null);
681 // System.out.println("Added " + data);
683 "CMD [-annotations " + data + "] executed successfully!");
685 // set or clear the sortbytree flag.
686 if (aparser.contains("sortbytree"))
688 af.getViewport().setSortByTree(true);
689 if (af.getViewport().getSortByTree())
691 System.out.println("CMD [-sortbytree] executed successfully!");
694 if (aparser.contains("no-annotation"))
696 af.getViewport().setShowAnnotation(false);
697 if (!af.getViewport().isShowAnnotation())
699 System.out.println("CMD no-annotation executed successfully!");
702 if (aparser.contains("nosortbytree"))
704 af.getViewport().setSortByTree(false);
705 if (!af.getViewport().getSortByTree())
708 .println("CMD [-nosortbytree] executed successfully!");
711 data = aparser.getValue("tree", true);
717 "CMD [-tree " + data + "] executed successfully!");
718 NewickFile nf = new NewickFile(data,
719 AppletFormatAdapter.checkProtocol(data));
721 .setCurrentTree(af.showNewickTree(nf, data).getTree());
722 } catch (IOException ex)
724 System.err.println("Couldn't add tree " + data);
725 ex.printStackTrace(System.err);
728 // TODO - load PDB structure(s) to alignment JAL-629
729 // (associate with identical sequence in alignment, or a specified
731 if (groovyscript != null)
733 // Execute the groovy script after we've done all the rendering stuff
734 // and before any images or figures are generated.
735 System.out.println("Executing script " + groovyscript);
736 executeGroovyScript(groovyscript, af);
737 System.out.println("CMD groovy[" + groovyscript
738 + "] executed successfully!");
741 String imageName = "unnamed.png";
742 while (aparser.getSize() > 1)
744 String outputFormat = aparser.nextValue();
745 file = aparser.nextValue();
747 if (outputFormat.equalsIgnoreCase("png"))
749 af.createPNG(new File(file));
750 imageName = (new File(file)).getName();
751 System.out.println("Creating PNG image: " + file);
754 else if (outputFormat.equalsIgnoreCase("svg"))
756 File imageFile = new File(file);
757 imageName = imageFile.getName();
758 af.createSVG(imageFile);
759 System.out.println("Creating SVG image: " + file);
762 else if (outputFormat.equalsIgnoreCase("html"))
764 File imageFile = new File(file);
765 imageName = imageFile.getName();
766 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
767 htmlSVG.exportHTML(file);
769 System.out.println("Creating HTML image: " + file);
772 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
776 System.err.println("The output html file must not be null");
781 BioJsHTMLOutput.refreshVersionInfo(
782 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
783 } catch (URISyntaxException e)
787 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
788 bjs.exportHTML(file);
790 .println("Creating BioJS MSA Viwer HTML file: " + file);
793 else if (outputFormat.equalsIgnoreCase("imgMap"))
795 af.createImageMap(new File(file), imageName);
796 System.out.println("Creating image map: " + file);
799 else if (outputFormat.equalsIgnoreCase("eps"))
801 File outputFile = new File(file);
803 "Creating EPS file: " + outputFile.getAbsolutePath());
804 af.createEPS(outputFile);
807 FileFormatI outFormat = null;
810 outFormat = FileFormats.getInstance().forName(outputFormat);
811 } catch (Exception formatP)
813 System.out.println("Couldn't parse " + outFormat
814 + " as a valid Jalview format string.");
816 if (outFormat != null)
818 if (!outFormat.isWritable())
821 "This version of Jalview does not support alignment export as "
826 af.saveAlignment(file, outFormat);
827 if (af.isSaveAlignmentSuccessful())
829 System.out.println("Written alignment in "
830 + outFormat.getName() + " format to " + file);
834 System.out.println("Error writing file " + file + " in "
835 + outFormat.getName() + " format!!");
842 while (aparser.getSize() > 0)
844 System.out.println("Unknown arg: " + aparser.nextValue());
848 AlignFrame startUpAlframe = null;
849 // We'll only open the default file if the desktop is visible.
851 // ////////////////////
853 if (!Platform.isJS() && !headless && file == null
854 && Cache.getDefault("SHOW_STARTUP_FILE", true))
861 file = Cache.getDefault("STARTUP_FILE",
862 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
863 + "/examples/exampleFile_2_7.jvp");
864 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
866 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
868 file.replace("http:", "https:");
869 // hardwire upgrade of the startup file
870 file.replace("_2_3", "_2_7");
871 file.replace("2_7.jar", "2_7.jvp");
872 // and remove the stale setting
873 Cache.removeProperty("STARTUP_FILE");
876 protocol = AppletFormatAdapter.checkProtocol(file);
878 if (file.endsWith(".jar"))
880 format = FileFormat.Jalview;
886 format = new IdentifyFile().identify(file, protocol);
887 } catch (FileFormatException e)
893 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
895 // extract groovy arguments before anything else.
898 // Once all other stuff is done, execute any groovy scripts (in order)
899 if (groovyscript != null)
901 if (Cache.groovyJarsPresent())
903 System.out.println("Executing script " + groovyscript);
904 executeGroovyScript(groovyscript, startUpAlframe);
909 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
913 // and finally, turn off batch mode indicator - if the desktop still exists
918 desktop.setProgressBar(null, progress);
920 desktop.setInBatchMode(false);
924 private static void setLookAndFeel()
926 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
928 // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
930 String lafProp = System.getProperty("laf");
931 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
937 else if (lafSetting != null)
941 boolean lafSet = false;
944 case "crossplatform":
945 lafSet = setCrossPlatformLookAndFeel();
948 Console.error("Could not set requested laf=" + laf);
952 lafSet = setSystemLookAndFeel();
955 Console.error("Could not set requested laf=" + laf);
959 lafSet = setGtkLookAndFeel();
962 Console.error("Could not set requested laf=" + laf);
966 lafSet = setMetalLookAndFeel();
969 Console.error("Could not set requested laf=" + laf);
973 lafSet = setNimbusLookAndFeel();
976 Console.error("Could not set requested laf=" + laf);
980 lafSet = setFlatLookAndFeel();
983 Console.error("Could not set requested laf=" + laf);
987 lafSet = setQuaquaLookAndFeel();
990 Console.error("Could not set requested laf=" + laf);
994 lafSet = setVaquaLookAndFeel();
997 Console.error("Could not set requested laf=" + laf);
1001 lafSet = setMacLookAndFeel();
1004 Console.error("Could not set requested laf=" + laf);
1010 Console.error("Requested laf=" + laf + " not implemented");
1014 setSystemLookAndFeel();
1015 if (Platform.isLinux())
1017 setMetalLookAndFeel();
1019 if (Platform.isMac())
1021 setMacLookAndFeel();
1026 private static boolean setCrossPlatformLookAndFeel()
1028 boolean set = false;
1031 UIManager.setLookAndFeel(
1032 UIManager.getCrossPlatformLookAndFeelClassName());
1034 } catch (Exception ex)
1036 Console.error("Unexpected Look and Feel Exception");
1037 Console.error(ex.getMessage());
1038 Console.debug(Cache.getStackTraceString(ex));
1043 private static boolean setSystemLookAndFeel()
1045 boolean set = false;
1048 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1050 } catch (Exception ex)
1052 Console.error("Unexpected Look and Feel Exception");
1053 Console.error(ex.getMessage());
1054 Console.debug(Cache.getStackTraceString(ex));
1059 private static boolean setSpecificLookAndFeel(String name,
1060 String className, boolean nameStartsWith)
1062 boolean set = false;
1065 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1067 if (info.getName() != null && nameStartsWith
1068 ? info.getName().toLowerCase(Locale.ROOT)
1069 .startsWith(name.toLowerCase(Locale.ROOT))
1070 : info.getName().toLowerCase(Locale.ROOT)
1071 .equals(name.toLowerCase(Locale.ROOT)))
1073 className = info.getClassName();
1077 UIManager.setLookAndFeel(className);
1079 } catch (Exception ex)
1081 Console.error("Unexpected Look and Feel Exception");
1082 Console.error(ex.getMessage());
1083 Console.debug(Cache.getStackTraceString(ex));
1088 private static boolean setGtkLookAndFeel()
1090 return setSpecificLookAndFeel("gtk",
1091 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1094 private static boolean setMetalLookAndFeel()
1096 return setSpecificLookAndFeel("metal",
1097 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1100 private static boolean setNimbusLookAndFeel()
1102 return setSpecificLookAndFeel("nimbus",
1103 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1106 private static boolean setFlatLookAndFeel()
1108 boolean set = setSpecificLookAndFeel("flatlaf light",
1109 "com.formdev.flatlaf.FlatLightLaf", false);
1112 if (Platform.isMac())
1114 System.setProperty("apple.laf.useScreenMenuBar", "true");
1115 System.setProperty("apple.awt.application.name",
1116 ChannelProperties.getProperty("app_name"));
1117 System.setProperty("apple.awt.application.appearance", "system");
1118 if (SystemInfo.isMacFullWindowContentSupported
1119 && Desktop.desktop != null)
1121 Desktop.desktop.getRootPane()
1122 .putClientProperty("apple.awt.fullWindowContent", true);
1123 Desktop.desktop.getRootPane()
1124 .putClientProperty("apple.awt.transparentTitleBar", true);
1127 SwingUtilities.invokeLater(() -> {
1128 FlatLightLaf.setup();
1132 UIManager.put("TabbedPane.showTabSeparators", true);
1133 UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1134 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1135 // UIManager.put("TabbedPane.hasFullBorder", true);
1136 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1137 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1138 UIManager.put("TabbedPane.smoothScrolling", true);
1139 UIManager.put("TabbedPane.tabWidthMode", "compact");
1140 UIManager.put("TabbedPane.selectedBackground", Color.white);
1145 private static boolean setQuaquaLookAndFeel()
1147 return setSpecificLookAndFeel("quaqua",
1148 ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel().getClass()
1153 private static boolean setVaquaLookAndFeel()
1155 return setSpecificLookAndFeel("vaqua",
1156 "org.violetlib.aqua.AquaLookAndFeel", false);
1159 private static boolean setMacLookAndFeel()
1161 boolean set = false;
1162 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1163 ChannelProperties.getProperty("app_name"));
1164 System.setProperty("apple.laf.useScreenMenuBar", "true");
1166 * broken native LAFs on (ARM?) macbooks
1167 set = setQuaquaLookAndFeel();
1168 if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1169 .toLowerCase(Locale.ROOT).contains("quaqua"))
1171 set = setVaquaLookAndFeel();
1174 set = setFlatLookAndFeel();
1178 private static void showUsage()
1181 "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1182 + "-nodisplay\tRun Jalview without User Interface.\n"
1183 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1184 + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1185 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1186 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1187 + "-features FILE\tUse the given file to mark features on the alignment.\n"
1188 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1189 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1190 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1191 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1192 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1193 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1194 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1195 + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1196 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1197 + "-png FILE\tCreate PNG image FILE from alignment.\n"
1198 + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1199 + "-html FILE\tCreate HTML file from alignment.\n"
1200 + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1201 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1202 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1203 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1204 + "-noquestionnaire\tTurn off questionnaire check.\n"
1205 + "-nonews\tTurn off check for Jalview news.\n"
1206 + "-nousagestats\tTurn off google analytics tracking for this session.\n"
1207 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1209 // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1210 // after all other properties files have been read\n\t
1211 // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1212 // passed in correctly)"
1213 + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1214 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1215 + "-groovy FILE\tExecute groovy script in FILE, after all other arguments have been processed (if FILE is the text 'STDIN' then the file will be read from STDIN)\n"
1216 + "-jvmmempc=PERCENT\tOnly available with standalone executable jar or jalview.bin.Launcher. Limit maximum heap size (memory) to PERCENT% of total physical memory detected. This defaults to 90 if total physical memory can be detected. See https://www.jalview.org/help/html/memory.html for more details.\n"
1217 + "-jvmmemmax=MAXMEMORY\tOnly available with standalone executable jar or jalview.bin.Launcher. Limit maximum heap size (memory) to MAXMEMORY. MAXMEMORY can be specified in bytes, kilobytes(k), megabytes(m), gigabytes(g) or if you're lucky enough, terabytes(t). This defaults to 32g if total physical memory can be detected, or to 8g if total physical memory cannot be detected. See https://www.jalview.org/help/html/memory.html for more details.\n"
1218 + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
1221 private static void startUsageStats(final Desktop desktop)
1224 * start a User Config prompt asking if we can log usage statistics.
1226 PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
1227 "USAGESTATS", "Jalview Usage Statistics",
1228 "Do you want to help make Jalview better by enabling "
1229 + "the collection of usage statistics with Google Analytics ?"
1230 + "\n\n(you can enable or disable usage tracking in the preferences)",
1237 "Initialising googletracker for usage stats.");
1238 Cache.initGoogleTracker();
1239 Console.debug("Tracking enabled.");
1246 Console.debug("Not enabling Google Tracking.");
1249 desktop.addDialogThread(prompter);
1253 * Locate the given string as a file and pass it to the groovy interpreter.
1255 * @param groovyscript
1256 * the script to execute
1257 * @param jalviewContext
1258 * the Jalview Desktop object passed in to the groovy binding as the
1261 private void executeGroovyScript(String groovyscript, AlignFrame af)
1264 * for scripts contained in files
1271 if (groovyscript.trim().equals("STDIN"))
1273 // read from stdin into a tempfile and execute it
1276 tfile = File.createTempFile("jalview", "groovy");
1277 PrintWriter outfile = new PrintWriter(
1278 new OutputStreamWriter(new FileOutputStream(tfile)));
1279 BufferedReader br = new BufferedReader(
1280 new InputStreamReader(System.in));
1282 while ((line = br.readLine()) != null)
1284 outfile.write(line + "\n");
1290 } catch (Exception ex)
1292 System.err.println("Failed to read from STDIN into tempfile "
1293 + ((tfile == null) ? "(tempfile wasn't created)"
1294 : tfile.toString()));
1295 ex.printStackTrace();
1300 sfile = tfile.toURI().toURL();
1301 } catch (Exception x)
1304 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1306 x.printStackTrace();
1314 sfile = new URI(groovyscript).toURL();
1315 } catch (Exception x)
1317 tfile = new File(groovyscript);
1318 if (!tfile.exists())
1320 System.err.println("File '" + groovyscript + "' does not exist.");
1323 if (!tfile.canRead())
1325 System.err.println("File '" + groovyscript + "' cannot be read.");
1328 if (tfile.length() < 1)
1330 System.err.println("File '" + groovyscript + "' is empty.");
1335 sfile = tfile.getAbsoluteFile().toURI().toURL();
1336 } catch (Exception ex)
1338 System.err.println("Failed to create a file URL for "
1339 + tfile.getAbsoluteFile());
1346 Map<String, java.lang.Object> vbinding = new HashMap<>();
1347 vbinding.put("Jalview", this);
1350 vbinding.put("currentAlFrame", af);
1352 Binding gbinding = new Binding(vbinding);
1353 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1354 gse.run(sfile.toString(), gbinding);
1355 if ("STDIN".equals(groovyscript))
1357 // delete temp file that we made -
1358 // only if it was successfully executed
1361 } catch (Exception e)
1363 System.err.println("Exception Whilst trying to execute file " + sfile
1364 + " as a groovy script.");
1365 e.printStackTrace(System.err);
1370 public static boolean isHeadlessMode()
1372 String isheadless = System.getProperty("java.awt.headless");
1373 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1380 public AlignFrame[] getAlignFrames()
1382 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1383 : Desktop.getAlignFrames();
1388 * Quit method delegates to Desktop.quit - unless running in headless mode
1389 * when it just ends the JVM
1393 if (desktop != null)
1403 public static AlignFrame getCurrentAlignFrame()
1405 return Jalview.currentAlignFrame;
1408 public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
1410 Jalview.currentAlignFrame = currentAlignFrame;