PL-7934 BackgroundWorkWindow does not cancel background task by click on Window close button

This commit is contained in:
Yuriy Artamonov 2016-10-28 14:41:45 +04:00
parent 763e050676
commit bd8aea655e
10 changed files with 110 additions and 128 deletions

View File

@ -461,14 +461,17 @@ public class DesktopWindowManager extends WindowManager {
return DesktopComponentsHelper.getComposition(window);
}
protected void addShortcuts(final Window window) {
protected void addShortcuts(Window window, OpenType openType) {
ClientConfig clientConfig = configuration.getConfig(ClientConfig.class);
String closeShortcut = clientConfig.getCloseShortcut();
window.addAction(new com.haulmont.cuba.gui.components.AbstractAction("closeWindowShortcutAction", closeShortcut) {
@Override
public void actionPerform(Component component) {
window.close("close");
if (openType.getOpenMode() != OpenMode.DIALOG
|| BooleanUtils.isNotFalse(window.getDialogOptions().getCloseable())) {
window.close("close");
}
}
});
@ -564,7 +567,7 @@ public class DesktopWindowManager extends WindowManager {
@Override
public void windowClosingAfterValidation(WindowEvent e) {
if (BooleanUtils.isNotFalse(window.getDialogOptions().getCloseable())) {
if (window.close("close", false)) {
if (window.close("close")) {
dialog.dispose();
}
}
@ -1715,7 +1718,7 @@ public class DesktopWindowManager extends WindowManager {
windowOpenMode.put(window, openInfo);
}
addShortcuts(window);
addShortcuts(window, openType);
}
public void checkModificationsAndCloseAll(final Runnable runIfOk, final @Nullable Runnable runIfCancel) {

View File

@ -17,7 +17,7 @@
package com.haulmont.cuba.gui.backgroundwork;
import com.haulmont.cuba.gui.WindowManager;
import com.haulmont.cuba.gui.WindowManager.OpenType;
import com.haulmont.cuba.gui.components.*;
import com.haulmont.cuba.gui.executors.BackgroundTask;
import com.haulmont.cuba.gui.executors.BackgroundTaskHandler;
@ -59,7 +59,7 @@ public class BackgroundWorkProgressWindow<T extends Number, V> extends AbstractW
@Inject
protected BackgroundWorker backgroundWorker;
@Inject
protected ProgressBar taskProgress;
protected ProgressBar taskProgressBar;
@Inject
protected ThemeConstants themeConstants;
@ -67,6 +67,9 @@ public class BackgroundWorkProgressWindow<T extends Number, V> extends AbstractW
protected BackgroundTaskHandler<V> taskHandler;
protected boolean cancelAllowed = false;
protected T totalProgress;
protected boolean percentProgress;
/**
* Show modal window with message which will last until task completes.
* Optionally cancel button can be displayed. By pressing cancel button user can cancel task execution.
@ -93,7 +96,7 @@ public class BackgroundWorkProgressWindow<T extends Number, V> extends AbstractW
params.put("cancelAllowed", cancelAllowed);
params.put("percentProgress", percentProgress);
task.getOwnerFrame().openWindow("backgroundWorkProgressWindow", WindowManager.OpenType.DIALOG, params);
task.getOwnerFrame().openWindow("backgroundWorkProgressWindow", OpenType.DIALOG, params);
}
/**
@ -153,11 +156,8 @@ public class BackgroundWorkProgressWindow<T extends Number, V> extends AbstractW
@Override
public void init(Map<String, Object> params) {
getDialogParams()
.setWidth(themeConstants.getInt("cuba.gui.BackgroundWorkProgressWindow.width"));
@SuppressWarnings("unchecked")
final BackgroundTask<T, V> task = (BackgroundTask<T, V>) params.get("task");
BackgroundTask<T, V> task = (BackgroundTask<T, V>) params.get("task");
String title = (String) params.get("title");
if (title != null) {
setCaption(title);
@ -172,71 +172,54 @@ public class BackgroundWorkProgressWindow<T extends Number, V> extends AbstractW
cancelAllowed = BooleanUtils.isTrue(cancelAllowedNullable);
Boolean percentProgressNullable = (Boolean) params.get("percentProgress");
boolean percentProgress = BooleanUtils.isTrue(percentProgressNullable);
this.percentProgress = BooleanUtils.isTrue(percentProgressNullable);
cancelButton.setVisible(cancelAllowed);
getDialogParams().setCloseable(cancelAllowed);
getDialogOptions().setCloseable(cancelAllowed);
@SuppressWarnings("unchecked")
final T total = (T) params.get("total");
this.totalProgress = total;
taskProgress.setValue(0.0f);
showProgress(0);
WrapperTask wrapperTask = new WrapperTask(task, total, percentProgress);
BackgroundTask<T, V> wrapperTask = new LocalizedTaskWrapper<>(task, this);
wrapperTask.addProgressListener(new BackgroundTask.ProgressListenerAdapter<T, V>() {
@Override
public void onProgress(List<T> changes) {
if (!changes.isEmpty()) {
Number lastProcessedValue = changes.get(changes.size() - 1);
showProgress(lastProcessedValue);
}
}
});
taskHandler = backgroundWorker.handle(wrapperTask);
taskHandler.execute();
}
public void cancel() {
if (!taskHandler.cancel()) {
close(Window.CLOSE_ACTION_ID);
}
close(Window.CLOSE_ACTION_ID);
}
@Override
protected boolean preClose(String actionId) {
if (cancelAllowed) {
if (!taskHandler.cancel()) {
return true;
}
public boolean close(String actionId) {
if (taskHandler.cancel()) {
return super.close(actionId);
}
return false;
}
protected class WrapperTask extends LocalizedTaskWrapper<T, V> {
protected void showProgress(Number processedValue) {
float value = processedValue.floatValue() / totalProgress.floatValue();
protected Number total;
protected boolean percentProgress = false;
taskProgressBar.setValue(value);
public WrapperTask(BackgroundTask<T, V> wrappedTask, Number total, boolean percentProgress) {
super(wrappedTask, BackgroundWorkProgressWindow.this);
this.total = total;
this.percentProgress = percentProgress;
showProgressText(0, 0);
}
protected void showProgressText(Number last, float progressValue) {
if (!percentProgress) {
progressText.setValue(formatMessage("backgroundWorkProgress.progressTextFormat", last, total));
} else {
int percentValue = (int) Math.ceil(progressValue * 100);
progressText.setValue(formatMessage("backgroundWorkProgress.progressPercentFormat", percentValue));
}
}
@Override
public void progress(List<T> changes) {
if (!changes.isEmpty()) {
Number last = changes.get(changes.size() - 1);
float value = last.floatValue() / total.floatValue();
taskProgress.setValue(value);
showProgressText(last, value);
}
super.progress(changes);
if (!percentProgress) {
progressText.setValue(formatMessage("backgroundWorkProgress.progressTextFormat", processedValue, totalProgress));
} else {
int percentValue = (int) Math.ceil(value * 100);
progressText.setValue(formatMessage("backgroundWorkProgress.progressPercentFormat", percentValue));
}
}
}

View File

@ -17,7 +17,7 @@
package com.haulmont.cuba.gui.backgroundwork;
import com.haulmont.cuba.gui.WindowManager;
import com.haulmont.cuba.gui.WindowManager.OpenType;
import com.haulmont.cuba.gui.components.AbstractWindow;
import com.haulmont.cuba.gui.components.Button;
import com.haulmont.cuba.gui.components.Label;
@ -46,7 +46,6 @@ import java.util.Map;
* <li>Shows Warning message if for background task specified owner window</li>
* </ul>
* <p/>
*
*/
public class BackgroundWorkWindow<T, V> extends AbstractWindow {
@ -88,7 +87,7 @@ public class BackgroundWorkWindow<T, V> extends AbstractWindow {
params.put("message", message);
params.put("cancelAllowed", cancelAllowed);
task.getOwnerFrame().openWindow("backgroundWorkWindow", WindowManager.OpenType.DIALOG, params);
task.getOwnerFrame().openWindow("backgroundWorkWindow", OpenType.DIALOG, params);
}
/**
@ -132,8 +131,6 @@ public class BackgroundWorkWindow<T, V> extends AbstractWindow {
@Override
public void init(Map<String, Object> params) {
getDialogParams().setWidth(themeConstants.getInt("cuba.gui.BackgroundWorkWindow.width"));
@SuppressWarnings("unchecked")
BackgroundTask<T, V> task = (BackgroundTask<T, V>) params.get("task");
String title = (String) params.get("title");
@ -149,7 +146,8 @@ public class BackgroundWorkWindow<T, V> extends AbstractWindow {
Boolean cancelAllowedNullable = (Boolean) params.get("cancelAllowed");
cancelAllowed = BooleanUtils.isTrue(cancelAllowedNullable);
cancelButton.setVisible(cancelAllowed);
getDialogParams().setCloseable(cancelAllowed);
getDialogOptions().setCloseable(cancelAllowed);
BackgroundTask<T, V> wrapperTask = new LocalizedTaskWrapper<>(task, this);
@ -158,13 +156,14 @@ public class BackgroundWorkWindow<T, V> extends AbstractWindow {
}
public void cancel() {
if (!taskHandler.cancel()) {
close(Window.CLOSE_ACTION_ID);
}
close(Window.CLOSE_ACTION_ID);
}
@Override
protected boolean preClose(String actionId) {
return cancelAllowed;
public boolean close(String actionId) {
if (taskHandler.cancel()) {
return super.close(actionId);
}
return false;
}
}

View File

@ -20,6 +20,7 @@ package com.haulmont.cuba.gui.backgroundwork;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.Messages;
import com.haulmont.cuba.gui.components.Frame;
import com.haulmont.cuba.gui.components.Frame.NotificationType;
import com.haulmont.cuba.gui.components.Window;
import com.haulmont.cuba.gui.executors.BackgroundTask;
import com.haulmont.cuba.gui.executors.BackgroundWorker;
@ -33,11 +34,10 @@ import java.util.Map;
public class LocalizedTaskWrapper<T, V> extends BackgroundTask<T, V> {
protected Logger log = LoggerFactory.getLogger(BackgroundWorker.class);
private final Logger log = LoggerFactory.getLogger(BackgroundWorker.class);
protected BackgroundTask<T, V> wrappedTask;
protected Window window;
protected Messages messages = AppBeans.get(Messages.NAME);
protected LocalizedTaskWrapper(BackgroundTask<T, V> wrappedTask, Window window) {
super(wrappedTask.getTimeoutSeconds(), window);
@ -56,60 +56,38 @@ public class LocalizedTaskWrapper<T, V> extends BackgroundTask<T, V> {
}
@Override
public boolean handleException(final Exception ex) {
public boolean handleException(Exception ex) {
boolean handled = wrappedTask.handleException(ex);
if (!handled) {
final Frame ownerFrame = wrappedTask.getOwnerFrame();
if (ownerFrame != null) {
window.closeAndRun("close", () -> showExecutionError(ex));
log.error("Exception occurred in background task", ex);
handled = true;
} else {
window.close("", true);
}
} else {
if (handled || wrappedTask.getOwnerFrame() == null) {
window.close("", true);
} else {
window.closeAndRun("close", () ->
showExecutionError(ex)
);
log.error("Exception occurred in background task", ex);
handled = true;
}
return handled;
}
protected void showExecutionError(Exception ex) {
final Frame ownerFrame = wrappedTask.getOwnerFrame();
if (ownerFrame != null) {
String localizedMessage = ex.getLocalizedMessage();
if (StringUtils.isNotBlank(localizedMessage)) {
ownerFrame.showNotification(messages.getMessage(getClass(), "backgroundWorkProgress.executionError"),
localizedMessage, Frame.NotificationType.WARNING);
} else {
ownerFrame.showNotification(messages.getMessage(getClass(), "backgroundWorkProgress.executionError"),
Frame.NotificationType.WARNING);
}
}
}
@Override
public boolean handleTimeoutException() {
boolean handled = wrappedTask.handleTimeoutException();
if (!handled) {
final Frame ownerFrame = wrappedTask.getOwnerFrame();
if (ownerFrame != null) {
window.closeAndRun("close", new Runnable() {
@Override
public void run() {
ownerFrame.showNotification(
messages.getMessage(getClass(), "backgroundWorkProgress.timeout"),
messages.getMessage(getClass(), "backgroundWorkProgress.timeoutMessage"),
Frame.NotificationType.WARNING);
}
});
handled = true;
} else {
window.close("", true);
}
} else {
if (handled || wrappedTask.getOwnerFrame() == null) {
window.close("", true);
} else {
window.closeAndRun("close", () -> {
Messages messages = AppBeans.get(Messages.NAME);
wrappedTask.getOwnerFrame().showNotification(
messages.getMessage(LocalizedTaskWrapper.class, "backgroundWorkProgress.timeout"),
messages.getMessage(LocalizedTaskWrapper.class, "backgroundWorkProgress.timeoutMessage"),
NotificationType.WARNING);
});
handled = true;
}
return handled;
}
@ -119,21 +97,19 @@ public class LocalizedTaskWrapper<T, V> extends BackgroundTask<T, V> {
window.close("", true);
try {
// after window close we should show exception messages immediately
wrappedTask.done(result);
} catch (Exception ex) {
// we should show exception messages immediately
showExecutionError(ex);
}
}
@Override
public void canceled() {
window.close("", true);
try {
// after window close we should show exception messages immediately
wrappedTask.canceled();
} catch (Exception ex) {
// we should show exception messages immediately
showExecutionError(ex);
}
}
@ -142,4 +118,22 @@ public class LocalizedTaskWrapper<T, V> extends BackgroundTask<T, V> {
public void progress(List<T> changes) {
wrappedTask.progress(changes);
}
protected void showExecutionError(Exception ex) {
Frame ownerFrame = wrappedTask.getOwnerFrame();
if (ownerFrame != null) {
String localizedMessage = ex.getLocalizedMessage();
Messages messages = AppBeans.get(Messages.NAME);
if (StringUtils.isNotBlank(localizedMessage)) {
ownerFrame.showNotification(
messages.getMessage(LocalizedTaskWrapper.class, "backgroundWorkProgress.executionError"),
localizedMessage, NotificationType.WARNING);
} else {
ownerFrame.showNotification(
messages.getMessage(LocalizedTaskWrapper.class, "backgroundWorkProgress.executionError"),
NotificationType.WARNING);
}
}
}
}

View File

@ -20,9 +20,11 @@
class="com.haulmont.cuba.gui.backgroundwork.BackgroundWorkProgressWindow"
messagesPack="com.haulmont.cuba.gui.backgroundwork">
<layout margin="true" spacing="true">
<dialogMode width="theme://cuba.gui.BackgroundWorkProgressWindow.width"/>
<layout spacing="true">
<label id="text" value="msg://backgroundWorkProgress.defaultText" width="100%"/>
<progressBar id="taskProgress" width="100%"/>
<progressBar id="taskProgressBar" width="100%"/>
<label id="progressText"/>
<hbox align="MIDDLE_RIGHT">
<button id="cancelButton" invoke="cancel" icon="icons/cancel.png" caption="msg://actions.Cancel"/>

View File

@ -20,7 +20,9 @@
class="com.haulmont.cuba.gui.backgroundwork.BackgroundWorkWindow"
messagesPack="com.haulmont.cuba.gui.backgroundwork">
<layout margin="true" spacing="true">
<dialogMode width="theme://cuba.gui.BackgroundWorkWindow.width"/>
<layout spacing="true">
<label id="text" value="msg://backgroundWork.defaultText" width="100%"/>
<progressBar id="taskProgress" width="100%" indeterminate="true"/>
<hbox align="MIDDLE_RIGHT">

View File

@ -17,14 +17,10 @@
backgroundWork.caption = Performing operation
backgroundWork.defaultText = Please wait for operation to complete
cancel = Cancel
backgroundWorkProgress.timeout = Error
backgroundWorkProgress.timeoutMessage = Exceeded the maximum execution time
backgroundWorkProgress.caption = Performing operation
backgroundWorkProgress.defaultText = Please wait for operation to complete
backgroundWorkProgress.progressText = Processed 0 items
backgroundWorkProgress.progressTextFormat = Processed %s items of %s
backgroundWorkProgress.progressPercentFormat = Processed %s%%
backgroundWorkProgress.executionError = Processing error

View File

@ -17,9 +17,8 @@
backgroundWork.caption=Выполняется операция
backgroundWork.defaultText=Пожалуйста, подождите
cancel=Отмена
backgroundWorkProgress.caption=Выполняется операция
backgroundWorkProgress.defaultText=Пожалуйста подождите
backgroundWorkProgress.defaultText=Пожалуйста, подождите
backgroundWorkProgress.progressTextFormat=Обработано: %s из %s
backgroundWorkProgress.progressPercentFormat=Обработано: %s%%
backgroundWorkProgress.executionError=Во время выполнения операции возникла ошибка

View File

@ -681,6 +681,7 @@ public class WebWindowManager extends WindowManager {
vWindow.addPreCloseListener(event -> {
event.setPreventClose(true);
// user has clicked on X
window.close(Window.CLOSE_ACTION_ID);
});
@ -693,8 +694,11 @@ public class WebWindowManager extends WindowManager {
KeyCombination.Modifier.codes(closeCombination.getModifiers())
);
Map<com.vaadin.event.Action, Runnable> actions = new HashMap<>();
actions.put(exitAction, () -> window.close(Window.CLOSE_ACTION_ID));
Map<com.vaadin.event.Action, Runnable> actions = Collections.singletonMap(exitAction, () -> {
if (openType.getOpenMode() != OpenMode.DIALOG || BooleanUtils.isNotFalse(window.getDialogOptions().getCloseable())) {
window.close(Window.CLOSE_ACTION_ID);
}
});
WebComponentsHelper.setActions(vWindow, actions);

View File

@ -326,10 +326,10 @@ public class WebComponentsHelper {
* Add actions to vaadin action container.
*
* @param container any {@link Action.Container}
* @param actions map of actions
* @param actions map of actions
*/
public static void setActions(final Action.Container container,
final Map<Action, Runnable> actions) {
public static void setActions(Action.Container container,
Map<Action, Runnable> actions) {
container.addActionHandler(new Action.Handler() {
@Override
public Action[] getActions(Object target, Object sender) {