001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.markup.html.basic;
018
019import org.apache.wicket.Component;
020import org.apache.wicket.markup.html.WebMarkupContainer;
021import org.apache.wicket.util.lang.Args;
022
023
024/**
025 * <code>&lt;wicket:enclosure&gt;</code> is nice and prevents that users have to add boilerplate to
026 * their application. But it is not without problems. The child components are children in the
027 * markup, but the auto-component generated for the enclosure tag will not magically re-parent the
028 * child components. Thus, the markup hierarchy and the component hierarchy will be out of sync. The
029 * automatically created enclosure container will be created alongside its "children" with both
030 * attached to the very same parent container. That leads to a tricky situation since e.g.
031 * <code>onBeforeRender()</code> will be called for enclosure children even if the enclosure is made
032 * invisible by it controlling child.
033 * <p>
034 * On top auto-components cannot keep any state. A new instance is created during each render
035 * process and automatically deleted at the end. That implies that we cannot prevent
036 * <code>validation()</code> from being called, since validation() is called before the actual
037 * render process has started.
038 * </p>
039 * <p>
040 * Where any of these problems apply, you may replace the tag and manually add this simple container
041 * which basically does the same. But instead of adding the children to the Page, Panel whatever,
042 * you must add the children to this container in order to keep the component hierarchy in sync.
043 * </p>
044 *
045 * <p>
046 * <strong>Note</strong>: Make sure the markup element associated with this {@link EnclosureContainer}
047 * is anything but <em>&lt;wicket:enclosure&gt;</em>, e.g. a &lt;div&gt;, a &lt;span&gt; or even a
048 * &lt;wicket:container&gt;
049 * </p>
050 * 
051 * @author Juergen Donnerstag
052 * @since 1.5
053 */
054public class EnclosureContainer extends WebMarkupContainer
055{
056        private static final long serialVersionUID = 1L;
057
058        /** The child component to delegate the isVisible() call to */
059        private final Component child;
060
061        /**
062         * Construct.
063         * 
064         * @param id
065         * @param child
066         *            child component that will control the visibility of the enclosure
067         */
068        public EnclosureContainer(final String id, final Component child)
069        {
070                super(id);
071
072                Args.notNull(child, "child");
073
074                this.child = child;
075
076                // Usually we don't want this extra tag
077                setRenderBodyOnly(true);
078        }
079
080        /**
081         * Overridden to set the visibility depending on children {@link #determineVisibility()}.
082         */
083        @Override
084        protected void onConfigure()
085        {
086                super.onConfigure();
087                child.configure();
088
089                setVisible(child.determineVisibility());
090        }
091}