001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Alexey A. Ivanov
019: * @version $Revision$
020: */package javax.swing.text.html;
021:
022: import java.util.Collections;
023: import java.util.Enumeration;
024: import java.util.Iterator;
025: import java.util.LinkedList;
026: import java.util.List;
027: import java.util.NoSuchElementException;
028:
029: import javax.swing.event.ChangeListener;
030: import javax.swing.text.AttributeSet;
031: import javax.swing.text.Element;
032: import javax.swing.text.Style;
033: import javax.swing.text.StyleConstants;
034:
035: import org.apache.harmony.x.swing.internal.nls.Messages;
036:
037: /**
038: * Storage for all the attributes applicable for the
039: * {@link javax.swing.text.Element} for which CascadedStyle
040: * is built. Applicability is defined by CSS1 specification (http://www.w3.org/TR/CSS1).
041: */
042: final class CascadedStyle implements Style {
043: private final StyleSheet styleSheet;
044: private final List styleList;
045: private final List sheetList;
046: private final String name;
047: private final Selector selector;
048:
049: CascadedStyle(final StyleSheet styleSheet, final Element element,
050: final List styleList, final Iterator sheetIt) {
051: this (styleSheet, getElementTreeSelector(element), styleList,
052: sheetIt);
053: }
054:
055: CascadedStyle(final StyleSheet styleSheet, final String name,
056: final List styleList, final Iterator sheetIt) {
057: this .styleSheet = styleSheet;
058: this .styleList = styleList;
059: this .name = name;
060: this .selector = new Selector(name);
061:
062: sheetList = new LinkedList();
063: while (sheetIt.hasNext()) {
064: sheetList.add(((StyleSheet) sheetIt.next()).getRule(name));
065: }
066: }
067:
068: public static String getElementTreeSelector(final Element element) {
069: final StringBuffer result = new StringBuffer();
070: result.append(getFullName(element));
071: Element parent = element.getParentElement();
072: while (parent != null) {
073: result.insert(0, ' ');
074: result.insert(0, getFullName(parent));
075: parent = parent.getParentElement();
076: }
077: return result.toString();
078: }
079:
080: public static String getFullName(final Element element) {
081: HTML.Tag tag = SelectorMatcher.getTag(element);
082: if (tag == null) {
083: return getFullName(element.getParentElement());
084: }
085:
086: return getFullElementName(element, tag);
087: }
088:
089: public static String getFullElementName(final Element element) {
090: HTML.Tag tag = SelectorMatcher.getTag(element);
091: if (tag == null) {
092: return null;
093: }
094:
095: return getFullElementName(element, tag);
096: }
097:
098: public static String getFullElementName(final Element element,
099: final HTML.Tag tag) {
100: final String tagName = tag.toString();
101: final String id = SelectorMatcher.getID(tag, element);
102: final String clazz = SelectorMatcher.getClass(tag, element);
103:
104: final StringBuffer result = new StringBuffer();
105: if (tagName != null) {
106: result.append(tagName);
107: }
108: if (id != null) {
109: result.append('#').append(id);
110: }
111: if (clazz != null) {
112: result.append('.').append(clazz);
113: }
114:
115: return result.toString();
116: }
117:
118: public String getName() {
119: return name;
120: }
121:
122: public void addChangeListener(final ChangeListener arg0) {
123: }
124:
125: public void removeChangeListener(final ChangeListener arg0) {
126: }
127:
128: public void removeAttribute(final Object arg0) {
129: // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$
130: }
131:
132: public void removeAttributes(final Enumeration arg0) {
133: // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$
134: }
135:
136: public void addAttributes(final AttributeSet arg0) {
137: // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$
138: }
139:
140: public void removeAttributes(final AttributeSet arg0) {
141: // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$
142: }
143:
144: public void setResolveParent(final AttributeSet arg0) {
145: // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$
146: }
147:
148: public void addAttribute(final Object arg0, final Object arg1) {
149: // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$
150: }
151:
152: public int getAttributeCount() {
153: Iterator it = styleList.iterator();
154: int result = 0;
155: while (it.hasNext()) {
156: result += styleSheet.getStyle(it.next().toString())
157: .getAttributeCount();
158: }
159:
160: it = sheetList.iterator();
161: while (it.hasNext()) {
162: result += ((AttributeSet) it.next()).getAttributeCount();
163: }
164: return result;
165: }
166:
167: public boolean isDefined(final Object arg0) {
168: Iterator it = styleList.iterator();
169: boolean result = false;
170: while (!result && it.hasNext()) {
171: Style style = styleSheet.getStyle(it.next().toString());
172: result = style.isDefined(arg0);
173: }
174: if (result) {
175: return result;
176: }
177:
178: it = sheetList.iterator();
179: while (!result && it.hasNext()) {
180: result = ((AttributeSet) it.next()).isDefined(arg0);
181: }
182: return result;
183: }
184:
185: public Enumeration getAttributeNames() {
186: return new Enumeration() {
187: private final Iterator styleIt = styleList.iterator();
188: private final Iterator sheetIt = sheetList.iterator();
189: private Enumeration current;
190:
191: public boolean hasMoreElements() {
192: return styleIt.hasNext() || current != null
193: && current.hasMoreElements()
194: || hasAttributesInSheets();
195: }
196:
197: public Object nextElement() {
198: if (current != null && current.hasMoreElements()) {
199: return current.nextElement();
200: }
201: if (styleIt.hasNext()) {
202: current = getAttributeNamesOfNextStyle();
203: return nextElement();
204: }
205: if (hasAttributesInSheets()) {
206: return current.nextElement();
207: }
208:
209: throw new NoSuchElementException();
210: }
211:
212: private boolean hasAttributesInSheets() {
213: if (sheetIt.hasNext()) {
214: current = ((AttributeSet) sheetIt.next())
215: .getAttributeNames();
216: }
217: return current != null && current.hasMoreElements();
218: }
219:
220: private Enumeration getAttributeNamesOfNextStyle() {
221: return styleSheet.getStyle(styleIt.next().toString())
222: .getAttributeNames();
223: }
224: };
225: }
226:
227: public AttributeSet copyAttributes() {
228: throw new UnsupportedOperationException(Messages
229: .getString("swing.27")); //$NON-NLS-1$
230: }
231:
232: public AttributeSet getResolveParent() {
233: return (AttributeSet) getAttribute(StyleConstants.ResolveAttribute);
234: }
235:
236: public boolean containsAttributes(final AttributeSet arg0) {
237: boolean result = true;
238: final Enumeration keys = arg0.getAttributeNames();
239: while (result && keys.hasMoreElements()) {
240: Object key = keys.nextElement();
241: Object value = arg0.getAttribute(key);
242: result = containsAttribute(key, value);
243: }
244: return result;
245: }
246:
247: public boolean isEqual(final AttributeSet arg0) {
248: if (getAttributeCount() != arg0.getAttributeCount()) {
249: return false;
250: }
251: return containsAttributes(arg0);
252: }
253:
254: public Object getAttribute(final Object key) {
255: Iterator it = styleList.iterator();
256: Object result = null;
257: while (result == null && it.hasNext()) {
258: Style style = styleSheet.getStyle(it.next().toString());
259: result = style.getAttribute(key);
260: }
261: if (result != null) {
262: return result;
263: }
264: it = sheetList.iterator();
265: while (result == null && it.hasNext()) {
266: result = ((AttributeSet) it.next()).getAttribute(key);
267: }
268: return result;
269: }
270:
271: public Object getAttribute(final Object key, final Element element) {
272: if (!(key instanceof CSS.Attribute)
273: || ((CSS.Attribute) key).isInherited()) {
274:
275: return getAttribute(key);
276: }
277: final String elementName = getFullElementName(element);
278: if (elementName == null) {
279: return null;
280: }
281: final SimpleSelector elementSelector = new SimpleSelector(
282: elementName);
283:
284: Iterator it = styleList.iterator();
285: Object result = null;
286: while (result == null && it.hasNext()) {
287: Selector styleSelector = (Selector) it.next();
288: if (!elementSelector.applies(styleSelector
289: .getLastSelector())) {
290: continue;
291: }
292: Style style = styleSheet.getStyle(styleSelector.toString());
293: result = style.getAttribute(key);
294: }
295: if (result != null) {
296: return result;
297: }
298: it = sheetList.iterator();
299: while (result == null && it.hasNext()) {
300: result = ((AttributeSet) it.next()).getAttribute(key);
301: }
302: return result;
303: }
304:
305: public boolean containsAttribute(final Object arg0,
306: final Object arg1) {
307: Iterator it = styleList.iterator();
308: boolean result = false;
309: while (!result && it.hasNext()) {
310: Style style = styleSheet.getStyle(it.next().toString());
311: result = style.containsAttribute(arg0, arg1);
312: }
313: if (result) {
314: return result;
315: }
316: it = sheetList.iterator();
317: while (!result && it.hasNext()) {
318: result = ((AttributeSet) it.next()).containsAttribute(arg0,
319: arg1);
320: }
321: return result;
322: }
323:
324: void addStyle(final String styleName) {
325: Selector styleSelector = new Selector(styleName);
326: if (selector.applies(styleSelector)) {
327: styleList.add(styleSelector);
328: Collections.sort(styleList, SpecificityComparator.compator);
329: }
330: }
331:
332: void removeStyle(final String styleName) {
333: Iterator it = styleList.iterator();
334: while (it.hasNext()) {
335: Selector s = (Selector) it.next();
336: if (styleName.equals(s.toString())) {
337: it.remove();
338: break;
339: }
340: }
341: }
342:
343: void addStyleSheet(final StyleSheet ss) {
344: sheetList.add(0, ss.getRule(name));
345: }
346:
347: void removeStyleSheet(final StyleSheet ss) {
348: final Iterator it = sheetList.iterator();
349: while (it.hasNext()) {
350: CascadedStyle rs = (CascadedStyle) it.next();
351: if (rs.styleSheet == ss) {
352: it.remove();
353: break;
354: }
355: }
356: }
357: }
|