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 Commands.processArgs(argparser, headless);
570 String file = null, data = null;
571 FileFormatI format = null;
572 DataSourceType protocol = null;
573 FileLoader fileLoader = new FileLoader(!headless);
575 String groovyscript = null; // script to execute after all loading is
576 // completed one way or another
577 // extract groovy argument and execute if necessary
578 groovyscript = aparser.getValue("groovy", true);
579 file = aparser.getValue("open", true);
581 if (file == null && desktop == null)
583 System.out.println("No files to open!");
587 // Finally, deal with the remaining input data.
592 desktop.setProgressBar(
594 .getString("status.processing_commandline_args"),
595 progress = System.currentTimeMillis());
597 System.out.println("CMD [-open " + file + "] executed successfully!");
599 if (!Platform.isJS())
601 * ignore in JavaScript -- can't just file existence - could load it?
606 if (!HttpUtils.startsWithHttpOrHttps(file))
608 if (!(new File(file)).exists())
610 System.out.println("Can't find " + file);
619 protocol = AppletFormatAdapter.checkProtocol(file);
623 format = new IdentifyFile().identify(file, protocol);
624 } catch (FileFormatException e1)
629 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
633 System.out.println("error");
637 setCurrentAlignFrame(af);
638 data = aparser.getValue("colour", true);
641 data.replaceAll("%20", " ");
643 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
644 af.getViewport(), af.getViewport().getAlignment(), data);
649 "CMD [-color " + data + "] executed successfully!");
654 // Must maintain ability to use the groups flag
655 data = aparser.getValue("groups", true);
658 af.parseFeaturesFile(data,
659 AppletFormatAdapter.checkProtocol(data));
660 // System.out.println("Added " + data);
662 "CMD groups[-" + data + "] executed successfully!");
664 data = aparser.getValue("features", true);
667 af.parseFeaturesFile(data,
668 AppletFormatAdapter.checkProtocol(data));
669 // System.out.println("Added " + data);
671 "CMD [-features " + data + "] executed successfully!");
674 data = aparser.getValue("annotations", true);
677 af.loadJalviewDataFile(data, null, null, null);
678 // System.out.println("Added " + data);
680 "CMD [-annotations " + data + "] executed successfully!");
682 // set or clear the sortbytree flag.
683 if (aparser.contains("sortbytree"))
685 af.getViewport().setSortByTree(true);
686 if (af.getViewport().getSortByTree())
688 System.out.println("CMD [-sortbytree] executed successfully!");
691 if (aparser.contains("no-annotation"))
693 af.getViewport().setShowAnnotation(false);
694 if (!af.getViewport().isShowAnnotation())
696 System.out.println("CMD no-annotation executed successfully!");
699 if (aparser.contains("nosortbytree"))
701 af.getViewport().setSortByTree(false);
702 if (!af.getViewport().getSortByTree())
705 .println("CMD [-nosortbytree] executed successfully!");
708 data = aparser.getValue("tree", true);
714 "CMD [-tree " + data + "] executed successfully!");
715 NewickFile nf = new NewickFile(data,
716 AppletFormatAdapter.checkProtocol(data));
718 .setCurrentTree(af.showNewickTree(nf, data).getTree());
719 } catch (IOException ex)
721 System.err.println("Couldn't add tree " + data);
722 ex.printStackTrace(System.err);
725 // TODO - load PDB structure(s) to alignment JAL-629
726 // (associate with identical sequence in alignment, or a specified
728 if (groovyscript != null)
730 // Execute the groovy script after we've done all the rendering stuff
731 // and before any images or figures are generated.
732 System.out.println("Executing script " + groovyscript);
733 executeGroovyScript(groovyscript, af);
734 System.out.println("CMD groovy[" + groovyscript
735 + "] executed successfully!");
738 String imageName = "unnamed.png";
739 while (aparser.getSize() > 1)
741 String outputFormat = aparser.nextValue();
742 file = aparser.nextValue();
744 if (outputFormat.equalsIgnoreCase("png"))
746 af.createPNG(new File(file));
747 imageName = (new File(file)).getName();
748 System.out.println("Creating PNG image: " + file);
751 else if (outputFormat.equalsIgnoreCase("svg"))
753 File imageFile = new File(file);
754 imageName = imageFile.getName();
755 af.createSVG(imageFile);
756 System.out.println("Creating SVG image: " + file);
759 else if (outputFormat.equalsIgnoreCase("html"))
761 File imageFile = new File(file);
762 imageName = imageFile.getName();
763 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
764 htmlSVG.exportHTML(file);
766 System.out.println("Creating HTML image: " + file);
769 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
773 System.err.println("The output html file must not be null");
778 BioJsHTMLOutput.refreshVersionInfo(
779 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
780 } catch (URISyntaxException e)
784 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
785 bjs.exportHTML(file);
787 .println("Creating BioJS MSA Viwer HTML file: " + file);
790 else if (outputFormat.equalsIgnoreCase("imgMap"))
792 af.createImageMap(new File(file), imageName);
793 System.out.println("Creating image map: " + file);
796 else if (outputFormat.equalsIgnoreCase("eps"))
798 File outputFile = new File(file);
800 "Creating EPS file: " + outputFile.getAbsolutePath());
801 af.createEPS(outputFile);
804 FileFormatI outFormat = null;
807 outFormat = FileFormats.getInstance().forName(outputFormat);
808 } catch (Exception formatP)
810 System.out.println("Couldn't parse " + outFormat
811 + " as a valid Jalview format string.");
813 if (outFormat != null)
815 if (!outFormat.isWritable())
818 "This version of Jalview does not support alignment export as "
823 af.saveAlignment(file, outFormat);
824 if (af.isSaveAlignmentSuccessful())
826 System.out.println("Written alignment in "
827 + outFormat.getName() + " format to " + file);
831 System.out.println("Error writing file " + file + " in "
832 + outFormat.getName() + " format!!");
839 while (aparser.getSize() > 0)
841 System.out.println("Unknown arg: " + aparser.nextValue());
845 AlignFrame startUpAlframe = null;
846 // We'll only open the default file if the desktop is visible.
848 // ////////////////////
850 if (!Platform.isJS() && !headless && file == null
851 && Cache.getDefault("SHOW_STARTUP_FILE", true))
858 file = Cache.getDefault("STARTUP_FILE",
859 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
860 + "/examples/exampleFile_2_7.jvp");
861 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
863 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
865 file.replace("http:", "https:");
866 // hardwire upgrade of the startup file
867 file.replace("_2_3", "_2_7");
868 file.replace("2_7.jar", "2_7.jvp");
869 // and remove the stale setting
870 Cache.removeProperty("STARTUP_FILE");
873 protocol = AppletFormatAdapter.checkProtocol(file);
875 if (file.endsWith(".jar"))
877 format = FileFormat.Jalview;
883 format = new IdentifyFile().identify(file, protocol);
884 } catch (FileFormatException e)
890 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
892 // extract groovy arguments before anything else.
895 // Once all other stuff is done, execute any groovy scripts (in order)
896 if (groovyscript != null)
898 if (Cache.groovyJarsPresent())
900 System.out.println("Executing script " + groovyscript);
901 executeGroovyScript(groovyscript, startUpAlframe);
906 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
910 // and finally, turn off batch mode indicator - if the desktop still exists
915 desktop.setProgressBar(null, progress);
917 desktop.setInBatchMode(false);
921 private static void setLookAndFeel()
923 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
925 // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
927 String lafProp = System.getProperty("laf");
928 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
934 else if (lafSetting != null)
938 boolean lafSet = false;
941 case "crossplatform":
942 lafSet = setCrossPlatformLookAndFeel();
945 Console.error("Could not set requested laf=" + laf);
949 lafSet = setSystemLookAndFeel();
952 Console.error("Could not set requested laf=" + laf);
956 lafSet = setGtkLookAndFeel();
959 Console.error("Could not set requested laf=" + laf);
963 lafSet = setMetalLookAndFeel();
966 Console.error("Could not set requested laf=" + laf);
970 lafSet = setNimbusLookAndFeel();
973 Console.error("Could not set requested laf=" + laf);
977 lafSet = setFlatLookAndFeel();
980 Console.error("Could not set requested laf=" + laf);
984 lafSet = setQuaquaLookAndFeel();
987 Console.error("Could not set requested laf=" + laf);
991 lafSet = setVaquaLookAndFeel();
994 Console.error("Could not set requested laf=" + laf);
998 lafSet = setMacLookAndFeel();
1001 Console.error("Could not set requested laf=" + laf);
1007 Console.error("Requested laf=" + laf + " not implemented");
1011 setSystemLookAndFeel();
1012 if (Platform.isLinux())
1014 setMetalLookAndFeel();
1016 if (Platform.isMac())
1018 setMacLookAndFeel();
1023 private static boolean setCrossPlatformLookAndFeel()
1025 boolean set = false;
1028 UIManager.setLookAndFeel(
1029 UIManager.getCrossPlatformLookAndFeelClassName());
1031 } catch (Exception ex)
1033 Console.error("Unexpected Look and Feel Exception");
1034 Console.error(ex.getMessage());
1035 Console.debug(Cache.getStackTraceString(ex));
1040 private static boolean setSystemLookAndFeel()
1042 boolean set = false;
1045 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1047 } catch (Exception ex)
1049 Console.error("Unexpected Look and Feel Exception");
1050 Console.error(ex.getMessage());
1051 Console.debug(Cache.getStackTraceString(ex));
1056 private static boolean setSpecificLookAndFeel(String name,
1057 String className, boolean nameStartsWith)
1059 boolean set = false;
1062 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1064 if (info.getName() != null && nameStartsWith
1065 ? info.getName().toLowerCase(Locale.ROOT)
1066 .startsWith(name.toLowerCase(Locale.ROOT))
1067 : info.getName().toLowerCase(Locale.ROOT)
1068 .equals(name.toLowerCase(Locale.ROOT)))
1070 className = info.getClassName();
1074 UIManager.setLookAndFeel(className);
1076 } catch (Exception ex)
1078 Console.error("Unexpected Look and Feel Exception");
1079 Console.error(ex.getMessage());
1080 Console.debug(Cache.getStackTraceString(ex));
1085 private static boolean setGtkLookAndFeel()
1087 return setSpecificLookAndFeel("gtk",
1088 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1091 private static boolean setMetalLookAndFeel()
1093 return setSpecificLookAndFeel("metal",
1094 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1097 private static boolean setNimbusLookAndFeel()
1099 return setSpecificLookAndFeel("nimbus",
1100 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1103 private static boolean setFlatLookAndFeel()
1105 boolean set = setSpecificLookAndFeel("flatlaf light",
1106 "com.formdev.flatlaf.FlatLightLaf", false);
1109 if (Platform.isMac())
1111 System.setProperty("apple.laf.useScreenMenuBar", "true");
1112 System.setProperty("apple.awt.application.name",
1113 ChannelProperties.getProperty("app_name"));
1114 System.setProperty("apple.awt.application.appearance", "system");
1115 if (SystemInfo.isMacFullWindowContentSupported
1116 && Desktop.desktop != null)
1118 Desktop.desktop.getRootPane()
1119 .putClientProperty("apple.awt.fullWindowContent", true);
1120 Desktop.desktop.getRootPane()
1121 .putClientProperty("apple.awt.transparentTitleBar", true);
1124 SwingUtilities.invokeLater(() -> {
1125 FlatLightLaf.setup();
1129 UIManager.put("TabbedPane.showTabSeparators", true);
1130 UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1131 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1132 // UIManager.put("TabbedPane.hasFullBorder", true);
1133 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1134 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1135 UIManager.put("TabbedPane.smoothScrolling", true);
1136 UIManager.put("TabbedPane.tabWidthMode", "compact");
1137 UIManager.put("TabbedPane.selectedBackground", Color.white);
1142 private static boolean setQuaquaLookAndFeel()
1144 return setSpecificLookAndFeel("quaqua",
1145 ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel().getClass()
1150 private static boolean setVaquaLookAndFeel()
1152 return setSpecificLookAndFeel("vaqua",
1153 "org.violetlib.aqua.AquaLookAndFeel", false);
1156 private static boolean setMacLookAndFeel()
1158 boolean set = false;
1159 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1160 ChannelProperties.getProperty("app_name"));
1161 System.setProperty("apple.laf.useScreenMenuBar", "true");
1163 * broken native LAFs on (ARM?) macbooks
1164 set = setQuaquaLookAndFeel();
1165 if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1166 .toLowerCase(Locale.ROOT).contains("quaqua"))
1168 set = setVaquaLookAndFeel();
1171 set = setFlatLookAndFeel();
1175 private static void showUsage()
1178 "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1179 + "-nodisplay\tRun Jalview without User Interface.\n"
1180 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1181 + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1182 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1183 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1184 + "-features FILE\tUse the given file to mark features on the alignment.\n"
1185 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1186 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1187 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1188 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1189 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1190 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1191 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1192 + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1193 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1194 + "-png FILE\tCreate PNG image FILE from alignment.\n"
1195 + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1196 + "-html FILE\tCreate HTML file from alignment.\n"
1197 + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1198 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1199 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1200 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1201 + "-noquestionnaire\tTurn off questionnaire check.\n"
1202 + "-nonews\tTurn off check for Jalview news.\n"
1203 + "-nousagestats\tTurn off google analytics tracking for this session.\n"
1204 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1206 // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1207 // after all other properties files have been read\n\t
1208 // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1209 // passed in correctly)"
1210 + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1211 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1212 + "-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"
1213 + "-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"
1214 + "-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"
1215 + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
1218 private static void startUsageStats(final Desktop desktop)
1221 * start a User Config prompt asking if we can log usage statistics.
1223 PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
1224 "USAGESTATS", "Jalview Usage Statistics",
1225 "Do you want to help make Jalview better by enabling "
1226 + "the collection of usage statistics with Google Analytics ?"
1227 + "\n\n(you can enable or disable usage tracking in the preferences)",
1234 "Initialising googletracker for usage stats.");
1235 Cache.initGoogleTracker();
1236 Console.debug("Tracking enabled.");
1243 Console.debug("Not enabling Google Tracking.");
1246 desktop.addDialogThread(prompter);
1250 * Locate the given string as a file and pass it to the groovy interpreter.
1252 * @param groovyscript
1253 * the script to execute
1254 * @param jalviewContext
1255 * the Jalview Desktop object passed in to the groovy binding as the
1258 private void executeGroovyScript(String groovyscript, AlignFrame af)
1261 * for scripts contained in files
1268 if (groovyscript.trim().equals("STDIN"))
1270 // read from stdin into a tempfile and execute it
1273 tfile = File.createTempFile("jalview", "groovy");
1274 PrintWriter outfile = new PrintWriter(
1275 new OutputStreamWriter(new FileOutputStream(tfile)));
1276 BufferedReader br = new BufferedReader(
1277 new InputStreamReader(System.in));
1279 while ((line = br.readLine()) != null)
1281 outfile.write(line + "\n");
1287 } catch (Exception ex)
1289 System.err.println("Failed to read from STDIN into tempfile "
1290 + ((tfile == null) ? "(tempfile wasn't created)"
1291 : tfile.toString()));
1292 ex.printStackTrace();
1297 sfile = tfile.toURI().toURL();
1298 } catch (Exception x)
1301 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1303 x.printStackTrace();
1311 sfile = new URI(groovyscript).toURL();
1312 } catch (Exception x)
1314 tfile = new File(groovyscript);
1315 if (!tfile.exists())
1317 System.err.println("File '" + groovyscript + "' does not exist.");
1320 if (!tfile.canRead())
1322 System.err.println("File '" + groovyscript + "' cannot be read.");
1325 if (tfile.length() < 1)
1327 System.err.println("File '" + groovyscript + "' is empty.");
1332 sfile = tfile.getAbsoluteFile().toURI().toURL();
1333 } catch (Exception ex)
1335 System.err.println("Failed to create a file URL for "
1336 + tfile.getAbsoluteFile());
1343 Map<String, java.lang.Object> vbinding = new HashMap<>();
1344 vbinding.put("Jalview", this);
1347 vbinding.put("currentAlFrame", af);
1349 Binding gbinding = new Binding(vbinding);
1350 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1351 gse.run(sfile.toString(), gbinding);
1352 if ("STDIN".equals(groovyscript))
1354 // delete temp file that we made -
1355 // only if it was successfully executed
1358 } catch (Exception e)
1360 System.err.println("Exception Whilst trying to execute file " + sfile
1361 + " as a groovy script.");
1362 e.printStackTrace(System.err);
1367 public static boolean isHeadlessMode()
1369 String isheadless = System.getProperty("java.awt.headless");
1370 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1377 public AlignFrame[] getAlignFrames()
1379 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1380 : Desktop.getAlignFrames();
1385 * Quit method delegates to Desktop.quit - unless running in headless mode
1386 * when it just ends the JVM
1390 if (desktop != null)
1400 public static AlignFrame getCurrentAlignFrame()
1402 return Jalview.currentAlignFrame;
1405 public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
1407 Jalview.currentAlignFrame = currentAlignFrame;