package org.nocket.gen.page.guiservice;
import java.awt.Dimension;
import java.io.Serializable;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.util.visit.IVisit;
import org.apache.wicket.util.visit.IVisitor;
import org.nocket.NocketSession;
import org.nocket.component.modal.AbstractModalPanel;
import org.nocket.component.modal.AbstractModalWindow;
import org.nocket.component.modal.ButtonFlag;
import org.nocket.component.modal.ModalCallback;
import org.nocket.component.modal.ModalSettings.ButtonDef;
import org.nocket.gen.notify.Notifier;
import org.nocket.gen.page.DMDWebGenPageContext;
import org.nocket.gen.page.element.BodyElement;
import org.nocket.gen.page.element.ModalElement;
import org.nocket.gen.page.element.synchronizer.SynchronizerHelper;
import org.nocket.page.DMDPageFactory;
import org.nocket.page.DMDPanelFactory;
import org.nocket.page.DMDWebPage;
import org.nocket.util.Assert;
import org.nocket.util.AssertionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import gengui.GUIServiceI.MessageType;
import gengui.util.ReflectionUtil;
@SuppressWarnings("serial")
public class DMDWebGenGuiServiceProvider implements WebGuiServiceI, Serializable {
final private static Logger log = LoggerFactory.getLogger(DMDWebGenGuiServiceProvider.class);
private static final String WICKET_ID_PANEL_INNER_CONTENT = "innerContent";
public class ShowModalPanelConfig implements Serializable {
private DMDWebGenPageContext showModalPanelParentContext;
private DMDWebGenPageContext overrideShowModalPanelParentContext;
private Object showModalPanel;
private boolean modalPanelActive;
private boolean closeModalPanel;
public AbstractModalWindow modalWindowFromANonGenericContext;
public boolean hideCloseButton;
void close() {
if (showModalPanelParentContext != null) {
AbstractModalWindow modal;
if (modalWindowFromANonGenericContext != null) {
modal = modalWindowFromANonGenericContext;
} else {
modal = getModalWindow(pageContext);
}
if (modal != null) {
modal.close(target);
modelChanged(showModalPanelParentContext);
SynchronizerHelper.updateAllFormsFromPage(showModalPanelParentContext, target);
}
}
}
private void modelChanged(DMDWebGenPageContext ctx) {
MarkupContainer root = SynchronizerHelper.findRoot(ctx.getPage());
root.visitChildren(new IVisitor<Component, Object>() {
@Override
public void component(Component object, IVisit<Object> visit) {
if (object instanceof Form) {
Form.class.cast(object).clearInput();
}
}
});
}
private void closeModalPanel() {
this.closeModalPanel = true;
if (showModalPanelParentContext != null) {
SynchronizerHelper.updateAllFormsFromPage(showModalPanelParentContext, target);
}
removeActiveConfig();
close();
}
public Panel newPanel(String id) {
return DMDPanelFactory.getViewPanelInstance(showModalPanel, id);
}
}
private boolean onloadAdded;
private transient DMDWebGenPageContext targetContext;
private transient AjaxRequestTarget target;
private ButtonDef[] confirmButtonDefs;
private String title;
private String message;
private MessageType messageType;
private String status;
private ModalResultCallback confirm;
private Object showPage;
private TouchedRegistry lastTouchedRegistry;
private ShowModalPanelConfig activeShowModalPanelConfig;
private ShowModalPanelConfig nextActiveShowModalPanelConfig;
private transient DMDWebGenPageContext newPanelContext;
private DMDWebGenPageContext pageContext = null;
private ShowModalPanelConfig getActiveShowModalPanelConfig() {
if (activeShowModalPanelConfig != null && activeShowModalPanelConfig.modalPanelActive
&& !activeShowModalPanelConfig.closeModalPanel) {
return activeShowModalPanelConfig;
} else {
return null;
}
}
public synchronized void onGeneratedBinding(final DMDWebGenPageContext ctx) {
lastTouchedRegistry = ctx.getTouchedRegistry();
Component modal = getModalWindow(ctx);
if (modal != null && !onloadAdded) {
onloadAdded = true;
ctx.getPage().add(new OnModalGeneratedBindingBehavior(ctx));
}
ctx.getPage().add(new AddNotificationStyleSheetsBehaviour());
newPanelContext = ctx;
}
protected class OnModalGeneratedBindingBehavior extends AjaxEventBehavior {
protected final DMDWebGenPageContext ctx;
public OnModalGeneratedBindingBehavior(DMDWebGenPageContext ctx) {
super("onload");
this.ctx = ctx;
}
@Override
protected void onEvent(AjaxRequestTarget target) {
DMDWebGenGuiServiceProvider webGuiServiceProvider = NocketSession.get().getDMDWebGenGuiServiceProvider();
webGuiServiceProvider.registerAjaxRequestTarget(ctx, target);
webGuiServiceProvider.unregisterAjaxRequestTarget(ctx, target);
onloadAdded = false;
}
// @Override
// public void renderHead(Component component, IHeaderResponse response) {
// response.render(OnLoadHeaderItem.forScript(getCallbackScript()));
// }
}
protected static class AddNotificationStyleSheetsBehaviour extends Behavior {
@Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
// Stylesheets für PNotify, falls man eine Statusmeldung anzeigen will
// Die Zeilen sorgen dafür, dass man sich nicht darauf verlassen muss,
// dass die Stylesheets im ...Page.html oder einem Basis-HTML bereits
// eingebunden wurden. Insbesondere die modalen Dialoge leiten direkt
// von DMDWebPage ab und erben daher keine HTML-Basisbestandteile
response.render(CssHeaderItem.forUrl("css/jquery.pnotify.default.icons.css"));
response.render(CssHeaderItem.forUrl("css/jquery.pnotify.default.css"));
response.render(JavaScriptHeaderItem.forUrl("js/defaultBtn.js"));
}
}
private DMDWebGenPageContext getNewPanelContext() {
return newPanelContext;
}
public synchronized void registerAjaxRequestTarget(final DMDWebGenPageContext ctx, AjaxRequestTarget target) {
ctx.updatePage(target);
if (this.target != null) {
System.err
.println("WARNING: Seems like the "
+ getClass().getSimpleName()
+ " state is inconsistent right now, since a previous "
+ AjaxRequestTarget.class.getSimpleName()
+ " is still set. Clearing everything to come to a sane state again! This might have been caused by some exception!");
eraseAllShowModalPanelConfig();
}
if (activeShowModalPanelConfig != null) {
activeShowModalPanelConfig.modalPanelActive = true;
}
this.targetContext = ctx;
this.target = target;
}
private void eraseAllShowModalPanelConfig() {
clear(false);
if (activeShowModalPanelConfig != null) {
activeShowModalPanelConfig.close();
}
activeShowModalPanelConfig = null;
nextActiveShowModalPanelConfig = null;
}
public synchronized void unregisterAjaxRequestTarget(DMDWebGenPageContext outerCtx, AjaxRequestTarget target) {
// Assert.test(target == this.target, "Wrong " + AjaxRequestTarget.class.getSimpleName() + " supplied!");
if (target != this.target) {
String text = "Wrong " + AjaxRequestTarget.class.getSimpleName() + " supplied! \ntarget == " + target
+ "\nthis.target == " + this.target;
// eraseAllShowModalPanelConfig();
// Assert.test(target == this.target, text);
log.debug(text);
return;
}
Assert.test(outerCtx == this.targetContext, "Wrong " + DMDWebGenPageContext.class.getSimpleName()
+ " supplied!");
final DMDWebGenPageContext ctx;
if (activeShowModalPanelConfig != null
&& activeShowModalPanelConfig.overrideShowModalPanelParentContext != null) {
ctx = activeShowModalPanelConfig.overrideShowModalPanelParentContext;
} else {
ctx = outerCtx;
}
lastTouchedRegistry = ctx.getTouchedRegistry();
if (showPage != null) {
ctx.getPage().setResponsePage(DMDPageFactory.getViewPageInstance(showPage));
clear(true);
} else {
boolean openModalMessage = message != null || title != null;
boolean openModalConfirm = confirm != null;
boolean openModalPanel = activeShowModalPanelConfig != null
&& activeShowModalPanelConfig.showModalPanelParentContext == null;
if (openModalMessage || openModalConfirm || openModalPanel) {
final AbstractModalWindow modal = getModalWindow(ctx);
if (openModalPanel) {
openModalPanel(ctx, modal, target);
} else if (openModalConfirm) {
openModalConfirm(ctx, modal);
} else {
openModalMessage(modal);
}
}
renderStatusMessage();
clear(false);
}
}
/**
* Modalen Dialog wenn m�glich von oberster Page laden
* @param ctx
* @return
*/
private AbstractModalWindow getModalWindow(DMDWebGenPageContext ctx) {
try {
MarkupContainer container = ctx.getPage();
while(container.getParent() != null) {
container = container.getParent();
}
final AbstractModalWindow modal = (AbstractModalWindow) ((DMDWebPage)container).getPageContext().getComponentRegistry().getComponent(ModalElement.DEFAULT_WICKET_ID);
Assert.test(modal != null, "There is no modal component in " + ctx.getPage().getClass().getSimpleName()
+ ". You need to add a tag for it for this to work once on the root of the page: <div wicket:id=\"modal\"></div>");
pageContext = ((DMDWebPage)container).getPageContext();
return modal;
} catch (AssertionException e) {
throw e;
} catch (ClassCastException e) {
return null;
}
}
private void renderStatusMessage() {
if (status == null)
return;
Notifier.info(target, status);
}
private void openModalPanel(DMDWebGenPageContext ctx, AbstractModalWindow modal, AjaxRequestTarget target) {
activeShowModalPanelConfig.showModalPanelParentContext = ctx;
String title = ReflectionUtil.toTitle(activeShowModalPanelConfig.showModalPanel);
Panel panel = activeShowModalPanelConfig.newPanel(WICKET_ID_PANEL_INNER_CONTENT);
CloserHandler closerHandler = new CloserHandler(activeShowModalPanelConfig.showModalPanelParentContext,
activeShowModalPanelConfig.hideCloseButton);
showPanel(modal, panel, title, closerHandler);
target.add(modal);
}
// TODO meis026 nur über den NichtGenerischen-Webadapter erreichbar machen
public synchronized <T> void openModalPanelFromNonGenericContext(AbstractModalWindow modal, AjaxRequestTarget target,
Object domainObject) {
openModalPanelFromNonGenericContext(modal, target, domainObject, false);
}
public synchronized <T> void openModalPanelFromNonGenericContext(AbstractModalWindow modal, AjaxRequestTarget target,
Object domainObject, boolean hideCloseButton) {
showModalPanel(domainObject, hideCloseButton);
Panel panel = activeShowModalPanelConfig.newPanel(WICKET_ID_PANEL_INNER_CONTENT);
CloserHandler closerHandler = new CloserHandler(getNewPanelContext(), hideCloseButton);
activeShowModalPanelConfig.modalWindowFromANonGenericContext = modal;
activeShowModalPanelConfig.showModalPanelParentContext = getNewPanelContext();
String title = ReflectionUtil.toTitle(activeShowModalPanelConfig.showModalPanel);
showPanel(modal, panel, title, closerHandler);
target.add(modal);
}
private void showPanel(AbstractModalWindow modal, Panel panel, String title, CloserHandler closeHandler) {
AbstractModalPanel modalPanel = modal.getNewModalPanel("content", Model.of(title));
modalPanel.setDefaultCloserButtonCallback(closeHandler);
modalPanel.setContent(panel);
modal.setModalPanel(modalPanel);
Dimension dimension = dimensionForModalPanel();
modal.setDimension(dimension);
modal.show();
}
private Dimension dimensionForModalPanel() {
BodyElement bodyElement = newPanelContext.getPageRegistry().getBodyElement();
Integer width = bodyElement.getWidth();
Integer height = bodyElement.getHeight();
return width != null && height != null ? new Dimension(width, height) : null;
}
private void openModalConfirm(final DMDWebGenPageContext ctx, final AbstractModalWindow modal) {
ModalCallback modalCallback = new ModalCallback() {
private final ModalResultCallback confirmCopy = confirm;
@Override
public boolean doAction(AjaxRequestTarget target, ButtonFlag flag) {
ctx.updatePage(target);
DMDWebGenGuiServiceProvider webGuiServiceProvider = NocketSession.get()
.getDMDWebGenGuiServiceProvider();
try {
webGuiServiceProvider.registerAjaxRequestTarget(ctx, target);
confirmCopy.onResult(flag);
SynchronizerHelper.updateAllFormsFromPage(ctx, target);
} finally {
webGuiServiceProvider.unregisterAjaxRequestTarget(ctx, target);
}
/*
* Wenn es noch ein modaler Dialog gezeigt werden soll, dann
* muss das mitgeteilt werden. Boolean.TRUE sorgt daf�r, dass
* genau dann das Schlieߟen des Modal Windows verhindert wird,
* damit nachfolgend im ModalWindow eingereichte Panels auch
* angezeigt werden.
*/
return webGuiServiceProvider.activeShowModalPanelConfig == null;
}
};
modal.showConfirm(title, message, modalCallback, confirmButtonDefs);
}
private void openModalMessage(final AbstractModalWindow modal) {
switch (messageType) {
case INFO:
modal.showInfo(title, message);
break;
case WARNING:
modal.showWarning(title, message);
break;
case ERROR:
modal.showError(title, message);
break;
default:
throw new IllegalArgumentException("Unknown " + MessageType.class.getSimpleName() + ": " + messageType);
}
}
private void removeActiveConfig() {
if (nextActiveShowModalPanelConfig != null) {
nextActiveShowModalPanelConfig.overrideShowModalPanelParentContext = activeShowModalPanelConfig.showModalPanelParentContext;
}
activeShowModalPanelConfig = nextActiveShowModalPanelConfig;
nextActiveShowModalPanelConfig = null;
}
private void clear(boolean redirecting) {
target = null;
targetContext = null;
if (!redirecting) {
title = null;
message = null;
messageType = null;
confirm = null;
status = null;
}
showPage = null;
}
@Override
public synchronized void errorMessage(String message) {
this.message = message;
this.messageType = MessageType.ERROR;
}
@Override
public synchronized void errorMessage(String title, String message) {
this.title = title;
errorMessage(message);
}
@Override
public synchronized void infoMessage(String message) {
this.message = message;
this.messageType = MessageType.INFO;
}
@Override
public synchronized void infoMessage(String title, String message) {
this.title = title;
infoMessage(message);
}
@Override
public synchronized void warningMessage(String message) {
this.message = message;
this.messageType = MessageType.WARNING;
}
@Override
public synchronized void warningMessage(String title, String message) {
this.title = title;
warningMessage(message);
}
@Override
public synchronized void confirmMessage(String message, ModalResultCallback<ButtonFlag> callback,
ButtonDef... buttonDefs) {
this.message = message;
this.confirm = callback;
this.confirmButtonDefs = buttonDefs;
}
@Override
public synchronized void confirmMessage(String title, String message, ModalResultCallback<ButtonFlag> callback,
ButtonDef... buttonDefs) {
this.title = title;
this.confirmButtonDefs = buttonDefs;
confirmMessage(message, callback, buttonDefs);
}
@Override
public synchronized void status(String message) {
this.status = message;
}
@Override
public synchronized void showPage(Object domainObject) {
if (domainObject == null) {
//do not reset selection
return;
}
this.showPage = domainObject;
}
@Override
public synchronized void showModalPanel(Object domainObject) {
showModalPanel(domainObject, false);
}
@Override
public synchronized <T> void showModalPanel(Object domainObject, boolean hideCloseButton) {
final ShowModalPanelConfig config = new ShowModalPanelConfig();
config.showModalPanel = domainObject;
config.hideCloseButton = hideCloseButton;
if (activeShowModalPanelConfig != null) {
nextActiveShowModalPanelConfig = config;
} else {
activeShowModalPanelConfig = config;
}
}
@Override
public synchronized boolean touched(String... wicketIdPrefixes) {
return lastTouchedRegistry.touched(wicketIdPrefixes);
}
@Override
public synchronized void touch(String... wicketIdPrefixes) {
lastTouchedRegistry.touch(wicketIdPrefixes);
}
@Override
public synchronized void untouch(String... wicketIdPrefixes) {
lastTouchedRegistry.untouch(wicketIdPrefixes);
}
@Override
public synchronized boolean isModalPanelActive() {
return getActiveShowModalPanelConfig() != null;
}
@Override
public synchronized void closeModalPanel() {
Assert.test(isModalPanelActive(), "No ModalPage currently active!");
getActiveShowModalPanelConfig().closeModalPanel();
}
@Override
public String workdir() {
return WebApplication.get().getServletContext().getRealPath(".");
}
@Override
public void resetModalPanelConfig() {
if (isModalPanelActive()) {
removeActiveConfig();
activeShowModalPanelConfig = null;
}
}
}