Skip to content

Commit

Permalink
use common codepath for desktop quit prompting
Browse files Browse the repository at this point in the history
  • Loading branch information
jjallaire committed Jun 28, 2011
1 parent 16b2a59 commit 63f2c71
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 197 deletions.
58 changes: 1 addition & 57 deletions src/cpp/desktop/DesktopMainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,63 +170,7 @@ void MainWindow::closeEvent(QCloseEvent* pEvent)
}
else
{
// determine saveAction by calling hook
QVariant saveAction = pFrame->evaluateJavaScript(
QString::fromAscii("window.desktopHooks.getSaveAction()"));

QVariant rEnvPath = pFrame->evaluateJavaScript(
QString::fromAscii("window.desktopHooks.getREnvironmentPath()"));

bool save;
switch (saveAction.toInt())
{
case 0:
save = false;
break;
case 1:
save = true;
break;
case -1:
default:
QMessageBox prompt(safeMessageBoxIcon(QMessageBox::Warning),
QString::fromUtf8("Quit R Session"),
QString::fromUtf8("Save workspace image to ") +
rEnvPath.toString() + QString::fromUtf8("?"),
QMessageBox::NoButton,
this,
Qt::Sheet | Qt::Dialog |
Qt::MSWindowsFixedSizeDialogHint);
prompt.setWindowModality(Qt::WindowModal);
QPushButton* pSave = prompt.addButton(QString::fromUtf8("&Save"),
QMessageBox::AcceptRole);
prompt.addButton(QString::fromUtf8("&Don't Save"), QMessageBox::DestructiveRole);
QPushButton* pCancel = prompt.addButton(QString::fromUtf8("Cancel"),
QMessageBox::RejectRole);
prompt.setDefaultButton(pSave);


FunctionSlotBinder aw(boost::bind(&QDialog::activateWindow, &prompt),
&prompt);
QTimer::singleShot(10, &aw, SLOT(execute()));
QTimer::singleShot(25, &aw, SLOT(execute()));
QTimer::singleShot(50, &aw, SLOT(execute()));
QTimer::singleShot(100, &aw, SLOT(execute()));

prompt.exec();

QAbstractButton* pClicked = prompt.clickedButton();
if (!pClicked || pClicked == pCancel)
{
pEvent->ignore();
return;
}
save = pClicked == pSave;
break;
}

pFrame->evaluateJavaScript(QString::fromAscii("window.desktopHooks.quitR(") +
(save ? QString::fromAscii("true") : QString::fromAscii("false")) +
QString::fromAscii(")"));
pFrame->evaluateJavaScript(QString::fromAscii("window.desktopHooks.quitR()"));
pEvent->ignore();
}
}
Expand Down
150 changes: 102 additions & 48 deletions src/gwt/src/org/rstudio/studio/client/application/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

import org.rstudio.core.client.Barrier;
import org.rstudio.core.client.CsvWriter;
import org.rstudio.core.client.Debug;
import org.rstudio.core.client.Barrier.Token;
import org.rstudio.core.client.command.CommandBinder;
import org.rstudio.core.client.command.Handler;
import org.rstudio.core.client.dom.DomUtils;
import org.rstudio.core.client.events.BarrierReleasedEvent;
import org.rstudio.core.client.events.BarrierReleasedHandler;
import org.rstudio.core.client.widget.Operation;
import org.rstudio.core.client.widget.ProgressIndicator;
import org.rstudio.core.client.widget.ProgressOperation;
Expand All @@ -42,6 +47,7 @@
import org.rstudio.studio.client.application.model.SessionSerializationAction;
import org.rstudio.studio.client.application.ui.RequestLogVisualization;
import org.rstudio.studio.client.common.GlobalDisplay;
import org.rstudio.studio.client.common.GlobalProgressDelayer;
import org.rstudio.studio.client.common.SimpleRequestCallback;
import org.rstudio.studio.client.projects.Projects;
import org.rstudio.studio.client.server.*;
Expand All @@ -50,6 +56,7 @@
import org.rstudio.studio.client.workbench.Workbench;
import org.rstudio.studio.client.workbench.WorkbenchContext;
import org.rstudio.studio.client.workbench.commands.Commands;
import org.rstudio.studio.client.workbench.events.LastChanceSaveEvent;
import org.rstudio.studio.client.workbench.events.SessionInitEvent;
import org.rstudio.studio.client.workbench.model.Agreement;
import org.rstudio.studio.client.workbench.model.Session;
Expand Down Expand Up @@ -239,65 +246,112 @@ public void onRaiseException() {
public final native void onRaiseException2() /*-{
$wnd.welfkjweg();
}-*/;


private void desktopQuitR(final boolean saveChanges)
{
final GlobalProgressDelayer progress = new GlobalProgressDelayer(
globalDisplay_,
"Quitting R Session...");

// Use a barrier and LastChanceSaveEvent to allow source documents
// and client state to be synchronized before quitting.

Barrier barrier = new Barrier();
barrier.addBarrierReleasedHandler(new BarrierReleasedHandler()
{
public void onBarrierReleased(BarrierReleasedEvent event)
{
// All last chance save operations have completed (or possibly
// failed). Now do the real quit.

server_.quitSession(
saveChanges,
new VoidServerRequestCallback(
globalDisplay_.getProgressIndicator("Error Quitting R"))
{

@Override
public void onResponseReceived(Void response)
{
progress.dismiss();
super.onResponseReceived(response);
}

@Override
public void onError(ServerError error)
{
progress.dismiss();
super.onError(error);
}
});
}
});

// We acquire a token to make sure that the barrier doesn't fire before
// all the LastChanceSaveEvent listeners get a chance to acquire their
// own tokens.
Token token = barrier.acquire();
try
{
events_.fireEvent(new LastChanceSaveEvent(barrier));
}
finally
{
token.release();
}
}

// implementatin of quit session
private Command doQuitSession_ = new Command()

@Handler
public void onQuitSession()
{
public void execute()
// quit session operation paramaterized by whether we save changes
class QuitOperation implements ProgressOperation
{
if (Desktop.isDesktop())
QuitOperation(boolean saveChanges)
{
Desktop.getFrame().close();
saveChanges_ = saveChanges;
}
else
public void execute(ProgressIndicator indicator)
{
// quit session operation paramaterized by whether we save changes
class QuitOperation implements ProgressOperation
if (Desktop.isDesktop())
{
QuitOperation(boolean saveChanges)
{
saveChanges_ = saveChanges;
}
public void execute(ProgressIndicator indicator)
{
indicator.onProgress("Quitting R Session...");
server_.quitSession(saveChanges_,
new VoidServerRequestCallback(indicator));
}
private final boolean saveChanges_ ;
}

if (saveAction_.getAction() == SaveAction.SAVEASK)
{
// confirm quit and do it
String prompt = "Save workspace image to " +
workbenchContext_.getREnvironmentPath() + "?";
globalDisplay_.showYesNoMessage(GlobalDisplay.MSG_QUESTION,
"Quit R Session",
prompt,
true,
new QuitOperation(true),
new QuitOperation(false),
true);
indicator.onCompleted();
desktopQuitR(saveChanges_);
}
else
{
// do the quit without prompting

ProgressIndicator indicator =
globalDisplay_.getProgressIndicator("Error Quitting R");

boolean save = saveAction_.getAction() == SaveAction.SAVE;
new QuitOperation(save).execute(indicator);
indicator.onProgress("Quitting R Session...");
server_.quitSession(saveChanges_,
new VoidServerRequestCallback(indicator));
}
}
}
};

@Handler
public void onQuitSession()
{
doQuitSession_.execute();
}
private final boolean saveChanges_ ;
}

if (saveAction_.getAction() == SaveAction.SAVEASK)
{
// confirm quit and do it
String prompt = "Save workspace image to " +
workbenchContext_.getREnvironmentPath() + "?";
globalDisplay_.showYesNoMessage(GlobalDisplay.MSG_QUESTION,
"Quit R Session",
prompt,
true,
new QuitOperation(true),
new QuitOperation(false),
true);
}
else
{
// do the quit without prompting
ProgressIndicator indicator =
globalDisplay_.getProgressIndicator("Error Quitting R");

boolean save = saveAction_.getAction() == SaveAction.SAVE;
new QuitOperation(save).execute(indicator);
}
}

@Handler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,8 @@
package org.rstudio.studio.client.application;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Timer;
import com.google.inject.Inject;
import org.rstudio.core.client.Barrier;
import org.rstudio.core.client.Barrier.Token;
import org.rstudio.core.client.command.AppCommand;
import org.rstudio.core.client.events.BarrierReleasedEvent;
import org.rstudio.core.client.events.BarrierReleasedHandler;
import org.rstudio.core.client.files.FileSystemItem;
import org.rstudio.core.client.js.BaseExpression;
import org.rstudio.core.client.js.JsObjectInjector;
Expand All @@ -32,11 +26,8 @@
import org.rstudio.studio.client.common.filetypes.FileTypeRegistry;
import org.rstudio.studio.client.common.filetypes.events.OpenProjectFileEvent;
import org.rstudio.studio.client.server.Server;
import org.rstudio.studio.client.server.ServerError;
import org.rstudio.studio.client.server.VoidServerRequestCallback;
import org.rstudio.studio.client.workbench.WorkbenchContext;
import org.rstudio.studio.client.workbench.commands.Commands;
import org.rstudio.studio.client.workbench.events.LastChanceSaveEvent;
import org.rstudio.studio.client.workbench.views.source.SourceShim;

/**
Expand All @@ -50,37 +41,6 @@ interface DesktopHooksInjector extends JsObjectInjector<DesktopHooks> {}
private static final DesktopHooksInjector injector =
GWT.create(DesktopHooksInjector.class);

/**
* Delay showing progress until DELAY_MILLIS have elapsed.
*/
private class ProgressDelayer
{
private ProgressDelayer(final String progressMessage)
{
final int DELAY_MILLIS = 250;

timer_ = new Timer()
{
@Override
public void run()
{
dismiss_ = globalDisplay_.showProgress(progressMessage);
}
};
timer_.schedule(DELAY_MILLIS);
}

public void dismiss()
{
timer_.cancel();
if (dismiss_ != null)
dismiss_.execute();
}

private final Timer timer_;
private Command dismiss_;
}

@Inject
public DesktopHooks(Commands commands,
EventBus events,
Expand Down Expand Up @@ -131,58 +91,6 @@ String getActiveProjectDir()
return "";
}

void quitR(final boolean saveChanges)
{
final ProgressDelayer progress = new ProgressDelayer(
"Quitting R Session...");

// Use a barrier and LastChanceSaveEvent to allow source documents
// and client state to be synchronized before quitting.

Barrier barrier = new Barrier();
barrier.addBarrierReleasedHandler(new BarrierReleasedHandler()
{
public void onBarrierReleased(BarrierReleasedEvent event)
{
// All last chance save operations have completed (or possibly
// failed). Now do the real quit.

server_.quitSession(
saveChanges,
new VoidServerRequestCallback(
globalDisplay_.getProgressIndicator("Error Quitting R")) {

@Override
public void onResponseReceived(org.rstudio.studio.client.server.Void response)
{
progress.dismiss();
super.onResponseReceived(response);
}

@Override
public void onError(ServerError error)
{
progress.dismiss();
super.onError(error);
}
});
}
});

// We acquire a token to make sure that the barrier doesn't fire before
// all the LastChanceSaveEvent listeners get a chance to acquire their
// own tokens.
Token token = barrier.acquire();
try
{
events_.fireEvent(new LastChanceSaveEvent(barrier));
}
finally
{
token.release();
}
}

void invokeCommand(String cmdId)
{
commands_.getCommandById(cmdId).execute();
Expand Down Expand Up @@ -228,6 +136,12 @@ void openFile(String filePath)
}
}

void quitR()
{
commands_.quitSession().execute();
}


int getSaveAction()
{
return saveAction_.getAction();
Expand Down
Loading

0 comments on commit 63f2c71

Please sign in to comment.