javauis/m2g_qt/javasrc/com/nokia/microedition/m2g/M2GDocument.java
changeset 80 d6dafc5d983f
child 87 1627c337e51e
equal deleted inserted replaced
78:71ad690e91f5 80:d6dafc5d983f
       
     1 /*
       
     2 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 package com.nokia.microedition.m2g;
       
    20 
       
    21 import org.w3c.dom.*;
       
    22 import org.w3c.dom.events.*;
       
    23 import org.w3c.dom.svg.SVGElement;
       
    24 import java.io.IOException;
       
    25 import java.util.Hashtable;
       
    26 import java.lang.ref.WeakReference;
       
    27 import java.util.Vector;
       
    28 import java.util.Enumeration;
       
    29 import javax.microedition.m2g.*;
       
    30 import com.nokia.microedition.m2g.connection.*;
       
    31 import com.nokia.mj.impl.utils.Logger;
       
    32 
       
    33 public class M2GDocument extends M2GObject
       
    34         implements Document, M2GConnectionPolicyHandler
       
    35 {
       
    36     //--------------------------------------------------
       
    37     // STATIC CONSTANTS
       
    38     //--------------------------------------------------
       
    39     // Error constants
       
    40     /* Optimization: static finals changed to local variables
       
    41     public static final String UNSUPORTED_ELEMENT_TYPE_ESTR =
       
    42       "The type of element is not supported by the implementation.";
       
    43     public static final String UNSUPORTED_NAMESPACE_ESTR =
       
    44       "The URI is not the SVG namespace URI.";
       
    45     public static final String ID_IS_NULL_ESTR =
       
    46       "The ID is null.";
       
    47     public static final String NAMESPACE_URI_IS_NULL_ESTR =
       
    48       "The namespace URI is null.";
       
    49     public static final String QUALIFIED_NAME_IS_NULL_ESTR =
       
    50       "The qualifiedName is null.";
       
    51     public static final String CANNOT_APPEND_CHILD_ESTR =
       
    52       "Cannot appendChild to a Document node.";
       
    53     public static final String CANNOT_INSERT_BEFORE_ESTR =
       
    54       "Cannot insertBefore a Document node.";
       
    55     public static final String CANNOT_REMOVE_CHILD_ESTR =
       
    56       "Cannot removeChild from a Document node.";
       
    57     public static final String DOCUMENT_IS_ILLEGAL_ESTR =
       
    58       "The SVG document does not conform to the XML 1.0 specification.";
       
    59     public static final String HEIGHT_IS_ILLEGAL_ESTR =
       
    60       "The height is negative.";
       
    61     public static final String WIDTH_IS_ILLEGAL_ESTR =
       
    62       "The width is negative.";
       
    63     */
       
    64 
       
    65     //--------------------------------------------------
       
    66     // VARIABLES
       
    67     //--------------------------------------------------
       
    68     private M2GEventDispatcher iEventDispatcher = null;
       
    69     private ExternalResourceHandler iResourceHandler = null;
       
    70     private M2GSVGImage iImage = null;
       
    71     private M2GSVGSVGElement iRootElement = null;
       
    72     private final M2GLiveElements iLiveElements = new M2GLiveElements(true);
       
    73     private M2GConnectionPolicy iConnectionPolicy =
       
    74         M2GConnectionFactory.getDefaultPolicy();
       
    75     boolean iConnectionRight = true;
       
    76     Vector iExternalResources = new Vector();
       
    77 
       
    78     /** A base url from where a document was downloaded */
       
    79     String iBaseUrl;
       
    80 
       
    81     /** The suffix of the url from where the document was open*/
       
    82     String iSuffixUrl;
       
    83 
       
    84     /**
       
    85        * Observer to be notified about changes in DOM
       
    86        * @see M2GDOMChangeObserver.notifyDOMChange()
       
    87        */
       
    88     private M2GDOMChangeObserver  iDOMChangeObserver = null;
       
    89 
       
    90     //--------------------------------------------------
       
    91     // METHODS
       
    92     //--------------------------------------------------
       
    93     /**
       
    94      * Creates new document object. If aData is null or empty then
       
    95      * an empty document is create.
       
    96      * @param aImage Svg image
       
    97     * @param aBaseUrl A base url from where a document is downloaded.
       
    98      * @param aSuffixUrl A suffix url from where a document is downloaded
       
    99      * @param aData Plain text svg data
       
   100      */
       
   101     public M2GDocument(M2GSVGImage aImage, String aBaseUrl, String aSuffixUrl,
       
   102                        String aData)
       
   103     {
       
   104         super();
       
   105         
       
   106      		
       
   107         iImage      = aImage;
       
   108         iBaseUrl    = aBaseUrl;
       
   109         iSuffixUrl  = aSuffixUrl;
       
   110 
       
   111         setHandle(_createDocument(
       
   112                       getNativeSVGProxyHandle(),
       
   113                       aData)
       
   114                  );
       
   115 
       
   116         doConstruct();
       
   117     }
       
   118 
       
   119     /**
       
   120     * @see org.w3c.dom.Node#appendChild()
       
   121      */
       
   122     public Node appendChild(Node newChild) throws DOMException
       
   123     {
       
   124         // Optimization: if(!getConnectionPolicy().getAccessRight())
       
   125         if (!iConnectionRight)
       
   126         {
       
   127             Logger.ELOG(Logger.EJavaUI, "appendChild() - access rights failure");
       
   128             throw new SecurityException(M2GSVGConstants.ACCESS_RIGHTS_ESTR);
       
   129         }
       
   130         Logger.ELOG(Logger.EJavaUI, "appendChild() - exception: "
       
   131                     + /*SF*/"Cannot appendChild to a Document node."/*SF*/);
       
   132         throw new DOMException(
       
   133             DOMException.HIERARCHY_REQUEST_ERR,
       
   134             /*SF*/"Cannot appendChild to a Document node."/*SF*/);
       
   135     }
       
   136 
       
   137     /**
       
   138      * Appends external resource uri to internal container
       
   139      * @param aUri External resource uri
       
   140      * @return true if succeeds
       
   141        */
       
   142     boolean appendExternalResourceURI(String aUri)
       
   143     {
       
   144         boolean result = false;
       
   145         if (aUri != null && !aUri.equals(""))
       
   146         {
       
   147             synchronized (iExternalResources)
       
   148             {
       
   149                 if (!iExternalResources.contains(aUri))
       
   150                 {
       
   151                     iExternalResources.addElement(aUri);
       
   152                     result = true;
       
   153                 }
       
   154             }
       
   155         }
       
   156         Logger.LOG(Logger.EJavaUI, Logger.EInfo, "appendExternalResourceURI() uri=" +
       
   157                    ((aUri != null) ? aUri : "null") + ", result=" + result + " - end");
       
   158         return result;
       
   159     }
       
   160 
       
   161     /**
       
   162      * Checks if document contains the element
       
   163      * @param id
       
   164      * @return true if document contains the element
       
   165      */
       
   166     public boolean containsElement(String id)
       
   167     {
       
   168         if (id == null || id.equals(""))
       
   169         {
       
   170             return false;
       
   171         }
       
   172         int handle = _getElementById(
       
   173                          getNativeSVGProxyHandle(),
       
   174                          getHandle(), id);
       
   175         return M2GObject.checkHandle(handle);
       
   176     }
       
   177 
       
   178     /**
       
   179      * Check if external resource uri exists in internal container
       
   180      * @param aUri External resource uri
       
   181      * @return true if uri exists in container
       
   182      */
       
   183     boolean containsExternalResourceURI(String aUri)
       
   184     {
       
   185         boolean result = false;
       
   186         if (aUri != null && !aUri.equals(""))
       
   187         {
       
   188             synchronized (iExternalResources)
       
   189             {
       
   190                 result = iExternalResources.contains(aUri);
       
   191             }
       
   192         }
       
   193         Logger.LOG(Logger.EJavaUI, Logger.EInfo, "containsExternalResourceURI() uri=" +
       
   194                    ((aUri != null) ? aUri : "null") + ", result=" + result + " - end");
       
   195         return result;
       
   196     }
       
   197 
       
   198 
       
   199     /**
       
   200      * @see org.w3c.dom.Document#createElementNS()
       
   201      */
       
   202     public Element createElementNS(String namespaceURI, String qualifiedName)
       
   203     {
       
   204         if (namespaceURI == null || namespaceURI.equals(""))
       
   205         {
       
   206             Logger.ELOG(Logger.EJavaUI,
       
   207                         "createElementNS() exception because namespace is null. qualifiedName="
       
   208                         + qualifiedName);
       
   209             throw new NullPointerException(/*SF*/"The namespace URI is null."/*SF*/);
       
   210         }
       
   211         if (qualifiedName == null || qualifiedName.equals(""))
       
   212         {
       
   213             Logger.ELOG(Logger.EJavaUI,
       
   214                         "createElementNS() exception - " + namespaceURI + ", "
       
   215                         + qualifiedName);
       
   216             throw new NullPointerException(/*SF*/"The qualifiedName is null."/*SF*/);
       
   217         }
       
   218         // Checks element validity
       
   219         if (!M2GSVGConstants.isQualifiedElement(qualifiedName))
       
   220         {
       
   221             Logger.ELOG(Logger.EJavaUI, "createElementNS() exception - "
       
   222                         + namespaceURI + ", " + qualifiedName);
       
   223             throw new DOMException(
       
   224                 DOMException.NOT_SUPPORTED_ERR,
       
   225                 /*SF*/"The type of element is not supported by the implementation."/*SF*/);
       
   226         }
       
   227         // Checks namespace validity
       
   228         if (!namespaceURI.equals(M2GSVGConstants.SVG_NAMESPACE_URI))
       
   229         {
       
   230             Logger.ELOG(Logger.EJavaUI, "createElementNS() exception - "
       
   231                         + namespaceURI + ", " + qualifiedName);
       
   232             throw new DOMException(
       
   233                 DOMException.NOT_SUPPORTED_ERR,
       
   234                 /*SF*/"The URI is not the SVG namespace URI."/*SF*/);
       
   235         }
       
   236         // Creates native element. A native document owns the new element.
       
   237         // NOTE: The element is NOT located in the DOM tree yet.
       
   238         int elementHandle = _createElementNS(
       
   239                                 getNativeSVGProxyHandle(),
       
   240                                 M2GSVGConstants.parseElementTypeId(qualifiedName),
       
   241                                 getHandle());
       
   242         M2GSVGLocatableElement element = null;
       
   243         // Checks native handle validity
       
   244         if (M2GObject.checkHandle(elementHandle))
       
   245         {
       
   246             // Creates java element object
       
   247             element = new M2GSVGLocatableElement(elementHandle, this);
       
   248             registerLiveElement(element, new Integer(elementHandle));
       
   249         }
       
   250         else
       
   251         {
       
   252             Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   253                        "createElementNS(): " + qualifiedName + " - end, NOK!!!");
       
   254         }
       
   255         return element;
       
   256     }
       
   257 
       
   258     /**
       
   259      * Checks document validity.
       
   260      * @return true if valid
       
   261      */
       
   262     public boolean doCheckValidity() throws IOException
       
   263     {
       
   264         boolean result = false;
       
   265         if (isHandleValid())
       
   266         {
       
   267             M2GSVGSVGElement root = getRootElement();
       
   268             if (root != null)
       
   269             {
       
   270                 // Check svg version and base profile
       
   271                 root.checkVersionAndProfile();
       
   272                 result = true;
       
   273             }
       
   274         }
       
   275         return result;
       
   276     }
       
   277 
       
   278     /**
       
   279      * Cleanup
       
   280      * @see com.nokia.microedition.m2g.M2GObject#doCleanup()
       
   281      */
       
   282     public void doCleanup()
       
   283     {
       
   284         if (isHandleValid())
       
   285         {
       
   286             _deleteDocument(
       
   287                 getNativeSVGProxyHandle(),
       
   288                 getHandle());
       
   289         }
       
   290         iImage = null;
       
   291         if (iEventDispatcher != null)
       
   292         {
       
   293             iEventDispatcher.clear();
       
   294             iEventDispatcher = null;
       
   295         }
       
   296         resetHandles();
       
   297     }
       
   298 
       
   299     /**
       
   300      * @see com.nokia.microedition.m2g.M2GObject#doConstruct()
       
   301      */
       
   302     protected void doConstruct()
       
   303     {
       
   304         super.doConstruct();
       
   305         iEventDispatcher = new M2GEventDispatcher();
       
   306     }
       
   307 
       
   308     /**
       
   309      * Find an element from the handle-to-element map.
       
   310      * @see M2GLiveElements#findElement()
       
   311      */
       
   312     public SVGElement findLiveElement(Integer aElementHandle)
       
   313     {
       
   314         return iLiveElements.findElement(aElementHandle);
       
   315     }
       
   316 
       
   317     /**
       
   318      * Get connection policy
       
   319      * @see M2GConnectionListener#getConnectionPolicy()
       
   320      */
       
   321     public M2GConnectionPolicy getConnectionPolicy()
       
   322     {
       
   323         return iConnectionPolicy;
       
   324     }
       
   325 
       
   326     /**
       
   327      * @see org.w3c.dom.Document#getDocumentElement()
       
   328        */
       
   329     public Element getDocumentElement()
       
   330     {
       
   331         // Optimization: if(!getConnectionPolicy().getAccessRight())
       
   332         if (!iConnectionRight)
       
   333         {
       
   334             Logger.ELOG(Logger.EJavaUI,
       
   335                         "getDocumentElement() - access rights failure");
       
   336             throw new SecurityException(M2GSVGConstants.ACCESS_RIGHTS_ESTR);
       
   337         }
       
   338         return getRootElement();
       
   339     }
       
   340 
       
   341     /**
       
   342     * @see org.w3c.dom.Document#getElementById()
       
   343      */
       
   344     public Element getElementById(String id)
       
   345     {
       
   346         // Optimization: if(!getConnectionPolicy().getAccessRight())
       
   347         if (!iConnectionRight)
       
   348         {
       
   349             Logger.ELOG(Logger.EJavaUI, "getElementById() - access rights failure");
       
   350             throw new SecurityException(M2GSVGConstants.ACCESS_RIGHTS_ESTR);
       
   351         }
       
   352         if (id == null || id.equals(""))
       
   353         {
       
   354             Logger.ELOG(Logger.EJavaUI, "getElementById() - exception");
       
   355             throw new NullPointerException(/*SF*/"The ID is null."/*SF*/);
       
   356         }
       
   357         int elementHandle = _getElementById(
       
   358                                 getNativeSVGProxyHandle(),
       
   359                                 getHandle(),
       
   360                                 id );
       
   361         return M2GSVGElement.buildElement(elementHandle, this);
       
   362     }
       
   363 
       
   364     /**
       
   365      * Returns the image
       
   366      */
       
   367     public M2GSVGImage getImage()
       
   368     {
       
   369         return iImage;
       
   370     }
       
   371 
       
   372     /**
       
   373      * @see org.w3c.dom.Node#getLocalName()
       
   374      */
       
   375     public String getLocalName()
       
   376     {
       
   377         // Optimization: if(!getConnectionPolicy().getAccessRight())
       
   378         if (!iConnectionRight)
       
   379         {
       
   380             Logger.ELOG(Logger.EJavaUI, "getLocalName() - access rights failure");
       
   381             throw new SecurityException(M2GSVGConstants.ACCESS_RIGHTS_ESTR);
       
   382         }
       
   383         return null;
       
   384     }
       
   385 
       
   386     /**
       
   387     * @see org.w3c.dom.Node#getNamespaceURI()
       
   388      */
       
   389     public String getNamespaceURI()
       
   390     {
       
   391         // Optimization: if(!getConnectionPolicy().getAccessRight())
       
   392         if (!iConnectionRight)
       
   393         {
       
   394             Logger.ELOG(Logger.EJavaUI, "getNamespaceURI() - access rights failure");
       
   395             throw new SecurityException(M2GSVGConstants.ACCESS_RIGHTS_ESTR);
       
   396         }
       
   397         return null;
       
   398     }
       
   399 
       
   400     /**
       
   401      * @see org.w3c.dom.Node#getParentNode()
       
   402      */
       
   403     public Node getParentNode()
       
   404     {
       
   405         // Optimization: if(!getConnectionPolicy().getAccessRight())
       
   406         if (!iConnectionRight)
       
   407         {
       
   408             Logger.ELOG(Logger.EJavaUI,
       
   409                         "getParentNode() - access rights failure");
       
   410             throw new SecurityException(M2GSVGConstants.ACCESS_RIGHTS_ESTR);
       
   411         }
       
   412         return null;
       
   413     }
       
   414 
       
   415     /**
       
   416      * Get root element
       
   417      * @return M2GSVGSVGElement
       
   418        */
       
   419     public M2GSVGSVGElement getRootElement()
       
   420     {
       
   421         if (iRootElement == null)
       
   422         {
       
   423             iRootElement = M2GSVGSVGElement.buildRootElement(this);
       
   424         }
       
   425         return iRootElement;
       
   426     }
       
   427 
       
   428     /**
       
   429      * @see javax.microedition.m2g.ScalableImage#getViewportHeight()
       
   430      */
       
   431     public int getViewportHeight()
       
   432     {
       
   433         return _getViewportHeight(
       
   434                    getNativeSVGProxyHandle(),
       
   435                    getHandle());
       
   436     }
       
   437 
       
   438     /**
       
   439      * @see javax.microedition.m2g.ScalableImage#getViewportWidth()
       
   440      */
       
   441     public int getViewportWidth()
       
   442     {
       
   443         return _getViewportWidth(
       
   444                    getNativeSVGProxyHandle(),
       
   445                    getHandle() );
       
   446     }
       
   447 
       
   448 
       
   449     /**
       
   450      * Called by SVGImage upon creating an Event instance
       
   451      * Calls the handleEvent() of all the listeners of the event
       
   452      */
       
   453     public void handleEvent(Event aEvent)
       
   454     {
       
   455         iEventDispatcher.handleEvent(aEvent);
       
   456     }
       
   457 
       
   458     /**
       
   459     * @see org.w3c.dom.Node#insertBefore()
       
   460      */
       
   461     public Node insertBefore(Node newChild, Node refChild)
       
   462     {
       
   463         // Optimization: if(!getConnectionPolicy().getAccessRight())
       
   464         if (!iConnectionRight)
       
   465         {
       
   466             Logger.ELOG(Logger.EJavaUI, "insertBefore() - access rights failure");
       
   467             throw new SecurityException(M2GSVGConstants.ACCESS_RIGHTS_ESTR);
       
   468         }
       
   469 
       
   470         Logger.ELOG(Logger.EJavaUI, "insertBefore() DOMException");
       
   471         throw new DOMException(
       
   472             DOMException.HIERARCHY_REQUEST_ERR,
       
   473             /*SF*/"Cannot insertBefore a Document node."/*SF*/);
       
   474     }
       
   475 
       
   476     /**
       
   477      * Checks if element is in DOM
       
   478      * @param aElementHandle -
       
   479      * @return true if element is in DOM
       
   480      */
       
   481     public boolean isElementInDOM(int aElementHandle)
       
   482     {
       
   483         if (!M2GObject.checkHandle(aElementHandle))
       
   484         {
       
   485             return false;
       
   486         }
       
   487         return (_isElementInDOM(
       
   488                     getNativeSVGProxyHandle(),
       
   489                     getHandle(),
       
   490                     aElementHandle) > 0 ? true : false);
       
   491     }
       
   492 
       
   493     /**
       
   494      * The external resource handler is invoked
       
   495      * for any external resource referenced in the document.
       
   496      * @param aUri External resource referenced in the document
       
   497      */
       
   498     public void invokeResourceHandler(String aUri)
       
   499     {
       
   500         Logger.LOG(Logger.EJavaUI, Logger.EInfo, "invokeResourceHandler() - URI="
       
   501                    + aUri + " - begin");
       
   502 
       
   503         if ((iImage != null) && (iResourceHandler != null) &&
       
   504                 (aUri != null) && (aUri.length() > 4))
       
   505         {
       
   506             StringBuffer urlBuf = new StringBuffer();
       
   507             // The uri format for external resource must include the base url
       
   508             // from which the document was loaded. It's also checked that the
       
   509             // url read from svg doesn't contain already the base part.
       
   510             if ((iBaseUrl != null) &&
       
   511                     !iBaseUrl.equals("") &&
       
   512                     (aUri.indexOf(iBaseUrl) == -1))
       
   513             {
       
   514                 Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   515                            "invokeResourceHandler() append base url=" + iBaseUrl);
       
   516                 urlBuf.append(iBaseUrl);
       
   517             }
       
   518 
       
   519             urlBuf.append(aUri);
       
   520 
       
   521             // append the url suffix in case of drm open mode
       
   522             if (iSuffixUrl != null && !iSuffixUrl.equals(""))
       
   523             {
       
   524                 Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   525                            "invokeResourceHandler() append suffix url=" + iSuffixUrl);
       
   526                 urlBuf.append(iSuffixUrl);
       
   527             }
       
   528 
       
   529             Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   530                        "invokeResourceHandler() handler uri=" + urlBuf.toString());
       
   531 
       
   532             iResourceHandler.requestResource(iImage, urlBuf.toString());
       
   533             appendExternalResourceURI(aUri);
       
   534         }
       
   535 
       
   536         Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   537                    "invokeResourceHandler() - URI:" + aUri + " - end");
       
   538     }
       
   539 
       
   540     /**
       
   541      * Registers an event target and an event listener.
       
   542      * @param aTarget Target element
       
   543      * @param aType Event type
       
   544      * @param aListener Event listener
       
   545      */
       
   546     void register(EventTarget aTarget, String aType, EventListener aListener)
       
   547     {
       
   548         iEventDispatcher.register(aTarget, aType, aListener);
       
   549     }
       
   550 
       
   551     /**
       
   552      * Register element
       
   553      * @see M2GLiveElements#registerElement()
       
   554      */
       
   555     public void registerLiveElement(SVGElement aElement, Integer aElementHandle)
       
   556     {
       
   557         iLiveElements.registerElement(aElement, aElementHandle);
       
   558     }
       
   559 
       
   560     /**
       
   561      * @see org.w3c.dom.Node#removeChild()
       
   562      */
       
   563     public Node removeChild(Node oldChild) throws DOMException
       
   564     {
       
   565         // Optimization: if(!getConnectionPolicy().getAccessRight())
       
   566         if (!iConnectionRight)
       
   567         {
       
   568             Logger.ELOG(Logger.EJavaUI, "removeChild() - access rights failure");
       
   569             throw new SecurityException(M2GSVGConstants.ACCESS_RIGHTS_ESTR);
       
   570         }
       
   571         Logger.ELOG(Logger.EJavaUI, "removeChild() DOMException");
       
   572         throw new DOMException(
       
   573             DOMException.NOT_SUPPORTED_ERR,
       
   574             /*SF*/"Cannot removeChild from a Document node."/*SF*/);
       
   575     }
       
   576 
       
   577     /**
       
   578      * Removes external resource uri from internal container
       
   579      * @param aUri External resource uri
       
   580      * @return true if succeeds
       
   581      */
       
   582     boolean removeExternalResourceURI(String aUri)
       
   583     {
       
   584         boolean result = false;
       
   585         if (aUri != null && !aUri.equals(""))
       
   586         {
       
   587             synchronized (iExternalResources)
       
   588             {
       
   589                 result = iExternalResources.removeElement(aUri);
       
   590             }
       
   591         }
       
   592         Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   593                    "removeExternalResourceURI() uri="
       
   594                    + ((aUri != null) ? aUri : "null") + ", result=" + result + " - end");
       
   595         return result;
       
   596     }
       
   597 
       
   598     /*
       
   599      * @see com.nokia.microedition.m2g.M2GSVGImage#requestCompleted()
       
   600      */
       
   601     public int requestCompleted(String aUri, byte[] aResourceData)
       
   602     {
       
   603         Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   604                    "requestCompleted() uri=" + aUri + " - begin");
       
   605         // If the aUri contains a base part it will be cut off
       
   606         if (!aUri.equals("") &&
       
   607                 (iBaseUrl != null) &&
       
   608                 !containsExternalResourceURI(aUri) &&
       
   609                 (aUri.indexOf(iBaseUrl, 0) != -1))
       
   610         {
       
   611             aUri = aUri.substring(iBaseUrl.length(), aUri.length());
       
   612             Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   613                        "requestCompleted() uri when base part is cut off=" + aUri);
       
   614         }
       
   615 
       
   616         // Execute tha request command.
       
   617         int status = _requestCompleted(
       
   618                          getNativeSVGProxyHandle(),
       
   619                          getHandle(), aUri, aResourceData);
       
   620         if ((status == 0) || aUri.equals(""))
       
   621         {
       
   622             Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   623                        "requestCompleted() remove URI=" + aUri);
       
   624             removeExternalResourceURI(aUri);
       
   625         }
       
   626         return status;
       
   627     }
       
   628 
       
   629     /**
       
   630      * Set connection policy
       
   631      * @see M2GConnectionListener#setConnectionPolicy()
       
   632      */
       
   633     public void setConnectionPolicy(M2GConnectionPolicy aConnectionPolicy)
       
   634     {
       
   635         iConnectionPolicy = aConnectionPolicy;
       
   636         if (iConnectionPolicy != null)
       
   637         {
       
   638             iConnectionRight = iConnectionPolicy.getAccessRight();
       
   639         }
       
   640         else
       
   641         {
       
   642             iConnectionRight = true;
       
   643         }
       
   644     }
       
   645 
       
   646     /**
       
   647      * Set image
       
   648      * @param aImage Image
       
   649      */
       
   650     public void setImage(M2GSVGImage aImage)
       
   651     {
       
   652         iImage = aImage;
       
   653     }
       
   654 
       
   655     /**
       
   656      * Set external resource handler
       
   657      * @param aHandler External resource handler
       
   658      */
       
   659     public void setResourceHandler(ExternalResourceHandler aHandler)
       
   660     {
       
   661         iResourceHandler = aHandler;
       
   662     }
       
   663 
       
   664     /**
       
   665      * @see javax.microedition.m2g.ScalableImage#setViewportHeight()
       
   666      */
       
   667     public void setViewportHeight(int height)
       
   668     {
       
   669         Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   670                    "setViewportHeight():" + height + " - begin");
       
   671         if (height < 0)
       
   672         {
       
   673             Logger.ELOG(Logger.EJavaUI, "setViewportHeight():"
       
   674                         + height + " - IllegalArgumentException is thrown");
       
   675             throw new IllegalArgumentException(/*SF*/"The height is negative."/*SF*/);
       
   676         }
       
   677         _setViewportHeight(
       
   678             getNativeSVGProxyHandle(),
       
   679             getHandle(),
       
   680             height);
       
   681         Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   682                    "setViewportHeight():" + height + " - end");
       
   683     }
       
   684 
       
   685     /**
       
   686      * @see javax.microedition.m2g.ScalableImage#setViewportWidth()
       
   687      */
       
   688     public void setViewportWidth(int width)
       
   689     {
       
   690         Logger.LOG(Logger.EJavaUI, Logger.EInfo, "setViewportWidth:" + width + " - begin");
       
   691         if (width < 0)
       
   692         {
       
   693             Logger.ELOG(Logger.EJavaUI, "setViewportWidth():"
       
   694                         + width + " - IllegalArgumentException is thrown");
       
   695             throw new IllegalArgumentException(/*SF*/"The width is negative."/*SF*/);
       
   696         }
       
   697         _setViewportWidth(
       
   698             getNativeSVGProxyHandle(),
       
   699             getHandle(),
       
   700             width );
       
   701         Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   702                    "setViewportWidth:" + width + " - end");
       
   703     }
       
   704 
       
   705     /**
       
   706      * Unregister event listener
       
   707      * @param aTarget Target element
       
   708      * @param aType Event type
       
   709      * @param aListener Event listener
       
   710      */
       
   711     void unregister(EventTarget aTarget, String aType, EventListener aListener)
       
   712     {
       
   713         iEventDispatcher.unregister(aTarget, aType, aListener);
       
   714     }
       
   715 
       
   716     /**
       
   717      * Unregister an element from the handle-to-element map
       
   718      * @see M2GLiveElements#unregisterElement()
       
   719      */
       
   720     public void unregisterLiveElement(Integer aElementHandle)
       
   721     {
       
   722         iLiveElements.unregisterElement(aElementHandle);
       
   723     }
       
   724 
       
   725     //--------------------------------------------------
       
   726     // INNER CLASSES
       
   727     //--------------------------------------------------
       
   728     /**
       
   729      * M2GLiveElements
       
   730      */
       
   731     class M2GLiveElements
       
   732     {
       
   733         private Hashtable iLiveElements = new Hashtable();
       
   734         private boolean iUseWeakReference;
       
   735 
       
   736         /**
       
   737          * Constructor
       
   738          */
       
   739         public M2GLiveElements(boolean aUseWeakReference)
       
   740         {
       
   741             iUseWeakReference = aUseWeakReference;
       
   742         }
       
   743 
       
   744         /**
       
   745         * Find an element from the handle-to-element map.
       
   746         * @param aElementHandle Handle
       
   747         * @return SVGElement. Null if not found
       
   748         */
       
   749         public SVGElement findElement(Integer aElementHandle)
       
   750         {
       
   751             SVGElement element = null;
       
   752             Object weakObject = null;
       
   753             Object object = null;
       
   754 
       
   755             synchronized (this)
       
   756             {
       
   757                 Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   758                            "** findElement() handle: " + aElementHandle + " - begin **");
       
   759                 object = iLiveElements.get(aElementHandle);
       
   760                 if (object != null)
       
   761                 {
       
   762                     if (iUseWeakReference)
       
   763                     {
       
   764                         weakObject = ((WeakReference)object).get();
       
   765                         if (weakObject == null)
       
   766                         {
       
   767                             Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   768                                        "** findElement() handle: " + aElementHandle
       
   769                                        + " is garbage collected. **");
       
   770                             iLiveElements.remove(aElementHandle);
       
   771                         }
       
   772                         else
       
   773                         {
       
   774                             element = (SVGElement)weakObject;
       
   775                         }
       
   776                     }
       
   777                     else
       
   778                     {
       
   779                         element = (SVGElement)object;
       
   780                     }
       
   781                 }
       
   782                 Logger.LOG(Logger.EJavaUI, Logger.EInfo,"** findElement() handle: " + aElementHandle
       
   783                            + ((element != null) ? " FOUND" : " NOT FOUND") + " - end **");
       
   784             }
       
   785             return element;
       
   786         }
       
   787 
       
   788         /**
       
   789          * Register element
       
   790          * @param aElement Element
       
   791          * @param aElementHandle Handle
       
   792          */
       
   793         public void registerElement(SVGElement aElement, Integer aElementHandle)
       
   794         {
       
   795             if (aElement == null)
       
   796             {
       
   797                 return;
       
   798             }
       
   799             synchronized (this)
       
   800             {
       
   801                 if (iUseWeakReference)
       
   802                 {
       
   803                     iLiveElements.put(aElementHandle, new WeakReference(aElement));
       
   804                 }
       
   805                 else
       
   806                 {
       
   807                     iLiveElements.put(aElementHandle, aElement);
       
   808                 }
       
   809             }
       
   810         }
       
   811 
       
   812         /**
       
   813          * Unregister an element from the handle-to-element map
       
   814          * @param aElementHandle Handle
       
   815          */
       
   816         public void unregisterElement(Integer aElementHandle)
       
   817         {
       
   818             synchronized (this)
       
   819             {
       
   820                 iLiveElements.remove(aElementHandle);
       
   821             }
       
   822         }
       
   823     }
       
   824 
       
   825 
       
   826     /**
       
   827      * M2GEventDispatcher
       
   828      */
       
   829     protected class M2GEventDispatcher
       
   830     {
       
   831         static public final int INDEX_UNDEFINED = -1;
       
   832         static public final int INDEX_CLICK = 0;
       
   833         static public final int INDEX_ACTIVATE = 1;
       
   834         static public final int INDEX_FOCUS_IN = 2;
       
   835         static public final int INDEX_FOCUS_OUT = 3;
       
   836 
       
   837         Hashtable[] iEventTypes;
       
   838         int iCurrentIndex;
       
   839         Hashtable iDelayedRegistrations = new Hashtable();
       
   840         M2GEventData iCurrentEventData = new M2GEventData();
       
   841 
       
   842         /**
       
   843          * Constructor
       
   844          */
       
   845         public M2GEventDispatcher()
       
   846         {
       
   847             iEventTypes = new Hashtable[4];
       
   848             iCurrentIndex = INDEX_UNDEFINED;
       
   849         }
       
   850 
       
   851         /**
       
   852          * Clear all
       
   853          */
       
   854         public void clear()
       
   855         {
       
   856             synchronized (this)
       
   857             {
       
   858                 for (int index = 0; index < iEventTypes.length; index++)
       
   859                 {
       
   860                     if (iEventTypes[index] != null)
       
   861                     {
       
   862                         iEventTypes[index].clear();
       
   863                         iEventTypes[index] = null;
       
   864                     }
       
   865                 }
       
   866             }
       
   867         }
       
   868 
       
   869         /**
       
   870          * Execute delayed registration
       
   871          * If an EventListener is added to an EventTarget while it is
       
   872          * processing an event, it will not be triggered by the current actions.
       
   873          */
       
   874         private void doDelayedRegistration()
       
   875         {
       
   876             try
       
   877             {
       
   878                 Enumeration registrations = iDelayedRegistrations.elements();
       
   879                 while (registrations.hasMoreElements())
       
   880                 {
       
   881                     M2GEventData eventData =
       
   882                         (M2GEventData)registrations.nextElement();
       
   883                     register(
       
   884                         eventData.iTarget, eventData.iType, eventData.iListener);
       
   885                 }
       
   886             }
       
   887             catch (NullPointerException e)
       
   888             {
       
   889             }
       
   890             iDelayedRegistrations.clear();
       
   891         }
       
   892 
       
   893 
       
   894         /**
       
   895          * Handle event
       
   896          * @param aEvent Event
       
   897          */
       
   898         public void handleEvent(Event aEvent)
       
   899         {
       
   900             synchronized (this)
       
   901             {
       
   902                 if ((aEvent == null) || !prepare(aEvent.getType()))
       
   903                 {
       
   904                     Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   905                                "handleEvent() FAILED - event invalid");
       
   906                     return;
       
   907                 }
       
   908                 Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   909                            "handleEvent(): " + aEvent.getType() + " - begin");
       
   910                 EventTarget target = aEvent.getCurrentTarget();
       
   911                 if (target == null)
       
   912                 {
       
   913                     Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   914                                "handleEvent() FAILED - event's target is null");
       
   915                     return;
       
   916                 }
       
   917                 // Check if wrapped event target
       
   918                 if (target instanceof M2GSVGElementWrapper)
       
   919                 {
       
   920                     target = ((M2GSVGElementWrapper)target).getWrappedTarget();
       
   921                     if (target == null)
       
   922                     {
       
   923                         Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   924                                    "handleEvent() FAILED - wrapped event's target is null");
       
   925                         return;
       
   926                     }
       
   927                 }
       
   928                 if (iEventTypes[iCurrentIndex].containsKey(target))
       
   929                 {
       
   930                     Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   931                                "handleEvent() - target handling begin");
       
   932                     iCurrentEventData.set(target, aEvent.getType(), null);
       
   933                     Vector listeners =
       
   934                         (Vector)iEventTypes[iCurrentIndex].get(iCurrentEventData.iTarget);
       
   935 
       
   936                     if (listeners != null)
       
   937                     {
       
   938                         Enumeration index = listeners.elements();
       
   939                         while (index.hasMoreElements())
       
   940                         {
       
   941                             Object listener = index.nextElement();
       
   942                             if ((listener != null) && (listener instanceof EventListener))
       
   943                             {
       
   944                                 ((EventListener)listener).handleEvent(aEvent);
       
   945                             }
       
   946                             else
       
   947                             {
       
   948                                 Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   949                                            "handleEvent(): listener is null!");
       
   950                             }
       
   951                         }
       
   952                     }
       
   953                     else
       
   954                     {
       
   955                         Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   956                                    "handleEvent(): listeners is null!");
       
   957                     }
       
   958                     iCurrentEventData.clear();
       
   959                 }
       
   960                 else
       
   961                 {
       
   962                     Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
   963                                "handleEvent(): target not found");
       
   964                 }
       
   965                 // Execute the delayed registration.
       
   966                 doDelayedRegistration();
       
   967             }
       
   968         }
       
   969 
       
   970         /**
       
   971          * Check is event targets are equal
       
   972          * @param aLhs Left hand side
       
   973          * @param aRhs Right hand side
       
   974          * @return True if equal
       
   975          */
       
   976         private boolean isEquals(EventTarget aLhs, EventTarget aRhs)
       
   977         {
       
   978             int lhsHandle = M2GObject.INVALID_NATIVE_HANDLE;
       
   979             int rhsHandle = M2GObject.INVALID_NATIVE_HANDLE;
       
   980             if (aLhs instanceof M2GSVGElement)
       
   981             {
       
   982                 lhsHandle = ((M2GSVGElement)aLhs).getHandle();
       
   983             }
       
   984             if (aRhs instanceof M2GSVGElement)
       
   985             {
       
   986                 rhsHandle = ((M2GSVGElement)aRhs).getHandle();
       
   987             }
       
   988             if ((lhsHandle == rhsHandle) && (lhsHandle != M2GObject.INVALID_NATIVE_HANDLE))
       
   989             {
       
   990                 return true;
       
   991             }
       
   992             return false;
       
   993         }
       
   994 
       
   995         /**
       
   996          * Set an index that points to an event type hash table.
       
   997          * The hash table is created if needed.
       
   998          * @param aType Type
       
   999          */
       
  1000         private boolean prepare(String aType)
       
  1001         {
       
  1002             if (!setIndex(aType))
       
  1003             {
       
  1004                 return false;
       
  1005             }
       
  1006             if (iEventTypes[iCurrentIndex] == null)
       
  1007             {
       
  1008                 iEventTypes[iCurrentIndex] = new Hashtable();
       
  1009             }
       
  1010             return true;
       
  1011         }
       
  1012 
       
  1013         /**
       
  1014          * Register an event target and an event listener pair
       
  1015          * @param aTarget Target
       
  1016          * @param aType Type
       
  1017          * @param aListener Listener
       
  1018          */
       
  1019         public void register(EventTarget aTarget,
       
  1020                              String aType,
       
  1021                              EventListener aListener)
       
  1022         {
       
  1023             // NOTE: no need to check validity of aTarget & aListener. It's
       
  1024             // already done.
       
  1025             synchronized (this)
       
  1026             {
       
  1027                 if (!prepare(aType))
       
  1028                 {
       
  1029                     Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
  1030                                "register() - failed: " + aType);
       
  1031                     return;
       
  1032                 }
       
  1033                 // Check if delayed registration is needed
       
  1034                 // If an EventListener is added to an EventTarget while it is
       
  1035                 // processing an event, it will not be triggered by
       
  1036                 // the current actions.
       
  1037                 if ((iCurrentEventData.iType == aType) &&
       
  1038                         isEquals(iCurrentEventData.iTarget, aTarget))
       
  1039                 {
       
  1040                     try
       
  1041                     {
       
  1042                         iDelayedRegistrations.put(
       
  1043                             aListener,
       
  1044                             new M2GEventData(aTarget, aType, aListener));
       
  1045                     }
       
  1046                     catch (NullPointerException e)
       
  1047                     {
       
  1048                     }
       
  1049                     return;
       
  1050                 }
       
  1051                 Vector listeners = null;
       
  1052                 if (iEventTypes[iCurrentIndex].containsKey(aTarget))
       
  1053                 {
       
  1054                     listeners = (Vector)iEventTypes[iCurrentIndex].get(aTarget);
       
  1055                 }
       
  1056                 else
       
  1057                 {
       
  1058                     listeners = new Vector();
       
  1059                     iEventTypes[iCurrentIndex].put(aTarget, listeners);
       
  1060                 }
       
  1061                 // Don't add if the event target already contains the same listener
       
  1062                 // for the same event.
       
  1063                 if (!listeners.contains(aListener))
       
  1064                 {
       
  1065                     listeners.addElement(aListener);
       
  1066                 }
       
  1067             }
       
  1068         }
       
  1069 
       
  1070         /**
       
  1071          * Set an event type container index
       
  1072          * @param aType Type
       
  1073          * @return False if the type is invalid
       
  1074          */
       
  1075         private boolean setIndex(String aType)
       
  1076         {
       
  1077             if (aType.equals(M2GSVGConstants.EVENT_ACTIVATE))
       
  1078             {
       
  1079                 iCurrentIndex = INDEX_ACTIVATE;
       
  1080             }
       
  1081             else if (aType.equals(M2GSVGConstants.EVENT_CLICK))
       
  1082             {
       
  1083                 iCurrentIndex = INDEX_CLICK;
       
  1084             }
       
  1085             else if (aType.equals(M2GSVGConstants.EVENT_FOCUS_IN))
       
  1086             {
       
  1087                 iCurrentIndex = INDEX_FOCUS_IN;
       
  1088             }
       
  1089             else if (aType.equals(M2GSVGConstants.EVENT_FOCUS_OUT))
       
  1090             {
       
  1091                 iCurrentIndex = INDEX_FOCUS_OUT;
       
  1092             }
       
  1093             else
       
  1094             {
       
  1095                 Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
  1096                            "setIndex() type:" + aType + " FALSE - end");
       
  1097                 // Wrong event type
       
  1098                 iCurrentIndex = INDEX_UNDEFINED;
       
  1099                 return false;
       
  1100             }
       
  1101             return true;
       
  1102         }
       
  1103 
       
  1104         /**
       
  1105          * Unregister an event target and an event listener pair
       
  1106          * @param aTarget Target
       
  1107          * @param aType Type
       
  1108          * @param aListener Listener
       
  1109          */
       
  1110         public void unregister(EventTarget aTarget,
       
  1111                                String aType,
       
  1112                                EventListener aListener)
       
  1113         {
       
  1114             synchronized (this)
       
  1115             {
       
  1116                 if (!prepare(aType))
       
  1117                 {
       
  1118                     return;
       
  1119                 }
       
  1120                 // Remove delayed registration
       
  1121                 iDelayedRegistrations.remove(aListener);
       
  1122                 // Remove real registration
       
  1123                 Vector listeners = (Vector)iEventTypes[iCurrentIndex].get(aTarget);
       
  1124                 boolean removed = false;
       
  1125                 if (listeners != null)
       
  1126                 {
       
  1127                     removed = listeners.removeElement(aListener);
       
  1128                     if (listeners.isEmpty())
       
  1129                     {
       
  1130                         iEventTypes[iCurrentIndex].remove(aTarget);
       
  1131                     }
       
  1132                 }
       
  1133                 if (removed)
       
  1134                 {
       
  1135                     Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
  1136                                "unregister() ok - end");
       
  1137                 }
       
  1138                 else
       
  1139                 {
       
  1140                     Logger.LOG(Logger.EJavaUI, Logger.EInfo,
       
  1141                                "unregister() failed - end");
       
  1142                 }
       
  1143             }
       
  1144         }
       
  1145 
       
  1146         /**
       
  1147          * Helper class for handling delayed registration
       
  1148          */
       
  1149         class M2GEventData
       
  1150         {
       
  1151             public EventTarget iTarget = null;
       
  1152             public String iType = null;
       
  1153             public EventListener iListener = null;
       
  1154 
       
  1155             /**
       
  1156              * Ctor
       
  1157              */
       
  1158             public M2GEventData()
       
  1159             {
       
  1160             }
       
  1161 
       
  1162             /**
       
  1163              * Ctor
       
  1164              * @param aTarget Target
       
  1165              * @param aType Event type
       
  1166              * @param aListener Event listener
       
  1167              */
       
  1168             public M2GEventData(
       
  1169                 EventTarget aTarget,
       
  1170                 String aType,
       
  1171                 EventListener aListener)
       
  1172             {
       
  1173                 set(aTarget, aType, aListener);
       
  1174             }
       
  1175 
       
  1176             /**
       
  1177              * Clearing
       
  1178              */
       
  1179             public void clear()
       
  1180             {
       
  1181                 iTarget = null;
       
  1182                 iType = null;
       
  1183                 iListener = null;
       
  1184             }
       
  1185 
       
  1186             /**
       
  1187              * Setter
       
  1188              * @param aTarget Target
       
  1189              * @param aType Event type
       
  1190              * @param aListener Event listener
       
  1191              */
       
  1192             public void set(EventTarget aTarget,
       
  1193                             String aType,
       
  1194                             EventListener aListener)
       
  1195             {
       
  1196                 iTarget = aTarget;
       
  1197                 iType = aType;
       
  1198                 iListener = aListener;
       
  1199             }
       
  1200         }
       
  1201     }
       
  1202 
       
  1203     //--------------------------------------------------
       
  1204     // STATIC METHODS
       
  1205     //--------------------------------------------------
       
  1206 
       
  1207     /**
       
  1208      * Creates an empty SVG document. The document contains a
       
  1209      * root <svg> element with default viewport size of 100x100.
       
  1210        * @param aImage -
       
  1211        * @param aHander -
       
  1212        * @return document object
       
  1213        * @throws IllegalArgumentException
       
  1214        * @throws IOException
       
  1215        */
       
  1216     static public M2GDocument buildEmptyDocument(M2GSVGImage aImage,
       
  1217             ExternalResourceHandler aHandler)
       
  1218     throws IllegalArgumentException, IOException
       
  1219     {
       
  1220         return M2GDocument.buildDocument(
       
  1221                    aImage,
       
  1222                    null,
       
  1223                    null,
       
  1224                    M2GSVGConstants.getInstance().iEmptySvgDocument,
       
  1225                    aHandler);
       
  1226     }
       
  1227 
       
  1228     /**
       
  1229      * Builds document
       
  1230      * @param aImage Svg image
       
  1231     * @param aBaseUrl A base url from where a document is downloaded.
       
  1232     * @param aSuffixUrl The suffix url from where a document is downloaded.
       
  1233      * @param aData Plain text svg data
       
  1234      * @param aHandler Resource handler. If null the default resource handler is
       
  1235      * used.
       
  1236      * @return document object
       
  1237      * @throws IllegalArgumentException
       
  1238      * @throws IOException
       
  1239      */
       
  1240     static public M2GDocument buildDocument(M2GSVGImage aImage,
       
  1241                                             String aBaseUrl,
       
  1242                                             String aSuffixUrl,
       
  1243                                             String aData,
       
  1244                                             ExternalResourceHandler aHandler)
       
  1245     throws IOException
       
  1246     {
       
  1247     		
       
  1248         if ((aData == null) || (aData.equals("")))
       
  1249         {
       
  1250         		
       
  1251             throw new IOException(
       
  1252                 /*SF*/"The SVG document does not conform to the XML 1.0 specification."/*SF*/);
       
  1253         }
       
  1254 
       
  1255         M2GDocument document = new M2GDocument(aImage, aBaseUrl, aSuffixUrl, aData);
       
  1256 
       
  1257         if (document.doCheckValidity())
       
  1258         {
       
  1259             document.setResourceHandler(aHandler);
       
  1260             return document;
       
  1261         }
       
  1262         throw new IOException(
       
  1263             /*SF*/"The SVG document does not conform to the XML 1.0 specification."/*SF*/);
       
  1264     }
       
  1265 
       
  1266     /**
       
  1267      * Registers an observer to any DOM change
       
  1268      * @since S60 3.2
       
  1269      */
       
  1270     public void registerDOMChangeObserver(M2GDOMChangeObserver aDOMChangeObserver)
       
  1271     {
       
  1272         iDOMChangeObserver = aDOMChangeObserver;
       
  1273     }
       
  1274 
       
  1275     /**
       
  1276      * Notify the observer about any change in DOM
       
  1277      * SVGSVGElement is always part of DOM
       
  1278      * @since S60 3.2
       
  1279      */
       
  1280     public void notifyDOMChangeObserver()
       
  1281     {
       
  1282         if (iDOMChangeObserver != null)
       
  1283         {
       
  1284             iDOMChangeObserver.notifyDOMChange();
       
  1285         }
       
  1286     }
       
  1287 
       
  1288     /**
       
  1289      * Notify the observer about any change in DOM only if the node is in DOM
       
  1290      * @param aNativeHandle the handle of a node
       
  1291      * @since S60 3.2
       
  1292      */
       
  1293     public void notifyDOMChangeObserver(int aNativeHandle)
       
  1294     {
       
  1295         if (iDOMChangeObserver != null && isElementInDOM(aNativeHandle))
       
  1296         {
       
  1297             iDOMChangeObserver.notifyDOMChange();
       
  1298         }
       
  1299     }
       
  1300 
       
  1301 
       
  1302     //--------------------------------------------------
       
  1303     // NATIVE METHODS
       
  1304     //--------------------------------------------------
       
  1305     private native static int _createDocument(
       
  1306         int aSvgProxyHandle, String aString);
       
  1307 
       
  1308     private native static int _createElementNS(
       
  1309         int aSvgProxyHandle, short aType,
       
  1310         int aDocumentHandle);
       
  1311 
       
  1312     private native static void _deleteDocument(
       
  1313         int aSvgProxyHandle, int aDocumentHandle);
       
  1314 
       
  1315     private native static int _getElementById(
       
  1316         int aSvgProxyHandle, int aDocumentHandle,
       
  1317         String aId);
       
  1318 
       
  1319     private static native int _getViewportHeight(
       
  1320          int aSvgProxyHandle, int aDocumentHandle);
       
  1321 
       
  1322     private static native int _getViewportWidth(
       
  1323          int aSvgProxyHandle, int aDocumentHandle);
       
  1324 
       
  1325     private native static int _isElementInDOM(
       
  1326          int aSvgProxyHandle, int aDocumentHandle,
       
  1327         int aElementHandle);
       
  1328 
       
  1329     private static native int _requestCompleted(
       
  1330         int aSvgProxyHandle, int aDocumentHandle,
       
  1331         String aUri, byte[] aResourceData);
       
  1332 
       
  1333     private static native void _setViewportHeight(
       
  1334         int aSvgProxyHandle, int aDocumentHandle, int aHeight);
       
  1335 
       
  1336     private static native void _setViewportWidth(
       
  1337         int aSvgProxyHandle, int aDocumentHandle, int aWidth);
       
  1338 }
       
  1339