FileDocCategorySizeDatePackage
ElementNodeProxy.javaAPI DocphoneME MR2 API (J2ME)13383Wed May 02 18:00:36 BST 2007com.sun.perseus.model

ElementNodeProxy

public class ElementNodeProxy extends ModelNode
A ElementNodeProxy delegates its rendering to a proxied ElementNode object. This class is used to model expanded content. SVG markup defines content that needs to be expanded before it is rendered. For example, the <use> element is expanded with ElementNodeProxy children to represent the expansion expressed by the element.
version
$Id: ElementNodeProxy.java,v 1.14 2006/06/29 10:47:30 ln156897 Exp $

Fields Summary
protected ElementNode
proxied
The proxied ModelNode
protected boolean
expanded
Controls whether content is expanded or not
protected ElementNodeProxy
nextProxy
The next proxy, if any.
protected ElementNodeProxy
prevProxy
The previous proxy, if any.
protected ModelNode
firstExpandedChild
The first expanded child, if content has been expanded.
protected ModelNode
lastExpandedChild
The last expanded child, if content has been expanded
Constructors Summary
protected ElementNodeProxy(ElementNode proxiedNode)

param
proxiedNode ElementNode to proxy

        super();
        this.proxied = proxiedNode;
        proxiedNode.addProxy(this);
        ownerDocument = proxiedNode.ownerDocument;
    
Methods Summary
protected com.sun.perseus.j2d.TransformappendTransform(com.sun.perseus.j2d.Transform tx, com.sun.perseus.j2d.Transform workTx)
Appends the proxied node's transform, if there is a proxied node.

param
tx the Transform to apply additional node transforms to. This may be null.
param
workTx a Transform which can be re-used if a new Transform needs to be created and workTx is not the same instance as tx.
return
a transform with this node's transform added.

        if (proxied != null) {
            return proxied.appendTransform(tx, workTx);
        }

        return tx;
    
protected voidclearLayouts()
Clears the text layouts, if any exist. This is typically called when the font selection has changed and nodes such as Text should recompute their layouts. This should recursively call clearLayouts on children node or expanded content, if any.

        clearLayouts(firstExpandedChild);
    
protected com.sun.perseus.model.ElementNodeProxycomputeProxiesChain(ElementNode proxiedChild)
Implementation helper: computes the set of chained proxies for the input node and return the head of the chain.

param
proxiedChild the ElementNode for which the chain of proxies should be computed.
return
the head of the proxies chaing. NOTE that the prevSibling is set on the head to point to the last element of the chain, creating a circular list for the 'prevSibling' reference. This circular reference should be broken by the code using this method.

        ElementNodeProxy firstProxy = null;
        ElementNodeProxy proxy = null;
        ElementNodeProxy previousProxy = null;
        while (proxiedChild != null) {
            proxy = proxiedChild.buildProxy();
            proxy.setParentQuiet(this);
            proxy.expand();
            if (previousProxy == null) {
                firstProxy = proxy;
            } else {
                previousProxy.nextSibling = proxy;
                proxy.prevSibling = previousProxy;
            }
            firstProxy.prevSibling = proxy;
            previousProxy = proxy;
            proxiedChild = (ElementNode) proxiedChild.nextSibling;
        }
        return firstProxy;
    
protected voidexpand()
Expand the content. This is done lazilly

        if (expanded) {
            return;
        }

        // Expand proxy tree. 
        //
        // NOTE: This implements the SVGElementInstance tree structure,
        // as described in the SVG 1.1 specification, section 5.17.
        //
        if (proxied != null) {
            firstExpandedChild = computeProxiesChain(
                    (ElementNode) proxied.getFirstChildNode());

            if (firstExpandedChild != null) {
                lastExpandedChild
                    = firstExpandedChild.prevSibling;

                // The prevSibling was set as a way to return both the first
                // and last element of the chain. We need to break the circular
                // reference.
                firstExpandedChild.prevSibling = null;
            } else {
                firstExpandedChild = null;
            }
        } 

        expanded = true;
    
public ModelNodegetFirstChildNode()

return
a reference to the node's first child, or null if there are no children.

        return null;
    
public ModelNodegetFirstComputedExpandedChild()
Some node types (such as ElementNodeProxy) have expanded children that they compute in some specific way depending on the implementation.

return
a reference to the node's first expanded child, or null if there are no expanded children.

        return firstExpandedChild;
    
public ModelNodegetFirstExpandedChild()
Some node types (such as ElementNodeProxy) have expanded children that they compute in some specific way depending on the implementation.

return
a reference to the node's first expanded child, or null if there are no expanded children. This forces the computation of expanded content if needed.

        expand();
        return firstExpandedChild;
    
public ModelNodegetLastChildNode()

return
a reference to the node's last child, or null if there are no children.

        return null;
    
public ModelNodegetLastExpandedChild()
Some node types (such as ElementNodeProxy) have expanded children that they compute in some specific way depending on the implementation.

return
a reference to the node's last expanded child, or null if there are no expanded children. This forces the computation of expanded content if needed.

        expand();
        return lastExpandedChild;
    
public ElementNodegetProxied()

return
a reference to the proxied ModelNode

        return proxied;
    
public booleanhasDescendants()

return
true if the ElementNodeProxy has children or if it has expanded content.

        if (super.hasDescendants()) {
            return true;
        } else {
            expand();
            return firstExpandedChild != null;
        }
            
    
public voidmodifiedProxied()
Proxied nodes should call this method when they have been modified.

        modifiedNode();
    
public voidmodifyingProxied()
Proxied nodes should call this method when they are being modified.

        modifyingNode();
    
public ModelNodenodeHitAt(float[] pt)
Returns the ModelNode, if any, hit by the point at coordinate x/y.

param
pt the x/y coordinate. Should never be null and be of size two. If not, the behavior is unspecified. The coordinates are in viewport space.
return
the ModelNode hit at the given point or null if none was hit.

        return proxied.proxyNodeHitAt(pt, this);
    
final voidonHookedInDocumentTree()
When a CompositeNode is hooked into the document tree, by default, it notifies its children and calls its own nodeHookedInDocumentTree method.

        super.onHookedInDocumentTree();

        ModelNode c = firstExpandedChild;
        while (c != null) {
            c.onHookedInDocumentTree();
            c = c.nextSibling;
        }
    
public voidproxiedChildAdded(ElementNode child)
Proxied nodes should call this method they got a new added child. This is an optimization of the more generic insertion case. Appending a child is a recursive process which avoids recomputing all the proxies recursively (a proxy referencing a proxy referencing a proxy .... referencing a composite on which nodes are appended). It might be advantageous to consider doing a generic optimized insertion into the children list.

param
child the ElementNode which was just added under the proxied node.
see
#proxiedExpandedChildAdded

        // If this node is not expanded at all, expand it now
        if (!expanded) {
            expand();
        } else {
            ElementNodeProxy newChildProxy = child.buildProxy();

            if (firstExpandedChild == null) {
                firstExpandedChild = newChildProxy;
                lastExpandedChild = newChildProxy;
                newChildProxy.nextSibling = null;
                newChildProxy.prevSibling = null;
            } else {
                lastExpandedChild.nextSibling = newChildProxy;
                newChildProxy.nextSibling = null;
                newChildProxy.prevSibling = lastExpandedChild;
                lastExpandedChild = newChildProxy;
            }

            newChildProxy.setParentQuiet(this);
            newChildProxy.expand();
            nodeInserted(newChildProxy);
        }
    
protected voidsetProxied(ElementNode newProxied)
Modifies the node proxied by this proxy.

param
newProxied this node's new proxied node

        if (this.proxied == newProxied) {
            return;
        }

        // We call modifyingNode because this node's rendering
        // may change as a result of changing the proxy.
        modifyingNode();

        if (this.proxied != null) {
            this.proxied.removeProxy(this);
        }

        unhookQuiet(firstExpandedChild);

        this.proxied = newProxied;
        firstExpandedChild = null;
        lastExpandedChild = null;
        expanded = false;

        if (newProxied != null) {
            newProxied.addProxy(this);
        }

        // Initialize the requiredFeatures/requiredExtensions/systemLanguage
        // bits to the same value as the proxied node.
        int oldCanRenderState = canRenderState;
        canRenderState &= CAN_RENDER_REQUIRED_FEATURES_MASK;
        canRenderState &= CAN_RENDER_REQUIRED_EXTENSIONS_MASK;
        canRenderState &= CAN_RENDER_SYSTEM_LANGUAGE_MASK;
        
        if (newProxied != null) {
            canRenderState |= (newProxied.canRenderState 
                                & CAN_RENDER_REQUIRED_FEATURES_BIT);
            canRenderState |= (newProxied.canRenderState 
                                & CAN_RENDER_REQUIRED_EXTENSIONS_BIT);
            canRenderState |= (newProxied.canRenderState 
                                & CAN_RENDER_SYSTEM_LANGUAGE_BIT);        
        }

        propagateCanRenderState(oldCanRenderState, canRenderState);
        
        // We call modifiedNode because this node's rendering
        // may have changed as a result of changing the proxy.
        modifiedNode();
    
protected voidunhookChildrenQuiet()
Does nothing, as there are no children.

    
protected voidunhookExpandedQuiet()
Utility method. Unhooks the expanded content.

        unhookQuiet(firstExpandedChild);
        firstExpandedChild = null;
        lastExpandedChild = null;
        expanded = false;