X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fjbgui%2FQuitHandler.java;fp=src%2Fjalview%2Fjbgui%2FQuitHandler.java;h=0000000000000000000000000000000000000000;hb=4c007a518fc7e2fdaa863f16cb715f8e45e6cfbf;hp=7b5be98e31281a53810b19dcc0e1f8d7595ccce9;hpb=193fda2755ccc72dce5175fa5445348b6fdcc92e;p=jalview.git diff --git a/src/jalview/jbgui/QuitHandler.java b/src/jalview/jbgui/QuitHandler.java deleted file mode 100644 index 7b5be98..0000000 --- a/src/jalview/jbgui/QuitHandler.java +++ /dev/null @@ -1,406 +0,0 @@ -package jalview.jbgui; - -import java.io.File; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.JTextPane; - -import com.formdev.flatlaf.extras.FlatDesktop; - -import jalview.api.AlignmentViewPanel; -import jalview.bin.Cache; -import jalview.bin.Console; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.SequenceI; -import jalview.gui.AlignFrame; -import jalview.gui.Desktop; -import jalview.gui.JvOptionPane; -import jalview.io.BackupFiles; -import jalview.project.Jalview2XML; -import jalview.util.MessageManager; -import jalview.util.Platform; - -public class QuitHandler -{ - private static final int MIN_WAIT_FOR_SAVE = 3000; - - private static final int MAX_WAIT_FOR_SAVE = 20000; - - private static final int NON_INTERACTIVE_WAIT_CYCLES = 2; - - public static enum QResponse - { - NULL, QUIT, CANCEL_QUIT, FORCE_QUIT - }; - - private static ExecutorService executor = Executors.newFixedThreadPool(3); - - public static QResponse setQuitHandler() - { - FlatDesktop.setQuitHandler(response -> { - Callable performQuit = () -> { - response.performQuit(); - return setResponse(QResponse.QUIT); - }; - Callable performForceQuit = () -> { - response.performQuit(); - return setResponse(QResponse.FORCE_QUIT); - }; - Callable cancelQuit = () -> { - response.cancelQuit(); - // reset - setResponse(QResponse.NULL); - // but return cancel - return QResponse.CANCEL_QUIT; - }; - QResponse qresponse = getQuitResponse(true, performQuit, - performForceQuit, cancelQuit); - }); - - return gotQuitResponse(); - } - - private static QResponse gotQuitResponse = QResponse.NULL; - - private static QResponse setResponse(QResponse qresponse) - { - gotQuitResponse = qresponse; - return qresponse; - } - - public static QResponse gotQuitResponse() - { - return gotQuitResponse; - } - - public static final Callable defaultCancelQuit = () -> { - Console.debug("QuitHandler: (default) Quit action CANCELLED by user"); - // reset - setResponse(QResponse.NULL); - // and return cancel - return QResponse.CANCEL_QUIT; - }; - - public static final Callable defaultOkQuit = () -> { - Console.debug("QuitHandler: (default) Quit action CONFIRMED by user"); - return setResponse(QResponse.QUIT); - }; - - public static final Callable defaultForceQuit = () -> { - Console.debug("QuitHandler: (default) Quit action FORCED by user"); - // note that shutdown hook will not be run - Runtime.getRuntime().halt(0); - return setResponse(QResponse.FORCE_QUIT); // this line never reached! - }; - - public static QResponse getQuitResponse(boolean ui) - { - return getQuitResponse(ui, defaultOkQuit, defaultForceQuit, - defaultCancelQuit); - } - - private static boolean interactive = true; - - public static QResponse getQuitResponse(boolean ui, - Callable okQuit, Callable forceQuit, - Callable cancelQuit) - { - QResponse got = gotQuitResponse(); - if (got != QResponse.NULL && got != QResponse.CANCEL_QUIT) - { - // quit has already been selected, continue with calling quit method - return got; - } - - interactive = ui && !Platform.isHeadless(); - // confirm quit if needed and wanted - boolean confirmQuit = true; - - if (!interactive) - { - Console.debug("Non interactive quit -- not confirming"); - confirmQuit = false; - } - else if (Jalview2XML.allSavedUpToDate()) - { - Console.debug("Nothing changed -- not confirming quit"); - confirmQuit = false; - } - else - { - confirmQuit = jalview.bin.Cache - .getDefault(jalview.gui.Desktop.CONFIRM_KEYBOARD_QUIT, true); - Console.debug("Jalview property '" - + jalview.gui.Desktop.CONFIRM_KEYBOARD_QUIT - + "' is/defaults to " + confirmQuit + " -- " - + (confirmQuit ? "" : "not ") + "confirming quit"); - } - got = confirmQuit ? QResponse.NULL : QResponse.QUIT; - setResponse(got); - - if (confirmQuit) - { - JvOptionPane.newOptionDialog() - .setResponseHandler(JOptionPane.YES_OPTION, defaultOkQuit) - .setResponseHandler(JOptionPane.NO_OPTION, defaultCancelQuit) - .showDialogOnTopAsync( - new StringBuilder(MessageManager - .getString("label.quit_jalview")) - .append("\n") - .append(MessageManager.getString( - "label.unsaved_changes")) - .toString(), - MessageManager.getString("action.quit"), - JOptionPane.YES_NO_OPTION, - JOptionPane.QUESTION_MESSAGE, null, new Object[] - { MessageManager.getString("action.quit"), - MessageManager.getString("action.cancel") }, - MessageManager.getString("action.quit"), true); - } - - got = gotQuitResponse(); - boolean wait = false; - if (got == QResponse.CANCEL_QUIT) - { - // reset - setResponse(QResponse.NULL); - // but return cancel - return QResponse.CANCEL_QUIT; - } - else if (got == QResponse.QUIT) - { - if (Cache.getDefault("WAIT_FOR_SAVE", true) - && BackupFiles.hasSavesInProgress()) - { - QResponse waitResponse = waitQuit(interactive, okQuit, forceQuit, - cancelQuit); - wait = waitResponse == QResponse.QUIT; - } - } - - Callable next = null; - switch (gotQuitResponse()) - { - case QUIT: - next = okQuit; - break; - case FORCE_QUIT: // not actually an option at this stage - next = forceQuit; - break; - default: - next = cancelQuit; - break; - } - try - { - got = executor.submit(next).get(); - } catch (InterruptedException | ExecutionException e) - { - jalview.bin.Console - .debug("Exception during quit handling (final choice)", e); - } - setResponse(got); - - return gotQuitResponse(); - } - - private static QResponse waitQuit(boolean interactive, - Callable okQuit, Callable forceQuit, - Callable cancelQuit) - { - // check for saves in progress - if (!BackupFiles.hasSavesInProgress()) - return QResponse.QUIT; - - int size = 0; - AlignFrame[] afArray = Desktop.getAlignFrames(); - if (!(afArray == null || afArray.length == 0)) - { - for (int i = 0; i < afArray.length; i++) - { - AlignFrame af = afArray[i]; - List avpList = af.getAlignPanels(); - for (AlignmentViewPanel avp : avpList) - { - AlignmentI a = avp.getAlignment(); - List sList = a.getSequences(); - for (SequenceI s : sList) - { - size += s.getLength(); - } - } - } - } - int waitTime = Math.min(MAX_WAIT_FOR_SAVE, - Math.max(MIN_WAIT_FOR_SAVE, size / 2)); - Console.debug("Set waitForSave to " + waitTime); - QResponse waitResponse = QResponse.NULL; - - int iteration = 0; - boolean doIterations = true; // note iterations not used in the gui now, - // only one pass without the "Wait" button - while (doIterations && BackupFiles.hasSavesInProgress() - && iteration++ < (interactive ? 100 : 5)) - { - // future that returns a Boolean when all files are saved - CompletableFuture filesAllSaved = new CompletableFuture<>(); - - // callback as each file finishes saving - for (CompletableFuture cf : BackupFiles - .savesInProgressCompletableFutures(false)) - { - // if this is the last one then complete filesAllSaved - cf.whenComplete((ret, e) -> { - if (!BackupFiles.hasSavesInProgress()) - { - filesAllSaved.complete(true); - } - }); - } - try - { - filesAllSaved.get(waitTime, TimeUnit.MILLISECONDS); - } catch (InterruptedException | ExecutionException e1) - { - Console.debug( - "Exception whilst waiting for files to save before quit", - e1); - } catch (TimeoutException e2) - { - // this Exception to be expected - } - - if (interactive && BackupFiles.hasSavesInProgress()) - { - boolean showForceQuit = iteration > 0; // iteration > 1 to not show - // force quit the first time - JFrame parent = new JFrame(); - JButton[] buttons = { new JButton(), new JButton() }; - JvOptionPane waitDialog = JvOptionPane.newOptionDialog(); - JTextPane messagePane = new JTextPane(); - messagePane.setBackground(waitDialog.getBackground()); - messagePane.setBorder(null); - messagePane.setText(waitingForSaveMessage()); - // callback as each file finishes saving - for (CompletableFuture cf : BackupFiles - .savesInProgressCompletableFutures(false)) - { - cf.whenComplete((ret, e) -> { - if (BackupFiles.hasSavesInProgress()) - { - // update the list of saving files as they save too - messagePane.setText(waitingForSaveMessage()); - } - else - { - if (!(QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT - || QuitHandler.gotQuitResponse() == QResponse.NULL)) - { - for (int i = 0; i < buttons.length; i++) - { - Console.debug("DISABLING BUTTON " + buttons[i].getText()); - buttons[i].setEnabled(false); - buttons[i].setVisible(false); - } - // if this is the last one then close the dialog - messagePane.setText(new StringBuilder() - .append(MessageManager.getString("label.all_saved")) - .append("\n") - .append(MessageManager - .getString("label.quitting_bye")) - .toString()); - messagePane.setEditable(false); - try - { - Thread.sleep(1500); - } catch (InterruptedException e1) - { - } - parent.dispose(); - } - } - }); - } - - String[] options; - int dialogType = -1; - if (showForceQuit) - { - options = new String[2]; - options[0] = MessageManager.getString("action.force_quit"); - options[1] = MessageManager.getString("action.cancel_quit"); - dialogType = JOptionPane.YES_NO_OPTION; - waitDialog.setResponseHandler(JOptionPane.YES_OPTION, forceQuit) - .setResponseHandler(JOptionPane.NO_OPTION, cancelQuit); - } - else - { - options = new String[1]; - options[0] = MessageManager.getString("action.cancel_quit"); - dialogType = JOptionPane.YES_OPTION; - waitDialog.setResponseHandler(JOptionPane.YES_OPTION, cancelQuit); - } - waitDialog.showDialogOnTopAsync(parent, messagePane, - MessageManager.getString("label.wait_for_save"), dialogType, - JOptionPane.WARNING_MESSAGE, null, options, - MessageManager.getString("action.cancel_quit"), true, - buttons); - - parent.dispose(); - final QResponse thisWaitResponse = gotQuitResponse(); - switch (thisWaitResponse) - { - case QUIT: // wait -- do another iteration - break; - case FORCE_QUIT: - doIterations = false; - break; - case CANCEL_QUIT: - doIterations = false; - break; - case NULL: // already cancelled - doIterations = false; - break; - default: - } - } // end if interactive - - } // end while wait iteration loop - waitResponse = gotQuitResponse(); - - return waitResponse; - }; - - private static String waitingForSaveMessage() - { - StringBuilder messageSB = new StringBuilder(); - - messageSB.append(MessageManager.getString("label.save_in_progress")); - List files = BackupFiles.savesInProgressFiles(false); - boolean any = files.size() > 0; - if (any) - { - for (File file : files) - { - messageSB.append("\n\u2022 ").append(file.getName()); - } - } - else - { - messageSB.append(MessageManager.getString("label.unknown")); - } - messageSB.append("\n\n") - .append(MessageManager.getString("label.quit_after_saving")); - return messageSB.toString(); - } -} \ No newline at end of file