/* GNU GENERAL LICENSE Copyright (C) 2006 The Lobo Project. Copyright (C) 2014 - 2017 Lobo Evolution This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either verion 3 of the License, or (at your option) any later version. This program 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 General License for more details. You should have received a copy of the GNU General Public along with this program. If not, see <http://www.gnu.org/licenses/>. Contact info: lobochief@users.sourceforge.net; ivan.difrancesco@yahoo.it */ /* * Created on Nov 19, 2005 */ package org.lobobrowser.html.domimpl; import java.awt.Image; import java.util.ArrayList; import org.lobobrowser.html.HtmlAttributeProperties; import org.lobobrowser.html.HtmlProperties; import org.lobobrowser.html.dombl.ImageEvent; import org.lobobrowser.html.dombl.ImageListener; import org.lobobrowser.html.dombl.UINode; import org.lobobrowser.html.js.Executor; import org.lobobrowser.html.renderstate.ImageRenderState; import org.lobobrowser.html.renderstate.RenderState; import org.lobobrowser.html.style.HtmlValues; import org.lobobrowser.w3c.html.HTMLImageElement; import org.mozilla.javascript.Function; /** * The Class HTMLImageElementImpl. */ public class HTMLImageElementImpl extends HTMLAbstractUIElement implements HTMLImageElement { /** The image. */ private Image image = null; /** The image src. */ private String imageSrc; /** The onload. */ private Function onload; /** * Instantiates a new HTML image element impl. */ public HTMLImageElementImpl() { super(HtmlProperties.IMG); } /** * Instantiates a new HTML image element impl. * * @param name * the name */ public HTMLImageElementImpl(String name) { super(name); } @Override public String getName() { return this.getAttribute(HtmlAttributeProperties.NAME); } @Override public void setName(String name) { this.setAttribute(HtmlAttributeProperties.NAME, name); } @Override public String getAlign() { return this.getAttribute(HtmlAttributeProperties.ALIGN); } @Override public void setAlign(String align) { this.setAttribute(HtmlAttributeProperties.ALIGN, align); } @Override public String getAlt() { return this.getAttribute(HtmlAttributeProperties.ALT); } @Override public void setAlt(String alt) { this.setAttribute(HtmlAttributeProperties.ALT, alt); } @Override public String getBorder() { return this.getAttribute(HtmlAttributeProperties.BORDER); } @Override public void setBorder(String border) { this.setAttribute(HtmlAttributeProperties.BORDER, border); } @Override public int getHeight() { String height = this.getAttribute(HtmlAttributeProperties.HEIGHT); UINode r = this.uiNode; if ((height != null) && (height.length() > 0)) { return HtmlValues.getPixelSize(height, null, 1); } return r == null ? 0 : r.getBounds().height; } @Override public void setHeight(int height) { this.setAttribute(HtmlAttributeProperties.HEIGHT, String.valueOf(height)); } @Override public int getHspace() { return this.getAttributeAsInt(HtmlAttributeProperties.HSPACE, 0); } @Override public void setHspace(int hspace) { this.setAttribute(HtmlAttributeProperties.HSPACE, String.valueOf(hspace)); } @Override public boolean getIsMap() { return this.getAttributeAsBoolean(HtmlAttributeProperties.ISMAP); } @Override public void setIsMap(boolean isMap) { this.setAttribute(HtmlAttributeProperties.ISMAP, isMap ? HtmlAttributeProperties.ISMAP : null); } @Override public String getLongDesc() { return this.getAttribute(HtmlAttributeProperties.LONGDESC); } @Override public void setLongDesc(String longDesc) { this.setAttribute(HtmlAttributeProperties.LONGDESC, longDesc); } @Override public String getSrc() { return this.getAttribute(HtmlAttributeProperties.SRC); } /** * 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. * * @param src * the new src */ @Override public void setSrc(String src) { this.setAttribute(HtmlAttributeProperties.SRC, src); } @Override public String getUseMap() { return this.getAttribute(HtmlAttributeProperties.USEMAP); } @Override public void setUseMap(String useMap) { this.setAttribute(HtmlAttributeProperties.USEMAP, useMap); } @Override public int getVspace() { return this.getAttributeAsInt(HtmlAttributeProperties.VSPACE, 0); } @Override public void setVspace(int vspace) { this.setAttribute(HtmlAttributeProperties.VSPACE, String.valueOf(vspace)); } @Override public int getWidth() { String width = this.getAttribute(HtmlAttributeProperties.WIDTH); UINode r = this.uiNode; if ((width != null) && (width.length() > 0)) { return HtmlValues.getPixelSize(width, null, 1); } return r == null ? 0 : r.getBounds().width; } @Override public void setWidth(int width) { this.setAttribute(HtmlAttributeProperties.WIDTH, String.valueOf(width)); } @Override protected void assignAttributeField(String normalName, String value) { super.assignAttributeField(normalName, value); if (HtmlAttributeProperties.SRC.equals(normalName)) { this.loadImage(value); } } @Override public Function getOnload() { return this.getEventFunction(this.onload, "onload"); } @Override public void setOnload(Function onload) { this.onload = onload; } /** * Load image. * * @param src * the src */ private void loadImage(String src) { HTMLDocumentImpl document = (HTMLDocumentImpl) this.document; if (document != null) { synchronized (this.listeners) { this.imageSrc = src; this.image = null; } if (src != null) { document.loadImage(src, new LocalImageListener(src)); } } } /** * Gets the image. * * @return the image */ public final Image getImage() { synchronized (this.listeners) { return this.image; } } /** The listeners. */ private final ArrayList<ImageListener> listeners = new ArrayList<ImageListener>(1); /** * Adds a listener of image loading events. The listener gets called right * away if there's already an image. * * @param listener * the listener */ public void addImageListener(ImageListener listener) { ArrayList<ImageListener> l = this.listeners; Image currentImage; synchronized (l) { currentImage = this.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. } } /** * Removes the image listener. * * @param listener * the listener */ public void removeImageListener(ImageListener listener) { ArrayList<ImageListener> l = this.listeners; synchronized (l) { l.remove(l); } } /** * Dispatch event. * * @param expectedImgSrc * the expected img src * @param event * the event */ private void dispatchEvent(String expectedImgSrc, ImageEvent event) { ArrayList<ImageListener> l = this.listeners; ImageListener[] listenerArray; synchronized (l) { if (!expectedImgSrc.equals(this.imageSrc)) { return; } this.image = event.image; // Get array of listeners while holding lock. listenerArray = 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 = this.getOnload(); if (onload != null) { // TODO: onload event object? Executor.executeFunction(HTMLImageElementImpl.this, onload, null); } } @Override protected RenderState createRenderState(RenderState prevRenderState) { return new ImageRenderState(prevRenderState, this); } @Override public int getNaturalWidth() { // TODO Auto-generated method stub return 0; } @Override public int getNaturalHeight() { // TODO Auto-generated method stub return 0; } @Override public boolean getComplete() { // TODO Auto-generated method stub return false; } /** * The listener interface for receiving localImage events. The class that is * interested in processing a localImage event implements this interface, * and the object created with that class is registered with a component * using the component's <code>addLocalImageListener</code> method. When the * localImage event occurs, that object's appropriate method is invoked. * * @see LocalImageEvent */ private class LocalImageListener implements ImageListener { /** The expected img src. */ private final String expectedImgSrc; /** * Instantiates a new local image listener. * * @param imgSrc * the img src */ public LocalImageListener(String imgSrc) { this.expectedImgSrc = imgSrc; } /* * (non-Javadoc) * * @see * org.lobobrowser.html.dombl.ImageListener#imageLoaded(org.lobobrowser. * html .dombl.ImageEvent) */ @Override public void imageLoaded(ImageEvent event) { dispatchEvent(this.expectedImgSrc, event); } } @Override public String getCrossOrigin() { // TODO Auto-generated method stub return null; } @Override public void setCrossOrigin(String crossOrigin) { // TODO Auto-generated method stub } }