< prev index next >

src/java.desktop/share/classes/javax/swing/text/StyleContext.java

Print this page




  40 /**
  41  * A pool of styles and their associated resources.  This class determines
  42  * the lifetime of a group of resources by being a container that holds
  43  * caches for various resources such as font and color that get reused
  44  * by the various style definitions.  This can be shared by multiple
  45  * documents if desired to maximize the sharing of related resources.
  46  * <p>
  47  * This class also provides efficient support for small sets of attributes
  48  * and compresses them by sharing across uses and taking advantage of
  49  * their immutable nature.  Since many styles are replicated, the potential
  50  * for sharing is significant, and copies can be extremely cheap.
  51  * Larger sets reduce the possibility of sharing, and therefore revert
  52  * automatically to a less space-efficient implementation.
  53  * <p>
  54  * <strong>Warning:</strong>
  55  * Serialized objects of this class will not be compatible with
  56  * future Swing releases. The current serialization support is
  57  * appropriate for short term storage or RMI between applications running
  58  * the same version of Swing.  As of 1.4, support for long term storage
  59  * of all JavaBeans&trade;
  60  * has been added to the <code>java.beans</code> package.
  61  * Please see {@link java.beans.XMLEncoder}.
  62  *
  63  * @author  Timothy Prinzing
  64  */
  65 @SuppressWarnings("serial") // Same-version serialization only
  66 public class StyleContext implements Serializable, AbstractDocument.AttributeContext {
  67 
  68     /**
  69      * Returns default AttributeContext shared by all documents that
  70      * don't bother to define/supply their own context.
  71      *
  72      * @return the context
  73      */
  74     public static final StyleContext getDefaultStyleContext() {
  75         if (defaultContext == null) {
  76             defaultContext = new StyleContext();
  77         }
  78         return defaultContext;
  79     }
  80 


 145      * Adds a listener to track when styles are added
 146      * or removed.
 147      *
 148      * @param l the change listener
 149      */
 150     public void addChangeListener(ChangeListener l) {
 151         styles.addChangeListener(l);
 152     }
 153 
 154     /**
 155      * Removes a listener that was tracking styles being
 156      * added or removed.
 157      *
 158      * @param l the change listener
 159      */
 160     public void removeChangeListener(ChangeListener l) {
 161         styles.removeChangeListener(l);
 162     }
 163 
 164     /**
 165      * Returns an array of all the <code>ChangeListener</code>s added
 166      * to this StyleContext with addChangeListener().
 167      *
 168      * @return all of the <code>ChangeListener</code>s added or an empty
 169      *         array if no listeners have been added
 170      * @since 1.4
 171      */
 172     public ChangeListener[] getChangeListeners() {
 173         return ((NamedStyle)styles).getChangeListeners();
 174     }
 175 
 176     /**
 177      * Gets the font from an attribute set.  This is
 178      * implemented to try and fetch a cached font
 179      * for the given AttributeSet, and if that fails
 180      * the font features are resolved and the
 181      * font is fetched from the low-level font cache.
 182      *
 183      * @param attr the attribute set
 184      * @return the font
 185      */
 186     public Font getFont(AttributeSet attr) {
 187         // PENDING(prinz) add cache behavior
 188         int style = Font.PLAIN;


 572     /**
 573      * Context-specific handling of reading in attributes
 574      * @param in the object stream to read the attribute data from.
 575      * @param a  the attribute set to place the attribute
 576      *   definitions in.
 577      * @exception ClassNotFoundException passed upward if encountered
 578      *  when reading the object stream.
 579      * @exception IOException passed upward if encountered when
 580      *  reading the object stream.
 581      */
 582     public void readAttributes(ObjectInputStream in,
 583                                MutableAttributeSet a) throws ClassNotFoundException, IOException {
 584         readAttributeSet(in, a);
 585     }
 586 
 587     /**
 588      * Writes a set of attributes to the given object stream
 589      * for the purpose of serialization.  This will take
 590      * special care to deal with static attribute keys that
 591      * have been registered wit the
 592      * <code>registerStaticAttributeKey</code> method.
 593      * Any attribute key not registered as a static key
 594      * will be serialized directly.  All values are expected
 595      * to be serializable.
 596      *
 597      * @param out the output stream
 598      * @param a the attribute set
 599      * @exception IOException on any I/O error
 600      */
 601     public static void writeAttributeSet(ObjectOutputStream out,
 602                                          AttributeSet a) throws IOException {
 603         int n = a.getAttributeCount();
 604         out.writeInt(n);
 605         Enumeration<?> keys = a.getAttributeNames();
 606         while (keys.hasMoreElements()) {
 607             Object key = keys.nextElement();
 608             if (key instanceof Serializable) {
 609                 out.writeObject(key);
 610             } else {
 611                 Object ioFmt = freezeKeyMap.get(key);
 612                 if (ioFmt == null) {


 615                 }
 616                 out.writeObject(ioFmt);
 617             }
 618             Object value = a.getAttribute(key);
 619             Object ioFmt = freezeKeyMap.get(value);
 620             if (value instanceof Serializable) {
 621                 out.writeObject((ioFmt != null) ? ioFmt : value);
 622             } else {
 623                 if (ioFmt == null) {
 624                     throw new NotSerializableException(value.getClass().
 625                                  getName() + " is not serializable as a value in an AttributeSet");
 626                 }
 627                 out.writeObject(ioFmt);
 628             }
 629         }
 630     }
 631 
 632     /**
 633      * Reads a set of attributes from the given object input
 634      * stream that have been previously written out with
 635      * <code>writeAttributeSet</code>.  This will try to restore
 636      * keys that were static objects to the static objects in
 637      * the current virtual machine considering only those keys
 638      * that have been registered with the
 639      * <code>registerStaticAttributeKey</code> method.
 640      * The attributes retrieved from the stream will be placed
 641      * into the given mutable set.
 642      *
 643      * @param in the object stream to read the attribute data from.
 644      * @param a  the attribute set to place the attribute
 645      *   definitions in.
 646      * @exception ClassNotFoundException passed upward if encountered
 647      *  when reading the object stream.
 648      * @exception IOException passed upward if encountered when
 649      *  reading the object stream.
 650      */
 651     public static void readAttributeSet(ObjectInputStream in,
 652         MutableAttributeSet a) throws ClassNotFoundException, IOException {
 653 
 654         int n = in.readInt();
 655         for (int i = 0; i < n; i++) {
 656             Object key = in.readObject();
 657             Object value = in.readObject();
 658             if (thawKeyMap != null) {
 659                 Object staticKey = thawKeyMap.get(key);
 660                 if (staticKey != null) {
 661                     key = staticKey;
 662                 }
 663                 Object staticValue = thawKeyMap.get(value);
 664                 if (staticValue != null) {
 665                     value = staticValue;
 666                 }
 667             }
 668             a.addAttribute(key, value);
 669         }
 670     }
 671 
 672     /**
 673      * Registers an object as a static object that is being
 674      * used as a key in attribute sets.  This allows the key
 675      * to be treated specially for serialization.
 676      * <p>
 677      * For operation under a 1.1 virtual machine, this
 678      * uses the value returned by <code>toString</code>
 679      * concatenated to the classname.  The value returned
 680      * by toString should not have the class reference
 681      * in it (ie it should be reimplemented from the
 682      * definition in Object) in order to be the same when
 683      * recomputed later.
 684      *
 685      * @param key the non-null object key
 686      */
 687     public static void registerStaticAttributeKey(Object key) {
 688         String ioFmt = key.getClass().getName() + "." + key.toString();
 689         if (freezeKeyMap == null) {
 690             freezeKeyMap = new Hashtable<Object, String>();
 691             thawKeyMap = new Hashtable<String, Object>();
 692         }
 693         freezeKeyMap.put(key, ioFmt);
 694         thawKeyMap.put(ioFmt, key);
 695     }
 696 
 697     /**
 698      * Returns the object previously registered with
 699      * <code>registerStaticAttributeKey</code>.
 700      * @param key the object key
 701      * @return Returns the object previously registered with
 702      * {@code registerStaticAttributeKey}
 703      */
 704     public static Object getStaticAttribute(Object key) {
 705         if (thawKeyMap == null || key == null) {
 706             return null;
 707         }
 708         return thawKeyMap.get(key);
 709     }
 710 
 711     /**
 712      * Returns the String that <code>key</code> will be registered with.
 713      * @see #getStaticAttribute
 714      * @see #registerStaticAttributeKey
 715      * @param key the object key
 716      * @return the String that {@code key} will be registered with
 717      */
 718     public static Object getStaticAttributeKey(Object key) {
 719         return key.getClass().getName() + "." + key.toString();
 720     }
 721 
 722     private void writeObject(java.io.ObjectOutputStream s)
 723         throws IOException
 724     {
 725         // clean out unused sets before saving
 726         removeUnusedSets();
 727 
 728         s.defaultWriteObject();
 729     }
 730 
 731     private void readObject(ObjectInputStream s)
 732       throws ClassNotFoundException, IOException


 859             }
 860             s = s + "}";
 861             return s;
 862         }
 863 
 864         /**
 865          * Returns a hashcode for this set of attributes.
 866          * @return     a hashcode value for this set of attributes.
 867          */
 868         public int hashCode() {
 869             int code = 0;
 870             Object[] tbl = attributes;
 871             for (int i = 1; i < tbl.length; i += 2) {
 872                 code ^= tbl[i].hashCode();
 873             }
 874             return code;
 875         }
 876 
 877         /**
 878          * Compares this object to the specified object.
 879          * The result is <code>true</code> if the object is an equivalent
 880          * set of attributes.
 881          * @param     obj   the object to compare with.
 882          * @return    <code>true</code> if the objects are equal;
 883          *            <code>false</code> otherwise.
 884          */
 885         public boolean equals(Object obj) {
 886             if (obj instanceof AttributeSet) {
 887                 AttributeSet attrs = (AttributeSet) obj;
 888                 return ((getAttributeCount() == attrs.getAttributeCount()) &&
 889                         containsAttributes(attrs));
 890             }
 891             return false;
 892         }
 893 
 894         /**
 895          * Clones a set of attributes.  Since the set is immutable, a
 896          * clone is basically the same set.
 897          *
 898          * @return the set of attributes
 899          */
 900         public Object clone() {
 901             return this;
 902         }
 903 


1029         // --- variables -----------------------------------------
1030 
1031         Object[] attributes;
1032         // This is also stored in attributes
1033         AttributeSet resolveParent;
1034     }
1035 
1036     /**
1037      * An enumeration of the keys in a SmallAttributeSet.
1038      */
1039     class KeyEnumeration implements Enumeration<Object> {
1040 
1041         KeyEnumeration(Object[] attr) {
1042             this.attr = attr;
1043             i = 0;
1044         }
1045 
1046         /**
1047          * Tests if this enumeration contains more elements.
1048          *
1049          * @return  <code>true</code> if this enumeration contains more elements;
1050          *          <code>false</code> otherwise.
1051          * @since   1.0
1052          */
1053         public boolean hasMoreElements() {
1054             return i < attr.length;
1055         }
1056 
1057         /**
1058          * Returns the next element of this enumeration.
1059          *
1060          * @return     the next element of this enumeration.
1061          * @exception  NoSuchElementException  if no more elements exist.
1062          * @since      1.0
1063          */
1064         public Object nextElement() {
1065             if (i < attr.length) {
1066                 Object o = attr[i];
1067                 i += 2;
1068                 return o;
1069             }
1070             throw new NoSuchElementException();


1229             setValue(family, style, size);
1230         }
1231 
1232         public void setValue(String family, int style, int size) {
1233             this.family = (family != null) ? family.intern() : null;
1234             this.style = style;
1235             this.size = size;
1236         }
1237 
1238         /**
1239          * Returns a hashcode for this font.
1240          * @return     a hashcode value for this font.
1241          */
1242         public int hashCode() {
1243             int fhash = (family != null) ? family.hashCode() : 0;
1244             return fhash ^ style ^ size;
1245         }
1246 
1247         /**
1248          * Compares this object to the specified object.
1249          * The result is <code>true</code> if and only if the argument is not
1250          * <code>null</code> and is a <code>Font</code> object with the same
1251          * name, style, and point size as this font.
1252          * @param     obj   the object to compare this font with.
1253          * @return    <code>true</code> if the objects are equal;
1254          *            <code>false</code> otherwise.
1255          */
1256         public boolean equals(Object obj) {
1257             if (obj instanceof FontKey) {
1258                 FontKey font = (FontKey)obj;
1259                 return (size == font.size) && (style == font.style) && (family == font.family);
1260             }
1261             return false;
1262         }
1263 
1264     }
1265 
1266     /**
1267      * A collection of attributes, typically used to represent
1268      * character and paragraph styles.  This is an implementation
1269      * of MutableAttributeSet that can be observed if desired.
1270      * These styles will take advantage of immutability while
1271      * the sets are small enough, and may be substantially more
1272      * efficient than something like SimpleAttributeSet.
1273      * <p>
1274      * <strong>Warning:</strong>
1275      * Serialized objects of this class will not be compatible with
1276      * future Swing releases. The current serialization support is
1277      * appropriate for short term storage or RMI between applications running
1278      * the same version of Swing.  As of 1.4, support for long term storage
1279      * of all JavaBeans&trade;
1280      * has been added to the <code>java.beans</code> package.
1281      * Please see {@link java.beans.XMLEncoder}.
1282      */
1283     @SuppressWarnings("serial") // Same-version serialization only
1284     public class NamedStyle implements Style, Serializable {
1285 
1286         /**
1287          * Creates a new named style.
1288          *
1289          * @param name the style name, null for unnamed
1290          * @param parent the parent style, null if none
1291          * @since 1.4
1292          */
1293         public NamedStyle(String name, Style parent) {
1294             attributes = getEmptySet();
1295             if (name != null) {
1296                 setName(name);
1297             }
1298             if (parent != null) {
1299                 setResolveParent(parent);
1300             }


1353         /**
1354          * Adds a change listener.
1355          *
1356          * @param l the change listener
1357          */
1358         public void addChangeListener(ChangeListener l) {
1359             listenerList.add(ChangeListener.class, l);
1360         }
1361 
1362         /**
1363          * Removes a change listener.
1364          *
1365          * @param l the change listener
1366          */
1367         public void removeChangeListener(ChangeListener l) {
1368             listenerList.remove(ChangeListener.class, l);
1369         }
1370 
1371 
1372         /**
1373          * Returns an array of all the <code>ChangeListener</code>s added
1374          * to this NamedStyle with addChangeListener().
1375          *
1376          * @return all of the <code>ChangeListener</code>s added or an empty
1377          *         array if no listeners have been added
1378          * @since 1.4
1379          */
1380         public ChangeListener[] getChangeListeners() {
1381             return listenerList.getListeners(ChangeListener.class);
1382         }
1383 
1384 
1385         /**
1386          * Notifies all listeners that have registered interest for
1387          * notification on this event type.  The event instance
1388          * is lazily created using the parameters passed into
1389          * the fire method.
1390          *
1391          * @see EventListenerList
1392          */
1393         protected void fireStateChanged() {
1394             // Guaranteed to return a non-null array
1395             Object[] listeners = listenerList.getListenerList();
1396             // Process the listeners last to first, notifying




  40 /**
  41  * A pool of styles and their associated resources.  This class determines
  42  * the lifetime of a group of resources by being a container that holds
  43  * caches for various resources such as font and color that get reused
  44  * by the various style definitions.  This can be shared by multiple
  45  * documents if desired to maximize the sharing of related resources.
  46  * <p>
  47  * This class also provides efficient support for small sets of attributes
  48  * and compresses them by sharing across uses and taking advantage of
  49  * their immutable nature.  Since many styles are replicated, the potential
  50  * for sharing is significant, and copies can be extremely cheap.
  51  * Larger sets reduce the possibility of sharing, and therefore revert
  52  * automatically to a less space-efficient implementation.
  53  * <p>
  54  * <strong>Warning:</strong>
  55  * Serialized objects of this class will not be compatible with
  56  * future Swing releases. The current serialization support is
  57  * appropriate for short term storage or RMI between applications running
  58  * the same version of Swing.  As of 1.4, support for long term storage
  59  * of all JavaBeans&trade;
  60  * has been added to the {@code java.beans} package.
  61  * Please see {@link java.beans.XMLEncoder}.
  62  *
  63  * @author  Timothy Prinzing
  64  */
  65 @SuppressWarnings("serial") // Same-version serialization only
  66 public class StyleContext implements Serializable, AbstractDocument.AttributeContext {
  67 
  68     /**
  69      * Returns default AttributeContext shared by all documents that
  70      * don't bother to define/supply their own context.
  71      *
  72      * @return the context
  73      */
  74     public static final StyleContext getDefaultStyleContext() {
  75         if (defaultContext == null) {
  76             defaultContext = new StyleContext();
  77         }
  78         return defaultContext;
  79     }
  80 


 145      * Adds a listener to track when styles are added
 146      * or removed.
 147      *
 148      * @param l the change listener
 149      */
 150     public void addChangeListener(ChangeListener l) {
 151         styles.addChangeListener(l);
 152     }
 153 
 154     /**
 155      * Removes a listener that was tracking styles being
 156      * added or removed.
 157      *
 158      * @param l the change listener
 159      */
 160     public void removeChangeListener(ChangeListener l) {
 161         styles.removeChangeListener(l);
 162     }
 163 
 164     /**
 165      * Returns an array of all the {@code ChangeListener}s added
 166      * to this StyleContext with addChangeListener().
 167      *
 168      * @return all of the {@code ChangeListener}s added or an empty
 169      *         array if no listeners have been added
 170      * @since 1.4
 171      */
 172     public ChangeListener[] getChangeListeners() {
 173         return ((NamedStyle)styles).getChangeListeners();
 174     }
 175 
 176     /**
 177      * Gets the font from an attribute set.  This is
 178      * implemented to try and fetch a cached font
 179      * for the given AttributeSet, and if that fails
 180      * the font features are resolved and the
 181      * font is fetched from the low-level font cache.
 182      *
 183      * @param attr the attribute set
 184      * @return the font
 185      */
 186     public Font getFont(AttributeSet attr) {
 187         // PENDING(prinz) add cache behavior
 188         int style = Font.PLAIN;


 572     /**
 573      * Context-specific handling of reading in attributes
 574      * @param in the object stream to read the attribute data from.
 575      * @param a  the attribute set to place the attribute
 576      *   definitions in.
 577      * @exception ClassNotFoundException passed upward if encountered
 578      *  when reading the object stream.
 579      * @exception IOException passed upward if encountered when
 580      *  reading the object stream.
 581      */
 582     public void readAttributes(ObjectInputStream in,
 583                                MutableAttributeSet a) throws ClassNotFoundException, IOException {
 584         readAttributeSet(in, a);
 585     }
 586 
 587     /**
 588      * Writes a set of attributes to the given object stream
 589      * for the purpose of serialization.  This will take
 590      * special care to deal with static attribute keys that
 591      * have been registered wit the
 592      * {@code registerStaticAttributeKey} method.
 593      * Any attribute key not registered as a static key
 594      * will be serialized directly.  All values are expected
 595      * to be serializable.
 596      *
 597      * @param out the output stream
 598      * @param a the attribute set
 599      * @exception IOException on any I/O error
 600      */
 601     public static void writeAttributeSet(ObjectOutputStream out,
 602                                          AttributeSet a) throws IOException {
 603         int n = a.getAttributeCount();
 604         out.writeInt(n);
 605         Enumeration<?> keys = a.getAttributeNames();
 606         while (keys.hasMoreElements()) {
 607             Object key = keys.nextElement();
 608             if (key instanceof Serializable) {
 609                 out.writeObject(key);
 610             } else {
 611                 Object ioFmt = freezeKeyMap.get(key);
 612                 if (ioFmt == null) {


 615                 }
 616                 out.writeObject(ioFmt);
 617             }
 618             Object value = a.getAttribute(key);
 619             Object ioFmt = freezeKeyMap.get(value);
 620             if (value instanceof Serializable) {
 621                 out.writeObject((ioFmt != null) ? ioFmt : value);
 622             } else {
 623                 if (ioFmt == null) {
 624                     throw new NotSerializableException(value.getClass().
 625                                  getName() + " is not serializable as a value in an AttributeSet");
 626                 }
 627                 out.writeObject(ioFmt);
 628             }
 629         }
 630     }
 631 
 632     /**
 633      * Reads a set of attributes from the given object input
 634      * stream that have been previously written out with
 635      * {@code writeAttributeSet}.  This will try to restore
 636      * keys that were static objects to the static objects in
 637      * the current virtual machine considering only those keys
 638      * that have been registered with the
 639      * {@code registerStaticAttributeKey} method.
 640      * The attributes retrieved from the stream will be placed
 641      * into the given mutable set.
 642      *
 643      * @param in the object stream to read the attribute data from.
 644      * @param a  the attribute set to place the attribute
 645      *   definitions in.
 646      * @exception ClassNotFoundException passed upward if encountered
 647      *  when reading the object stream.
 648      * @exception IOException passed upward if encountered when
 649      *  reading the object stream.
 650      */
 651     public static void readAttributeSet(ObjectInputStream in,
 652         MutableAttributeSet a) throws ClassNotFoundException, IOException {
 653 
 654         int n = in.readInt();
 655         for (int i = 0; i < n; i++) {
 656             Object key = in.readObject();
 657             Object value = in.readObject();
 658             if (thawKeyMap != null) {
 659                 Object staticKey = thawKeyMap.get(key);
 660                 if (staticKey != null) {
 661                     key = staticKey;
 662                 }
 663                 Object staticValue = thawKeyMap.get(value);
 664                 if (staticValue != null) {
 665                     value = staticValue;
 666                 }
 667             }
 668             a.addAttribute(key, value);
 669         }
 670     }
 671 
 672     /**
 673      * Registers an object as a static object that is being
 674      * used as a key in attribute sets.  This allows the key
 675      * to be treated specially for serialization.
 676      * <p>
 677      * For operation under a 1.1 virtual machine, this
 678      * uses the value returned by {@code toString}
 679      * concatenated to the classname.  The value returned
 680      * by toString should not have the class reference
 681      * in it (ie it should be reimplemented from the
 682      * definition in Object) in order to be the same when
 683      * recomputed later.
 684      *
 685      * @param key the non-null object key
 686      */
 687     public static void registerStaticAttributeKey(Object key) {
 688         String ioFmt = key.getClass().getName() + "." + key.toString();
 689         if (freezeKeyMap == null) {
 690             freezeKeyMap = new Hashtable<Object, String>();
 691             thawKeyMap = new Hashtable<String, Object>();
 692         }
 693         freezeKeyMap.put(key, ioFmt);
 694         thawKeyMap.put(ioFmt, key);
 695     }
 696 
 697     /**
 698      * Returns the object previously registered with
 699      * {@code registerStaticAttributeKey}.
 700      * @param key the object key
 701      * @return Returns the object previously registered with
 702      * {@code registerStaticAttributeKey}
 703      */
 704     public static Object getStaticAttribute(Object key) {
 705         if (thawKeyMap == null || key == null) {
 706             return null;
 707         }
 708         return thawKeyMap.get(key);
 709     }
 710 
 711     /**
 712      * Returns the String that {@code key} will be registered with.
 713      * @see #getStaticAttribute
 714      * @see #registerStaticAttributeKey
 715      * @param key the object key
 716      * @return the String that {@code key} will be registered with
 717      */
 718     public static Object getStaticAttributeKey(Object key) {
 719         return key.getClass().getName() + "." + key.toString();
 720     }
 721 
 722     private void writeObject(java.io.ObjectOutputStream s)
 723         throws IOException
 724     {
 725         // clean out unused sets before saving
 726         removeUnusedSets();
 727 
 728         s.defaultWriteObject();
 729     }
 730 
 731     private void readObject(ObjectInputStream s)
 732       throws ClassNotFoundException, IOException


 859             }
 860             s = s + "}";
 861             return s;
 862         }
 863 
 864         /**
 865          * Returns a hashcode for this set of attributes.
 866          * @return     a hashcode value for this set of attributes.
 867          */
 868         public int hashCode() {
 869             int code = 0;
 870             Object[] tbl = attributes;
 871             for (int i = 1; i < tbl.length; i += 2) {
 872                 code ^= tbl[i].hashCode();
 873             }
 874             return code;
 875         }
 876 
 877         /**
 878          * Compares this object to the specified object.
 879          * The result is {@code true} if the object is an equivalent
 880          * set of attributes.
 881          * @param     obj   the object to compare with.
 882          * @return    {@code true} if the objects are equal;
 883          *            {@code false} otherwise.
 884          */
 885         public boolean equals(Object obj) {
 886             if (obj instanceof AttributeSet) {
 887                 AttributeSet attrs = (AttributeSet) obj;
 888                 return ((getAttributeCount() == attrs.getAttributeCount()) &&
 889                         containsAttributes(attrs));
 890             }
 891             return false;
 892         }
 893 
 894         /**
 895          * Clones a set of attributes.  Since the set is immutable, a
 896          * clone is basically the same set.
 897          *
 898          * @return the set of attributes
 899          */
 900         public Object clone() {
 901             return this;
 902         }
 903 


1029         // --- variables -----------------------------------------
1030 
1031         Object[] attributes;
1032         // This is also stored in attributes
1033         AttributeSet resolveParent;
1034     }
1035 
1036     /**
1037      * An enumeration of the keys in a SmallAttributeSet.
1038      */
1039     class KeyEnumeration implements Enumeration<Object> {
1040 
1041         KeyEnumeration(Object[] attr) {
1042             this.attr = attr;
1043             i = 0;
1044         }
1045 
1046         /**
1047          * Tests if this enumeration contains more elements.
1048          *
1049          * @return  {@code true} if this enumeration contains more elements;
1050          *          {@code false} otherwise.
1051          * @since   1.0
1052          */
1053         public boolean hasMoreElements() {
1054             return i < attr.length;
1055         }
1056 
1057         /**
1058          * Returns the next element of this enumeration.
1059          *
1060          * @return     the next element of this enumeration.
1061          * @exception  NoSuchElementException  if no more elements exist.
1062          * @since      1.0
1063          */
1064         public Object nextElement() {
1065             if (i < attr.length) {
1066                 Object o = attr[i];
1067                 i += 2;
1068                 return o;
1069             }
1070             throw new NoSuchElementException();


1229             setValue(family, style, size);
1230         }
1231 
1232         public void setValue(String family, int style, int size) {
1233             this.family = (family != null) ? family.intern() : null;
1234             this.style = style;
1235             this.size = size;
1236         }
1237 
1238         /**
1239          * Returns a hashcode for this font.
1240          * @return     a hashcode value for this font.
1241          */
1242         public int hashCode() {
1243             int fhash = (family != null) ? family.hashCode() : 0;
1244             return fhash ^ style ^ size;
1245         }
1246 
1247         /**
1248          * Compares this object to the specified object.
1249          * The result is {@code true} if and only if the argument is not
1250          * {@code null} and is a {@code Font} object with the same
1251          * name, style, and point size as this font.
1252          * @param     obj   the object to compare this font with.
1253          * @return    {@code true} if the objects are equal;
1254          *            {@code false} otherwise.
1255          */
1256         public boolean equals(Object obj) {
1257             if (obj instanceof FontKey) {
1258                 FontKey font = (FontKey)obj;
1259                 return (size == font.size) && (style == font.style) && (family == font.family);
1260             }
1261             return false;
1262         }
1263 
1264     }
1265 
1266     /**
1267      * A collection of attributes, typically used to represent
1268      * character and paragraph styles.  This is an implementation
1269      * of MutableAttributeSet that can be observed if desired.
1270      * These styles will take advantage of immutability while
1271      * the sets are small enough, and may be substantially more
1272      * efficient than something like SimpleAttributeSet.
1273      * <p>
1274      * <strong>Warning:</strong>
1275      * Serialized objects of this class will not be compatible with
1276      * future Swing releases. The current serialization support is
1277      * appropriate for short term storage or RMI between applications running
1278      * the same version of Swing.  As of 1.4, support for long term storage
1279      * of all JavaBeans&trade;
1280      * has been added to the {@code java.beans} package.
1281      * Please see {@link java.beans.XMLEncoder}.
1282      */
1283     @SuppressWarnings("serial") // Same-version serialization only
1284     public class NamedStyle implements Style, Serializable {
1285 
1286         /**
1287          * Creates a new named style.
1288          *
1289          * @param name the style name, null for unnamed
1290          * @param parent the parent style, null if none
1291          * @since 1.4
1292          */
1293         public NamedStyle(String name, Style parent) {
1294             attributes = getEmptySet();
1295             if (name != null) {
1296                 setName(name);
1297             }
1298             if (parent != null) {
1299                 setResolveParent(parent);
1300             }


1353         /**
1354          * Adds a change listener.
1355          *
1356          * @param l the change listener
1357          */
1358         public void addChangeListener(ChangeListener l) {
1359             listenerList.add(ChangeListener.class, l);
1360         }
1361 
1362         /**
1363          * Removes a change listener.
1364          *
1365          * @param l the change listener
1366          */
1367         public void removeChangeListener(ChangeListener l) {
1368             listenerList.remove(ChangeListener.class, l);
1369         }
1370 
1371 
1372         /**
1373          * Returns an array of all the {@code ChangeListener}s added
1374          * to this NamedStyle with addChangeListener().
1375          *
1376          * @return all of the {@code ChangeListener}s added or an empty
1377          *         array if no listeners have been added
1378          * @since 1.4
1379          */
1380         public ChangeListener[] getChangeListeners() {
1381             return listenerList.getListeners(ChangeListener.class);
1382         }
1383 
1384 
1385         /**
1386          * Notifies all listeners that have registered interest for
1387          * notification on this event type.  The event instance
1388          * is lazily created using the parameters passed into
1389          * the fire method.
1390          *
1391          * @see EventListenerList
1392          */
1393         protected void fireStateChanged() {
1394             // Guaranteed to return a non-null array
1395             Object[] listeners = listenerList.getListenerList();
1396             // Process the listeners last to first, notifying


< prev index next >