Table of contents
Object Container / Adding Flash to a Wicket Application
General Object Class
First, we create a Object base class to extend for all kinds of embedded objects:
package org.apache.wicket.components.embed; import java.util.List; import org.apache.wicket.Component; import org.apache.wicket.ResourceReference; import org.apache.wicket.Response; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.MarkupStream; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.protocol.http.ClientProperties; import org.apache.wicket.protocol.http.WebRequestCycle; import org.apache.wicket.protocol.http.WebSession; import org.apache.wicket.protocol.http.request.WebClientInfo; import org.apache.wicket.request.ClientInfo; import org.apache.wicket.util.value.IValueMap; public abstract class ObjectContainer extends WebMarkupContainer { // Some general attributes for the object tag: private static final String ATTRIBUTE_CONTENTTYPE = "type"; private static final String ATTRIBUTE_CLASSID = "classid"; private static final String ATTRIBUTE_CODEBASE = "codebase"; // This is used for browser specific adjustments private ClientProperties clientProperties = null; public ObjectContainer( String id ) { super( id ); } // Set an attribute/property public abstract void setValue( String name, String value ); // Get an attribute/property public abstract String getValue( String name ); // Set the object's content type protected abstract String getContentType( ); // Set the object's clsid (for IE) protected abstract String getClsid( ); // Where to get the browser plugin (for IE) protected abstract String getCodebase( ); // Object's valid attribute names protected abstract List<String> getAttributeNames( ); // Object's valid parameter names protected abstract List<String> getParameterNames( ); // Utility function to get the URL for the object's data protected String resolveResource( String src ) { // if it's an absolute path, return it: if( src.startsWith( "/" ) || src.startsWith( "http://" ) || src.startsWith( "https://" ) ) return(src); // use the parent container class to resolve the resource reference Component parent = getParent(); if( parent != null ) { ResourceReference resRef = new ResourceReference( parent.getClass(), src ); return(urlFor( resRef ).toString()); } return(src); } public void onComponentTag( ComponentTag tag ) { super.onComponentTag( tag ); // get the attributes from the html-source IValueMap attributeMap = tag.getAttributes(); // set the content type String contentType = getContentType(); if( contentType != null && !"".equals( contentType ) ) attributeMap.put( ATTRIBUTE_CONTENTTYPE, contentType ); // set clsid and codebase for IE if( getClientProperties().isBrowserInternetExplorer() ) { String clsid = getClsid(); String codeBase = getCodebase(); if( clsid != null && !"".equals( clsid ) ) attributeMap.put( ATTRIBUTE_CLASSID, clsid ); if( codeBase != null && !"".equals( codeBase ) ) attributeMap.put( ATTRIBUTE_CODEBASE, codeBase ); } // add all attributes for( String name : getAttributeNames() ) { String value = getValue( name ); if( value != null ) attributeMap.put( name, value ); } } public void onComponentTagBody( MarkupStream markupStream, ComponentTag openTag ) { Response response = getResponse(); response.write( "\n" ); // add all object's parameters: for( String name : getParameterNames() ) { String value = getValue( name ); if( value != null ) { response.write( "<param name=\"" ); response.write( name ); response.write( "\" value=\"" ); response.write( value ); response.write( "\"/>\n" ); } } super.onComponentTagBody( markupStream, openTag ); } // shortcut to the client properties: protected ClientProperties getClientProperties( ) { if( clientProperties == null ) { ClientInfo clientInfo = WebSession.get().getClientInfo(); if( clientInfo == null || !(clientInfo instanceof WebClientInfo) ) { clientInfo = new WebClientInfo( (WebRequestCycle) getRequestCycle() ); WebSession.get().setClientInfo( clientInfo ); } clientProperties = ((WebClientInfo) clientInfo).getProperties(); } return(clientProperties); } }
Flash Component
Then we implement our FlashComponent:
package org.apache.wicket.components.embed; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.wicket.Response; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.MarkupStream; import org.apache.wicket.util.value.IValueMap; /** * @author Jan Kriesten * @author manuelbarzi * */ public class ShockWaveComponent extends ObjectContainer { private static final long serialVersionUID = 1L; private static final String CONTENTTYPE = "application/x-shockwave-flash"; private static final String CLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"; private static final String CODEBASE = "http://fpdownload.adobe.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0"; // valid attributes private static final List<String> attributeNames = Arrays.asList(new String[] { "classid", "width", "height", "codebase", "align", "base", "data" }); // valid parameters private static final List<String> parameterNames = Arrays.asList(new String[] { "devicefont", "movie", "play", "loop", "quality", "bgcolor", "scale", "salign", "menu", "wmode", "allowscriptaccess", "seamlesstabbing" }); // combined options (to iterate over them) private static final List<String> optionNames = new ArrayList<String>(attributeNames.size() + parameterNames.size()); static { optionNames.addAll(attributeNames); optionNames.addAll(parameterNames); } private Map<String, String> attributes; private Map<String, String> parameters; public ShockWaveComponent(String id) { super(id); attributes = new HashMap<String, String>(); parameters = new HashMap<String, String>(); } public ShockWaveComponent(String id, String movie, String width, String height) { this(id); setValue("movie", movie); setValue("width", width); setValue("height", height); } public void setValue(String name, String value) { // IE and other browsers handle movie/data differently. So movie is used // for IE, whereas // data is used for all other browsers. The class uses movie parameter // to handle url and // puts the values to the maps depending on the browser information String parameter = name.toLowerCase(); if ("data".equals(parameter)) parameter = "movie"; if ("movie".equals(parameter) && !getClientProperties().isBrowserInternetExplorer()) attributes.put("data", value); if (attributeNames.contains(parameter)) attributes.put(parameter, value); else if (parameterNames.contains(parameter)) parameters.put(parameter, value); } public String getValue(String name) { String parameter = name.toLowerCase(); String value = null; if ("data".equals(parameter)) { if (getClientProperties().isBrowserInternetExplorer()) return null; parameter = "movie"; } if (attributeNames.contains(parameter)) value = attributes.get(parameter); else if (parameterNames.contains(parameter)) value = parameters.get(parameter); // special treatment of movie to resolve to the url if (value != null && parameter.equals("movie")) value = resolveResource(value); return value; } public void onComponentTag(ComponentTag tag) { // get options from the markup IValueMap valueMap = tag.getAttributes(); // Iterate over valid options for (String s : optionNames) { if (valueMap.containsKey(s)) { // if option isn't set programmatically, set value from markup if (!attributes.containsKey(s) && !parameters.containsKey(s)) setValue(s, valueMap.getString(s)); // remove attribute - they are added in super.onComponentTag() // to // the right place as attribute or param valueMap.remove(s); } } super.onComponentTag(tag); } public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) { super.onComponentTagBody(markupStream, openTag); Response response = getResponse(); // add all object's parameters in embed tag too: response.write("<embed"); addParameter(response, "type", CONTENTTYPE); for (String name : getParameterNames()) { String value = getValue(name); if (value != null) { name = "movie".equals(name) ? "src" : name; addParameter(response, name, value); } } for (String name : getAttributeNames()) { if ("width".equals(name) || "height".equals(name)) { String value = getValue(name); if (value != null) { addParameter(response, name, value); } } } response.write(" />\n"); } private void addParameter(Response response, String name, String value) { response.write(" "); response.write(name); response.write("=\""); response.write(value); response.write("\""); } @Override protected String getClsid() { return CLSID; } @Override protected String getCodebase() { return CODEBASE; } @Override protected String getContentType() { return CONTENTTYPE; } @Override protected List<String> getAttributeNames() { return attributeNames; } @Override protected List<String> getParameterNames() { return parameterNames; } }
Now you can just use it and add it to a Panel:
public class HeaderPanel extends Panel { private static final long serialVersionUID = 1L; public HeaderPanel( String id ) { super( id ); ShockWaveComponent swf = new ShockWaveComponent( "swf" ); add( swf ); } }
<wicket:panel> <object wicket:id="swf" data="res/test.swf" width="700" height="70" style="float: right; margin: 15px 0 0 0;"></object> </wicket:panel>