001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.visualweb.designer.cssengine;
042:
043: import org.w3c.dom.css.CSSPrimitiveValue;
044: import org.apache.batik.css.engine.CSSEngine;
045: import org.apache.batik.css.engine.CSSStylableElement;
046: import org.apache.batik.css.engine.StyleMap;
047: import org.apache.batik.css.engine.value.AbstractValueManager;
048: import org.apache.batik.css.engine.value.IdentifierProvider;
049: import org.apache.batik.css.engine.value.FloatValue;
050: import org.apache.batik.css.engine.value.ListValue;
051: import org.apache.batik.css.engine.value.StringMap;
052: import org.apache.batik.css.engine.value.Value;
053: import org.w3c.css.sac.LexicalUnit;
054: import org.w3c.dom.DOMException;
055:
056: /**
057: * This class provides a manager for the "background-position" CSS property
058: * @todo I should make value constants for 50% and 100%
059: *
060: * @author Tor Norbye
061: */
062: public class BackgroundPositionManager extends AbstractValueManager
063: implements IdentifierProvider {
064:
065: protected final static StringMap values = new StringMap();
066: static {
067:
068: values.put(CssConstants.CSS_TOP_VALUE,
069: CssValueConstants.TOP_VALUE);
070: values.put(CssConstants.CSS_CENTER_VALUE,
071: CssValueConstants.CENTER_VALUE);
072: values.put(CssConstants.CSS_BOTTOM_VALUE,
073: CssValueConstants.BOTTOM_VALUE);
074: values.put(CssConstants.CSS_LEFT_VALUE,
075: CssValueConstants.LEFT_VALUE);
076: values.put(CssConstants.CSS_RIGHT_VALUE,
077: CssValueConstants.RIGHT_VALUE);
078: }
079:
080: public boolean isInheritedProperty() {
081: return false;
082: }
083:
084: public String getPropertyName() {
085: return CssConstants.CSS_BACKGROUND_POSITION_PROPERTY;
086: }
087:
088: public Value getDefaultValue() {
089: return DEFAULT_VALUE;
090: }
091:
092: private final static ListValue DEFAULT_VALUE = new ListValue();
093: static {
094: DEFAULT_VALUE.append(CssValueConstants.NUMBER_0);
095: DEFAULT_VALUE.append(CssValueConstants.NUMBER_0);
096: }
097:
098: public Value createValue(LexicalUnit lu, CSSEngine engine)
099: throws DOMException {
100: ListValue result = new ListValue();
101: // This is a little bit complicated because the user is not
102: // required to put the horizontal and vertical position words
103: // in a particular order, and "center" can mean both center
104: // horizontally and center vertically. Thus, we have to use
105: // the other word to disambiguate.
106: isHorizontal = true;
107: Value v1 = createNewValue(lu, engine);
108: Value v2 = null;
109: boolean swapped = !isHorizontal;
110: LexicalUnit lu2 = lu.getNextLexicalUnit();
111: if (lu2 == null) {
112: v2 = new FloatValue(CSSPrimitiveValue.CSS_PERCENTAGE, 50.0f);
113: } else {
114: if (swapped) {
115: isHorizontal = true;
116: } else {
117: isHorizontal = false;
118: }
119: v2 = createNewValue(lu2, engine);
120: // if swapped then we expect isHorizontal = true now... otherwise
121: // the user entered two vertical numbers... which is wrong
122: if (swapped && !isHorizontal) {
123: // Discard value
124: v2 = CssValueConstants.NUMBER_0;
125: }
126: if (lu2.getNextLexicalUnit() != null) { // should only have two!
127: throw createInvalidLexicalUnitDOMException(lu
128: .getLexicalUnitType(), engine);
129: }
130: }
131:
132: if (v1 == CssValueConstants.CENTER_VALUE) {
133: v1 = new FloatValue(CSSPrimitiveValue.CSS_PERCENTAGE, 50.0f);
134: }
135: if (v2 == CssValueConstants.CENTER_VALUE) {
136: v2 = new FloatValue(CSSPrimitiveValue.CSS_PERCENTAGE, 50.0f);
137: }
138: if (swapped) {
139: result.append(v2);
140: result.append(v1);
141: } else {
142: result.append(v1);
143: result.append(v2);
144: }
145: return result;
146: }
147:
148: /**
149: * Flag used to communicate an additional return value from createValue(LexicalUnit): whether
150: * the return value implied a particular axis (e.g. top implies vertical, right implies
151: * horizontal. Numbers, percentages and "center" doesn't tell us anything so createValue
152: * will leave it unmodified.
153: */
154: private boolean isHorizontal;
155:
156: /** Create a value for the given lexical unit. Set the member "isHorizontal" if
157: * we can infer something about whether the property applies to the horizontal
158: * or vertical direction.
159: */
160: private Value createNewValue(LexicalUnit lu, CSSEngine engine) {
161: switch (lu.getLexicalUnitType()) {
162: case LexicalUnit.SAC_INHERIT:
163: return CssValueConstants.INHERIT_VALUE;
164:
165: case LexicalUnit.SAC_EM:
166: return new FloatValue(CSSPrimitiveValue.CSS_EMS, lu
167: .getFloatValue());
168:
169: case LexicalUnit.SAC_EX:
170: return new FloatValue(CSSPrimitiveValue.CSS_EXS, lu
171: .getFloatValue());
172:
173: case LexicalUnit.SAC_PIXEL:
174: return new FloatValue(CSSPrimitiveValue.CSS_PX, lu
175: .getFloatValue());
176:
177: case LexicalUnit.SAC_CENTIMETER:
178: return new FloatValue(CSSPrimitiveValue.CSS_CM, lu
179: .getFloatValue());
180:
181: case LexicalUnit.SAC_MILLIMETER:
182: return new FloatValue(CSSPrimitiveValue.CSS_MM, lu
183: .getFloatValue());
184:
185: case LexicalUnit.SAC_INCH:
186: return new FloatValue(CSSPrimitiveValue.CSS_IN, lu
187: .getFloatValue());
188:
189: case LexicalUnit.SAC_POINT:
190: return new FloatValue(CSSPrimitiveValue.CSS_PT, lu
191: .getFloatValue());
192:
193: case LexicalUnit.SAC_PICA:
194: return new FloatValue(CSSPrimitiveValue.CSS_PC, lu
195: .getFloatValue());
196:
197: // XXX illegal for background-position
198: case LexicalUnit.SAC_INTEGER:
199: return new FloatValue(CSSPrimitiveValue.CSS_NUMBER, lu
200: .getIntegerValue());
201:
202: // XXX illegal for background-position
203: case LexicalUnit.SAC_REAL:
204: return new FloatValue(CSSPrimitiveValue.CSS_NUMBER, lu
205: .getFloatValue());
206:
207: case LexicalUnit.SAC_PERCENTAGE:
208: return new FloatValue(CSSPrimitiveValue.CSS_PERCENTAGE, lu
209: .getFloatValue());
210:
211: case LexicalUnit.SAC_IDENT:
212: String s = lu.getStringValue().toLowerCase().intern();
213: Object v = values.get(s);
214: if (v == CssValueConstants.CENTER_VALUE) {
215: // The caller needs to figure out if we're talking about the first
216: // or the second parameter here
217: return CssValueConstants.CENTER_VALUE;
218: } else if (v == CssValueConstants.TOP_VALUE) {
219: isHorizontal = false;
220: return CssValueConstants.NUMBER_0;
221: } else if (v == CssValueConstants.BOTTOM_VALUE) {
222: isHorizontal = false;
223: return new FloatValue(CSSPrimitiveValue.CSS_PERCENTAGE,
224: 100.0f);
225: } else if (v == CssValueConstants.LEFT_VALUE) {
226: isHorizontal = true;
227: return CssValueConstants.NUMBER_0;
228: } else if (v == CssValueConstants.RIGHT_VALUE) {
229: isHorizontal = true;
230: return new FloatValue(CSSPrimitiveValue.CSS_PERCENTAGE,
231: 100.0f);
232: } else {
233: throw createInvalidIdentifierDOMException(lu
234: .getStringValue(), engine);
235: }
236: }
237: return null;
238: }
239:
240: public Value computeValue(CSSStylableElement elt, String pseudo,
241: CSSEngine engine, int idx, StyleMap sm, Value value) {
242: // XXX what about INHERIT? Can't have that!
243:
244: // We're supposed to leave percentages alone according to the CSS2.1 spec;
245: // the computed value will be either a length or the percentage.
246: return value;
247: }
248:
249: public StringMap getIdentifierMap() {
250: return values;
251: }
252: }
|