/* * GNU LESSER GENERAL PUBLIC LICENSE Copyright (C) 2006 The Lobo Project * * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Contact info: xamjadmin@users.sourceforge.net */ /* * Created on Nov 19, 2005 */ package org.cobra_grendel.html.domimpl; import java.util.ArrayList; import org.cobra_grendel.html.js.Executor; import org.mozilla.javascript.Function; import org.w3c.dom.html2.HTMLImageElement; public class HTMLImageElementImpl extends HTMLAbstractUIElement implements HTMLImageElement { private class LocalImageListener implements ImageListener { private final String expectedImgSrc; public LocalImageListener(final String imgSrc) { expectedImgSrc = imgSrc; } @Override public void imageLoaded(final ImageEvent event) { dispatchEvent(expectedImgSrc, event); } } /** * */ private static final long serialVersionUID = 1L; private java.awt.Image image = null; private String imageSrc; private final ArrayList listeners = new ArrayList(1); private Function onload; public HTMLImageElementImpl(final int transactionId) { super("IMG", transactionId); } public HTMLImageElementImpl(final String name, final int transactionId) { super(name, transactionId); } /** * Adds a listener of image loading events. The listener gets called right away if there's already an image. * * @param listener */ public void addImageListener(final ImageListener listener) { ArrayList l = listeners; java.awt.Image currentImage; synchronized (l) { currentImage = image; l.add(listener); } if (currentImage != null) { // Call listener right away if there's already an // image; holding no locks. listener.imageLoaded(new ImageEvent(this, currentImage)); // Should not call onload handler here. That's taken // care of otherwise. } } @Override protected void assignAttributeField(final String normalName, final String value) { super.assignAttributeField(normalName, value); if ("src".equals(normalName)) { loadImage(value); } } private void dispatchEvent(final String expectedImgSrc, final ImageEvent event) { ArrayList l = listeners; ImageListener[] listenerArray; synchronized (l) { if (!expectedImgSrc.equals(imageSrc)) { return; } image = event.image; // Get array of listeners while holding lock. listenerArray = (ImageListener[]) l.toArray(ImageListener.EMPTY_ARRAY); } int llength = listenerArray.length; for (int i = 0; i < llength; i++) { // Inform listener, holding no lock. listenerArray[i].imageLoaded(event); } Function onload = getOnload(); if (onload != null) { // TODO: onload event object? Executor.executeFunction(HTMLImageElementImpl.this, onload, null); } } @Override public String getAlign() { return getAttribute("align"); } @Override public String getAlt() { return getAttribute("alt"); } @Override public String getBorder() { return getAttribute("border"); } @Override public int getHeight() { UINode r = uiNode; return r == null ? 0 : r.getBounds().height; } @Override public int getHspace() { return getAttributeAsInt("hspace", 0); } public final java.awt.Image getImage() { synchronized (listeners) { return image; } } @Override public boolean getIsMap() { return getAttributeAsBoolean("isMap"); } @Override public String getLongDesc() { return getAttribute("longDesc"); } @Override public String getName() { return getAttribute("name"); } public Function getOnload() { return getEventFunction(onload, "onload"); } @Override public String getSrc() { return getAttribute("src"); } @Override public String getUseMap() { return getAttribute("useMap"); } @Override public int getVspace() { return getAttributeAsInt("vspace", 0); } @Override public int getWidth() { UINode r = uiNode; return r == null ? 0 : r.getBounds().width; } private void loadImage(final String src) { HTMLDocumentImpl document = (HTMLDocumentImpl) this.document; if (document != null) { synchronized (listeners) { imageSrc = src; image = null; } if (src != null) { document.loadImage(src, new LocalImageListener(src)); } } } public void removeImageListener(final ImageListener listener) { ArrayList l = listeners; synchronized (l) { l.remove(l); } } // /* (non-Javadoc) // * @see org.xamjwg.html.renderer.RenderableContext#getHeightLength() // */ // public HtmlLength getHeightLength() { // return this.heightLength; // } // // /* (non-Javadoc) // * @see org.xamjwg.html.renderer.RenderableContext#getWidthLength() // */ // public HtmlLength getWidthLength() { // return this.widthLength; // } // /* (non-Javadoc) // * @see org.xamjwg.html.renderer.RenderableContext#getAlignmentX() // */ // public float getAlignmentX() { // return 0.5f; // } // // /* (non-Javadoc) // * @see org.xamjwg.html.renderer.RenderableContext#getAlignmentY() // */ // public float getAlignmentY() { // return this.alignmentY; // } // private HtmlLength widthLength; // private HtmlLength heightLength; // private float alignmentY = 1.0f; // /* (non-Javadoc) // * @see // org.xamjwg.html.domimpl.ElementImpl#assignAttributeField(java.lang.String, // java.lang.String) // */ // protected void assignAttributeField(String normalName, String value) { // super.assignAttributeField(normalName, value); // if("width".equals(normalName)) { // try { // this.widthLength = new HtmlLength(value); // } catch(Exception err) { // this.warn("Bad width spec: " + value, err); // this.widthLength = null; // } // } // else if("height".equals(normalName)) { // try { // this.heightLength = new HtmlLength(value); // } catch(Exception err) { // this.warn("Bad height spec: " + value, err); // this.heightLength = null; // } // } // } // // private final void assignAlignment(String value) { // if(value.equalsIgnoreCase("middle")) { // this.alignmentY = 0.5f; // } // else if(value.equalsIgnoreCase("top")) { // this.alignmentY = 0.0f; // } // else if(value.equalsIgnoreCase("bottom")) { // this.alignmentY = 1.0f; // } // else { // this.alignmentY = 1.0f; // } // } @Override public void setAlign(final String align) { setAttribute("align", align); } @Override public void setAlt(final String alt) { setAttribute("alt", alt); } @Override public void setBorder(final String border) { setAttribute("border", border); } @Override public void setHeight(final int height) { setAttribute("height", String.valueOf(height)); } @Override public void setHspace(final int hspace) { setAttribute("hspace", String.valueOf("hspace")); } @Override public void setIsMap(final boolean isMap) { setAttribute("isMap", isMap ? "isMap" : null); } @Override public void setLongDesc(final String longDesc) { setAttribute("longDesc", longDesc); } @Override public void setName(final String name) { setAttribute("name", name); } public void setOnload(final Function onload) { this.onload = onload; } /** * Sets the image URI and starts to load the image. Note that an HtmlRendererContext should be available to the HTML document for images to be loaded. */ @Override public void setSrc(final String src) { setAttribute("src", src); } @Override public void setUseMap(final String useMap) { setAttribute("useMap", useMap); } @Override public void setVspace(final int vspace) { setAttribute("vspace", String.valueOf(vspace)); } @Override public void setWidth(final int width) { setAttribute("width", String.valueOf(width)); } }