if (jvnews != null)
{
storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
+ }
+
+ closeAll_actionPerformed(null);
+ // check for aborted quit
+ if (QuitHandler.quitCancelled())
+ {
+ jalview.bin.Console.debug("Desktop aborting quit");
+ return null;
}
if (dialogExecutor != null)
dialogExecutor.shutdownNow();
}
- closeAll_actionPerformed(null);
-
if (groovyConsole != null)
{
// suppress a possible repeat prompt to save script
{
// TODO show a progress bar while closing?
JInternalFrame[] frames = desktop.getAllFrames();
+ boolean quitting = QuitHandler.quitting();
for (int i = 0; i < frames.length; i++)
{
try
{
frames[i].setClosed(true);
+ // check for cancelled quit
+ if (quitting && QuitHandler.quitCancelled())
+ {
+ return;
+ }
} catch (java.beans.PropertyVetoException ex)
{
}
/**
* single thread that handles display of dialogs to user.
*/
- ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
+ ExecutorService dialogExecutor = Executors.newFixedThreadPool(3);
/**
* flag indicating if dialogExecutor should try to acquire a permit
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.Icon;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
+import jalview.bin.Console;
import jalview.util.ChannelProperties;
import jalview.util.Platform;
import jalview.util.dialogrunner.DialogRunnerI;
private Component parentComponent;
+ private ExecutorService executor = Executors.newCachedThreadPool();
+
+ private JDialog dialog = null;
+
private Map<Object, Callable<Void>> callbacks = new HashMap<>();
/*
JOptionPane joptionpane = (JOptionPane) joptionpaneObject;
joptionpane.setValue(buttonAction);
if (action != null)
- Executors.newSingleThreadExecutor().submit(action);
+ getExecutor().submit(action);
joptionpane.transferFocusBackward();
joptionpane.setVisible(false);
// put focus and raise parent window if possible, unless cancel or
jb.setText((String) o);
jb.addActionListener(new ActionListener()
{
+
@Override
public void actionPerformed(ActionEvent e)
{
joptionpane.setValue(buttonAction);
if (action != null)
- Executors.newSingleThreadExecutor().submit(action);
+ getExecutor().submit(action);
// joptionpane.transferFocusBackward();
joptionpane.transferFocusBackward();
joptionpane.setVisible(false);
: ModalityType.MODELESS);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
+ setDialog(dialog);
}
}
return this;
}
+ public ExecutorService getExecutor()
+ {
+ if (executor == null)
+ executor = Executors.newSingleThreadExecutor();
+ return executor;
+ }
+
+ public void setExecutor(ExecutorService es)
+ {
+ executor = es;
+ }
+
+ public void setDialog(JDialog d)
+ {
+ dialog = d;
+ }
+
+ public JDialog getDialog()
+ {
+ return dialog;
+ }
+
/**
* showDialogOnTop will create a dialog that (attempts to) come to top of OS
* desktop windows
public static int showDialogOnTop(String label, String actionString,
int JOPTIONPANE_OPTION, int JOPTIONPANE_MESSAGETYPE)
{
+ return showDialogOnTop(null, label, actionString, JOPTIONPANE_OPTION,
+ JOPTIONPANE_MESSAGETYPE);
+ }
+
+ public static int showDialogOnTop(Component dialogParentComponent,
+ String label, String actionString, int JOPTIONPANE_OPTION,
+ int JOPTIONPANE_MESSAGETYPE)
+ {
if (!isInteractiveMode())
{
return (int) getMockResponse();
// A better hack which works is to create a new JFrame parent with
// setAlwaysOnTop(true)
JFrame dialogParent = new JFrame();
- dialogParent.setIconImages(ChannelProperties.getIconList());
- dialogParent.setAlwaysOnTop(true);
+ if (dialogParentComponent == null)
+ {
+ dialogParent.setIconImages(ChannelProperties.getIconList());
+ dialogParent.setAlwaysOnTop(true);
+ }
- int answer = JOptionPane.showConfirmDialog(dialogParent, label,
- actionString, JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE);
+ int answer = JOptionPane.showConfirmDialog(
+ dialogParentComponent == null ? dialogParent
+ : dialogParentComponent,
+ label, actionString, JOPTIONPANE_OPTION,
+ JOPTIONPANE_MESSAGETYPE);
- dialogParent.setAlwaysOnTop(false);
- dialogParent.dispose();
+ if (dialogParentComponent == null)
+ {
+ dialogParent.setAlwaysOnTop(false);
+ dialogParent.dispose();
+ }
return answer;
}
{
try
{
- action.call();
+ getExecutor().submit(action).get();
+ // action.call();
} catch (Exception e)
{
e.printStackTrace();
{
joptionpane.setValue(buttonAction);
if (action != null)
- Executors.newSingleThreadExecutor().submit(action);
+ getExecutor().submit(action);
// joptionpane.transferFocusBackward();
joptionpane.transferFocusBackward();
joptionpane.setVisible(false);
dialog.setModalityType(
modal ? ModalityType.APPLICATION_MODAL : ModalityType.MODELESS);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ setDialog(dialog);
return dialog;
}
parent.remove(f);
}
}
+
+ public static JvOptionPane frameDialog(String message, String title,
+ int messageType, String[] buttonsText, String defaultButton,
+ Callable<Void>[] handlers, boolean modal)
+ {
+ JFrame parent = new JFrame();
+ JvOptionPane jvop = JvOptionPane.newOptionDialog();
+ JButton[] buttons = new JButton[buttonsText.length];
+ for (int i = 0; i < buttonsText.length; i++)
+ {
+ buttons[i] = new JButton();
+ buttons[i].setText(buttonsText[i]);
+ Console.debug("DISABLING BUTTON " + buttons[i].getText());
+ buttons[i].setEnabled(false);
+ buttons[i].setVisible(false);
+ }
+
+ int dialogType = -1;
+ if (buttonsText.length == 1)
+ {
+ dialogType = JOptionPane.OK_OPTION;
+ }
+ else if (buttonsText.length == 2)
+ {
+ dialogType = JOptionPane.YES_NO_OPTION;
+ }
+ else
+ {
+ dialogType = JOptionPane.YES_NO_CANCEL_OPTION;
+ }
+ jvop.setResponseHandler(JOptionPane.YES_OPTION, handlers[0]);
+ if (dialogType == JOptionPane.YES_NO_OPTION
+ || dialogType == JOptionPane.YES_NO_CANCEL_OPTION)
+ {
+ jvop.setResponseHandler(JOptionPane.NO_OPTION, handlers[1]);
+ }
+ if (dialogType == JOptionPane.YES_NO_CANCEL_OPTION)
+ {
+ jvop.setResponseHandler(JOptionPane.CANCEL_OPTION, handlers[2]);
+ }
+
+ final int dt = dialogType;
+ jvop.getExecutor().execute(() -> {
+ jvop.showDialog(message, title, dt, messageType, null, buttonsText,
+ defaultButton, modal, buttons);
+ });
+
+ return jvop;
+ }
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
if (confirmQuit)
{
- JvOptionPane.newOptionDialog()
+ setQuitDialog(JvOptionPane.newOptionDialog()
.setResponseHandler(JOptionPane.YES_OPTION, defaultOkQuit)
- .setResponseHandler(JOptionPane.NO_OPTION, cancelQuit)
- .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);
+ .setResponseHandler(JOptionPane.NO_OPTION, cancelQuit));
+ JvOptionPane qd = getQuitDialog();
+ qd.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();
{
executor.submit(next).get();
got = gotQuitResponse();
+ } catch (RejectedExecutionException e)
+ {
+ // QuitHander.abortQuit() probably called
+ // CANCEL_QUIT test will reset QuitHandler
+ Console.info("Quit aborted!");
+ got = QResponse.NULL;
+ setResponse(QResponse.NULL);
} catch (InterruptedException | ExecutionException e)
{
jalview.bin.Console
}
setResponse(got);
- if (gotQuitResponse() == QResponse.CANCEL_QUIT)
+ if (quitCancelled())
{
// reset if cancelled
+ Console.debug("Quit cancelled");
setResponse(QResponse.NULL);
return QResponse.CANCEL_QUIT;
}
}
else
{
- if (!(QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT
- || QuitHandler.gotQuitResponse() == QResponse.NULL))
+ if (!(quitCancelled()))
{
for (int i = 0; i < buttons.length; i++)
{
public static void abortQuit()
{
- setResponse(QResponse.CANCEL_QUIT);
+ setResponse(QResponse.NULL);
+ // executor.shutdownNow();
+ }
+
+ private static JvOptionPane quitDialog = null;
+
+ private static void setQuitDialog(JvOptionPane qd)
+ {
+ quitDialog = qd;
+ }
+
+ private static JvOptionPane getQuitDialog()
+ {
+ return quitDialog;
+ }
+
+ public static boolean quitCancelled()
+ {
+ return QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT
+ || QuitHandler.gotQuitResponse() == QResponse.NULL;
+ }
+
+ public static boolean quitting()
+ {
+ return QuitHandler.gotQuitResponse() == QResponse.QUIT
+ || QuitHandler.gotQuitResponse() == QResponse.FORCE_QUIT;
}
}
\ No newline at end of file
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
+import java.beans.PropertyVetoException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Random;
import java.util.Vector;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
if (!forceClose)
{
String viewerName = getViewerName();
+
+ int confirm = JvOptionPane.CANCEL_OPTION;
String prompt = MessageManager
.formatMessage("label.confirm_close_viewer", new Object[]
{ binding.getViewerTitle(viewerName, false), viewerName });
prompt = JvSwingUtils.wrapTooltip(true, prompt);
- int confirm = JvOptionPane.showConfirmDialog(this, prompt,
- MessageManager.getString("label.close_viewer"),
- JvOptionPane.YES_NO_CANCEL_OPTION);
+ String title = MessageManager.getString("label.close_viewer");
+ confirm = showCloseDialog(title, prompt);
+
/*
* abort closure if user hits escape or Cancel
*/
{
// abort possible quit handling if CANCEL chosen
if (confirm == JvOptionPane.CANCEL_OPTION)
+ {
+ try
+ {
+ // this is a bit futile
+ this.setClosed(false);
+ } catch (PropertyVetoException e)
+ {
+ }
QuitHandler.abortQuit();
+ }
return;
}
forceClose = confirm == JvOptionPane.YES_OPTION;
dispose();
}
+ private int showCloseDialog(final String title, final String prompt)
+ {
+ confirmResponse = JvOptionPane.CANCEL_OPTION;
+
+ if (QuitHandler.quitting())
+ {
+
+ Callable<Void> yesCall = () -> {
+ Console.debug("YES");
+ confirmResponse = JvOptionPane.YES_OPTION;
+ return null;
+ };
+ Callable<Void> noCall = () -> {
+ Console.debug("NO");
+ confirmResponse = JvOptionPane.NO_OPTION;
+ return null;
+ };
+ Callable<Void> cancelCall = () -> {
+ Console.debug("CANCEL");
+ confirmResponse = JvOptionPane.CANCEL_OPTION;
+ return null;
+ };
+ Callable<Void>[] calls = new Callable[] { yesCall, noCall,
+ cancelCall };
+ String cancelQuit = MessageManager.getString("action.cancel_quit");
+ String[] buttonsText = { MessageManager.getString("action.yes"),
+ MessageManager.getString("action.no"), cancelQuit };
+ JvOptionPane dialog = JvOptionPane.frameDialog(prompt,
+ MessageManager.getString("label.close_viewer"),
+ JvOptionPane.WARNING_MESSAGE, buttonsText, cancelQuit, calls,
+ false);
+ // wait for response
+ ExecutorService executor = dialog.getExecutor();
+ executor.shutdown();
+ try
+ {
+ Console.debug("### executor.awaitTermination() starting");
+ executor.awaitTermination(60, TimeUnit.SECONDS);
+ Console.debug("### executor.awaitTermination() finished");
+ } catch (InterruptedException e)
+ {
+ }
+ }
+ else
+ {
+ confirmResponse = JvOptionPane.showConfirmDialog(this, prompt,
+ MessageManager.getString("label.close_viewer"),
+ JvOptionPane.YES_NO_CANCEL_OPTION,
+ JvOptionPane.WARNING_MESSAGE);
+ }
+ return confirmResponse;
+ }
+
@Override
public void showHelp_actionPerformed()
{
&& viewerActionMenu.getItemCount() > 0
&& viewerActionMenu.isVisible();
}
+
+ private static int confirmResponse = 0;
}