1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 /** 18 * @author Alexey A. Ivanov 19 */ 20 package javax.swing.text.html; 21 22 import java.util.Collections; 23 import java.util.Enumeration; 24 import java.util.Iterator; 25 import java.util.LinkedList; 26 import java.util.List; 27 import java.util.NoSuchElementException; 28 29 import javax.swing.event.ChangeListener; 30 import javax.swing.text.AttributeSet; 31 import javax.swing.text.Element; 32 import javax.swing.text.Style; 33 import javax.swing.text.StyleConstants; 34 35 import org.apache.harmony.x.swing.internal.nls.Messages; 36 37 /** 38 * Storage for all the attributes applicable for the 39 * {@link javax.swing.text.Element} for which CascadedStyle 40 * is built. Applicability is defined by CSS1 specification (http://www.w3.org/TR/CSS1). 41 */ 42 final class CascadedStyle implements Style { 43 private final StyleSheet styleSheet; 44 private final List styleList; 45 private final List sheetList; 46 private final String name; 47 private final Selector selector; 48 49 CascadedStyle(final StyleSheet styleSheet, final Element element, 50 final List styleList, final Iterator sheetIt) { 51 this(styleSheet, getElementTreeSelector(element), styleList, sheetIt); 52 } 53 54 CascadedStyle(final StyleSheet styleSheet, final String name, 55 final List styleList, final Iterator sheetIt) { 56 this.styleSheet = styleSheet; 57 this.styleList = styleList; 58 this.name = name; 59 this.selector = new Selector(name); 60 61 sheetList = new LinkedList(); 62 while (sheetIt.hasNext()) { 63 sheetList.add(((StyleSheet)sheetIt.next()).getRule(name)); 64 } 65 } 66 67 public static String getElementTreeSelector(final Element element) { 68 final StringBuilder result = new StringBuilder(); 69 result.append(getFullName(element)); 70 Element parent = element.getParentElement(); 71 while (parent != null) { 72 result.insert(0, ' '); 73 result.insert(0, getFullName(parent)); 74 parent = parent.getParentElement(); 75 } 76 return result.toString(); 77 } 78 79 public static String getFullName(final Element element) { 80 HTML.Tag tag = SelectorMatcher.getTag(element); 81 if (tag == null) { 82 return getFullName(element.getParentElement()); 83 } 84 85 return getFullElementName(element, tag); 86 } 87 88 public static String getFullElementName(final Element element) { 89 HTML.Tag tag = SelectorMatcher.getTag(element); 90 if (tag == null) { 91 return null; 92 } 93 94 return getFullElementName(element, tag); 95 } 96 97 public static String getFullElementName(final Element element, 98 final HTML.Tag tag) { 99 final String tagName = tag.toString(); 100 final String id = SelectorMatcher.getID(tag, element); 101 final String clazz = SelectorMatcher.getClass(tag, element); 102 103 final StringBuilder result = new StringBuilder(); 104 if (tagName != null) { 105 result.append(tagName); 106 } 107 if (id != null) { 108 result.append('#').append(id); 109 } 110 if (clazz != null) { 111 result.append('.').append(clazz); 112 } 113 114 return result.toString(); 115 } 116 117 public String getName() { 118 return name; 119 } 120 121 public void addChangeListener(final ChangeListener arg0) { 122 } 123 124 public void removeChangeListener(final ChangeListener arg0) { 125 } 126 127 public void removeAttribute(final Object arg0) { 128 // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$ 129 } 130 131 public void removeAttributes(final Enumeration arg0) { 132 // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$ 133 } 134 135 public void addAttributes(final AttributeSet arg0) { 136 // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$ 137 } 138 139 public void removeAttributes(final AttributeSet arg0) { 140 // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$ 141 } 142 143 public void setResolveParent(final AttributeSet arg0) { 144 // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$ 145 } 146 147 public void addAttribute(final Object arg0, final Object arg1) { 148 // throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$ 149 } 150 151 public int getAttributeCount() { 152 Iterator it = styleList.iterator(); 153 int result = 0; 154 while (it.hasNext()) { 155 result += styleSheet.getStyle(it.next().toString()) 156 .getAttributeCount(); 157 } 158 159 it = sheetList.iterator(); 160 while (it.hasNext()) { 161 result += ((AttributeSet)it.next()).getAttributeCount(); 162 } 163 return result; 164 } 165 166 public boolean isDefined(final Object arg0) { 167 Iterator it = styleList.iterator(); 168 boolean result = false; 169 while (!result && it.hasNext()) { 170 Style style = styleSheet.getStyle(it.next().toString()); 171 result = style.isDefined(arg0); 172 } 173 if (result) { 174 return result; 175 } 176 177 it = sheetList.iterator(); 178 while (!result && it.hasNext()) { 179 result = ((AttributeSet)it.next()).isDefined(arg0); 180 } 181 return result; 182 } 183 184 public Enumeration getAttributeNames() { 185 return new Enumeration() { 186 private final Iterator styleIt = styleList.iterator(); 187 private final Iterator sheetIt = sheetList.iterator(); 188 private Enumeration current; 189 190 public boolean hasMoreElements() { 191 return styleIt.hasNext() 192 || current != null && current.hasMoreElements() 193 || hasAttributesInSheets(); 194 } 195 196 public Object nextElement() { 197 if (current != null && current.hasMoreElements()) { 198 return current.nextElement(); 199 } 200 if (styleIt.hasNext()) { 201 current = getAttributeNamesOfNextStyle(); 202 return nextElement(); 203 } 204 if (hasAttributesInSheets()) { 205 return current.nextElement(); 206 } 207 208 throw new NoSuchElementException(); 209 } 210 211 private boolean hasAttributesInSheets() { 212 if (sheetIt.hasNext()) { 213 current = 214 ((AttributeSet)sheetIt.next()).getAttributeNames(); 215 } 216 return current != null && current.hasMoreElements(); 217 } 218 219 private Enumeration getAttributeNamesOfNextStyle() { 220 return styleSheet.getStyle(styleIt.next().toString()) 221 .getAttributeNames(); 222 } 223 }; 224 } 225 226 public AttributeSet copyAttributes() { 227 throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$ 228 } 229 230 public AttributeSet getResolveParent() { 231 return (AttributeSet)getAttribute(StyleConstants.ResolveAttribute); 232 } 233 234 public boolean containsAttributes(final AttributeSet arg0) { 235 boolean result = true; 236 final Enumeration keys = arg0.getAttributeNames(); 237 while (result && keys.hasMoreElements()) { 238 Object key = keys.nextElement(); 239 Object value = arg0.getAttribute(key); 240 result = containsAttribute(key, value); 241 } 242 return result; 243 } 244 245 public boolean isEqual(final AttributeSet arg0) { 246 if (getAttributeCount() != arg0.getAttributeCount()) { 247 return false; 248 } 249 return containsAttributes(arg0); 250 } 251 252 public Object getAttribute(final Object key) { 253 Iterator it = styleList.iterator(); 254 Object result = null; 255 while (result == null && it.hasNext()) { 256 Style style = styleSheet.getStyle(it.next().toString()); 257 result = style.getAttribute(key); 258 } 259 if (result != null) { 260 return result; 261 } 262 it = sheetList.iterator(); 263 while (result == null && it.hasNext()) { 264 result = ((AttributeSet)it.next()).getAttribute(key); 265 } 266 return result; 267 } 268 269 public Object getAttribute(final Object key, final Element element) { 270 if (!(key instanceof CSS.Attribute) 271 || ((CSS.Attribute)key).isInherited()) { 272 273 return getAttribute(key); 274 } 275 final String elementName = getFullElementName(element); 276 if (elementName == null) { 277 return null; 278 } 279 final SimpleSelector elementSelector = new SimpleSelector(elementName); 280 281 Iterator it = styleList.iterator(); 282 Object result = null; 283 while (result == null && it.hasNext()) { 284 Selector styleSelector = (Selector)it.next(); 285 if (!elementSelector.applies(styleSelector.getLastSelector())) { 286 continue; 287 } 288 Style style = styleSheet.getStyle(styleSelector.toString()); 289 result = style.getAttribute(key); 290 } 291 if (result != null) { 292 return result; 293 } 294 it = sheetList.iterator(); 295 while (result == null && it.hasNext()) { 296 result = ((AttributeSet)it.next()).getAttribute(key); 297 } 298 return result; 299 } 300 301 public boolean containsAttribute(final Object arg0, final Object arg1) { 302 Iterator it = styleList.iterator(); 303 boolean result = false; 304 while (!result && it.hasNext()) { 305 Style style = styleSheet.getStyle(it.next().toString()); 306 result = style.containsAttribute(arg0, arg1); 307 } 308 if (result) { 309 return result; 310 } 311 it = sheetList.iterator(); 312 while (!result && it.hasNext()) { 313 result = ((AttributeSet)it.next()).containsAttribute(arg0, arg1); 314 } 315 return result; 316 } 317 318 void addStyle(final String styleName) { 319 Selector styleSelector = new Selector(styleName); 320 if (selector.applies(styleSelector)) { 321 styleList.add(styleSelector); 322 Collections.sort(styleList, SpecificityComparator.compator); 323 } 324 } 325 326 void removeStyle(final String styleName) { 327 Iterator it = styleList.iterator(); 328 while (it.hasNext()) { 329 Selector s = (Selector)it.next(); 330 if (styleName.equals(s.toString())) { 331 it.remove(); 332 break; 333 } 334 } 335 } 336 337 void addStyleSheet(final StyleSheet ss) { 338 sheetList.add(0, ss.getRule(name)); 339 } 340 341 void removeStyleSheet(final StyleSheet ss) { 342 final Iterator it = sheetList.iterator(); 343 while (it.hasNext()) { 344 CascadedStyle rs = (CascadedStyle)it.next(); 345 if (rs.styleSheet == ss) { 346 it.remove(); 347 break; 348 } 349 } 350 } 351 }