THIS IS A TEST INSTANCE. ALL YOUR CHANGES WILL BE LOST!!!!
...
Here is a simple solution that relies on a "source" ResourceReference and a "decoration" ResourceReference array, used to decorate the source.
Code Block |
---|
import java.awt.AlphaComposite; import java.awt.Graphics2D; import java.awt.Image; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ImageObserver; import java.io.IOException; import javax.imageio.ImageIO; import org.apache.wicket.Application; import org.apache.wicket.ResourceReference; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.markup.html.image.resource.RenderedDynamicImageResource; import org.apache.wicket.util.resource.ResourceStreamNotFoundException; /** * Dynamic image resource * * @author Antoine * */ public class CompositeImageResource extends RenderedDynamicImageResource { implements ImageObserver { /** * */ private static final long serialVersionUID = 1L; /** * Default icon width. Other implementations could obtain this data from the * images meta datas */ private static final int ICON_WIDTH = 16; /** * Default icon height. Other implementations could obtain this data from * the images meta datas */ private static final int ICON_HEIGHT = 16; /** * {@link ResourceReference} to the base image to decorate */ private final ResourceReference source; /** * {@link ResourceReference}[] to use as decorations (will be stacked over * the source) */ private final ResourceReference[] overlays; /** * Internal field to monitor the awt image rendering process */ private int ongoing = 0; /** * @param width * @param height */ public CompositeImageResource(ResourceReference originalIcon, ResourceReference... overlays) { super(ICON_WIDTH, ICON_HEIGHT); // Disable any caching setCacheable(false); // Set GIF format to stay away from transparency issues on IE < 7 setFormat("png"); // Insure transparency management setType(BufferedImage.TYPE_INT_ARGB); this.source = originalIcon; this.source.bind(Application.get()); this.overlays = overlays; for (ResourceReference ref : this.overlays) { // Not sure this is the right way to ensure binding? ref.bind(Application.get()); } } /* * (non-Javadoc) * * @see org.apache.wicket.markup.html.image.resource.RenderedDynamicImageResource#render(java.awt.Graphics2D) */ @Override protected boolean render(Graphics2D g2) { this.source.bind(Application.get()); for (ResourceReference ref : this.overlays) { // Not sure this is the right way to ensure binding? ref.bind(Application.get()); } BufferedImage baseIcon; BufferedImage[] errorIcons = new BufferedImage[overlays.length]; ongoing = 0; // Try reading the original images from the resource reference // resource // streams try { baseIcon = ImageIO.read(source.getResource().getResourceStream() .getInputStream()); ongoing++; for (int i = 0; i < overlays.length; i++) { errorIcons[i] = ImageIO.read(overlays[i].getResource() .getResourceStream().getInputStream()); ongoing++; } } catch (IOException e) { throw new WicketRuntimeException(e); } catch (ResourceStreamNotFoundException e) { throw new WicketRuntimeException(e); } // Prepare g2 for trnasparencytransparency g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f)); Rectangle2D.Double rect = new Rectangle2D.Double(0, 0, ICON_WIDTH, ICON_HEIGHT); g2.fill(rect); // Prepare g2 for image overlay g2 .setComposite(AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 1f)); if (g2.drawImage(baseIcon, null, this)) { ongoing--; }null); for (Image overlay : errorIcons) { g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f)); if (g2.drawImage(overlay, null, this)) { ongoing--; }null); } // Wait until the awt process finishes loading the images while (ongoing > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } return true; } /* (non-Javadoc) * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) */ @Override public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { boolean done = (infoflags & ImageObserver.ALLBITS) != 0; if (done) { ongoing--; } return done; } } |
Let's see how to use this for implement a Tree that renders the node's icon decorated with errors, notification, etc... images :
Code Block |
---|
import java.io.Serializable; import javax.swing.tree.TreeNode; import org.apache.wicket.Component; import org.apache.wicket.IResourceListener; import org.apache.wicket.MarkupContainer; import org.apache.wicket.RequestCycle; import org.apache.wicket.Resource; import org.apache.wicket.ResourceReference; import org.apache.wicket.extensions.markup.html.tree.Tree; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.link.Link; public class DecoratedTree extends Tree { static final ResourceReference ERROR = new ResourceReference( FormTree.class, "error.gif"); [...] @Override protected Component newNodeIcon(MarkupContainer parent, String id, final TreeNode node) { class IconComponent extends WebMarkupContainer implements IResourceListener { private static final long serialVersionUID = 1L; private Resource icon; private ResourceReference reference; IconComponent(String id) { super(id); // Obtain the original image resource reference ResourceReference icon = ... if (hasError) { // Error? Let's use the CompositeImageResource with our icon // and the static ERROR decoration and name accordingly the ResourceReference this.reference = new DynamicResourceReference(icon =.getName() + "_error", new CompositeImageResource(icon, ERROR)); } else { // No error? let's stick to the source resource reference this.reference = icon; } } protected void onComponentTag(ComponentTag tag) { super.onComponentTag(tag); // Obtain an url to our image, wheter it be the original icon // or the generated image CharSequence url = reference != null ? RequestCycle.get() .urlFor(reference) : this .urlFor(IResourceListener.INTERFACE); tag.put("style", "background-image: url('" + RequestCycle.get().getOriginalResponse().encodeURL( url) + "')"); } @Override public void onResourceRequested() { this.icon.onResourceRequested(); } } return new IconComponent(id); } /** * A resource reference implem used to wrap the dynamic generated resource */ private static class DynamicResourceReference extends ResourceReference { //Wrapped resource private final Resource res; public DynamicResourceReference(String name, Resource res) { super(DecoratedTree.class, name); this.res = res; } @Override protected Resource newResource() { return res; } } [...] } |