import jalview.gui.AlignFrame;
import jalview.gui.Desktop;
import jalview.gui.PromptUserConfig;
+import jalview.gui.QuitHandler;
+import jalview.gui.QuitHandler.QResponse;
import jalview.io.AppletFormatAdapter;
import jalview.io.BioJsHTMLOutput;
import jalview.io.DataSourceType;
if (!Platform.isJS())
{
System.setSecurityManager(null);
+
+ Runtime.getRuntime().addShutdownHook(new Thread()
+ {
+ public void run()
+ {
+ Console.debug("Running shutdown hook");
+ if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
+ {
+ // Got to here by a SIGTERM signal.
+ // Note we will not actually cancel the quit from here -- it's too
+ // late -- but we can wait for saving files.
+ Console.debug("Checking for saving files");
+ QuitHandler.getQuitResponse(false);
+ }
+ else
+ {
+ Console.debug("Nothing more to do");
+ }
+ Console.debug("Exiting, bye!");
+ // shutdownHook cannot be cancelled, JVM will now halt
+ }
+ });
}
System.out
System.out.println(System.getProperty("os.arch") + " "
+ System.getProperty("os.name") + " "
+ System.getProperty("os.version"));
+
String val = System.getProperty("sys.install4jVersion");
if (val != null)
{
Cache.loadBuildProperties(true);
ArgsParser aparser = new ArgsParser(args);
+
boolean headless = false;
String usrPropsFile = aparser.getValue("props");
- Cache.loadProperties(usrPropsFile); // must do this before
+ Cache.loadProperties(usrPropsFile); // must do this
+ // before
if (usrPropsFile != null)
{
System.out.println(
try
{
Console.initLogger();
- } catch (NoClassDefFoundError error)
+ } catch (
+
+ NoClassDefFoundError error)
{
error.printStackTrace();
System.out.println("\nEssential logging libraries not found."
}
String file = null, data = null;
+
FileFormatI format = null;
+
DataSourceType protocol = null;
+
FileLoader fileLoader = new FileLoader(!headless);
String groovyscript = null; // script to execute after all loading is
System.out.println("No files to open!");
System.exit(1);
}
+
long progress = -1;
// Finally, deal with the remaining input data.
if (file != null)
}
}
}
+
AlignFrame startUpAlframe = null;
// We'll only open the default file if the desktop is visible.
// And the user
setSystemLookAndFeel();
if (Platform.isLinux())
{
- setMetalLookAndFeel();
+ setLinuxLookAndFeel();
}
if (Platform.isMac())
{
return set;
}
+ private static boolean setLinuxLookAndFeel()
+ {
+ boolean set = false;
+ set = setFlatLookAndFeel();
+ if (!set)
+ set = setMetalLookAndFeel();
+ // avoid GtkLookAndFeel -- not good results especially on HiDPI
+ if (!set)
+ set = setNimbusLookAndFeel();
+ return set;
+ }
+
private static void showUsage()
{
System.out.println(
}
/**
- * Quit method delegates to Desktop.quit - unless running in headless mode
- * when it just ends the JVM
+ * jalview.bin.Jalview.quit() will just run the non-GUI shutdownHook and exit
*/
public void quit()
{
- if (desktop != null)
- {
- desktop.quit();
- }
- else
- {
- System.exit(0);
- }
+ // System.exit will run the shutdownHook first
+ System.exit(0);
}
public static AlignFrame getCurrentAlignFrame()
import java.util.ListIterator;
import java.util.Locale;
import java.util.Vector;
+import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
+import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkEvent.EventType;
import javax.swing.event.InternalFrameAdapter;
import jalview.bin.Cache;
import jalview.bin.Jalview;
import jalview.gui.ImageExporter.ImageWriterI;
+import jalview.gui.QuitHandler.QResponse;
import jalview.io.BackupFiles;
import jalview.io.DataSourceType;
import jalview.io.FileFormat;
{
DRAG_MODE = b ? JDesktopPane.LIVE_DRAG_MODE
: JDesktopPane.OUTLINE_DRAG_MODE;
+ if (desktop != null)
+ desktop.setDragMode(DRAG_MODE);
}
private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
setIconImages(ChannelProperties.getIconList());
+ // override quit handling when GUI OS close [X] button pressed
+ this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent ev)
{
- quit();
+ QuitHandler.QResponse ret = desktopQuit(true, true); // ui, disposeFlag
}
});
this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
- this.addWindowListener(new WindowAdapter()
- {
- @Override
- public void windowClosing(WindowEvent evt)
- {
- quit();
- }
- });
-
MouseAdapter ma;
this.addMouseListener(ma = new MouseAdapter()
{
MessageManager.getString("label.open_local_file"));
chooser.setToolTipText(MessageManager.getString("action.open"));
- chooser.setResponseHandler(0, new Runnable()
- {
- @Override
- public void run()
- {
- File selectedFile = chooser.getSelectedFile();
- Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
+ chooser.setResponseHandler(0, () -> {
+ File selectedFile = chooser.getSelectedFile();
+ Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
- FileFormatI format = chooser.getSelectedFormat();
+ FileFormatI format = chooser.getSelectedFormat();
- /*
- * Call IdentifyFile to verify the file contains what its extension implies.
- * Skip this step for dynamically added file formats, because IdentifyFile does
- * not know how to recognise them.
- */
- if (FileFormats.getInstance().isIdentifiable(format))
+ /*
+ * Call IdentifyFile to verify the file contains what its extension implies.
+ * Skip this step for dynamically added file formats, because IdentifyFile does
+ * not know how to recognise them.
+ */
+ if (FileFormats.getInstance().isIdentifiable(format))
+ {
+ try
{
- try
- {
- format = new IdentifyFile().identify(selectedFile,
- DataSourceType.FILE);
- } catch (FileFormatException e)
- {
- // format = null; //??
- }
+ format = new IdentifyFile().identify(selectedFile,
+ DataSourceType.FILE);
+ } catch (FileFormatException e)
+ {
+ // format = null; //??
}
-
- new FileLoader().LoadFile(viewport, selectedFile,
- DataSourceType.FILE, format);
}
+
+ new FileLoader().LoadFile(viewport, selectedFile, DataSourceType.FILE,
+ format);
+ return null;
});
chooser.showOpenDialog(this);
}
Object[] options = new Object[] { MessageManager.getString("action.ok"),
MessageManager.getString("action.cancel") };
- Runnable action = new Runnable()
- {
- @Override
- public void run()
+ Callable<Void> action = () -> {
+ @SuppressWarnings("unchecked")
+ String url = (history instanceof JTextField
+ ? ((JTextField) history).getText()
+ : ((JComboBox<String>) history).getEditor().getItem()
+ .toString().trim());
+
+ if (url.toLowerCase(Locale.ROOT).endsWith(".jar"))
{
- @SuppressWarnings("unchecked")
- String url = (history instanceof JTextField
- ? ((JTextField) history).getText()
- : ((JComboBox<String>) history).getEditor().getItem()
- .toString().trim());
-
- if (url.toLowerCase(Locale.ROOT).endsWith(".jar"))
+ if (viewport != null)
{
- if (viewport != null)
- {
- new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
- FileFormat.Jalview);
- }
- else
- {
- new FileLoader().LoadFile(url, DataSourceType.URL,
- FileFormat.Jalview);
- }
+ new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
+ FileFormat.Jalview);
}
else
{
- FileFormatI format = null;
- try
- {
- format = new IdentifyFile().identify(url, DataSourceType.URL);
- } catch (FileFormatException e)
- {
- // TODO revise error handling, distinguish between
- // URL not found and response not valid
- }
+ new FileLoader().LoadFile(url, DataSourceType.URL,
+ FileFormat.Jalview);
+ }
+ }
+ else
+ {
+ FileFormatI format = null;
+ try
+ {
+ format = new IdentifyFile().identify(url, DataSourceType.URL);
+ } catch (FileFormatException e)
+ {
+ // TODO revise error handling, distinguish between
+ // URL not found and response not valid
+ }
- if (format == null)
- {
- String msg = MessageManager
- .formatMessage("label.couldnt_locate", url);
- JvOptionPane.showInternalMessageDialog(Desktop.desktop, msg,
- MessageManager.getString("label.url_not_found"),
- JvOptionPane.WARNING_MESSAGE);
+ if (format == null)
+ {
+ String msg = MessageManager.formatMessage("label.couldnt_locate",
+ url);
+ JvOptionPane.showInternalMessageDialog(Desktop.desktop, msg,
+ MessageManager.getString("label.url_not_found"),
+ JvOptionPane.WARNING_MESSAGE);
- return;
- }
+ return null; // Void
+ }
- if (viewport != null)
- {
- new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
- format);
- }
- else
- {
- new FileLoader().LoadFile(url, DataSourceType.URL, format);
- }
+ if (viewport != null)
+ {
+ new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
+ format);
+ }
+ else
+ {
+ new FileLoader().LoadFile(url, DataSourceType.URL, format);
}
}
+ return null; // Void
};
String dialogOption = MessageManager
.getString("label.input_alignment_from_url");
}
/*
- * Exit the program
+ * Check with user and saving files before actually quitting
*/
- @Override
- public void quit()
+ public void desktopQuit()
{
- Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
- Cache.setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
- Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height + "");
- storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
- getWidth(), getHeight()));
+ desktopQuit(true, false);
+ }
- if (jconsole != null)
- {
- storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
- jconsole.stopConsole();
- }
- if (jvnews != null)
- {
- storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
+ public QuitHandler.QResponse desktopQuit(boolean ui, boolean disposeFlag)
+ {
+ final Callable<Void> doDesktopQuit = () -> {
+ Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+ Cache.setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
+ Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height + "");
+ storeLastKnownDimensions("", new Rectangle(getBounds().x,
+ getBounds().y, getWidth(), getHeight()));
- }
- if (dialogExecutor != null)
- {
- dialogExecutor.shutdownNow();
- }
- closeAll_actionPerformed(null);
+ if (jconsole != null)
+ {
+ storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
+ jconsole.stopConsole();
+ }
- if (groovyConsole != null)
- {
- // suppress a possible repeat prompt to save script
- groovyConsole.setDirty(false);
- groovyConsole.exit();
- }
+ if (jvnews != null)
+ {
+ storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
+
+ }
+
+ if (dialogExecutor != null)
+ {
+ dialogExecutor.shutdownNow();
+ }
+
+ closeAll_actionPerformed(null);
+
+ if (groovyConsole != null)
+ {
+ // suppress a possible repeat prompt to save script
+ groovyConsole.setDirty(false);
+ groovyConsole.exit();
+ }
+
+ if (QuitHandler.gotQuitResponse() == QResponse.FORCE_QUIT)
+ {
+ // note that shutdown hook will not be run
+ jalview.bin.Console.debug("Force Quit selected by user");
+ Runtime.getRuntime().halt(0);
+ }
+
+ jalview.bin.Console.debug("Quit selected by user");
+ if (disposeFlag)
+ {
+ instance.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ // instance.dispose();
+ }
+ instance.quit();
+
+ return null; // Void
+ };
+
+ return QuitHandler.getQuitResponse(ui, doDesktopQuit, doDesktopQuit,
+ QuitHandler.defaultCancelQuit);
+ }
+
+ /**
+ * Don't call this directly, use desktopQuit() above. Exits the program.
+ */
+ @Override
+ public void quit()
+ {
+ // this will run the shutdownHook but QuitHandler.getQuitResponse() should
+ // not run a second time if gotQuitResponse flag has been set (i.e. user
+ // confirmed quit of some kind).
System.exit(0);
}
saveState_actionPerformed(true);
}
- private void setProjectFile(File choice)
+ protected void setProjectFile(File choice)
{
this.projectFile = choice;
}
// allowBackupFiles
chooser.setFileView(new JalviewFileView());
chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
- chooser.setResponseHandler(0, new Runnable()
- {
- @Override
- public void run()
+ chooser.setResponseHandler(0, () -> {
+ File selectedFile = chooser.getSelectedFile();
+ setProjectFile(selectedFile);
+ String choice = selectedFile.getAbsolutePath();
+ Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
+ new Thread(new Runnable()
{
- File selectedFile = chooser.getSelectedFile();
- setProjectFile(selectedFile);
- String choice = selectedFile.getAbsolutePath();
- Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
- new Thread(new Runnable()
+ @Override
+ public void run()
{
- @Override
- public void run()
+ try
{
- try
- {
- new Jalview2XML().loadJalviewAlign(selectedFile);
- } catch (OutOfMemoryError oom)
- {
- new OOMWarning("Whilst loading project from " + choice, oom);
- } catch (Exception ex)
- {
- jalview.bin.Console.error(
- "Problems whilst loading project from " + choice, ex);
- JvOptionPane.showMessageDialog(Desktop.desktop,
- MessageManager.formatMessage(
- "label.error_whilst_loading_project_from",
- new Object[]
- { choice }),
- MessageManager
- .getString("label.couldnt_load_project"),
- JvOptionPane.WARNING_MESSAGE);
- }
+ new Jalview2XML().loadJalviewAlign(selectedFile);
+ } catch (OutOfMemoryError oom)
+ {
+ new OOMWarning("Whilst loading project from " + choice, oom);
+ } catch (Exception ex)
+ {
+ jalview.bin.Console.error(
+ "Problems whilst loading project from " + choice, ex);
+ JvOptionPane.showMessageDialog(Desktop.desktop,
+ MessageManager.formatMessage(
+ "label.error_whilst_loading_project_from",
+ new Object[]
+ { choice }),
+ MessageManager.getString("label.couldnt_load_project"),
+ JvOptionPane.WARNING_MESSAGE);
}
- }, "Project Loader").start();
- }
+ }
+ }, "Project Loader").start();
+ return null;
});
chooser.showOpenDialog(this);
@Override
public void actionPerformed(ActionEvent e)
{
- quit();
+ desktopQuit();
}
});
}