All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.wicket.markup.html.border.Border Maven / Gradle / Ivy

Go to download

Wicket is a Java web application framework that takes simplicity, separation of concerns and ease of development to a whole new level. Wicket pages can be mocked up, previewed and later revised using standard WYSIWYG HTML design tools. Dynamic content processing and form handling is all handled in Java code using a first-class component model backed by POJO data beans that can easily be persisted using your favorite technology.

There is a newer version: 10.0.0
Show newest version
/*
 * 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 org.apache.wicket.markup.html.border;

import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.IMarkupFragment;
import org.apache.wicket.markup.MarkupElement;
import org.apache.wicket.markup.MarkupException;
import org.apache.wicket.markup.MarkupFragment;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.TagUtils;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.panel.BorderMarkupSourcingStrategy;
import org.apache.wicket.markup.html.panel.IMarkupSourcingStrategy;
import org.apache.wicket.markup.parser.XmlTag.TagType;
import org.apache.wicket.markup.resolver.IComponentResolver;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.lang.Args;

/**
 * A border component has associated markup which is drawn and determines placement of markup and/or
 * components nested within the border component.
 * 

* The portion of the border's associated markup file which is to be used in rendering the border is * denoted by a <wicket:border> tag. The children of the border component instance are then * inserted into this markup, replacing the first <wicket:body> tag in the border's associated * markup. *

* For example, if a border's associated markup looked like this: * *

 *   <html>
 *   <body>
 *     <wicket:border>
 *       First <wicket:body/> Last
 *     </wicket:border>
 *   </body>
 *   </html>
 * 
* * And the border was used on a page like this: * *
 *   <html>
 *   <body>
 *     <span wicket:id = "myBorder">
 *       Middle
 *     </span>
 *   </body>
 *   </html>
 * 
* * Then the resulting HTML would look like this: * *
 *   <html>
 *   <body>
 *     First Middle Last
 *   </body>
 *   </html>
 * 
* * In other words, the body of the myBorder component is substituted into the border's associated * markup at the position indicated by the <wicket:body> tag. *

* Regarding <wicket:body/> you have two options. Either use <wicket:body/> (open-close * tag) which will automatically be expanded to <wicket:body>body content</wicket:body> * or use <wicket:body>preview region</wicket:body> in your border's markup. The preview * region (everything in between the open and close tag) will automatically be removed. *

* The border body container will automatically be created for you and added to the border * container. It is accessible via {@link #getBodyContainer()}. In case the body markup is not an * immediate child of border (see the example below), then you must use code such as * someContainer.add(getBodyContainer()) to add the body component to the correct * container. * *

 *   <html>
 *   <body>
 *     <wicket:border>
 *       <span wicket:id="someContainer">
 *         <wicket:body/>
 *       </span>
 *     </wicket:border>
 *   </body>
 *   </html>
 * 
* * The component "someContainer" in the previous example must be added to the border, and not the * body, which is achieved via {@link #addToBorder(Component...)}. *

* {@link #add(Component...)} is an alias to {@code getBodyContainer().add(Component...)} and will * add a child component to the border body as shown in the example below. * *

 *   <html>
 *   <body>
 *     <span wicket:id = "myBorder">
 *       <input wicket:id="name"/;>
 *     </span>
 *   </body>
 *   </html>
 * 
* * This implementation does not apply any magic with respect to component handling. In doubt think * simple. But everything you can do with a MarkupContainer or Component, you can do with a Border * or its Body as well. *

* * Other methods like {@link #remove()}, {@link #get(int)}, {@link #iterator()}, etc. are not * aliased to work on the border's body and attention must be paid when they need to be used. * * @see BorderPanel An alternative implementation based on Panel * @see BorderBehavior A behavior which adds (raw) markup before and after the component * * @author Jonathan Locke * @author Juergen Donnerstag */ public abstract class Border extends WebMarkupContainer implements IComponentResolver { private static final long serialVersionUID = 1L; /** */ public static final String BODY = "body"; /** */ public static final String BORDER = "border"; /** The body component associated with */ private final BorderBodyContainer body; /** * @see org.apache.wicket.Component#Component(String) */ public Border(final String id) { this(id, null); } /** * @see org.apache.wicket.Component#Component(String, IModel) */ public Border(final String id, final IModel model) { super(id, model); body = new BorderBodyContainer(id + "_" + BODY); addToBorder(body); } /** * @return The border body container */ public final BorderBodyContainer getBodyContainer() { return body; } /** * This is for all components which have been added to the markup like this: * *

	 * 	<span wicket:id="myBorder">
	 * 		<input wicket:id="text1" .. />
	 * 		...
	 * 	</span>
	 * 
	 * 
* * Whereas {@link #addToBorder(Component...)} will add a component associated with the following * markup: * *
	 * 	<wicket:border>
	 * 		<form wicket:id="myForm" .. >
	 * 			<wicket:body/>
	 * 		</form>
	 * 	</wicket:border>
	 * 
	 * 
* * @see org.apache.wicket.MarkupContainer#add(org.apache.wicket.Component[]) */ @Override public Border add(final Component... children) { getBodyContainer().add(children); return this; } @Override public Border addOrReplace(final Component... children) { getBodyContainer().addOrReplace(children); return this; } @Override public Border remove(final Component component) { if (component == body) { // when the user calls foo.add(getBodyContainer()) this method will be called with it to // clear body container's old parent, in which case we do not want to redirect to body // container but to border's old remove. super.remove(body); } else { getBodyContainer().remove(component); } return this; } @Override public Border remove(final String id) { getBodyContainer().remove(id); return this; } @Override public Border removeAll() { getBodyContainer().removeAll(); return this; } @Override public Border replace(final Component replacement) { getBodyContainer().replace(replacement); return this; } /** * Adds children components to the Border itself * * @param children * the children components to add * @return this */ public Border addToBorder(final Component... children) { super.add(children); return this; } /** * Removes child from the Border itself * * @param child * @return {@code this} */ public Border removeFromBorder(final Component child) { super.remove(child); return this; } /** * Replaces component in the Border itself * * @param component * @return {@code this} */ public Border replaceInBorder(final Component component) { super.replace(component); return this; } /** * {@inheritDoc} */ @Override public Component resolve(final MarkupContainer container, final MarkupStream markupStream, final ComponentTag tag) { // make sure nested borders are resolved properly if (body.rendering == false) { // We are only interested in border body tags. The tag ID actually is irrelevant since // always preset with the same default if (TagUtils.isWicketBodyTag(tag)) { return body; } } return null; } /** * {@inheritDoc} */ @Override protected IMarkupSourcingStrategy newMarkupSourcingStrategy() { return new BorderMarkupSourcingStrategy(); } /** * Search for the child markup in the file associated with the Border. The child markup must in * between the <wicket:border> tags. */ @Override public IMarkupFragment getMarkup(final Component child) { // Border require an associated markup resource file IMarkupFragment markup = getAssociatedMarkup(); if (markup == null) { throw new MarkupException("Unable to find associated markup file for Border: " + this.toString()); } // Find IMarkupFragment borderMarkup = null; for (int i = 0; i < markup.size(); i++) { MarkupElement elem = markup.get(i); if (TagUtils.isWicketBorderTag(elem)) { borderMarkup = new MarkupFragment(markup, i); break; } } if (borderMarkup == null) { throw new MarkupException(markup.getMarkupResourceStream(), "Unable to find tag in associated markup file for Border: " + this.toString()); } // If child == null, return the markup fragment starting with the tag if (child == null) { return borderMarkup; } // Is child == BorderBody? if (child == body) { // Get the markup return body.getMarkup(); } // Find the markup for the child component IMarkupFragment childMarkup = borderMarkup.find(child.getId()); if (childMarkup != null) { return childMarkup; } return ((BorderMarkupSourcingStrategy)getMarkupSourcingStrategy()).findMarkupInAssociatedFileHeader( this, child); } /** * The container to be associated with the <wicket:body> tag */ public class BorderBodyContainer extends WebMarkupContainer { private static final long serialVersionUID = 1L; /** The markup */ private transient IMarkupFragment markup; // properly resolve borders added to borders protected boolean rendering; /** * Constructor * * @param id */ public BorderBodyContainer(final String id) { super(id); } @Override protected void onComponentTag(final ComponentTag tag) { // Convert open-close to open-body-close if (tag.isOpenClose()) { tag.setType(TagType.OPEN); tag.setModified(true); } super.onComponentTag(tag); } @Override public void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag) { // skip the body if (markupStream.getPreviousTag().isOpen()) { // Only RawMarkup is allowed within the preview region, // which gets stripped from output markupStream.skipRawMarkup(); } // Get the markup and render that instead IMarkupFragment markup = Border.this.getMarkup(); MarkupStream stream = new MarkupStream(markup); ComponentTag tag = stream.getTag(); stream.next(); super.onComponentTagBody(stream, tag); } @Override protected void onRender() { rendering = true; try { super.onRender(); } finally { rendering = false; } } /** * Get the <wicket:body> markup from the body's parent container */ @Override public IMarkupFragment getMarkup() { if (markup == null) { markup = findByName(getParent().getMarkup(null), BODY); } return markup; } /** * Search for <wicket:'name' ...> on the same level, but ignoring other "transparent" * tags such as <wicket:enclosure> etc. * * @param markup * @param name * @return null, if not found */ private final IMarkupFragment findByName(final IMarkupFragment markup, final String name) { Args.notEmpty(name, "name"); MarkupStream stream = new MarkupStream(markup); // Skip any raw markup stream.skipUntil(ComponentTag.class); // Skip stream.next(); while (stream.skipUntil(ComponentTag.class)) { ComponentTag tag = stream.getTag(); if (tag.isOpen() || tag.isOpenClose()) { if (TagUtils.isWicketBodyTag(tag)) { return stream.getMarkupFragment(); } } stream.next(); } return null; } /** * Get the child markup which must be in between the <span wicktet:id="myBorder"> tags */ @Override public IMarkupFragment getMarkup(final Component child) { IMarkupFragment markup = Border.this.getMarkup(); if (markup == null) { return null; } if (child == null) { return markup; } return markup.find(child.getId()); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy