Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / javax / swing / text / StyleContext.java
blobbeb809b89e4835f4a760df2d5c7d730f03a43696
1 /* StyleContext.java --
2 Copyright (C) 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.swing.text;
41 import java.awt.Color;
42 import java.awt.Font;
43 import java.awt.FontMetrics;
44 import java.awt.Toolkit;
45 import java.io.IOException;
46 import java.io.ObjectInputStream;
47 import java.io.ObjectOutputStream;
48 import java.io.Serializable;
49 import java.util.Enumeration;
50 import java.util.EventListener;
51 import java.util.Hashtable;
53 import javax.swing.event.ChangeEvent;
54 import javax.swing.event.ChangeListener;
55 import javax.swing.event.EventListenerList;
57 public class StyleContext
58 implements Serializable, AbstractDocument.AttributeContext
60 public class NamedStyle
61 implements Serializable, Style
63 protected ChangeEvent changeEvent;
64 protected EventListenerList listenerList;
66 AttributeSet attributes;
67 String name;
69 public NamedStyle()
71 this(null, null);
74 public NamedStyle(Style parent)
76 this(null, parent);
79 public NamedStyle(String name, Style parent)
81 this.name = name;
82 this.attributes = getEmptySet();
83 this.changeEvent = new ChangeEvent(this);
84 this.listenerList = new EventListenerList();
85 setResolveParent(parent);
88 public String getName()
90 return name;
93 public void setName(String n)
95 name = n;
96 fireStateChanged();
99 public void addChangeListener(ChangeListener l)
101 listenerList.add(ChangeListener.class, l);
104 public void removeChangeListener(ChangeListener l)
106 listenerList.remove(ChangeListener.class, l);
109 public EventListener[] getListeners(Class listenerType)
111 return listenerList.getListeners(listenerType);
114 public ChangeListener[] getChangeListeners()
116 return (ChangeListener[]) getListeners(ChangeListener.class);
119 protected void fireStateChanged()
121 ChangeListener[] listeners = getChangeListeners();
122 for (int i = 0; i < listeners.length; ++i)
124 listeners[i].stateChanged(changeEvent);
128 public void addAttribute(Object name, Object value)
130 attributes = StyleContext.this.addAttribute(attributes, name, value);
131 fireStateChanged();
134 public void addAttributes(AttributeSet attr)
136 attributes = StyleContext.this.addAttributes(attributes, attr);
137 fireStateChanged();
140 public boolean containsAttribute(Object name, Object value)
142 return attributes.containsAttribute(name, value);
145 public boolean containsAttributes(AttributeSet attrs)
147 return attributes.containsAttributes(attrs);
150 public AttributeSet copyAttributes()
152 return attributes.copyAttributes();
155 public Object getAttribute(Object attrName)
157 return attributes.getAttribute(attrName);
160 public int getAttributeCount()
162 return attributes.getAttributeCount();
165 public Enumeration getAttributeNames()
167 return attributes.getAttributeNames();
170 public boolean isDefined(Object attrName)
172 return attributes.isDefined(attrName);
175 public boolean isEqual(AttributeSet attr)
177 return attributes.isEqual(attr);
180 public void removeAttribute(Object name)
182 attributes = StyleContext.this.removeAttribute(attributes, name);
183 fireStateChanged();
186 public void removeAttributes(AttributeSet attrs)
188 attributes = StyleContext.this.removeAttributes(attributes, attrs);
189 fireStateChanged();
192 public void removeAttributes(Enumeration names)
194 attributes = StyleContext.this.removeAttributes(attributes, names);
195 fireStateChanged();
199 public AttributeSet getResolveParent()
201 return attributes.getResolveParent();
204 public void setResolveParent(AttributeSet parent)
206 attributes = StyleContext.this.addAttribute(attributes, ResolveAttribute, parent);
207 fireStateChanged();
210 public String toString()
212 return ("[NamedStyle: name=" + name + ", attrs=" + attributes.toString() + "]");
216 public class SmallAttributeSet
217 implements AttributeSet
219 final Object [] attrs;
220 public SmallAttributeSet(AttributeSet a)
222 if (a == null)
223 attrs = new Object[0];
224 else
226 int n = a.getAttributeCount();
227 int i = 0;
228 attrs = new Object[n * 2];
229 Enumeration e = a.getAttributeNames();
230 while (e.hasMoreElements())
232 Object name = e.nextElement();
233 attrs[i++] = name;
234 attrs[i++] = a.getAttribute(name);
239 public SmallAttributeSet(Object [] a)
241 if (a == null)
242 attrs = new Object[0];
243 else
245 attrs = new Object[a.length];
246 System.arraycopy(a, 0, attrs, 0, a.length);
250 public Object clone()
252 return new SmallAttributeSet(this.attrs);
255 public boolean containsAttribute(Object name, Object value)
257 for (int i = 0; i < attrs.length; i += 2)
259 if (attrs[i].equals(name) &&
260 attrs[i+1].equals(value))
261 return true;
263 return false;
266 public boolean containsAttributes(AttributeSet a)
268 Enumeration e = a.getAttributeNames();
269 while (e.hasMoreElements())
271 Object name = e.nextElement();
272 Object val = a.getAttribute(name);
273 if (!containsAttribute(name, val))
274 return false;
276 return true;
279 public AttributeSet copyAttributes()
281 return (AttributeSet) clone();
284 public boolean equals(Object obj)
286 return
287 (obj instanceof SmallAttributeSet)
288 && this.isEqual((AttributeSet)obj);
291 public Object getAttribute(Object key)
293 for (int i = 0; i < attrs.length; i += 2)
295 if (attrs[i].equals(key))
296 return attrs[i+1];
299 Object p = getResolveParent();
300 if (p != null && p instanceof AttributeSet)
301 return (((AttributeSet)p).getAttribute(key));
303 return null;
306 public int getAttributeCount()
308 return attrs.length / 2;
311 public Enumeration getAttributeNames()
313 return new Enumeration()
315 int i = 0;
316 public boolean hasMoreElements()
318 return i < attrs.length;
320 public Object nextElement()
322 i += 2;
323 return attrs[i-2];
328 public AttributeSet getResolveParent()
330 return (AttributeSet) getAttribute(ResolveAttribute);
333 public int hashCode()
335 return java.util.Arrays.asList(attrs).hashCode();
338 public boolean isDefined(Object key)
340 for (int i = 0; i < attrs.length; i += 2)
342 if (attrs[i].equals(key))
343 return true;
345 return false;
348 public boolean isEqual(AttributeSet attr)
350 return attr != null
351 && attr.containsAttributes(this)
352 && this.containsAttributes(attr);
355 public String toString()
357 StringBuffer sb = new StringBuffer();
358 sb.append("[StyleContext.SmallattributeSet:");
359 for (int i = 0; i < attrs.length; ++i)
361 sb.append(" (");
362 sb.append(attrs[i].toString());
363 sb.append("=");
364 sb.append(attrs[i+1].toString());
365 sb.append(")");
367 sb.append("]");
368 return sb.toString();
372 // FIXME: official javadocs suggest that these might be more usefully
373 // implemented using a WeakHashMap, but not sure if that works most
374 // places or whether it really matters anyways.
376 // FIXME: also not sure if these tables ought to be static (singletons),
377 // shared across all StyleContexts. I think so, but it's not clear in
378 // docs. revert to non-shared if you think it matters.
380 public static final String DEFAULT_STYLE = "default";
382 static Hashtable sharedAttributeSets = new Hashtable();
383 static Hashtable sharedFonts = new Hashtable();
385 static StyleContext defaultStyleContext = new StyleContext();
386 static final int compressionThreshold = 9;
388 EventListenerList listenerList;
389 Hashtable styleTable;
391 public StyleContext()
393 listenerList = new EventListenerList();
394 styleTable = new Hashtable();
397 protected SmallAttributeSet createSmallAttributeSet(AttributeSet a)
399 return new SmallAttributeSet(a);
402 protected MutableAttributeSet createLargeAttributeSet(AttributeSet a)
404 return new SimpleAttributeSet(a);
407 public void addChangeListener(ChangeListener listener)
409 listenerList.add(ChangeListener.class, listener);
412 public void removeChangeListener(ChangeListener listener)
414 listenerList.remove(ChangeListener.class, listener);
417 public ChangeListener[] getChangeListeners()
419 return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
422 public Style addStyle(String name, Style parent)
424 Style newStyle = new NamedStyle(name, parent);
425 if (name != null)
426 styleTable.put(name, newStyle);
427 return newStyle;
430 public void removeStyle(String name)
432 styleTable.remove(name);
435 public Style getStyle(String name)
437 return (Style) styleTable.get(name);
440 public Enumeration getStyleNames()
442 return styleTable.keys();
446 // StyleContexts only understand the "simple" model of fonts present in
447 // pre-java2d systems: fonts are a family name, a size (integral number
448 // of points), and a mask of style parameters (plain, bold, italic, or
449 // bold|italic). We have an inner class here called SimpleFontSpec which
450 // holds such triples.
452 // A SimpleFontSpec can be built for *any* AttributeSet because the size,
453 // family, and style keys in an AttributeSet have default values (defined
454 // over in StyleConstants).
456 // We keep a static cache mapping SimpleFontSpecs to java.awt.Fonts, so
457 // that we reuse Fonts between styles and style contexts.
460 private static class SimpleFontSpec
462 String family;
463 int style;
464 int size;
465 public SimpleFontSpec(String family,
466 int style,
467 int size)
469 this.family = family;
470 this.style = style;
471 this.size = size;
473 public boolean equals(Object obj)
475 return (obj != null)
476 && (obj instanceof SimpleFontSpec)
477 && (((SimpleFontSpec)obj).family.equals(this.family))
478 && (((SimpleFontSpec)obj).style == this.style)
479 && (((SimpleFontSpec)obj).size == this.size);
481 public int hashCode()
483 return family.hashCode() + style + size;
487 public Font getFont(AttributeSet attr)
489 String family = StyleConstants.getFontFamily(attr);
490 int style = Font.PLAIN;
491 if (StyleConstants.isBold(attr))
492 style += Font.BOLD;
493 if (StyleConstants.isItalic(attr))
494 style += Font.ITALIC;
495 int size = StyleConstants.getFontSize(attr);
496 return getFont(family, style, size);
499 public Font getFont(String family, int style, int size)
501 SimpleFontSpec spec = new SimpleFontSpec(family, style, size);
502 if (sharedFonts.containsKey(spec))
503 return (Font) sharedFonts.get(spec);
504 else
506 Font tmp = new Font(family, style, size);
507 sharedFonts.put(spec, tmp);
508 return tmp;
512 public FontMetrics getFontMetrics(Font f)
514 return Toolkit.getDefaultToolkit().getFontMetrics(f);
517 public Color getForeground(AttributeSet a)
519 return StyleConstants.getForeground(a);
522 public Color getBackground(AttributeSet a)
524 return StyleConstants.getBackground(a);
527 protected int getCompressionThreshold()
529 return compressionThreshold;
532 public static StyleContext getDefaultStyleContext()
534 return defaultStyleContext;
537 public AttributeSet addAttribute(AttributeSet old, Object name, Object value)
539 if (old instanceof MutableAttributeSet)
541 ((MutableAttributeSet)old).addAttribute(name, value);
542 return old;
544 else
546 MutableAttributeSet mutable = createLargeAttributeSet(old);
547 mutable.addAttribute(name, value);
548 if (mutable.getAttributeCount() >= getCompressionThreshold())
549 return mutable;
550 else
552 SmallAttributeSet small = createSmallAttributeSet(mutable);
553 if (sharedAttributeSets.containsKey(small))
554 small = (SmallAttributeSet) sharedAttributeSets.get(small);
555 else
556 sharedAttributeSets.put(small,small);
557 return small;
562 public AttributeSet addAttributes(AttributeSet old, AttributeSet attributes)
564 if (old instanceof MutableAttributeSet)
566 ((MutableAttributeSet)old).addAttributes(attributes);
567 return old;
569 else
571 MutableAttributeSet mutable = createLargeAttributeSet(old);
572 mutable.addAttributes(attributes);
573 if (mutable.getAttributeCount() >= getCompressionThreshold())
574 return mutable;
575 else
577 SmallAttributeSet small = createSmallAttributeSet(mutable);
578 if (sharedAttributeSets.containsKey(small))
579 small = (SmallAttributeSet) sharedAttributeSets.get(small);
580 else
581 sharedAttributeSets.put(small,small);
582 return small;
587 public AttributeSet getEmptySet()
589 AttributeSet e = createSmallAttributeSet(null);
590 if (sharedAttributeSets.containsKey(e))
591 e = (AttributeSet) sharedAttributeSets.get(e);
592 else
593 sharedAttributeSets.put(e, e);
594 return e;
597 public void reclaim(AttributeSet attributes)
599 if (sharedAttributeSets.containsKey(attributes))
600 sharedAttributeSets.remove(attributes);
603 public AttributeSet removeAttribute(AttributeSet old, Object name)
605 if (old instanceof MutableAttributeSet)
607 ((MutableAttributeSet)old).removeAttribute(name);
608 if (old.getAttributeCount() < getCompressionThreshold())
610 SmallAttributeSet small = createSmallAttributeSet(old);
611 if (!sharedAttributeSets.containsKey(small))
612 sharedAttributeSets.put(small,small);
613 old = (AttributeSet) sharedAttributeSets.get(small);
615 return old;
617 else
619 MutableAttributeSet mutable = createLargeAttributeSet(old);
620 mutable.removeAttribute(name);
621 SmallAttributeSet small = createSmallAttributeSet(mutable);
622 if (sharedAttributeSets.containsKey(small))
623 small = (SmallAttributeSet) sharedAttributeSets.get(small);
624 else
625 sharedAttributeSets.put(small,small);
626 return small;
630 public AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes)
632 return removeAttributes(old, attributes.getAttributeNames());
635 public AttributeSet removeAttributes(AttributeSet old, Enumeration names)
637 if (old instanceof MutableAttributeSet)
639 ((MutableAttributeSet)old).removeAttributes(names);
640 if (old.getAttributeCount() < getCompressionThreshold())
642 SmallAttributeSet small = createSmallAttributeSet(old);
643 if (!sharedAttributeSets.containsKey(small))
644 sharedAttributeSets.put(small,small);
645 old = (AttributeSet) sharedAttributeSets.get(small);
647 return old;
649 else
651 MutableAttributeSet mutable = createLargeAttributeSet(old);
652 mutable.removeAttributes(names);
653 SmallAttributeSet small = createSmallAttributeSet(mutable);
654 if (sharedAttributeSets.containsKey(small))
655 small = (SmallAttributeSet) sharedAttributeSets.get(small);
656 else
657 sharedAttributeSets.put(small,small);
658 return small;
663 // FIXME: there's some sort of quasi-serialization stuff in here which I
664 // have left incomplete; I'm not sure I understand the intent properly.
666 public static Object getStaticAttribute(Object key)
668 throw new InternalError("not implemented");
671 public static Object getStaticAttributeKey(Object key)
673 throw new InternalError("not implemented");
676 public static void readAttributeSet(ObjectInputStream in, MutableAttributeSet a)
677 throws ClassNotFoundException, IOException
679 throw new InternalError("not implemented");
682 public static void writeAttributeSet(ObjectOutputStream out, AttributeSet a)
683 throws IOException
685 throw new InternalError("not implemented");
688 public void readAttributes(ObjectInputStream in, MutableAttributeSet a)
689 throws ClassNotFoundException, IOException
691 throw new InternalError("not implemented");
694 public void writeAttributes(ObjectOutputStream out, AttributeSet a)
695 throws IOException
697 throw new InternalError("not implemented");