/*
* Copyright 2009 Rodrigo Reyes reyes.rr at gmail dot com
*
* Licensed 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 net.kornr.swit.wicket.border;
import java.util.HashMap;
import net.kornr.swit.util.MappedString;
import net.kornr.swit.wicket.border.graphics.BorderMaker;
import net.kornr.swit.wicket.border.graphics.SizedBorder;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.markup.html.IHeaderContributor;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.border.Border;
import org.apache.wicket.util.string.CssUtils;
import org.apache.wicket.util.template.PackagedTextTemplate;
/**
* ImageBorder implements a pure-css liquid border built with images, suitable for rounded borders for instance.
* Note however that css-based liquid borders are significantly harder to use than the TableImageBorder, because of the many constraints
* of CSS. So, unless you really need to avoid tables, for technical or ideological reasons, we recommend using TableImageBorder whenever possible.
*
* <p>
* Before using this class, you should be familiar with the liquid rounded-corner CSS technique, please check the web for tutorials.
* Basically, it relies on images parts overlapping each other, and has the following constraints over the images used:
* <ul>
* <li>The external color of the border (outside the border) must NOT be transparent. This is a major drawback, as you need to make the
* component aware of the background (unlike the TableImageBorder, which can use a transparent background color)</li>
* <li>The maximum size of the display must be known in advance. Yes, that's make liquid css mildly liquid, really, but that's the constraint of this CSS technique.
* </ul>
*
* As a consequence of those constraints, here is what you must do on your code to make it work smoothly:
* <ul>
* <li>The graphics of the border must have a non-transparent background, and have a size as big as possible. To do that, you just need to apply the following
* border objects to your initial border:
* <pre>
* static private Long FORCESIZE = SizedBorder.register(YOURBORDER, 1200, 800);
* static private Long FORCEBACKGROUND = MarginBorder.register(s_big, 0, 0, 0, 0, BACKGROUNDCOLOR);
* </pre>
* This transform your original <tt>YOURBORDER</tt> border into something suitable for the css liquid layout. Note the width and height of the newly created border,
* 1200x800, this is the maximum size your liquid layout should be able to reach.
* <p> To create an ImageTable object, just use <tt>ImageTable.createFromBorder("someId", FORCEBACKGROUND)</tt> (note that you must use the FORCEBACKGROUND border:
* the <tt>YOURBORDER</tt> border is not modified, you must use the result of the chain of transformation that ends with the <tt>FORCEBACKGROUND</tt> object.
* </li>
* <li>
* To ensure your layout doesn't get bigger than your maximum, specify a <tt>style="max-width:1200px; max-height:800px"</tt> on your html markup.
* </li>
* </ul>
*
*/
public class ImageBorder extends Border implements IHeaderContributor
{
private WebMarkupContainer m_roundBoxTop, m_roundBoxTopRight, m_roundBoxTopLeft, m_roundBoxBottomRight, m_roundBoxBottomLeft;
private WebMarkupContainer m_content;
private String m_topRightImg, m_topLeftImg, m_bottomRightImg, m_bottomLeftImg;
static private MappedString s_css = // new MappedString("#${0} { margin:0; padding:0; background:url('${1}') white repeat-x left top; }\n"
new MappedString(""
+ "#${2} { margin:0; padding:0; background:url('${3}') white no-repeat right top; }\n"
+ "#${4} { margin:0; padding:0; background: url('${5}') no-repeat left top; }\n"
+ "#${6} { margin:0; padding:0; background: url('${7}') no-repeat right bottom; }\n"
+ "#${8} { margin:0; padding:0; background: url('${9}') no-repeat left bottom; }\n"
+ "#${10} { margin:0; padding: 0; }");
/**
* Use this static factory method to create an ImageBorder using a borderId. Please refer to the documentation of the class
* for the constraints.
* @param id the wicket component id
* @param borderId an id for the border
* @return an ImageBorder border
*/
public static ImageBorder createFromBorder(String id, Long borderId)
{
BorderMaker border = BorderMaker.get(borderId);
String tr = border.getUrl(borderId, "cell2356", false);
String tl = border.getUrl(borderId, "cell14", false);
String br = border.getUrl(borderId, "cell89", false);
String bl = border.getUrl(borderId, "bl", false);
return new ImageBorder(id, tr, tl, br, bl);
}
/**
* Creates an image border with the four image URL provided as string
* @param id id of the wicket component
* @param topRightImg the top right image url
* @param topLeftImg the top left image url
* @param bottomRightImg the bottom right image url
* @param bottomLeftImg the bottom left image url
*/
public ImageBorder(String id, String topRightImg, String topLeftImg, String bottomRightImg, String bottomLeftImg)
{
super(id);
m_topRightImg = topRightImg;
m_topLeftImg = topLeftImg;
m_bottomRightImg = bottomRightImg;
m_bottomLeftImg = bottomLeftImg;
init();
}
/**
* Creates an image border using the four images provided as ResourceReference objects.
* @param id id of the wicket component
* @param topRightImg the top right image
* @param topLeftImg the top left image
* @param bottomRightImg the bottom right image
* @param bottomLeftImg the bottom left image
*/
public ImageBorder(String id, ResourceReference topRightImg, ResourceReference topLeftImg, ResourceReference bottomRightImg, ResourceReference bottomLeftImg)
{
super(id);
m_topRightImg = this.urlFor(topRightImg).toString();
m_topLeftImg = this.urlFor(topLeftImg).toString();
m_bottomRightImg = this.urlFor(bottomRightImg).toString();
m_bottomLeftImg = this.urlFor(bottomLeftImg).toString();
init();
}
public void init()
{
m_roundBoxTop = new WebMarkupContainer("roundbox-top");
m_roundBoxTopRight = new WebMarkupContainer("roundbox-tr");
m_roundBoxTopLeft = new WebMarkupContainer("roundbox-tl");
m_roundBoxBottomRight = new WebMarkupContainer("roundbox-br");
m_roundBoxBottomLeft = new WebMarkupContainer("roundbox-bl");
m_content = new WebMarkupContainer("roundbox-content");
m_roundBoxTop.setOutputMarkupId(true);
m_roundBoxTopRight.setOutputMarkupId(true);
m_roundBoxTopLeft.setOutputMarkupId(true);
m_roundBoxBottomRight.setOutputMarkupId(true);
m_roundBoxBottomLeft.setOutputMarkupId(true);
m_content.setOutputMarkupId(true);
m_roundBoxTop.add(m_roundBoxTopRight);
m_roundBoxTopRight.add(m_roundBoxTopLeft);
m_roundBoxTopLeft.add(m_roundBoxBottomRight);
m_roundBoxBottomRight.add(m_roundBoxBottomLeft);
m_roundBoxBottomLeft.add(m_content);
m_content.add(getBodyContainer());
this.add(m_roundBoxTop);
}
public void renderHead(IHeaderResponse response)
{
String css = CssUtils.INLINE_OPEN_TAG
+ s_css.map(
"", "",
m_roundBoxTopRight.getMarkupId(), m_topRightImg,
m_roundBoxTopLeft.getMarkupId(), m_topLeftImg,
m_roundBoxBottomRight.getMarkupId(), m_bottomRightImg,
m_roundBoxBottomLeft.getMarkupId(), m_bottomLeftImg,
m_content.getMarkupId()
)
+ CssUtils.INLINE_CLOSE_TAG;
response.renderString(css);
}
}