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.gui.QuitHandler;
65 import jalview.gui.QuitHandler.QResponse;
66 import jalview.io.AppletFormatAdapter;
67 import jalview.io.BioJsHTMLOutput;
68 import jalview.io.DataSourceType;
69 import jalview.io.FileFormat;
70 import jalview.io.FileFormatException;
71 import jalview.io.FileFormatI;
72 import jalview.io.FileFormats;
73 import jalview.io.FileLoader;
74 import jalview.io.HtmlSvgOutput;
75 import jalview.io.IdentifyFile;
76 import jalview.io.NewickFile;
77 import jalview.io.gff.SequenceOntologyFactory;
78 import jalview.schemes.ColourSchemeI;
79 import jalview.schemes.ColourSchemeProperty;
80 import jalview.util.ChannelProperties;
81 import jalview.util.HttpUtils;
82 import jalview.util.LaunchUtils;
83 import jalview.util.MessageManager;
84 import jalview.util.Platform;
85 import jalview.ws.jws2.Jws2Discoverer;
88 * Main class for Jalview Application <br>
90 * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
93 * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
94 * jalview.bin.Jalview jalview.bin.Jalview
96 * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
97 * embellish '*' to e.g. '*.jar')
100 * @version $Revision$
106 Platform.getURLCommandArguments();
107 Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
108 Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
109 Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
110 Platform.addJ2SDirectDatabaseCall("https://www.compbio.dundee.ac.uk");
114 * singleton instance of this class
116 private static Jalview instance;
118 private Desktop desktop;
120 public static AlignFrame currentAlignFrame;
124 if (!Platform.isJS())
131 // grab all the rights we can for the JVM
132 Policy.setPolicy(new Policy()
135 public PermissionCollection getPermissions(CodeSource codesource)
137 Permissions perms = new Permissions();
138 perms.add(new AllPermission());
143 public void refresh()
151 * keep track of feature fetching tasks.
159 * TODO: generalise to track all jalview events to orchestrate batch processing
163 private int queued = 0;
165 private int running = 0;
167 public FeatureFetcher()
172 public void addFetcher(final AlignFrame af,
173 final Vector<String> dasSources)
175 final long id = System.currentTimeMillis();
177 final FeatureFetcher us = this;
178 new Thread(new Runnable()
190 af.setProgressBar(MessageManager
191 .getString("status.das_features_being_retrived"), id);
192 af.featureSettings_actionPerformed(null);
193 af.setProgressBar(null, id);
202 public synchronized boolean allFinished()
204 return queued == 0 && running == 0;
209 public static Jalview getInstance()
215 * main class for Jalview application
218 * open <em>filename</em>
220 public static void main(String[] args)
222 // setLogging(); // BH - for event debugging in JavaScript
223 instance = new Jalview();
224 instance.doMain(args);
227 private static void logClass(String name)
229 // BH - for event debugging in JavaScript
230 ConsoleHandler consoleHandler = new ConsoleHandler();
231 consoleHandler.setLevel(Level.ALL);
232 Logger logger = Logger.getLogger(name);
233 logger.setLevel(Level.ALL);
234 logger.addHandler(consoleHandler);
237 @SuppressWarnings("unused")
238 private static void setLogging()
246 System.out.println("not in js");
249 // BH - for event debugging in JavaScript (Java mode only)
250 if (!Platform.isJS())
257 Logger.getLogger("").setLevel(Level.ALL);
258 logClass("java.awt.EventDispatchThread");
259 logClass("java.awt.EventQueue");
260 logClass("java.awt.Component");
261 logClass("java.awt.focus.Component");
262 logClass("java.awt.focus.DefaultKeyboardFocusManager");
270 void doMain(String[] args)
273 if (!Platform.isJS())
275 System.setSecurityManager(null);
277 Runtime.getRuntime().addShutdownHook(new Thread()
281 Console.debug("Running shutdown hook");
282 if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
284 // Got to here by a SIGTERM signal.
285 // Note we will not actually cancel the quit from here -- it's too
286 // late -- but we can wait for saving files.
287 Console.debug("Checking for saving files");
288 QuitHandler.getQuitResponse(false);
292 Console.debug("Nothing more to do");
294 Console.debug("Exiting, bye!");
295 // shutdownHook cannot be cancelled, JVM will now halt
301 .println("Java version: " + System.getProperty("java.version"));
302 System.out.println("Java Home: " + System.getProperty("java.home"));
303 System.out.println(System.getProperty("os.arch") + " "
304 + System.getProperty("os.name") + " "
305 + System.getProperty("os.version"));
307 String val = System.getProperty("sys.install4jVersion");
310 System.out.println("Install4j version: " + val);
312 val = System.getProperty("installer_template_version");
315 System.out.println("Install4j template version: " + val);
317 val = System.getProperty("launcher_version");
320 System.out.println("Launcher version: " + val);
323 // report Jalview version
324 Cache.loadBuildProperties(true);
326 ArgsParser aparser = new ArgsParser(args);
328 boolean headless = false;
330 String usrPropsFile = aparser.getValue("props");
331 Cache.loadProperties(usrPropsFile); // must do this
333 if (usrPropsFile != null)
336 "CMD [-props " + usrPropsFile + "] executed successfully!");
339 if (!Platform.isJS())
346 if (aparser.contains("help") || aparser.contains("h"))
351 if (aparser.contains("nodisplay") || aparser.contains("nogui")
352 || aparser.contains("headless"))
354 System.setProperty("java.awt.headless", "true");
359 // allow https handshakes to download intermediate certs if necessary
360 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
362 final String jabawsUrl = aparser.getValue("jabaws");
363 if (jabawsUrl != null)
367 Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
369 "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
370 } catch (MalformedURLException e)
373 "Invalid jabaws parameter: " + jabawsUrl + " ignored");
378 String defs = aparser.getValue("setprop");
381 int p = defs.indexOf('=');
384 System.err.println("Ignoring invalid setprop argument : " + defs);
388 System.out.println("Executing setprop argument: " + defs);
391 Cache.setProperty(defs.substring(0, p), defs.substring(p + 1));
393 // DISABLED FOR SECURITY REASONS
394 // TODO: add a property to allow properties to be overriden by cli args
395 // Cache.setProperty(defs.substring(0,p), defs.substring(p+1));
397 defs = aparser.getValue("setprop");
399 if (System.getProperty("java.awt.headless") != null
400 && System.getProperty("java.awt.headless").equals("true"))
404 System.setProperty("http.agent",
405 "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
409 Console.initLogger();
412 NoClassDefFoundError error)
414 error.printStackTrace();
415 System.out.println("\nEssential logging libraries not found."
416 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview");
425 * configure 'full' SO model if preferences say to, else use the default (full SO)
426 * - as JS currently doesn't have OBO parsing, it must use 'Lite' version
428 boolean soDefault = !Platform.isJS();
429 if (Cache.getDefault("USE_FULL_SO", soDefault))
431 SequenceOntologyFactory.setInstance(new SequenceOntology());
436 Desktop.nosplash = aparser.contains("nosplash");
437 desktop = new Desktop();
438 desktop.setInBatchMode(true); // indicate we are starting up
442 JalviewTaskbar.setTaskbar(this);
443 } catch (Exception e)
445 Console.info("Cannot set Taskbar");
446 Console.error(e.getMessage());
447 // e.printStackTrace();
448 } catch (Throwable t)
450 Console.info("Cannot set Taskbar");
451 Console.error(t.getMessage());
452 // t.printStackTrace();
455 // set Proxy settings before all the internet calls
456 Cache.setProxyPropertiesFromPreferences();
458 desktop.setVisible(true);
460 if (!Platform.isJS())
469 * Check to see that the JVM version being run is suitable for the Java
470 * version this Jalview was compiled for. Popup a warning if not.
472 if (!LaunchUtils.checkJavaVersion())
474 Console.warn("The Java version being used (Java "
475 + LaunchUtils.getJavaVersion()
476 + ") may lead to problems. This installation of Jalview should be used with Java "
477 + LaunchUtils.getJavaCompileVersion() + ".");
480 .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
483 MessageManager.getString("label.continue") };
484 JOptionPane.showOptionDialog(null,
485 MessageManager.formatMessage(
486 "warning.wrong_jvm_version_message",
487 LaunchUtils.getJavaVersion(),
488 LaunchUtils.getJavaCompileVersion()),
490 .getString("warning.wrong_jvm_version_title"),
491 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
492 null, options, options[0]);
496 if (!aparser.contains("nowebservicediscovery"))
498 desktop.startServiceDiscovery();
500 if (!aparser.contains("nousagestats"))
502 startUsageStats(desktop);
506 System.err.println("CMD [-nousagestats] executed successfully!");
509 if (!aparser.contains("noquestionnaire"))
511 String url = aparser.getValue("questionnaire");
514 // Start the desktop questionnaire prompter with the specified
516 Console.debug("Starting questionnaire url at " + url);
517 desktop.checkForQuestionnaire(url);
518 System.out.println("CMD questionnaire[-" + url
519 + "] executed successfully!");
523 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
525 // Start the desktop questionnaire prompter with the specified
528 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
530 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
532 "Starting questionnaire with default url: " + defurl);
533 desktop.checkForQuestionnaire(defurl);
540 .println("CMD [-noquestionnaire] executed successfully!");
543 if (!aparser.contains("nonews")
544 || Cache.getProperty("NONEWS") == null)
546 desktop.checkForNews();
549 if (!aparser.contains("nohtmltemplates")
550 || Cache.getProperty("NOHTMLTEMPLATES") == null)
552 BioJsHTMLOutput.updateBioJS();
557 // Check if JVM and compile version might cause problems and log if it
559 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
561 Console.warn("The Java version being used (Java "
562 + LaunchUtils.getJavaVersion()
563 + ") may lead to problems. This installation of Jalview should be used with Java "
564 + LaunchUtils.getJavaCompileVersion() + ".");
567 // Move any new getdown-launcher-new.jar into place over old
568 // getdown-launcher.jar
569 String appdirString = System.getProperty("getdownappdir");
570 if (appdirString != null && appdirString.length() > 0)
572 final File appdir = new File(appdirString);
578 LaunchUtil.upgradeGetdown(
579 new File(appdir, "getdown-launcher-old.jar"),
580 new File(appdir, "getdown-launcher.jar"),
581 new File(appdir, "getdown-launcher-new.jar"));
586 String file = null, data = null;
588 FileFormatI format = null;
590 DataSourceType protocol = null;
592 FileLoader fileLoader = new FileLoader(!headless);
594 String groovyscript = null; // script to execute after all loading is
595 // completed one way or another
596 // extract groovy argument and execute if necessary
597 groovyscript = aparser.getValue("groovy", true);
598 file = aparser.getValue("open", true);
600 if (file == null && desktop == null)
602 System.out.println("No files to open!");
607 // Finally, deal with the remaining input data.
612 desktop.setProgressBar(
614 .getString("status.processing_commandline_args"),
615 progress = System.currentTimeMillis());
617 System.out.println("CMD [-open " + file + "] executed successfully!");
619 if (!Platform.isJS())
621 * ignore in JavaScript -- can't just file existence - could load it?
626 if (!HttpUtils.startsWithHttpOrHttps(file))
628 if (!(new File(file)).exists())
630 System.out.println("Can't find " + file);
639 protocol = AppletFormatAdapter.checkProtocol(file);
643 format = new IdentifyFile().identify(file, protocol);
644 } catch (FileFormatException e1)
649 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
653 System.out.println("error");
657 setCurrentAlignFrame(af);
658 data = aparser.getValue("colour", true);
661 data.replaceAll("%20", " ");
663 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
664 af.getViewport(), af.getViewport().getAlignment(), data);
669 "CMD [-color " + data + "] executed successfully!");
674 // Must maintain ability to use the groups flag
675 data = aparser.getValue("groups", true);
678 af.parseFeaturesFile(data,
679 AppletFormatAdapter.checkProtocol(data));
680 // System.out.println("Added " + data);
682 "CMD groups[-" + data + "] executed successfully!");
684 data = aparser.getValue("features", true);
687 af.parseFeaturesFile(data,
688 AppletFormatAdapter.checkProtocol(data));
689 // System.out.println("Added " + data);
691 "CMD [-features " + data + "] executed successfully!");
694 data = aparser.getValue("annotations", true);
697 af.loadJalviewDataFile(data, null, null, null);
698 // System.out.println("Added " + data);
700 "CMD [-annotations " + data + "] executed successfully!");
702 // set or clear the sortbytree flag.
703 if (aparser.contains("sortbytree"))
705 af.getViewport().setSortByTree(true);
706 if (af.getViewport().getSortByTree())
708 System.out.println("CMD [-sortbytree] executed successfully!");
711 if (aparser.contains("no-annotation"))
713 af.getViewport().setShowAnnotation(false);
714 if (!af.getViewport().isShowAnnotation())
716 System.out.println("CMD no-annotation executed successfully!");
719 if (aparser.contains("nosortbytree"))
721 af.getViewport().setSortByTree(false);
722 if (!af.getViewport().getSortByTree())
725 .println("CMD [-nosortbytree] executed successfully!");
728 data = aparser.getValue("tree", true);
734 "CMD [-tree " + data + "] executed successfully!");
735 NewickFile nf = new NewickFile(data,
736 AppletFormatAdapter.checkProtocol(data));
738 .setCurrentTree(af.showNewickTree(nf, data).getTree());
739 } catch (IOException ex)
741 System.err.println("Couldn't add tree " + data);
742 ex.printStackTrace(System.err);
745 // TODO - load PDB structure(s) to alignment JAL-629
746 // (associate with identical sequence in alignment, or a specified
748 if (groovyscript != null)
750 // Execute the groovy script after we've done all the rendering stuff
751 // and before any images or figures are generated.
752 System.out.println("Executing script " + groovyscript);
753 executeGroovyScript(groovyscript, af);
754 System.out.println("CMD groovy[" + groovyscript
755 + "] executed successfully!");
758 String imageName = "unnamed.png";
759 while (aparser.getSize() > 1)
761 String outputFormat = aparser.nextValue();
762 file = aparser.nextValue();
764 if (outputFormat.equalsIgnoreCase("png"))
766 af.createPNG(new File(file));
767 imageName = (new File(file)).getName();
768 System.out.println("Creating PNG image: " + file);
771 else if (outputFormat.equalsIgnoreCase("svg"))
773 File imageFile = new File(file);
774 imageName = imageFile.getName();
775 af.createSVG(imageFile);
776 System.out.println("Creating SVG image: " + file);
779 else if (outputFormat.equalsIgnoreCase("html"))
781 File imageFile = new File(file);
782 imageName = imageFile.getName();
783 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
784 htmlSVG.exportHTML(file);
786 System.out.println("Creating HTML image: " + file);
789 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
793 System.err.println("The output html file must not be null");
798 BioJsHTMLOutput.refreshVersionInfo(
799 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
800 } catch (URISyntaxException e)
804 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
805 bjs.exportHTML(file);
807 .println("Creating BioJS MSA Viwer HTML file: " + file);
810 else if (outputFormat.equalsIgnoreCase("imgMap"))
812 af.createImageMap(new File(file), imageName);
813 System.out.println("Creating image map: " + file);
816 else if (outputFormat.equalsIgnoreCase("eps"))
818 File outputFile = new File(file);
820 "Creating EPS file: " + outputFile.getAbsolutePath());
821 af.createEPS(outputFile);
824 FileFormatI outFormat = null;
827 outFormat = FileFormats.getInstance().forName(outputFormat);
828 } catch (Exception formatP)
830 System.out.println("Couldn't parse " + outFormat
831 + " as a valid Jalview format string.");
833 if (outFormat != null)
835 if (!outFormat.isWritable())
838 "This version of Jalview does not support alignment export as "
843 af.saveAlignment(file, outFormat);
844 if (af.isSaveAlignmentSuccessful())
846 System.out.println("Written alignment in "
847 + outFormat.getName() + " format to " + file);
851 System.out.println("Error writing file " + file + " in "
852 + outFormat.getName() + " format!!");
859 while (aparser.getSize() > 0)
861 System.out.println("Unknown arg: " + aparser.nextValue());
866 AlignFrame startUpAlframe = null;
867 // We'll only open the default file if the desktop is visible.
869 // ////////////////////
871 if (!Platform.isJS() && !headless && file == null
872 && Cache.getDefault("SHOW_STARTUP_FILE", true))
879 file = Cache.getDefault("STARTUP_FILE",
880 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
881 + "/examples/exampleFile_2_7.jvp");
882 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
884 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
886 file.replace("http:", "https:");
887 // hardwire upgrade of the startup file
888 file.replace("_2_3", "_2_7");
889 file.replace("2_7.jar", "2_7.jvp");
890 // and remove the stale setting
891 Cache.removeProperty("STARTUP_FILE");
894 protocol = AppletFormatAdapter.checkProtocol(file);
896 if (file.endsWith(".jar"))
898 format = FileFormat.Jalview;
904 format = new IdentifyFile().identify(file, protocol);
905 } catch (FileFormatException e)
911 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
913 // extract groovy arguments before anything else.
916 // Once all other stuff is done, execute any groovy scripts (in order)
917 if (groovyscript != null)
919 if (Cache.groovyJarsPresent())
921 System.out.println("Executing script " + groovyscript);
922 executeGroovyScript(groovyscript, startUpAlframe);
927 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
931 // and finally, turn off batch mode indicator - if the desktop still exists
936 desktop.setProgressBar(null, progress);
938 desktop.setInBatchMode(false);
942 private static void setLookAndFeel()
944 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
946 // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
948 String lafProp = System.getProperty("laf");
949 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
955 else if (lafSetting != null)
959 boolean lafSet = false;
962 case "crossplatform":
963 lafSet = setCrossPlatformLookAndFeel();
966 Console.error("Could not set requested laf=" + laf);
970 lafSet = setSystemLookAndFeel();
973 Console.error("Could not set requested laf=" + laf);
977 lafSet = setGtkLookAndFeel();
980 Console.error("Could not set requested laf=" + laf);
984 lafSet = setMetalLookAndFeel();
987 Console.error("Could not set requested laf=" + laf);
991 lafSet = setNimbusLookAndFeel();
994 Console.error("Could not set requested laf=" + laf);
998 lafSet = setFlatLookAndFeel();
1001 Console.error("Could not set requested laf=" + laf);
1005 lafSet = setQuaquaLookAndFeel();
1008 Console.error("Could not set requested laf=" + laf);
1012 lafSet = setVaquaLookAndFeel();
1015 Console.error("Could not set requested laf=" + laf);
1019 lafSet = setMacLookAndFeel();
1022 Console.error("Could not set requested laf=" + laf);
1028 Console.error("Requested laf=" + laf + " not implemented");
1032 setSystemLookAndFeel();
1033 if (Platform.isLinux())
1035 setMetalLookAndFeel();
1037 if (Platform.isMac())
1039 setMacLookAndFeel();
1044 private static boolean setCrossPlatformLookAndFeel()
1046 boolean set = false;
1049 UIManager.setLookAndFeel(
1050 UIManager.getCrossPlatformLookAndFeelClassName());
1052 } catch (Exception ex)
1054 Console.error("Unexpected Look and Feel Exception");
1055 Console.error(ex.getMessage());
1056 Console.debug(Cache.getStackTraceString(ex));
1061 private static boolean setSystemLookAndFeel()
1063 boolean set = false;
1066 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
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 setSpecificLookAndFeel(String name,
1078 String className, boolean nameStartsWith)
1080 boolean set = false;
1083 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1085 if (info.getName() != null && nameStartsWith
1086 ? info.getName().toLowerCase(Locale.ROOT)
1087 .startsWith(name.toLowerCase(Locale.ROOT))
1088 : info.getName().toLowerCase(Locale.ROOT)
1089 .equals(name.toLowerCase(Locale.ROOT)))
1091 className = info.getClassName();
1095 UIManager.setLookAndFeel(className);
1097 } catch (Exception ex)
1099 Console.error("Unexpected Look and Feel Exception");
1100 Console.error(ex.getMessage());
1101 Console.debug(Cache.getStackTraceString(ex));
1106 private static boolean setGtkLookAndFeel()
1108 return setSpecificLookAndFeel("gtk",
1109 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1112 private static boolean setMetalLookAndFeel()
1114 return setSpecificLookAndFeel("metal",
1115 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1118 private static boolean setNimbusLookAndFeel()
1120 return setSpecificLookAndFeel("nimbus",
1121 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1124 private static boolean setFlatLookAndFeel()
1126 boolean set = setSpecificLookAndFeel("flatlaf light",
1127 "com.formdev.flatlaf.FlatLightLaf", false);
1130 if (Platform.isMac())
1132 System.setProperty("apple.laf.useScreenMenuBar", "true");
1133 System.setProperty("apple.awt.application.name",
1134 ChannelProperties.getProperty("app_name"));
1135 System.setProperty("apple.awt.application.appearance", "system");
1136 if (SystemInfo.isMacFullWindowContentSupported
1137 && Desktop.desktop != null)
1139 Desktop.desktop.getRootPane()
1140 .putClientProperty("apple.awt.fullWindowContent", true);
1141 Desktop.desktop.getRootPane()
1142 .putClientProperty("apple.awt.transparentTitleBar", true);
1145 SwingUtilities.invokeLater(() -> {
1146 FlatLightLaf.setup();
1150 UIManager.put("TabbedPane.showTabSeparators", true);
1151 UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1152 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1153 // UIManager.put("TabbedPane.hasFullBorder", true);
1154 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1155 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1156 UIManager.put("TabbedPane.smoothScrolling", true);
1157 UIManager.put("TabbedPane.tabWidthMode", "compact");
1158 UIManager.put("TabbedPane.selectedBackground", Color.white);
1163 private static boolean setQuaquaLookAndFeel()
1165 return setSpecificLookAndFeel("quaqua",
1166 ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel().getClass()
1171 private static boolean setVaquaLookAndFeel()
1173 return setSpecificLookAndFeel("vaqua",
1174 "org.violetlib.aqua.AquaLookAndFeel", false);
1177 private static boolean setMacLookAndFeel()
1179 boolean set = false;
1180 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1181 ChannelProperties.getProperty("app_name"));
1182 System.setProperty("apple.laf.useScreenMenuBar", "true");
1184 * broken native LAFs on (ARM?) macbooks
1185 set = setQuaquaLookAndFeel();
1186 if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1187 .toLowerCase(Locale.ROOT).contains("quaqua"))
1189 set = setVaquaLookAndFeel();
1192 set = setFlatLookAndFeel();
1196 private static void showUsage()
1199 "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1200 + "-nodisplay\tRun Jalview without User Interface.\n"
1201 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1202 + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1203 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1204 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1205 + "-features FILE\tUse the given file to mark features on the alignment.\n"
1206 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1207 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1208 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1209 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1210 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1211 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1212 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1213 + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1214 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1215 + "-png FILE\tCreate PNG image FILE from alignment.\n"
1216 + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1217 + "-html FILE\tCreate HTML file from alignment.\n"
1218 + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1219 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1220 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1221 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1222 + "-noquestionnaire\tTurn off questionnaire check.\n"
1223 + "-nonews\tTurn off check for Jalview news.\n"
1224 + "-nousagestats\tTurn off google analytics tracking for this session.\n"
1225 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1227 // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1228 // after all other properties files have been read\n\t
1229 // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1230 // passed in correctly)"
1231 + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1232 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1233 + "-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"
1234 + "-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"
1235 + "-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"
1236 + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
1239 private static void startUsageStats(final Desktop desktop)
1242 * start a User Config prompt asking if we can log usage statistics.
1244 PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
1245 "USAGESTATS", "Jalview Usage Statistics",
1246 "Do you want to help make Jalview better by enabling "
1247 + "the collection of usage statistics with Google Analytics ?"
1248 + "\n\n(you can enable or disable usage tracking in the preferences)",
1255 "Initialising googletracker for usage stats.");
1256 Cache.initGoogleTracker();
1257 Console.debug("Tracking enabled.");
1264 Console.debug("Not enabling Google Tracking.");
1267 desktop.addDialogThread(prompter);
1271 * Locate the given string as a file and pass it to the groovy interpreter.
1273 * @param groovyscript
1274 * the script to execute
1275 * @param jalviewContext
1276 * the Jalview Desktop object passed in to the groovy binding as the
1279 private void executeGroovyScript(String groovyscript, AlignFrame af)
1282 * for scripts contained in files
1289 if (groovyscript.trim().equals("STDIN"))
1291 // read from stdin into a tempfile and execute it
1294 tfile = File.createTempFile("jalview", "groovy");
1295 PrintWriter outfile = new PrintWriter(
1296 new OutputStreamWriter(new FileOutputStream(tfile)));
1297 BufferedReader br = new BufferedReader(
1298 new InputStreamReader(System.in));
1300 while ((line = br.readLine()) != null)
1302 outfile.write(line + "\n");
1308 } catch (Exception ex)
1310 System.err.println("Failed to read from STDIN into tempfile "
1311 + ((tfile == null) ? "(tempfile wasn't created)"
1312 : tfile.toString()));
1313 ex.printStackTrace();
1318 sfile = tfile.toURI().toURL();
1319 } catch (Exception x)
1322 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1324 x.printStackTrace();
1332 sfile = new URI(groovyscript).toURL();
1333 } catch (Exception x)
1335 tfile = new File(groovyscript);
1336 if (!tfile.exists())
1338 System.err.println("File '" + groovyscript + "' does not exist.");
1341 if (!tfile.canRead())
1343 System.err.println("File '" + groovyscript + "' cannot be read.");
1346 if (tfile.length() < 1)
1348 System.err.println("File '" + groovyscript + "' is empty.");
1353 sfile = tfile.getAbsoluteFile().toURI().toURL();
1354 } catch (Exception ex)
1356 System.err.println("Failed to create a file URL for "
1357 + tfile.getAbsoluteFile());
1364 Map<String, java.lang.Object> vbinding = new HashMap<>();
1365 vbinding.put("Jalview", this);
1368 vbinding.put("currentAlFrame", af);
1370 Binding gbinding = new Binding(vbinding);
1371 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1372 gse.run(sfile.toString(), gbinding);
1373 if ("STDIN".equals(groovyscript))
1375 // delete temp file that we made -
1376 // only if it was successfully executed
1379 } catch (Exception e)
1381 System.err.println("Exception Whilst trying to execute file " + sfile
1382 + " as a groovy script.");
1383 e.printStackTrace(System.err);
1388 public static boolean isHeadlessMode()
1390 String isheadless = System.getProperty("java.awt.headless");
1391 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1398 public AlignFrame[] getAlignFrames()
1400 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1401 : Desktop.getAlignFrames();
1406 * jalview.bin.Jalview.quit() will just run the non-GUI shutdownHook and exit
1410 // System.exit will run the shutdownHook first
1414 public static AlignFrame getCurrentAlignFrame()
1416 return Jalview.currentAlignFrame;
1419 public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
1421 Jalview.currentAlignFrame = currentAlignFrame;