/*
* Copyright 2013 Pavel Stastny <pavel.stastny at gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aplikator.client.local.wizards;
import java.util.ArrayList;
import java.util.List;
import org.aplikator.client.local.Aplikator;
import org.aplikator.client.local.widgets.Messages;
import org.aplikator.client.local.widgets.WizardFormWidget;
import org.aplikator.client.shared.data.ClientContext;
import org.aplikator.client.shared.data.FunctionParameters;
import org.aplikator.client.shared.data.FunctionResult;
import org.aplikator.client.shared.data.FunctionResultType;
import org.aplikator.client.shared.data.RecordDTO;
import org.aplikator.client.shared.descriptor.FunctionDTO;
import org.aplikator.client.shared.descriptor.WizardPageDTO;
import org.aplikator.client.shared.rpc.AplikatorErrorCallback;
import org.aplikator.client.shared.rpc.AplikatorService;
import org.gwtbootstrap3.client.shared.event.ModalHiddenEvent;
import org.gwtbootstrap3.client.shared.event.ModalHiddenHandler;
import org.gwtbootstrap3.client.ui.Button;
import org.gwtbootstrap3.client.ui.Container;
import org.gwtbootstrap3.client.ui.Modal;
import org.gwtbootstrap3.client.ui.ModalBody;
import org.gwtbootstrap3.client.ui.ModalFooter;
import org.gwtbootstrap3.client.ui.ModalSize;
import org.gwtbootstrap3.client.ui.constants.ModalBackdrop;
import org.jboss.errai.common.client.api.RemoteCallback;
import org.jboss.errai.enterprise.client.jaxrs.api.RestClient;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.DeckPanel;
/**
* Wizard support
*
* @author Pavel Stastny <pavel.stastny at gmail.com>
*/
public class WizardSupport {
/**
* Function DTO object
*/
private FunctionDTO function;
/**
* Dialog box
*/
private Modal dialogBox;
/**
* Deckpanel
*/
private DeckPanel deckPanel;
/**
* Buttons
*/
private Button okButton;
private Button cancelButton;
private Button nextButton;
private Button prevButton;
/**
* Current form widget
*/
private WizardFormWidget currentWidget;
/**
* Current pageDTO
*/
private WizardPageDTO currentPageDTO;
/**
* Client properties record
*/
private RecordDTO clientPropertiesRecordDTO;
/**
* Flag - true if the window is intialized
*/
private boolean windowInitialized = false;
/**
* Containers
*/
private Container currentContainer;
private ModalBody dialogContents;
//private Record originalRecord;
private ClientContext clientContext;
private WizardSupportCallbacks callbacks;
private List<HandlerRegistration> keyHandlers = new ArrayList<HandlerRegistration>();
public WizardSupport(final FunctionDTO function, final ClientContext clientContext, final WizardSupportCallbacks callbacks) {
this.function = function;
this.clientContext = clientContext;
this.callbacks = callbacks;
}
public ClientContext getClientContext() {
return clientContext;
}
/**
* Collecting record
*/
private void collectRecord() {
if (this.clientPropertiesRecordDTO != null && this.currentWidget != null) {
this.clientPropertiesRecordDTO = this.currentWidget.addFieldsToExistingRecord(this.clientPropertiesRecordDTO);
} else {
this.clientPropertiesRecordDTO = new RecordDTO();
}
}
/**
* Request for change page
*/
public void changePageRequest(final boolean forw) {
this.collectRecord();
FunctionParameters param = new FunctionParameters(
this.function.getId(),
clientContext,
this.clientPropertiesRecordDTO);
RestClient.create(AplikatorService.class,
new RemoteCallback<WizardPageDTO>() {
@Override
public void callback(WizardPageDTO response) {
WizardSupport.this.callbacks.wizardPageCallback(response, forw);
if (response != null) {
if (windowInitialized) {
onReceiveNewPageDTO(response);
} else {
initializeDialog(response);
}
} else {
runFunction();
WizardSupport.this.callbacks.runAfterFunctionCallback();
}
}
},
new AplikatorErrorCallback("aplikator.function.error")
).getWizardPage(this.currentPageDTO != null ? this.currentPageDTO.getPageId() : null, forw, param);
}
/**
* On received page
*
* @param pageDTO
*/
private void onReceiveNewPageDTO(WizardPageDTO pageDTO) {
this.currentPageDTO = pageDTO;
this.currentContainer = new Container();
this.currentContainer.setFluid(true);
this.currentWidget = new WizardFormWidget(pageDTO, pageDTO.getFormDescriptor());
if (pageDTO.getClientRecord() != null) {
this.clientPropertiesRecordDTO = pageDTO.getClientRecord();
this.currentWidget.setOriginal(this.clientPropertiesRecordDTO);
this.currentWidget.populateFormWithSimpleData(true);
}
this.currentContainer.add(this.currentWidget);
this.currentContainer.setWidth("90%");
this.deckPanel.add(this.currentContainer);
this.deckPanel.showWidget(this.deckPanel.getVisibleWidget() + 1);
if (this.deckPanel.getWidgetCount() > 1) {
this.deckPanel.remove(0);
}
this.currentWidget.focusFirstField();
this.onPageChanged();
}
private void onPageChanged() {
if (this.currentPageDTO != null) {
this.okButton.setEnabled(this.currentPageDTO.isHasExecute());
this.nextButton.setEnabled(this.currentPageDTO.isHasNext());
this.prevButton.setEnabled(this.currentPageDTO.isHasPrevious());
if (this.currentPageDTO.isHasNext() && this.currentPageDTO.isHandleEnter()) {
this.currentWidget.addEnterHandler(new Command() {
@Override
public void execute() {
changePageRequest(true);
}
});
} else if (this.currentPageDTO.isHasExecute() && this.currentPageDTO.isHandleEnter()) {
this.currentWidget.addEnterHandler(new Command() {
@Override
public void execute() {
onExecute();
}
});
}
}
}
/**
* Dialog initialization
*
* @param pageDTO
*/
private void initializeDialog(WizardPageDTO pageDTO) {
this.deckPanel = new DeckPanel();
this.dialogContents = new ModalBody();
this.dialogBox = new Modal();
this.dialogBox.getElement().getStyle().setOverflowY(Style.Overflow.AUTO);//fix against hidding scrollbar in modal stack
this.dialogBox.setSize(ModalSize.LARGE);
this.dialogBox.setDataBackdrop(ModalBackdrop.STATIC);
this.dialogBox.addHiddenHandler(new ModalHiddenHandler() {
@Override
public void onHidden(ModalHiddenEvent evt) {
hideDialog();
}
});
this.dialogBox.setRemoveOnHide(true);
this.dialogBox.add(this.dialogContents);
this.dialogContents.add(this.deckPanel);
this.dialogContents.add(buttonsPane());
this.onReceiveNewPageDTO(pageDTO);
this.dialogBox.setTitle(Aplikator.application.getConfigString("aplikator.function.parameters") + " " + function.getLocalizedName());
this.windowInitialized = true;
this.dialogBox.show();
}
public void runFunction() {
this.callbacks.runBeforeFunctionCallback();
RestClient.create(AplikatorService.class,
new RemoteCallback<FunctionResult>() {
public void callback(FunctionResult response) {
WizardSupport.this.callbacks.runAfterFunctionCallback();
if (response.isSuccess()) {
if (FunctionResultType.REPORT.equals(response.getType())) {
Window.open(response.getMessage(), "_blank", "menubar=yes,location=no,resizable=yes,scrollbars=yes,status=no");
} else if (FunctionResultType.DOWNLOAD.equals(response.getType())) {
download(response.getMessage());
} else {
Messages.success(Aplikator.application.getConfigString("aplikator.function.result") + ": " + response.getMessage());
}
} else {
Messages.error(Aplikator.application.getConfigString("aplikator.function.result") + ": " + response.getMessage());
}
}
},
new AplikatorErrorCallback("aplikator.function.error")
).runFunction(new FunctionParameters(this.function.getId(), clientContext, this.clientPropertiesRecordDTO));
Messages.info(Aplikator.application.getConfigString("aplikator.function.started") + " " + function.getLocalizedName());
}
public static native void download(String url) /*-{
$wnd.location.href = url;
}-*/;
private ModalFooter buttonsPane() {
ModalFooter footer = new ModalFooter();
this.okButton = createOKButton();
this.cancelButton = createCancelButton();
this.nextButton = createNextButton();
this.prevButton = createPrevButton();
footer.add(this.prevButton);
footer.add(this.nextButton);
footer.add(this.cancelButton);
footer.add(this.okButton);
footer.addStyleName("app-mg-top-15");
return footer;
}
private void hideDialog() {
this.dialogBox = null;
this.deckPanel = null;
this.okButton = null;
this.cancelButton = null;
this.nextButton = null;
this.prevButton = null;
this.currentWidget = null;
this.currentPageDTO = null;
this.clientPropertiesRecordDTO = null;
this.windowInitialized = false;
WizardSupport.this.callbacks.runAfterFunctionCallback();
}
private void onExecute() {
collectRecord();
runFunction();
dialogBox.hide();
}
private Button createOKButton() {
Button okButton = new Button(Aplikator.application.getConfigString("aplikator.function.ok"), new ClickHandler() {
public void onClick(ClickEvent event) {
onExecute();
}
});
return okButton;
}
private Button createCancelButton() {
Button closeButton = new Button(Aplikator.application.getConfigString("aplikator.function.cancel"), new ClickHandler() {
public void onClick(ClickEvent event) {
dialogBox.hide();
}
});
return closeButton;
}
private Button createPrevButton() {
Button prevButton = new Button(Aplikator.application.getConfigString("aplikator.function.prev"), new ClickHandler() {
public void onClick(ClickEvent event) {
changePageRequest(false);
}
});
return prevButton;
}
private Button createNextButton() {
Button nextButton = new Button(Aplikator.application.getConfigString("aplikator.function.next"), new ClickHandler() {
public void onClick(ClickEvent event) {
changePageRequest(true);
}
});
return nextButton;
}
}