001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package com.sun.perseus.model;
027:
028: import org.w3c.dom.svg.SVGRect;
029:
030: import com.sun.perseus.j2d.Transform;
031:
032: /**
033: * A <code>UseProxy</code> proxies a <code>Use</code> node and
034: * computes the expanded content from the proxied use's children
035: * and its proxy expanded child.
036: *
037: * <p>A <code>UseProxy</code> has a first expanded child corresponding
038: * to the proxied <code>Use</code>'s proxy content. Follow on expanded
039: * children come from the <code>Use</code>'s children.</p>
040: *
041: * @version $Id: UseProxy.java,v 1.6 2006/06/29 10:47:36 ln156897 Exp $
042: */
043: public class UseProxy extends StructureNodeProxy {
044: /**
045: * @param proxiedUse <code>Use</code> node to proxy
046: */
047: UseProxy(final Use proxiedUse) {
048: super (proxiedUse);
049: }
050:
051: /**
052: * Called by the proxied node when the given property's computed value has
053: * changed.
054: *
055: * @param propertyIndex index for the property whose value is changing.
056: * @param proxiedComputedValue computed value for the proxied node.
057: *
058: */
059: protected void proxiedPropertyStateChange(final int propertyIndex,
060: final Object proxiedComputedValue) {
061: Object inheritValue = proxiedComputedValue;
062: if (!((CompositeGraphicsNode) proxied)
063: .isInherited(propertyIndex)) {
064: // The property is specified on the proxied node, update the
065: // state with that specified value.
066: setPropertyState(propertyIndex, proxiedComputedValue);
067: } else {
068: // The property is unspecified on the proxied node. Inherit from
069: // the proxy's parent (and not the proxied's parent).
070: inheritValue = getInheritedPropertyState(propertyIndex);
071: setPropertyState(propertyIndex, inheritValue);
072: }
073:
074: // Propagate to children.
075: ModelNode c = firstExpandedChild;
076: while (c != null) {
077: propagatePropertyState(propertyIndex, inheritValue);
078: c = c.nextSibling;
079: }
080: }
081:
082: /**
083: * Disallow proxying of anything else than <code>Use</code> nodes.
084: *
085: * @param newProxied this node's new proxied node
086: * @throws IllegalArgumentException if the input new proxy is not
087: * a <code>Use</code> node.
088: * @see ElementNodeProxy#setProxied
089: */
090: protected void setProxied(final ElementNode newProxied) {
091: if (newProxied != null && !(newProxied instanceof Use)) {
092: throw new IllegalArgumentException();
093: }
094:
095: super .setProxied(newProxied);
096: }
097:
098: /**
099: * @return the tight bounding box in current user coordinate
100: * space.
101: */
102: public SVGRect getBBox() {
103: Transform t = null;
104: Use proxiedUse = (Use) proxied;
105:
106: if (proxiedUse != null
107: && (proxiedUse.x != 0 || proxiedUse.y != 0)) {
108: t = new Transform(1, 0, 0, 1, proxiedUse.x, proxiedUse.y);
109: }
110:
111: return addBBox(null, t);
112: }
113:
114: /**
115: * Expand the content. For a use node, we create additional expanded
116: * content to account for the use proxy.
117: */
118: protected void expand() {
119: if (expanded) {
120: return;
121: }
122: if (proxied != null) {
123: //
124: // The first expanded content comes from the proxied <use>'s
125: // proxy.
126: // At the end of this first computation, the firstExpandedChild
127: // points to a proxy for the <use>'s proxy or is null and the
128: // lastExpandedChild is equal to the firstExpandedChild
129: //
130: Use proxiedUse = (Use) proxied;
131: if (proxiedUse.proxy != null) {
132: firstExpandedChild = buildProxiedProxy();
133: } else {
134: firstExpandedChild = null;
135: }
136:
137: lastExpandedChild = firstExpandedChild;
138:
139: //
140: // Now, do the regular expansion, in case the <use> element
141: // has regular element children.
142: //
143: ElementNodeProxy firstRegularProxies = computeProxiesChain((ElementNode) proxied
144: .getFirstChildNode());
145:
146: if (firstRegularProxies != null) {
147: lastExpandedChild = firstRegularProxies.prevSibling;
148: if (firstExpandedChild == null) {
149: // The proxied <use> has no proxy
150: firstExpandedChild = firstRegularProxies;
151: firstRegularProxies.prevSibling = null;
152: } else {
153: // The proxied <use> had a proxy
154: firstExpandedChild.nextSibling = firstRegularProxies;
155: firstRegularProxies.prevSibling = firstExpandedChild;
156: }
157: }
158:
159: }
160:
161: expanded = true;
162: }
163:
164: /**
165: * Notifies this proxy that the proxied Use's proxy has just been set.
166: */
167: void useProxySet() {
168: if (!expanded) {
169: expand();
170: } else {
171: ElementNodeProxy newFirstExpandedChild = buildProxiedProxy();
172: newFirstExpandedChild.nextSibling = firstExpandedChild;
173: if (firstExpandedChild != null) {
174: firstExpandedChild.prevSibling = newFirstExpandedChild;
175: }
176: firstExpandedChild = newFirstExpandedChild;
177: if (lastExpandedChild == null) {
178: lastExpandedChild = firstExpandedChild;
179: }
180: }
181: }
182:
183: /**
184: * Implementation helper. This handles getting the proxy from the
185: * proxied <code>Use</code>'s proxy's proxied (see comments in the
186: * code).
187: *
188: * @return an expanded <code>ElementNodeProxy</code> for the proxied
189: * <code>Use</code>'s proxy.
190: */
191: ElementNodeProxy buildProxiedProxy() {
192: //
193: // Here we are in a situation like:
194: //
195: // + u -> u2 -> rect
196: //
197: // Which we expand into
198: //
199: // + rect
200: // + u2
201: // +~~> ElementNodeProxy(rect)
202: // + u
203: // +~~> UseProxy(u2)
204: // +~~> ElementNodeProxy(rect)
205: //
206: // To understand the following code, we are building
207: // the equivalent of UseProxy(u2)
208: //
209: // proxied.expandedContent[0] is a reference to
210: // u2's ElementNodeProxy(rect)
211: //
212: Use proxiedUse = (Use) proxied;
213: ElementNodeProxy proxy = proxiedUse.proxy.getProxied()
214: .buildExpandedProxy();
215: proxy.setParentQuiet(this);
216: return proxy;
217: }
218: }
|