org.projectforge.web.wicket.flowlayout.ToggleContainerPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.projectforge.web.wicket.flowlayout.ToggleContainerPanel.java

Source

/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
//         www.projectforge.org
//
// Copyright (C) 2001-2013 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.web.wicket.flowlayout;

import org.apache.wicket.AttributeModifier;
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.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.projectforge.web.wicket.bootstrap.GridBuilder;

/**
 * @author Kai Reinhard (k.reinhard@micromata.de)
 * 
 */
public class ToggleContainerPanel extends Panel {
    private static final long serialVersionUID = 6130552547273354134L;

    public static final String CONTENT_ID = "content";

    public static final String HEADING_TEXT_ID = "text";

    private static final String ICON_STATUS_OPENED = "icon-minus";

    private static final String ICON_OPENED = "icon-minus icon-white";

    private static final String ICON_CLOSED = "icon-plus icon-white";

    private final WebMarkupContainer panel, toggleContainer, toggleHeading, iconContainer;

    private Component heading;

    private String headingText;

    private boolean headingChanged;

    private ToggleStatus toggleStatus = ToggleStatus.OPENED;

    /**
     * @param id
     */
    @SuppressWarnings("serial")
    public ToggleContainerPanel(final String id, final DivType... cssClasses) {
        super(id);
        panel = new WebMarkupContainer("panel");
        panel.setOutputMarkupId(true);
        super.add(panel);
        if (cssClasses != null) {
            for (final DivType cssClass : cssClasses) {
                panel.add(AttributeModifier.append("class", cssClass.getClassAttrValue()));
            }
        }
        panel.add(toggleContainer = new WebMarkupContainer("toggleContainer"));
        toggleContainer.setOutputMarkupId(true);
        panel.add(toggleHeading = new WebMarkupContainer("heading"));
        toggleHeading.add(iconContainer = new WebMarkupContainer("icon"));
        iconContainer.setOutputMarkupId(true);
        setOpen();

        if (wantsOnStatusChangedNotification()) {
            final AjaxEventBehavior behavior = new AjaxEventBehavior("onClick") {
                @Override
                protected void onEvent(final AjaxRequestTarget target) {
                    if (toggleStatus == ToggleStatus.OPENED) {
                        target.appendJavaScript("$('#" + toggleContainer.getMarkupId() + "').collapse('hide')");
                        toggleStatus = ToggleStatus.CLOSED;
                    } else {
                        target.appendJavaScript("$('#" + toggleContainer.getMarkupId() + "').collapse('show')");
                        toggleStatus = ToggleStatus.OPENED;
                    }
                    headingChanged = false;
                    ToggleContainerPanel.this.onToggleStatusChanged(target, toggleStatus);
                    if (headingChanged == true) {
                        target.add(heading);
                    }
                    target.add(iconContainer);
                    setIcon();
                }
            };
            toggleHeading.add(behavior);
        } else {
            toggleHeading.add(AttributeModifier.replace("onClick",
                    "$('#" + toggleContainer.getMarkupId() + "').collapse('toggle'); toggleCollapseIcon($('#"
                            + iconContainer.getMarkupId() + "'), '" + ICON_STATUS_OPENED + "','" + ICON_OPENED
                            + "','" + ICON_CLOSED + "'); return false;"));
        }
    }

    /**
     * Appends class "highlight" to the heading class: "collapse-header highlight"
     * @return
     */
    public ToggleContainerPanel setHighlightedHeader() {
        toggleHeading.add(AttributeModifier.append("class", "highlight"));
        return this;
    }

    private void setIcon() {
        if (toggleStatus == ToggleStatus.OPENED) {
            iconContainer.add(AttributeModifier.replace("class", ICON_OPENED));
        } else {
            iconContainer.add(AttributeModifier.replace("class", ICON_CLOSED));
        }
    }

    @SuppressWarnings("serial")
    public ToggleContainerPanel setHeading(final String heading) {
        if (this.heading == null) {
            toggleHeading.add(this.heading = new Label(HEADING_TEXT_ID, new Model<String>() {
                /**
                 * @see org.apache.wicket.model.Model#getObject()
                 */
                @Override
                public String getObject() {
                    return ToggleContainerPanel.this.headingText;
                }
            }).setOutputMarkupId(true));
        }
        if (heading.equals(this.headingText) == false) {
            headingChanged = true;
        }
        this.headingText = heading;
        return this;
    }

    /**
     * @param heading Must have the component id {@link #HEADING_TEXT_ID}.
     * @return
     */
    public ToggleContainerPanel setHeading(final Component heading) {
        if (this.heading != null) {
            throw new IllegalArgumentException("Can't set heading component twice!");
        }
        this.heading = heading;
        toggleHeading.add(heading);
        return this;
    }

    @Override
    public ToggleContainerPanel setMarkupId(final String id) {
        toggleContainer.setMarkupId(id);
        return this;
    }

    public WebMarkupContainer getContainer() {
        return toggleContainer;
    }

    /**
     * Returns whether the subclass wants to be notified on toggle status change
     * 
     * @return
     */
    protected boolean wantsOnStatusChangedNotification() {
        return false;
    }

    /**
     * Hook method when the toggle status of this {@link ToggleContainerPanel} was changed.
     * 
     * @param target
     * @param toggleClosed this represents the <b>new</b> state of the toggle.
     */
    protected void onToggleStatusChanged(final AjaxRequestTarget target, final ToggleStatus toggleStatus) {
    }

    /**
     * @see org.apache.wicket.MarkupContainer#add(org.apache.wicket.Component[])
     */
    public MarkupContainer add(final DivPanel content) {
        return toggleContainer.add(content);
    }

    /**
     * Calls div.add(...);
     * @see org.apache.wicket.Component#add(org.apache.wicket.behavior.Behavior[])
     */
    @Override
    public Component add(final Behavior... behaviors) {
        return toggleContainer.add(behaviors);
    }

    /**
     * Has only effect before rendering this component the first time. Must be called after heading was set.
     * @return this for chaining.
     */
    public ToggleContainerPanel setOpen() {
        toggleStatus = ToggleStatus.OPENED;
        toggleContainer.add(AttributeModifier.replace("class", "in collapse"));
        setIcon();
        return this;
    }

    /**
     * Has only effect before rendering this component the first time. Must be called after heading was set.
     * @return this for chaining.
     */
    public ToggleContainerPanel setClosed() {
        toggleStatus = ToggleStatus.CLOSED;
        toggleContainer.add(AttributeModifier.replace("class", "collapse"));
        setIcon();
        return this;
    }

    /**
     * @return the toggleStatus
     */
    public ToggleStatus getToggleStatus() {
        return toggleStatus;
    }

    public GridBuilder createGridBuilder() {
        final DivPanel content = new DivPanel(ToggleContainerPanel.CONTENT_ID);
        this.add(content);
        final GridBuilder gridBuilder = new GridBuilder(content, content.newChildId(), true);
        return gridBuilder;
    }

    public enum ToggleStatus {
        OPENED, CLOSED
    };
}