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.ext.so.SequenceOntology;
61 import jalview.gui.AlignFrame;
62 import jalview.gui.Desktop;
63 import jalview.gui.PromptUserConfig;
64 import jalview.io.AppletFormatAdapter;
65 import jalview.io.BioJsHTMLOutput;
66 import jalview.io.DataSourceType;
67 import jalview.io.FileFormat;
68 import jalview.io.FileFormatException;
69 import jalview.io.FileFormatI;
70 import jalview.io.FileFormats;
71 import jalview.io.FileLoader;
72 import jalview.io.HtmlSvgOutput;
73 import jalview.io.IdentifyFile;
74 import jalview.io.NewickFile;
75 import jalview.io.gff.SequenceOntologyFactory;
76 import jalview.schemes.ColourSchemeI;
77 import jalview.schemes.ColourSchemeProperty;
78 import jalview.util.ChannelProperties;
79 import jalview.util.HttpUtils;
80 import jalview.util.LaunchUtils;
81 import jalview.util.MessageManager;
82 import jalview.util.Platform;
83 import jalview.ws.jws2.Jws2Discoverer;
86 * Main class for Jalview Application <br>
88 * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
91 * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
92 * jalview.bin.Jalview jalview.bin.Jalview
94 * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
95 * embellish '*' to e.g. '*.jar')
104 Platform.getURLCommandArguments();
105 Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
106 Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
107 Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
108 Platform.addJ2SDirectDatabaseCall("https://www.compbio.dundee.ac.uk");
112 * singleton instance of this class
114 private static Jalview instance;
116 private Desktop desktop;
118 public static AlignFrame currentAlignFrame;
122 if (!Platform.isJS())
129 // grab all the rights we can for the JVM
130 Policy.setPolicy(new Policy()
133 public PermissionCollection getPermissions(CodeSource codesource)
135 Permissions perms = new Permissions();
136 perms.add(new AllPermission());
141 public void refresh()
149 * keep track of feature fetching tasks.
157 * TODO: generalise to track all jalview events to orchestrate batch processing
161 private int queued = 0;
163 private int running = 0;
165 public FeatureFetcher()
170 public void addFetcher(final AlignFrame af,
171 final Vector<String> dasSources)
173 final long id = System.currentTimeMillis();
175 final FeatureFetcher us = this;
176 new Thread(new Runnable()
188 af.setProgressBar(MessageManager
189 .getString("status.das_features_being_retrived"), id);
190 af.featureSettings_actionPerformed(null);
191 af.setProgressBar(null, id);
200 public synchronized boolean allFinished()
202 return queued == 0 && running == 0;
207 public static Jalview getInstance()
213 * main class for Jalview application
216 * open <em>filename</em>
218 public static void main(String[] args)
220 // setLogging(); // BH - for event debugging in JavaScript
221 instance = new Jalview();
222 instance.doMain(args);
225 private static void logClass(String name)
227 // BH - for event debugging in JavaScript
228 ConsoleHandler consoleHandler = new ConsoleHandler();
229 consoleHandler.setLevel(Level.ALL);
230 Logger logger = Logger.getLogger(name);
231 logger.setLevel(Level.ALL);
232 logger.addHandler(consoleHandler);
235 @SuppressWarnings("unused")
236 private static void setLogging()
244 System.out.println("not in js");
247 // BH - for event debugging in JavaScript (Java mode only)
248 if (!Platform.isJS())
255 Logger.getLogger("").setLevel(Level.ALL);
256 logClass("java.awt.EventDispatchThread");
257 logClass("java.awt.EventQueue");
258 logClass("java.awt.Component");
259 logClass("java.awt.focus.Component");
260 logClass("java.awt.focus.DefaultKeyboardFocusManager");
268 void doMain(String[] args)
271 if (!Platform.isJS())
273 System.setSecurityManager(null);
277 .println("Java version: " + System.getProperty("java.version"));
278 System.out.println("Java Home: " + System.getProperty("java.home"));
279 System.out.println(System.getProperty("os.arch") + " "
280 + System.getProperty("os.name") + " "
281 + System.getProperty("os.version"));
282 String val = System.getProperty("sys.install4jVersion");
285 System.out.println("Install4j version: " + val);
287 val = System.getProperty("installer_template_version");
290 System.out.println("Install4j template version: " + val);
292 val = System.getProperty("launcher_version");
295 System.out.println("Launcher version: " + val);
298 // report Jalview version
299 Cache.loadBuildProperties(true);
302 ArgsParser aparser = new ArgsParser(args);
304 ArgParser argparser = new ArgParser(args);
305 boolean headless = false;
307 String usrPropsFile = aparser.getValue("props");
308 Cache.loadProperties(usrPropsFile); // must do this before
309 if (usrPropsFile != null)
312 "CMD [-props " + usrPropsFile + "] executed successfully!");
315 if (!Platform.isJS())
322 if (aparser.contains("help") || aparser.contains("h"))
327 if (aparser.contains("nodisplay") || aparser.contains("nogui")
328 || aparser.contains("headless"))
330 System.setProperty("java.awt.headless", "true");
335 // allow https handshakes to download intermediate certs if necessary
336 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
338 final String jabawsUrl = aparser.getValue("jabaws");
339 if (jabawsUrl != null)
343 Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
345 "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
346 } catch (MalformedURLException e)
349 "Invalid jabaws parameter: " + jabawsUrl + " ignored");
354 String defs = aparser.getValue("setprop");
357 int p = defs.indexOf('=');
360 System.err.println("Ignoring invalid setprop argument : " + defs);
364 System.out.println("Executing setprop argument: " + defs);
367 Cache.setProperty(defs.substring(0, p), defs.substring(p + 1));
369 // DISABLED FOR SECURITY REASONS
370 // TODO: add a property to allow properties to be overriden by cli args
371 // Cache.setProperty(defs.substring(0,p), defs.substring(p+1));
373 defs = aparser.getValue("setprop");
375 if (System.getProperty("java.awt.headless") != null
376 && System.getProperty("java.awt.headless").equals("true"))
380 System.setProperty("http.agent",
381 "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
385 Console.initLogger();
386 } catch (NoClassDefFoundError error)
388 error.printStackTrace();
389 System.out.println("\nEssential logging libraries not found."
390 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview");
399 * configure 'full' SO model if preferences say to, else use the default (full SO)
400 * - as JS currently doesn't have OBO parsing, it must use 'Lite' version
402 boolean soDefault = !Platform.isJS();
403 if (Cache.getDefault("USE_FULL_SO", soDefault))
405 SequenceOntologyFactory.setInstance(new SequenceOntology());
410 Desktop.nosplash = aparser.contains("nosplash");
411 desktop = new Desktop();
412 desktop.setInBatchMode(true); // indicate we are starting up
416 JalviewTaskbar.setTaskbar(this);
417 } catch (Exception e)
419 Console.info("Cannot set Taskbar");
420 Console.error(e.getMessage());
421 // e.printStackTrace();
422 } catch (Throwable t)
424 Console.info("Cannot set Taskbar");
425 Console.error(t.getMessage());
426 // t.printStackTrace();
429 // set Proxy settings before all the internet calls
430 Cache.setProxyPropertiesFromPreferences();
432 desktop.setVisible(true);
434 if (!Platform.isJS())
443 * Check to see that the JVM version being run is suitable for the Java
444 * version this Jalview was compiled for. Popup a warning if not.
446 if (!LaunchUtils.checkJavaVersion())
448 Console.warn("The Java version being used (Java "
449 + LaunchUtils.getJavaVersion()
450 + ") may lead to problems. This installation of Jalview should be used with Java "
451 + LaunchUtils.getJavaCompileVersion() + ".");
454 .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
457 MessageManager.getString("label.continue") };
458 JOptionPane.showOptionDialog(null,
459 MessageManager.formatMessage(
460 "warning.wrong_jvm_version_message",
461 LaunchUtils.getJavaVersion(),
462 LaunchUtils.getJavaCompileVersion()),
464 .getString("warning.wrong_jvm_version_title"),
465 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
466 null, options, options[0]);
470 if (!aparser.contains("nowebservicediscovery"))
472 desktop.startServiceDiscovery();
474 if (!aparser.contains("nousagestats"))
476 startUsageStats(desktop);
480 System.err.println("CMD [-nousagestats] executed successfully!");
483 if (!aparser.contains("noquestionnaire"))
485 String url = aparser.getValue("questionnaire");
488 // Start the desktop questionnaire prompter with the specified
490 Console.debug("Starting questionnaire url at " + url);
491 desktop.checkForQuestionnaire(url);
492 System.out.println("CMD questionnaire[-" + url
493 + "] executed successfully!");
497 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
499 // Start the desktop questionnaire prompter with the specified
502 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
504 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
506 "Starting questionnaire with default url: " + defurl);
507 desktop.checkForQuestionnaire(defurl);
514 .println("CMD [-noquestionnaire] executed successfully!");
517 if (!aparser.contains("nonews")
518 || Cache.getProperty("NONEWS") == null)
520 desktop.checkForNews();
523 if (!aparser.contains("nohtmltemplates")
524 || Cache.getProperty("NOHTMLTEMPLATES") == null)
526 BioJsHTMLOutput.updateBioJS();
531 // Check if JVM and compile version might cause problems and log if it
533 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
535 Console.warn("The Java version being used (Java "
536 + LaunchUtils.getJavaVersion()
537 + ") may lead to problems. This installation of Jalview should be used with Java "
538 + LaunchUtils.getJavaCompileVersion() + ".");
541 // Move any new getdown-launcher-new.jar into place over old
542 // getdown-launcher.jar
543 String appdirString = System.getProperty("getdownappdir");
544 if (appdirString != null && appdirString.length() > 0)
546 final File appdir = new File(appdirString);
552 LaunchUtil.upgradeGetdown(
553 new File(appdir, "getdown-launcher-old.jar"),
554 new File(appdir, "getdown-launcher.jar"),
555 new File(appdir, "getdown-launcher-new.jar"));
560 Commands.processArgs(argparser, headless);
562 String file = null, data = null;
563 FileFormatI format = null;
564 DataSourceType protocol = null;
565 FileLoader fileLoader = new FileLoader(!headless);
567 String groovyscript = null; // script to execute after all loading is
568 // completed one way or another
569 // extract groovy argument and execute if necessary
570 groovyscript = aparser.getValue("groovy", true);
571 file = aparser.getValue("open", true);
573 if (file == null && desktop == null)
575 System.out.println("No files to open!");
579 // Finally, deal with the remaining input data.
584 desktop.setProgressBar(
586 .getString("status.processing_commandline_args"),
587 progress = System.currentTimeMillis());
589 System.out.println("CMD [-open " + file + "] executed successfully!");
591 if (!Platform.isJS())
593 * ignore in JavaScript -- can't just file existence - could load it?
598 if (!HttpUtils.startsWithHttpOrHttps(file))
600 if (!(new File(file)).exists())
602 System.out.println("Can't find " + file);
611 protocol = AppletFormatAdapter.checkProtocol(file);
615 format = new IdentifyFile().identify(file, protocol);
616 } catch (FileFormatException e1)
621 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
625 System.out.println("error");
629 setCurrentAlignFrame(af);
630 data = aparser.getValue("colour", true);
633 data.replaceAll("%20", " ");
635 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
636 af.getViewport(), af.getViewport().getAlignment(), data);
641 "CMD [-color " + data + "] executed successfully!");
646 // Must maintain ability to use the groups flag
647 data = aparser.getValue("groups", true);
650 af.parseFeaturesFile(data,
651 AppletFormatAdapter.checkProtocol(data));
652 // System.out.println("Added " + data);
654 "CMD groups[-" + data + "] executed successfully!");
656 data = aparser.getValue("features", true);
659 af.parseFeaturesFile(data,
660 AppletFormatAdapter.checkProtocol(data));
661 // System.out.println("Added " + data);
663 "CMD [-features " + data + "] executed successfully!");
666 data = aparser.getValue("annotations", true);
669 af.loadJalviewDataFile(data, null, null, null);
670 // System.out.println("Added " + data);
672 "CMD [-annotations " + data + "] executed successfully!");
674 // set or clear the sortbytree flag.
675 if (aparser.contains("sortbytree"))
677 af.getViewport().setSortByTree(true);
678 if (af.getViewport().getSortByTree())
680 System.out.println("CMD [-sortbytree] executed successfully!");
683 if (aparser.contains("no-annotation"))
685 af.getViewport().setShowAnnotation(false);
686 if (!af.getViewport().isShowAnnotation())
688 System.out.println("CMD no-annotation executed successfully!");
691 if (aparser.contains("nosortbytree"))
693 af.getViewport().setSortByTree(false);
694 if (!af.getViewport().getSortByTree())
697 .println("CMD [-nosortbytree] executed successfully!");
700 data = aparser.getValue("tree", true);
706 "CMD [-tree " + data + "] executed successfully!");
707 NewickFile nf = new NewickFile(data,
708 AppletFormatAdapter.checkProtocol(data));
710 .setCurrentTree(af.showNewickTree(nf, data).getTree());
711 } catch (IOException ex)
713 System.err.println("Couldn't add tree " + data);
714 ex.printStackTrace(System.err);
717 // TODO - load PDB structure(s) to alignment JAL-629
718 // (associate with identical sequence in alignment, or a specified
720 if (groovyscript != null)
722 // Execute the groovy script after we've done all the rendering stuff
723 // and before any images or figures are generated.
724 System.out.println("Executing script " + groovyscript);
725 executeGroovyScript(groovyscript, af);
726 System.out.println("CMD groovy[" + groovyscript
727 + "] executed successfully!");
730 String imageName = "unnamed.png";
731 while (aparser.getSize() > 1)
733 String outputFormat = aparser.nextValue();
734 file = aparser.nextValue();
736 if (outputFormat.equalsIgnoreCase("png"))
738 af.createPNG(new File(file));
739 imageName = (new File(file)).getName();
740 System.out.println("Creating PNG image: " + file);
743 else if (outputFormat.equalsIgnoreCase("svg"))
745 File imageFile = new File(file);
746 imageName = imageFile.getName();
747 af.createSVG(imageFile);
748 System.out.println("Creating SVG image: " + file);
751 else if (outputFormat.equalsIgnoreCase("html"))
753 File imageFile = new File(file);
754 imageName = imageFile.getName();
755 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
756 htmlSVG.exportHTML(file);
758 System.out.println("Creating HTML image: " + file);
761 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
765 System.err.println("The output html file must not be null");
770 BioJsHTMLOutput.refreshVersionInfo(
771 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
772 } catch (URISyntaxException e)
776 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
777 bjs.exportHTML(file);
779 .println("Creating BioJS MSA Viwer HTML file: " + file);
782 else if (outputFormat.equalsIgnoreCase("imgMap"))
784 af.createImageMap(new File(file), imageName);
785 System.out.println("Creating image map: " + file);
788 else if (outputFormat.equalsIgnoreCase("eps"))
790 File outputFile = new File(file);
792 "Creating EPS file: " + outputFile.getAbsolutePath());
793 af.createEPS(outputFile);
796 FileFormatI outFormat = null;
799 outFormat = FileFormats.getInstance().forName(outputFormat);
800 } catch (Exception formatP)
802 System.out.println("Couldn't parse " + outFormat
803 + " as a valid Jalview format string.");
805 if (outFormat != null)
807 if (!outFormat.isWritable())
810 "This version of Jalview does not support alignment export as "
815 af.saveAlignment(file, outFormat);
816 if (af.isSaveAlignmentSuccessful())
818 System.out.println("Written alignment in "
819 + outFormat.getName() + " format to " + file);
823 System.out.println("Error writing file " + file + " in "
824 + outFormat.getName() + " format!!");
831 while (aparser.getSize() > 0)
833 System.out.println("Unknown arg: " + aparser.nextValue());
837 AlignFrame startUpAlframe = null;
838 // We'll only open the default file if the desktop is visible.
840 // ////////////////////
842 if (!Platform.isJS() && !headless && file == null
843 && Cache.getDefault("SHOW_STARTUP_FILE", true))
850 file = Cache.getDefault("STARTUP_FILE",
851 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
852 + "/examples/exampleFile_2_7.jvp");
853 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
855 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
857 file.replace("http:", "https:");
858 // hardwire upgrade of the startup file
859 file.replace("_2_3", "_2_7");
860 file.replace("2_7.jar", "2_7.jvp");
861 // and remove the stale setting
862 Cache.removeProperty("STARTUP_FILE");
865 protocol = AppletFormatAdapter.checkProtocol(file);
867 if (file.endsWith(".jar"))
869 format = FileFormat.Jalview;
875 format = new IdentifyFile().identify(file, protocol);
876 } catch (FileFormatException e)
882 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
884 // extract groovy arguments before anything else.
887 // Once all other stuff is done, execute any groovy scripts (in order)
888 if (groovyscript != null)
890 if (Cache.groovyJarsPresent())
892 System.out.println("Executing script " + groovyscript);
893 executeGroovyScript(groovyscript, startUpAlframe);
898 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
902 // and finally, turn off batch mode indicator - if the desktop still exists
907 desktop.setProgressBar(null, progress);
909 desktop.setInBatchMode(false);
913 private static void setLookAndFeel()
915 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
917 // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
919 String lafProp = System.getProperty("laf");
920 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
926 else if (lafSetting != null)
930 boolean lafSet = false;
933 case "crossplatform":
934 lafSet = setCrossPlatformLookAndFeel();
937 Console.error("Could not set requested laf=" + laf);
941 lafSet = setSystemLookAndFeel();
944 Console.error("Could not set requested laf=" + laf);
948 lafSet = setGtkLookAndFeel();
951 Console.error("Could not set requested laf=" + laf);
955 lafSet = setMetalLookAndFeel();
958 Console.error("Could not set requested laf=" + laf);
962 lafSet = setNimbusLookAndFeel();
965 Console.error("Could not set requested laf=" + laf);
969 lafSet = setFlatLookAndFeel();
972 Console.error("Could not set requested laf=" + laf);
976 lafSet = setQuaquaLookAndFeel();
979 Console.error("Could not set requested laf=" + laf);
983 lafSet = setVaquaLookAndFeel();
986 Console.error("Could not set requested laf=" + laf);
990 lafSet = setMacLookAndFeel();
993 Console.error("Could not set requested laf=" + laf);
999 Console.error("Requested laf=" + laf + " not implemented");
1003 setSystemLookAndFeel();
1004 if (Platform.isLinux())
1006 setMetalLookAndFeel();
1008 if (Platform.isMac())
1010 setMacLookAndFeel();
1015 private static boolean setCrossPlatformLookAndFeel()
1017 boolean set = false;
1020 UIManager.setLookAndFeel(
1021 UIManager.getCrossPlatformLookAndFeelClassName());
1023 } catch (Exception ex)
1025 Console.error("Unexpected Look and Feel Exception");
1026 Console.error(ex.getMessage());
1027 Console.debug(Cache.getStackTraceString(ex));
1032 private static boolean setSystemLookAndFeel()
1034 boolean set = false;
1037 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1039 } catch (Exception ex)
1041 Console.error("Unexpected Look and Feel Exception");
1042 Console.error(ex.getMessage());
1043 Console.debug(Cache.getStackTraceString(ex));
1048 private static boolean setSpecificLookAndFeel(String name,
1049 String className, boolean nameStartsWith)
1051 boolean set = false;
1054 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1056 if (info.getName() != null && nameStartsWith
1057 ? info.getName().toLowerCase(Locale.ROOT)
1058 .startsWith(name.toLowerCase(Locale.ROOT))
1059 : info.getName().toLowerCase(Locale.ROOT)
1060 .equals(name.toLowerCase(Locale.ROOT)))
1062 className = info.getClassName();
1066 UIManager.setLookAndFeel(className);
1068 } catch (Exception ex)
1070 Console.error("Unexpected Look and Feel Exception");
1071 Console.error(ex.getMessage());
1072 Console.debug(Cache.getStackTraceString(ex));
1077 private static boolean setGtkLookAndFeel()
1079 return setSpecificLookAndFeel("gtk",
1080 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1083 private static boolean setMetalLookAndFeel()
1085 return setSpecificLookAndFeel("metal",
1086 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1089 private static boolean setNimbusLookAndFeel()
1091 return setSpecificLookAndFeel("nimbus",
1092 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1095 private static boolean setFlatLookAndFeel()
1097 boolean set = setSpecificLookAndFeel("flatlaf light",
1098 "com.formdev.flatlaf.FlatLightLaf", false);
1101 if (Platform.isMac())
1103 System.setProperty("apple.laf.useScreenMenuBar", "true");
1104 System.setProperty("apple.awt.application.name",
1105 ChannelProperties.getProperty("app_name"));
1106 System.setProperty("apple.awt.application.appearance", "system");
1107 if (SystemInfo.isMacFullWindowContentSupported
1108 && Desktop.desktop != null)
1110 Desktop.desktop.getRootPane()
1111 .putClientProperty("apple.awt.fullWindowContent", true);
1112 Desktop.desktop.getRootPane()
1113 .putClientProperty("apple.awt.transparentTitleBar", true);
1116 SwingUtilities.invokeLater(() -> {
1117 FlatLightLaf.setup();
1121 UIManager.put("TabbedPane.showTabSeparators", true);
1122 UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1123 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1124 // UIManager.put("TabbedPane.hasFullBorder", true);
1125 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1126 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1127 UIManager.put("TabbedPane.smoothScrolling", true);
1128 UIManager.put("TabbedPane.tabWidthMode", "compact");
1129 UIManager.put("TabbedPane.selectedBackground", Color.white);
1134 private static boolean setQuaquaLookAndFeel()
1136 return setSpecificLookAndFeel("quaqua",
1137 ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel().getClass()
1142 private static boolean setVaquaLookAndFeel()
1144 return setSpecificLookAndFeel("vaqua",
1145 "org.violetlib.aqua.AquaLookAndFeel", false);
1148 private static boolean setMacLookAndFeel()
1150 boolean set = false;
1151 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1152 ChannelProperties.getProperty("app_name"));
1153 System.setProperty("apple.laf.useScreenMenuBar", "true");
1155 * broken native LAFs on (ARM?) macbooks
1156 set = setQuaquaLookAndFeel();
1157 if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1158 .toLowerCase(Locale.ROOT).contains("quaqua"))
1160 set = setVaquaLookAndFeel();
1163 set = setFlatLookAndFeel();
1167 private static void showUsage()
1170 "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1171 + "-nodisplay\tRun Jalview without User Interface.\n"
1172 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1173 + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1174 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1175 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1176 + "-features FILE\tUse the given file to mark features on the alignment.\n"
1177 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1178 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1179 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1180 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1181 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1182 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1183 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1184 + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1185 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1186 + "-png FILE\tCreate PNG image FILE from alignment.\n"
1187 + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1188 + "-html FILE\tCreate HTML file from alignment.\n"
1189 + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1190 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1191 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1192 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1193 + "-noquestionnaire\tTurn off questionnaire check.\n"
1194 + "-nonews\tTurn off check for Jalview news.\n"
1195 + "-nousagestats\tTurn off google analytics tracking for this session.\n"
1196 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1198 // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1199 // after all other properties files have been read\n\t
1200 // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1201 // passed in correctly)"
1202 + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1203 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1204 + "-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"
1205 + "-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"
1206 + "-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"
1207 + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
1210 private static void startUsageStats(final Desktop desktop)
1213 * start a User Config prompt asking if we can log usage statistics.
1215 PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
1216 "USAGESTATS", "Jalview Usage Statistics",
1217 "Do you want to help make Jalview better by enabling "
1218 + "the collection of usage statistics with Google Analytics ?"
1219 + "\n\n(you can enable or disable usage tracking in the preferences)",
1226 "Initialising googletracker for usage stats.");
1227 Cache.initGoogleTracker();
1228 Console.debug("Tracking enabled.");
1235 Console.debug("Not enabling Google Tracking.");
1238 desktop.addDialogThread(prompter);
1242 * Locate the given string as a file and pass it to the groovy interpreter.
1244 * @param groovyscript
1245 * the script to execute
1246 * @param jalviewContext
1247 * the Jalview Desktop object passed in to the groovy binding as the
1250 private void executeGroovyScript(String groovyscript, AlignFrame af)
1253 * for scripts contained in files
1260 if (groovyscript.trim().equals("STDIN"))
1262 // read from stdin into a tempfile and execute it
1265 tfile = File.createTempFile("jalview", "groovy");
1266 PrintWriter outfile = new PrintWriter(
1267 new OutputStreamWriter(new FileOutputStream(tfile)));
1268 BufferedReader br = new BufferedReader(
1269 new InputStreamReader(System.in));
1271 while ((line = br.readLine()) != null)
1273 outfile.write(line + "\n");
1279 } catch (Exception ex)
1281 System.err.println("Failed to read from STDIN into tempfile "
1282 + ((tfile == null) ? "(tempfile wasn't created)"
1283 : tfile.toString()));
1284 ex.printStackTrace();
1289 sfile = tfile.toURI().toURL();
1290 } catch (Exception x)
1293 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1295 x.printStackTrace();
1303 sfile = new URI(groovyscript).toURL();
1304 } catch (Exception x)
1306 tfile = new File(groovyscript);
1307 if (!tfile.exists())
1309 System.err.println("File '" + groovyscript + "' does not exist.");
1312 if (!tfile.canRead())
1314 System.err.println("File '" + groovyscript + "' cannot be read.");
1317 if (tfile.length() < 1)
1319 System.err.println("File '" + groovyscript + "' is empty.");
1324 sfile = tfile.getAbsoluteFile().toURI().toURL();
1325 } catch (Exception ex)
1327 System.err.println("Failed to create a file URL for "
1328 + tfile.getAbsoluteFile());
1335 Map<String, java.lang.Object> vbinding = new HashMap<>();
1336 vbinding.put("Jalview", this);
1339 vbinding.put("currentAlFrame", af);
1341 Binding gbinding = new Binding(vbinding);
1342 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1343 gse.run(sfile.toString(), gbinding);
1344 if ("STDIN".equals(groovyscript))
1346 // delete temp file that we made -
1347 // only if it was successfully executed
1350 } catch (Exception e)
1352 System.err.println("Exception Whilst trying to execute file " + sfile
1353 + " as a groovy script.");
1354 e.printStackTrace(System.err);
1359 public static boolean isHeadlessMode()
1361 String isheadless = System.getProperty("java.awt.headless");
1362 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1369 public AlignFrame[] getAlignFrames()
1371 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1372 : Desktop.getAlignFrames();
1377 * Quit method delegates to Desktop.quit - unless running in headless mode
1378 * when it just ends the JVM
1382 if (desktop != null)
1392 public static AlignFrame getCurrentAlignFrame()
1394 return Jalview.currentAlignFrame;
1397 public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
1399 Jalview.currentAlignFrame = currentAlignFrame;