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.JFrame;
import javax.swing.JOptionPane;
public class QuitHandler
{
- private static final int INITIAL_WAIT_FOR_SAVE = 3000;
+ private static final int MIN_WAIT_FOR_SAVE = 5000;
+
+ private static final int MAX_WAIT_FOR_SAVE = 20000;
private static final int NON_INTERACTIVE_WAIT_CYCLES = 2;
private static QResponse setResponse(QResponse qresponse)
{
gotQuitResponse = qresponse;
- Console.debug("##### Setting gotQuitResponse to " + qresponse);
return qresponse;
}
if (got != QResponse.NULL && got != QResponse.CANCEL_QUIT)
{
// quit has already been selected, continue with calling quit method
- Console.debug("##### getQuitResponse called. gotQuitResponse=" + got);
return got;
}
if (confirmQuit)
{
-
- Console.debug("********************ABOUT TO CONFIRM QUIT");
- JvOptionPane quitDialog = JvOptionPane.newOptionDialog()
+ JvOptionPane.newOptionDialog()
.setResponseHandler(JOptionPane.YES_OPTION, defaultOkQuit)
- .setResponseHandler(JOptionPane.NO_OPTION, defaultCancelQuit);
- quitDialog.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, 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();
- Console.debug("first user response, got=" + got);
boolean wait = false;
if (got == QResponse.CANCEL_QUIT)
{
switch (gotQuitResponse())
{
case QUIT:
- Console.debug("### User selected QUIT");
next = okQuit;
break;
case FORCE_QUIT: // not actually an option at this stage
- Console.debug("### User selected FORCE QUIT");
next = forceQuit;
break;
default:
- Console.debug("### User selected CANCEL QUIT");
next = cancelQuit;
break;
}
jalview.bin.Console
.debug("Exception during quit handling (final choice)", e);
}
- jalview.bin.Console.debug("### nextResponse=" + got.toString());
setResponse(got);
return gotQuitResponse();
Callable<QResponse> okQuit, Callable<QResponse> forceQuit,
Callable<QResponse> cancelQuit)
{
- jalview.bin.Console.debug("#### waitQuit started");
// check for saves in progress
if (!BackupFiles.hasSavesInProgress())
return QResponse.QUIT;
- int waitTime = INITIAL_WAIT_FOR_SAVE; // start with 3 second wait
+ int size = 0;
AlignFrame[] afArray = Desktop.getAlignFrames();
if (!(afArray == null || afArray.length == 0))
{
- int size = 0;
for (int i = 0; i < afArray.length; i++)
{
AlignFrame af = afArray[i];
}
}
}
- waitTime = Math.max(waitTime, size / 2);
- Console.debug("Set waitForSave to " + waitTime);
}
- final int waitTimeFinal = waitTime;
+ 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;
- // future that returns a Boolean when all files are saved
- CompletableFuture<Boolean> filesAllSaved = new CompletableFuture<>();
-
- // callback as each file finishes saving
- for (CompletableFuture<Boolean> cf : BackupFiles
- .savesInProgressCompletableFutures(false))
- {
- // if this is the last one then complete filesAllSaved
- cf.whenComplete((ret, e) -> {
- if (!BackupFiles.hasSavesInProgress())
- {
- filesAllSaved.complete(true);
- }
- });
- }
-
- // timeout the wait -- will result in another wait button when looped
- CompletableFuture<Boolean> waitTimeout = CompletableFuture
- .supplyAsync(() -> {
- Console.debug("################# STARTING WAIT SLEEP");
- try
- {
- Thread.sleep(waitTimeFinal);
- } catch (InterruptedException e)
- {
- // probably interrupted by all files saving
- }
- return true;
- });
- CompletableFuture<Object> waitForSave = CompletableFuture
- .anyOf(waitTimeout, filesAllSaved);
-
int iteration = 0;
boolean doIterations = true;
while (doIterations && BackupFiles.hasSavesInProgress()
&& iteration++ < (interactive ? 100 : 5))
{
+ // future that returns a Boolean when all files are saved
+ CompletableFuture<Boolean> filesAllSaved = new CompletableFuture<>();
+
+ // callback as each file finishes saving
+ for (CompletableFuture<Boolean> cf : BackupFiles
+ .savesInProgressCompletableFutures(false))
+ {
+ // if this is the last one then complete filesAllSaved
+ cf.whenComplete((ret, e) -> {
+ if (!BackupFiles.hasSavesInProgress())
+ {
+ filesAllSaved.complete(true);
+ }
+ });
+ }
try
{
- waitForSave.copy().get();
+ 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())
{
- Console.debug("********************About to make waitDialog");
+ boolean allowForceQuit = iteration > 0; // iteration > 1 to not show
+ // force quit the first time
JFrame parent = new JFrame();
- JvOptionPane waitDialog = JvOptionPane.newOptionDialog()
- .setResponseHandler(JOptionPane.YES_OPTION, defaultOkQuit)
- .setResponseHandler(JOptionPane.NO_OPTION, forceQuit)
- .setResponseHandler(JOptionPane.CANCEL_OPTION, cancelQuit);
-
+ JvOptionPane waitDialog = JvOptionPane.newOptionDialog();
+ if (allowForceQuit)
+ {
+ waitDialog
+ .setResponseHandler(JOptionPane.YES_OPTION, defaultOkQuit)
+ .setResponseHandler(JOptionPane.NO_OPTION, forceQuit)
+ .setResponseHandler(JOptionPane.CANCEL_OPTION,
+ cancelQuit);
+ }
+ else
+ {
+ waitDialog
+ .setResponseHandler(JOptionPane.YES_OPTION, defaultOkQuit)
+ .setResponseHandler(JOptionPane.NO_OPTION, cancelQuit);
+ }
JTextPane messagePane = new JTextPane();
messagePane.setBackground(waitDialog.getBackground());
messagePane.setBorder(null);
.savesInProgressCompletableFutures(false))
{
cf.whenComplete((ret, e) -> {
- Console.debug("############# A FILE SAVED!");
- // update the list of saving files as they save too
- messagePane.setText(waitingForSaveMessage());
- // if this is the last one then close the dialog
- if (!BackupFiles.hasSavesInProgress())
+ if (BackupFiles.hasSavesInProgress())
+ // update the list of saving files as they save too
+ messagePane.setText(waitingForSaveMessage());
+ else
{
+ // 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());
+ try
+ {
+ Console.debug("WAITING FOR MESSAGE");
+ Thread.sleep(500);
+ } catch (InterruptedException e1)
+ {
+ }
// like a click on Wait button
waitDialog.setValue(JOptionPane.YES_OPTION);
parent.dispose();
});
}
+ String[] options = new String[allowForceQuit ? 3 : 2];
+ if (allowForceQuit)
+ {
+ options[0] = MessageManager.getString("action.wait");
+ options[1] = MessageManager.getString("action.force_quit");
+ options[2] = MessageManager.getString("action.cancel_quit");
+ }
+ else
+ {
+ options[0] = MessageManager.getString("action.wait");
+ options[1] = MessageManager.getString("action.cancel_quit");
+ }
waitDialog.showDialogOnTopAsync(parent, messagePane,
MessageManager.getString("action.wait"),
- JOptionPane.YES_NO_CANCEL_OPTION,
- JOptionPane.WARNING_MESSAGE, null, new Object[]
- { MessageManager.getString("action.wait"),
- MessageManager.getString("action.force_quit"),
- MessageManager.getString("action.cancel_quit") },
+ allowForceQuit ? JOptionPane.YES_NO_CANCEL_OPTION
+ : JOptionPane.YES_NO_OPTION,
+ JOptionPane.WARNING_MESSAGE, null, options,
MessageManager.getString("action.wait"), true);
- Console.debug("********************Finished waitDialog");
+ parent.dispose();
final QResponse thisWaitResponse = gotQuitResponse();
- Console.debug("####### WAITFORSAVE SET: " + thisWaitResponse);
switch (thisWaitResponse)
{
case QUIT: // wait -- do another iteration
} // end while wait iteration loop
waitResponse = gotQuitResponse();
- Console.debug("####### WAITFORSAVE RETURNING: " + waitResponse);
return waitResponse;
};
{
StringBuilder messageSB = new StringBuilder();
+ messageSB.append(MessageManager.getString("label.save_in_progress"));
List<File> files = BackupFiles.savesInProgressFiles(false);
boolean any = files.size() > 0;
if (any)
{
- messageSB.append(MessageManager.getString("label.save_in_progress"));
for (File file : files)
{
messageSB.append("\n- ").append(file.getName());
}
else
{
- messageSB.append(MessageManager.getString("label.all_saved"))
- .append("\n")
- .append(MessageManager.getString("label.quitting_bye"));
+ messageSB.append(MessageManager.getString("label.unknown"));
}
return messageSB.toString();
}
- private static Boolean waitForSave(long t)
- {
- boolean ret = false;
- try
- {
- Console.debug("Wait for save to complete: " + t + "ms");
- long c = 0;
- int i = 100;
- while (c < t)
- {
- Thread.sleep(i);
- c += i;
- ret = !BackupFiles.hasSavesInProgress();
- if (ret)
- {
- Console.debug(
- "Save completed whilst waiting (" + c + "/" + t + "ms)");
- return ret;
- }
- if (c % 1000 < i) // just gone over another second
- {
- Console.debug("...waiting (" + c + "/" + t + "ms]");
- }
- }
- } catch (InterruptedException e)
- {
- Console.debug("Wait for save interrupted");
- }
- Console.debug("Save has " + (ret ? "" : "not ") + "completed");
- return ret;
- }
-
-}
+}
\ No newline at end of file