com.doculibre.constellio.wicket.components.modal.NonAjaxModalWindow.java Source code

Java tutorial

Introduction

Here is the source code for com.doculibre.constellio.wicket.components.modal.NonAjaxModalWindow.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 com.doculibre.constellio.wicket.components.modal;

import org.apache.wicket.Component;
import org.apache.wicket.IClusterable;
import org.apache.wicket.IPageMap;
import org.apache.wicket.Page;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.Session;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.AbstractBehavior;
import org.apache.wicket.behavior.HeaderContributor;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.html.resources.CompressedResourceReference;
import org.apache.wicket.markup.html.resources.JavascriptResourceReference;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.RequestParameters;
import org.apache.wicket.settings.IPageSettings;
import org.apache.wicket.util.lang.EnumeratedType;
import org.apache.wicket.util.string.AppendingStringBuffer;
import org.apache.wicket.util.string.Strings;

/**
 * Modal window component.
 * <p>
 * Modal window is a draggable window (with either div or iframe content) that prevent user from
 * interacting the rest of page (using a mask) until the window is closed.
 * <p>
 * If you want this to work under IE, don't attach this component to a &lt;span&gt; tag, make sure
 * you use a &lt;div&gt;.
 * <p>
 * The window is draggable and optionally resizable. The content can be either
 * <ul>
 * <li><b>a component</b> - you need to add the component to modal window (with id obtained using
 * <code>{@link #getContentId()}</code>, or
 * <li><b>a page</b> - you need to pass a <code>{@link PageCreator}</code> instance to a
 * <code>{@link #setPageCreator(NonAjaxModalWindow.PageCreator)}</code> method.
 * </ul>
 * In case the content is a component, it is not rendered until the window is shown (method
 * <code>{@link #show(AjaxRequestTarget)})</code>. In case the content is another page, you can set
 * the desired pagemap name using <code>{@link #setPageMapName(String)}</code>. Setting pagemap is
 * only needed when wicket multiwindow support is on.
 * <p>
 * The window can be made visible from an ajax handler using
 * <code>{@link #show(AjaxRequestTarget)}</code>.
 * <p>
 * To close the window there are multiple options. Static method
 * <code>{@link #close(AjaxRequestTarget)}</code> can be used to close the window from a handler of
 * ajax link inside the window. By default the close button in the upper right corner of the window
 * closes it. This behavior can be altered using
 * <code>{@link #setCloseButtonCallback(NonAjaxModalWindow.CloseButtonCallback)}</code>. If you want to be
 * notified when the window is closed (either using the close button or calling
 * <code>{@link #close(AjaxRequestTarget)})</code>, you can use
 * <code>{@link #setWindowClosedCallback(NonAjaxModalWindow.WindowClosedCallback)}</code>.
 * <p>
 * Title is specified using {@link #setTitle(String)}. If the content is a page (iframe), the title
 * can remain unset, in that case title from the page inside window will be shown.
 * <p>
 * There are several options to specify the visual properties of the window. In all methods where
 * size is expected, width refers to width of entire window (including frame), height refers to the
 * height of window content (without frame).
 * <p>
 * <ul>
 * <li><code>{@link #setResizable(boolean)}</code> specifies, whether the window can be resized.
 * <li><code>{@link #setInitialWidth(int)}</code> and <code>{@link #setInitialHeight(int)}</code>
 * specify the initial width and height of window. If the window is resizable, the unit of these
 * dimensions is always "px". If the window is not resizable, the unit can be specified using
 * <code>{@link #setWidthUnit(String)}</code> and <code>{@link #setHeightUnit(String)}</code>. If
 * the window is not resizable and the content is a component (not a page), the initial height value
 * can be ignored and the actual height can be determined from the height of the content. To enable
 * this behavior use <code>{@link #setUseInitialHeight(boolean)}</code>.
 * <li>The window position (and size if the window is resizable) can be stored in a cookie, so that
 * it is preserved when window is close. The name of the cookie is specified via
 * <code>{@link #setCookieName(String)}</code>. If the name is <code>null</code>, position is not
 * stored (initial width and height are always used). Default cookie name is null (position is not
 * stored).
 * <li><code>{@link #setMinimalWidth(int)}</code> and <code>{@link #setMinimalHeight(int)}</code>
 * set the minimal dimensions of resizable window.
 * <li>Modal window can chose between two colors of frame.
 * <code>{@link #setCssClassName(String)}</code> sets the dialog css class, possible values are
 * <code>{@link #CSS_CLASS_BLUE}</code> for blue frame and <code>{@link #CSS_CLASS_GRAY}</code> for
 * gray frame.
 * <li>Mask (element that prevents user from interacting the rest of the page) can be either
 * transparent or semitransparent. <code>{@link #setMaskType(NonAjaxModalWindow.MaskType)}</code> alters
 * this.
 * </ul>
 * Also it is recommended to put the modal window component in markup before any component (i.e.
 * AjaxLink or AjaxButton) that shows it.
 * <p>
 * If you want to use form in modal window component make sure that you put the modal window itself
 * in another form (nesting forms is legal in Wicket).
 * 
 * @see IPageSettings#setAutomaticMultiWindowSupport(boolean)
 * @author Matej Knopp
 */
public class NonAjaxModalWindow extends Panel {
    private static final long serialVersionUID = 1L;

    private static ResourceReference JAVASCRIPT = new JavascriptResourceReference(NonAjaxModalWindow.class,
            "res/modal.js");

    private static ResourceReference CSS = new CompressedResourceReference(NonAjaxModalWindow.class,
            "res/modal.css");

    /**
     * Creates a new modal window component.
     * 
     * @param id
     *            Id of component
     */
    public NonAjaxModalWindow(String id) {
        super(id);
        setVersioned(false);
        cookieName = null;
        add(empty = new WebMarkupContainer(getContentId()));

        add(new CloseButtonBehavior());
        add(new WindowClosedBehavior());
        add(HeaderContributor.forJavaScript(JAVASCRIPT));
        add(HeaderContributor.forCss(CSS));
    }

    /**
     * Interface for lazy page creation. The advantage of creating page using this interface over
     * just passing a page instance is that page created in <code>{@link #createPage()}</code> will
     * have the pagemap automatically set to the pagemap specified for
     * <code>{@link NonAjaxModalWindow}</code>.
     * 
     * @author Matej Knopp
     */
    public static interface PageCreator extends IClusterable {
        /**
         * Creates a new instance of content page.
         * 
         * @return new page instance
         */
        public Page createPage();
    }

    /**
     * Callback for close button that contains a method that is invoked after the button has been
     * clicked. If no callback instance is specified using
     * <code>{@link #setCloseButtonCallback(NonAjaxModalWindow.CloseButtonCallback)}</code>, no ajax
     * request will be fired. Clicking the button will just close the window.
     * 
     * @author Matej Knopp
     */
    public static interface CloseButtonCallback extends IClusterable {
        /**
         * Methods invoked after the button has been clicked. The invocation is done using an ajax
         * call, so <code>{@link AjaxRequestTarget}</code> instance is available.
         * 
         * @param target
         *            <code>{@link AjaxRequestTarget}</code> instance bound with the ajax request.
         * 
         * @return True if the window can be closed (will close the window), false otherwise
         */
        public boolean onCloseButtonClicked();
    }

    /**
     * Callback called after the window has been closed. If no callback instance is specified using
     * {@link NonAjaxModalWindow#setWindowClosedCallback(NonAjaxModalWindow.WindowClosedCallback)}, no ajax
     * request will be fired.
     * 
     * @author Matej Knopp
     */
    public static interface WindowClosedCallback extends IClusterable {
        /**
         * Called after the window has been closed.
         * 
         * @param target
         *            <code>{@link AjaxRequestTarget}</code> instance bound with the ajax request.
         */
        public void onClose();
    }

    /**
     * Is this window currently showing.
     * 
     * @return the shown
     */
    public boolean isShown() {
        return shown;
    }

    /**
     * Sets the name of the page ma for the content page. This makes only sense when the content is
     * a page, not a component and if wicket multiwindow support is turned on.
     * 
     * @param pageMapName
     *            Name of the page map
     */
    public void setPageMapName(String pageMapName) {
        this.pageMapName = pageMapName;
    }

    /**
     * Returns the page map name.
     * 
     * @return The page map name.
     */
    public String getPageMapName() {
        return pageMapName;
    }

    /**
     * Sets the <code>{@link PageCreator}</code> instance. The instance is only used when no custom
     * component has been added to the dialog.
     * 
     * @param creator
     *            <code>{@link PageCreator}</code> instance
     */
    public void setPageCreator(PageCreator creator) {
        setContent(empty);
        pageCreator = creator;
    }

    /**
     * Sets the <code>{@link CloseButtonCallback}</code> instance.
     * 
     * @param callback
     *            Callback instance
     */
    public void setCloseButtonCallback(CloseButtonCallback callback) {
        closeButtonCallback = callback;
    }

    /**
     * Sets the <code>@{link {@link WindowClosedCallback}</code> instance.
     * 
     * @param callback
     *            Callback instance
     */
    public void setWindowClosedCallback(WindowClosedCallback callback) {
        windowClosedCallback = callback;
    }

    /**
     * Shows the modal window.
     * 
     * @param target
     *            Request target associated with current ajax request.
     */
    public void show() {
        if (shown == false) {
            getContent().setVisible(true);
            shown = true;
        }
    }

    /**
     * Closes the modal window.
     * 
     * @param target
     *            Request target associated with current ajax request.
     */
    public void close() {
        getContent().setVisible(false);
        shown = false;
    }

    /**
     * @return javascript that closes current modal window
     */
    private static String getCloseJavacript() {
        return "var win;\n" //
                + "try {\n" + " win = window.parent.Wicket.Window;\n" + "} catch (ignore) {\n" + "}\n"
                + "if (typeof(win) == \"undefined\" || typeof(win.current) == \"undefined\") {\n" + "  try {\n"
                + "     win = window.Wicket.Window;\n" + "  } catch (ignore) {\n" + "  }\n" + "}\n"
                + "if (typeof(win) != \"undefined\" && typeof(win.current) != \"undefined\") {\n"
                + " var close = function(w) { w.setTimeout(function() {\n" + "     win.current.close();\n"
                + " }, 0);  } \n" + " try { close(window.parent); } catch (ignore) { close(window); };\n" + "}";
    }

    /**
     * Returns the id of content component.
     * 
     * <pre>
     * ModalWindow window = new ModalWindow(parent, &quot;window&quot;);
     * new MyPanel(window, window.getContentId());
     * </pre>
     * 
     * @return Id of content component.
     */
    public String getContentId() {
        return "content";
    }

    /**
     * Sets the minimal width of window. This value is only used if the window is resizable. The
     * width is specified in pixels and it is the width of entire window (including frame).
     * 
     * @param minimalWidth
     *            Minimal window width.
     */
    public void setMinimalWidth(int minimalWidth) {
        this.minimalWidth = minimalWidth;
    }

    /**
     * Returns the minimal width of window (in pixels).
     * 
     * @return Minimal width of window
     */
    public int getMinimalWidth() {
        return minimalWidth;
    }

    /**
     * Sets the minimal height of window. This value is only used if window is resizable. The height
     * is specified in pixels and it is the height of window content (without frame).
     * 
     * @param minimalHeight
     *            Minimal height
     */
    public void setMinimalHeight(int minimalHeight) {
        this.minimalHeight = minimalHeight;
    }

    /**
     * Returns the minimal height of window (in pixels).
     * 
     * @return Minimal height of window
     */
    public int getMinimalHeight() {
        return minimalHeight;
    }

    /**
     * CSS class for window with blue border.
     */
    public final static String CSS_CLASS_BLUE = "w_blue";

    /**
     * CSS class for window with gray border.
     */
    public final static String CSS_CLASS_GRAY = "w_silver";

    /**
     * Sets the CSS class name for this window. This class affects the look of window frame.
     * Possible values (if you don't make your style sheet) are <code>{@link #CSS_CLASS_BLUE}</code>
     * and <code>{@link #CSS_CLASS_GRAY}</code>.
     * 
     * @param cssClassName
     */
    public void setCssClassName(String cssClassName) {
        this.cssClassName = cssClassName;
    }

    /**
     * Returns the CSS class name for this window.
     * 
     * @return CSS class name
     */
    public String getCssClassName() {
        return cssClassName;
    }

    /**
     * Sets the initial width of the window. The width refers to the width of entire window
     * (including frame). If the window is resizable, the width unit is always "px". If the window
     * is not resizable, the unit can be specified using {@link #setWidthUnit(String)}. If cookie
     * name is set and window is resizable, the initial width may be ignored in favor of width
     * stored in cookie.
     * 
     * @param initialWidth
     *            Initial width of the window
     */
    public void setInitialWidth(int initialWidth) {
        this.initialWidth = initialWidth;
    }

    /**
     * Returns the initial width of the window.
     * 
     * @return Initial height of the window
     */
    public int getInitialWidth() {
        return initialWidth;
    }

    /**
     * Sets the initial height of the window. The height refers to the height of window content
     * (without frame). If the window is resizable, the height unit is always "px". If the window is
     * not resizable, the unit can be specified using {@link #setHeightUnit(String)}. If cookie name
     * is set and window is resizable, the initial height may be ignored in favor of height stored
     * in cookie.
     * 
     * @param initialHeight
     *            Initial height of the window
     */
    public void setInitialHeight(int initialHeight) {
        this.initialHeight = initialHeight;
    }

    /**
     * Returns the initial height of the window.
     * 
     * @return Initial height of the window
     */
    public int getInitialHeight() {
        return initialHeight;
    }

    /**
     * Sets whether to use initial height or preserve the real content height. This can only be used
     * if the content is a component (not a page) and the window is not resizable.
     * 
     * @param useInitialHeight
     *            Whether to use initial height instead of preserving content height instead of
     *            using initial height
     */
    public void setUseInitialHeight(boolean useInitialHeight) {
        this.useInitialHeight = useInitialHeight;
    }

    /**
     * Returns true if the initial height should be used (in favor of preserving real content
     * height).
     * 
     * @return True if initial height should be used, false is real content height should be
     *         preserved (valid only if the window is not resizable and the content is a component
     *         (not a page)
     */
    public boolean isUseInitialHeight() {
        return useInitialHeight;
    }

    /**
     * Sets whether the user will be able to resize the window.
     * 
     * @param resizable
     *            Whether the window is resizable
     */
    public void setResizable(boolean resizable) {
        this.resizable = resizable;
    }

    /**
     * Returns whether the window is resizable.
     * 
     * @return True if the window is resizable, false otherwise
     */
    public boolean isResizable() {
        return resizable;
    }

    /**
     * Sets the CSS unit used for initial window width. This is only applicable when the window is
     * not resizable.
     * 
     * @param widthUnit
     *            CSS unit for initial window width.
     */
    public void setWidthUnit(String widthUnit) {
        this.widthUnit = widthUnit;
    }

    /**
     * Returns the CSS unit for initial window width.
     * 
     * @return CSS unit for initial window width.
     */
    public String getWidthUnit() {
        return widthUnit;
    }

    /**
     * Sets the CSS unit used for initial window height. This is only applicable when the window is
     * not resizable.
     * 
     * @param heightUnit
     *            CSS unit for initial window height.
     */
    public void setHeightUnit(String heightUnit) {
        this.heightUnit = heightUnit;
    }

    /**
     * Retrns the CSS unit for initial window height.
     * 
     * @return CSS unit for initial window height.
     */
    public String getHeightUnit() {
        return heightUnit;
    }

    /**
     * Sets the name of the cookie that is used to remember window position (and size if the window
     * is resizable).
     * 
     * @param cookieName
     *            Name of the cookie
     */
    public void setCookieName(String cookieName) {
        if (cookieName != null && cookieName.indexOf(",") != -1 && cookieName.indexOf("|") != -1) {
            throw new IllegalArgumentException("Cookie name may not contain ',' or '|' characters.");
        }
        this.cookieName = cookieName;
    }

    /**
     * Returns the name of cookie that is used to remember window position (and size if the window
     * is resizable).
     * 
     * @return Name of the cookie
     */
    public String getCookieName() {
        return cookieName;
    }

    /**
     * Sets the title of window. If the window is a page, title can be <code>null</code>. In that
     * case it will display the title document inside the window.
     * 
     * @param title
     *            Title of the window
     */
    public void setTitle(String title) {
        this.title = new Model(title);
    }

    /**
     * Sets the title of window. If the window is a page, title can be <code>null</code>. In that
     * case it will display the title document inside the window.
     * 
     * @param title
     *            Title of the window
     */
    public void setTitle(IModel title) {
        title = wrap(title);
        this.title = title;
    }

    /**
     * Returns the title of the window.
     * 
     * @return Title of the window
     */
    public IModel getTitle() {
        return title;
    }

    /**
     * Mask is the element behind the window, that prevents user from interacting the rest of page.
     * Mask can be either
     * <ul>
     * <li><code>{@link #TRANSPARENT}</code> - the mask is invisible
     * <li><code>{@link #SEMI_TRANSPARENT}</code> - the mask is black with small opacity (10%)
     * </ul>
     * 
     * @author Matej Knopp
     */
    public static final class MaskType extends EnumeratedType {

        private static final long serialVersionUID = 1L;

        /**
         * Transparent mask (not visible).
         */
        public static final MaskType TRANSPARENT = new MaskType("TRANSPARENT");

        /**
         * Visible mask (black with low opacity).
         */
        public static final MaskType SEMI_TRANSPARENT = new MaskType("SEMI_TRANSPARENT");

        /**
         * Constructor.
         * 
         * @param name
         */
        public MaskType(String name) {
            super(name);
        }
    };

    /**
     * Sets the mask type of the window.
     * 
     * @param mask
     *            The mask type
     */
    public void setMaskType(MaskType mask) {
        maskType = mask;
    }

    /**
     * Returns the mask type of the window
     * 
     * @return The mask type
     */
    public MaskType getMaskType() {
        return maskType;
    }

    /**
     * Creates the page.
     * 
     * @return Page instance or null if page couldn't be created.
     */
    private Page createPage() {
        if (pageCreator == null) {
            return null;
        } else {
            RequestParameters parameters = RequestCycle.get().getRequest().getRequestParameters();
            String oldPageMapName = parameters.getPageMapName();

            // if there is a pagemap name specified and multiwindow support is
            // on
            if (getPageMapName() != null) {
                // try to find out whether the pagemap already exists
                Session session = Session.get();
                if (session.pageMapForName(getPageMapName(), false) == null) {
                    deletePageMap = true;
                }
                parameters.setPageMapName(getPageMapName());
            }
            try {
                Page page = pageCreator.createPage();
                return page;
            } finally {
                parameters.setPageMapName(oldPageMapName);
            }
        }
    }

    /**
     * @see org.apache.wicket.Component#onBeforeRender()
     */
    protected void onBeforeRender() {
        getContent().setOutputMarkupId(true);
        getContent().setVisible(shown);

        super.onBeforeRender();
    }

    /**
     * @see org.apache.wicket.markup.html.panel.Panel#onComponentTag(org.apache.wicket.markup.ComponentTag)
     */
    protected void onComponentTag(ComponentTag tag) {
        super.onComponentTag(tag);
        tag.put("style", "display:none");
    }

    /**
     * Returns a content component. In case user haven't specified any content component, it returns
     * an empty WebMarkupContainer.
     * 
     * @return Content component
     */
    private Component getContent() {
        return get(getContentId());
    }

    /**
     * Returns true if user has added own component to the window.
     * 
     * @return True if user has added own component to the window, false otherwise.
     */
    private boolean isCustomComponent() {
        return getContent() != empty;
    }

    /**
     * @see org.apache.wicket.MarkupContainer#remove(org.apache.wicket.Component)
     */
    public void remove(Component component) {
        super.remove(component);
        if (component.getId().equals(getContentId())) {
            add(empty = new WebMarkupContainer(getContentId()));
        }
    }

    /**
     * Sets the content of the modal window.
     * 
     * @param component
     */
    public void setContent(Component component) {
        if (component.getId().equals(getContentId()) == false) {
            throw new WicketRuntimeException("Modal window content id is wrong.");
        }
        component.setOutputMarkupPlaceholderTag(true);
        component.setVisible(false);
        replace(component);
        shown = false;
        pageCreator = null;
    }

    /**
     * @author Matej Knopp
     */
    private class WindowClosedBehavior extends AbstractBehavior {
        private static final long serialVersionUID = 1L;

        protected void respond() {
            shown = false;

            // should we cleanup the pagemap?
            if (deletePageMap == true) {
                // get the pagemap
                Session session = Session.get();
                IPageMap pageMap = session.pageMapForName(getPageMapName(), false);

                // if there is any remove it
                if (pageMap != null) {
                    session.removePageMap(pageMap);
                    deletePageMap = false;
                }
            }

            if (windowClosedCallback != null) {
                windowClosedCallback.onClose();
            }
        }
    };

    /**
     * @author Matej Knopp
     */
    private class CloseButtonBehavior extends AbstractBehavior {
        private static final long serialVersionUID = 1L;

        protected void respond() {
            if (closeButtonCallback == null || closeButtonCallback.onCloseButtonClicked() == true) {
                close();
            }
        }
    }

    /**
     * Returns the markup id of the component.
     * 
     * @return component id
     */
    private String getContentMarkupId() {
        return getContent().getMarkupId();
    }

    /**
     * Replaces all occurrences of " in string with \".
     * 
     * @param string
     *            String to be escaped.
     * 
     * @return escaped string
     */
    private String escapeQuotes(String string) {
        if (string.indexOf('"') != -1) {
            string = Strings.replaceAll(string, "\"", "\\\"").toString();
        }
        return string;
    }

    /**
     * Returns the javascript used to open the window.
     * 
     * @return javascript that opens the window
     */
    private String getWindowOpenJavascript() {
        AppendingStringBuffer buffer = new AppendingStringBuffer();

        if (isCustomComponent() == true) {
            buffer.append("var element = document.getElementById(\"" + getContentMarkupId() + "\");\n");
        }

        buffer.append("var settings = new Object();\n");
        buffer.append("settings.minWidth=" + getMinimalWidth() + ";\n");
        buffer.append("settings.minHeight=" + getMinimalHeight() + ";\n");
        buffer.append("settings.className=\"" + getCssClassName() + "\";\n");
        buffer.append("settings.width=\"" + getInitialWidth() + "\";\n");

        if (isUseInitialHeight() == true || isCustomComponent() == false)
            buffer.append("settings.height=\"" + getInitialHeight() + "\";\n");
        else
            buffer.append("settings.height=null;\n");

        buffer.append("settings.resizable=" + Boolean.toString(isResizable()) + ";\n");

        if (isResizable() == false) {
            buffer.append("settings.widthUnit=\"" + getWidthUnit() + "\";\n");
            buffer.append("settings.heightUnit=\"" + getHeightUnit() + "\";\n");
        }

        if (isCustomComponent() == false) {
            Page page = createPage();
            if (page == null) {
                throw new WicketRuntimeException("Error creating page for modal dialog.");
            }
            RequestCycle.get().setUrlForNewWindowEncoding();
            buffer.append("settings.src=\"" + RequestCycle.get().urlFor(page) + "\";\n");

            if (getPageMapName() != null) {
                buffer.append("settings.iframeName=\"" + getPageMapName() + "\";\n");
            }
        } else {
            buffer.append("settings.element = element;\n");
        }

        if (getCookieName() != null) {
            buffer.append("settings.cookieId=\"" + getCookieName() + "\";\n");
        }

        Object title = getTitle() != null ? getTitle().getObject() : null;
        if (title != null) {
            buffer.append("settings.title=\"" + escapeQuotes(title.toString()) + "\";\n");
        }

        if (getMaskType() == MaskType.TRANSPARENT) {
            buffer.append("settings.mask=\"transparent\";\n");
        } else if (getMaskType() == MaskType.SEMI_TRANSPARENT) {
            buffer.append("settings.mask=\"semi-transparent\";\n");
        }

        // set true if we set a windowclosedcallback
        boolean haveCloseCallback = false;

        // in case user is interested in window close callback or we have a
        // pagemap to clean
        // attach notification request
        if ((isCustomComponent() == false && deletePageMap) || windowClosedCallback != null) {
            WindowClosedBehavior behavior = (WindowClosedBehavior) getBehaviors(WindowClosedBehavior.class).get(0);
            buffer.append("settings.onClose = function() { " + /*behavior.getCallbackScript() +*/
                    " };\n");

            haveCloseCallback = true;
        }

        // in case we didn't set windowclosecallback, we need at least callback
        // on close button,
        // to close window property (thus cleaning the shown flag)
        if (closeButtonCallback != null || haveCloseCallback == false) {
            CloseButtonBehavior behavior = (CloseButtonBehavior) getBehaviors(CloseButtonBehavior.class).get(0);
            buffer.append("settings.onCloseButton = function() { " + /*behavior.getCallbackScript() +*/
                    "};\n");
        }

        postProcessSettings(buffer);

        buffer.append("Wicket.Window.create(settings).show();\n");

        return buffer.toString();
    }

    /**
     * Method that allows tweaking the settings
     * 
     * @param settings
     * @return settings javascript
     */
    protected AppendingStringBuffer postProcessSettings(AppendingStringBuffer settings) {
        return settings;
    }

    private boolean deletePageMap = false;
    private boolean shown = false;

    // empty container - used when no component is added
    private WebMarkupContainer empty;

    private int minimalWidth = 200;
    private int minimalHeight = 200;
    private String cssClassName = CSS_CLASS_BLUE;
    private int initialWidth = 600;
    private int initialHeight = 400;
    private boolean useInitialHeight = true;
    private boolean resizable = true;
    private String widthUnit = "px";
    private String heightUnit = "px";
    private String cookieName;
    private IModel title = null;
    private MaskType maskType = MaskType.SEMI_TRANSPARENT;

    private String pageMapName = "modal-dialog-pagemap";

    private PageCreator pageCreator = null;
    private CloseButtonCallback closeButtonCallback = null;
    private WindowClosedCallback windowClosedCallback = null;

    protected void onDetach() {
        super.onDetach();
        if (title != null) {
            title.detach();
        }
    }
}