1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52:
53: import ;
54: import ;
55: import ;
56:
57: public class StyleContext
58: implements Serializable, AbstractDocument.AttributeContext
59: {
60:
61: private static final long serialVersionUID = 8042858831190784241L;
62:
63: public class NamedStyle
64: implements Serializable, Style
65: {
66:
67: private static final long serialVersionUID = -6690628971806226374L;
68:
69: protected ChangeEvent changeEvent;
70: protected EventListenerList listenerList;
71:
72: AttributeSet attributes;
73: String name;
74:
75: public NamedStyle()
76: {
77: this(null, null);
78: }
79:
80: public NamedStyle(Style parent)
81: {
82: this(null, parent);
83: }
84:
85: public NamedStyle(String name, Style parent)
86: {
87: this.name = name;
88: this.attributes = getEmptySet();
89: this.changeEvent = new ChangeEvent(this);
90: this.listenerList = new EventListenerList();
91: setResolveParent(parent);
92: }
93:
94: public String getName()
95: {
96: return name;
97: }
98:
99: public void setName(String n)
100: {
101: name = n;
102: fireStateChanged();
103: }
104:
105: public void addChangeListener(ChangeListener l)
106: {
107: listenerList.add(ChangeListener.class, l);
108: }
109:
110: public void removeChangeListener(ChangeListener l)
111: {
112: listenerList.remove(ChangeListener.class, l);
113: }
114:
115: public EventListener[] getListeners(Class listenerType)
116: {
117: return listenerList.getListeners(listenerType);
118: }
119:
120: public ChangeListener[] getChangeListeners()
121: {
122: return (ChangeListener[]) getListeners(ChangeListener.class);
123: }
124:
125: protected void fireStateChanged()
126: {
127: ChangeListener[] listeners = getChangeListeners();
128: for (int i = 0; i < listeners.length; ++i)
129: {
130: listeners[i].stateChanged(changeEvent);
131: }
132: }
133:
134: public void addAttribute(Object name, Object value)
135: {
136: attributes = StyleContext.this.addAttribute(attributes, name, value);
137: fireStateChanged();
138: }
139:
140: public void addAttributes(AttributeSet attr)
141: {
142: attributes = StyleContext.this.addAttributes(attributes, attr);
143: fireStateChanged();
144: }
145:
146: public boolean containsAttribute(Object name, Object value)
147: {
148: return attributes.containsAttribute(name, value);
149: }
150:
151: public boolean containsAttributes(AttributeSet attrs)
152: {
153: return attributes.containsAttributes(attrs);
154: }
155:
156: public AttributeSet copyAttributes()
157: {
158: return attributes.copyAttributes();
159: }
160:
161: public Object getAttribute(Object attrName)
162: {
163: return attributes.getAttribute(attrName);
164: }
165:
166: public int getAttributeCount()
167: {
168: return attributes.getAttributeCount();
169: }
170:
171: public Enumeration getAttributeNames()
172: {
173: return attributes.getAttributeNames();
174: }
175:
176: public boolean isDefined(Object attrName)
177: {
178: return attributes.isDefined(attrName);
179: }
180:
181: public boolean isEqual(AttributeSet attr)
182: {
183: return attributes.isEqual(attr);
184: }
185:
186: public void removeAttribute(Object name)
187: {
188: attributes = StyleContext.this.removeAttribute(attributes, name);
189: fireStateChanged();
190: }
191:
192: public void removeAttributes(AttributeSet attrs)
193: {
194: attributes = StyleContext.this.removeAttributes(attributes, attrs);
195: fireStateChanged();
196: }
197:
198: public void removeAttributes(Enumeration names)
199: {
200: attributes = StyleContext.this.removeAttributes(attributes, names);
201: fireStateChanged();
202: }
203:
204:
205: public AttributeSet getResolveParent()
206: {
207: return attributes.getResolveParent();
208: }
209:
210: public void setResolveParent(AttributeSet parent)
211: {
212: if (parent != null)
213: {
214: attributes = StyleContext.this.addAttribute
215: (attributes, ResolveAttribute, parent);
216: }
217: fireStateChanged();
218: }
219:
220: public String toString()
221: {
222: return ("[NamedStyle: name=" + name + ", attrs=" + attributes.toString() + "]");
223: }
224: }
225:
226: public class SmallAttributeSet
227: implements AttributeSet
228: {
229: final Object [] attrs;
230: public SmallAttributeSet(AttributeSet a)
231: {
232: if (a == null)
233: attrs = new Object[0];
234: else
235: {
236: int n = a.getAttributeCount();
237: int i = 0;
238: attrs = new Object[n * 2];
239: Enumeration e = a.getAttributeNames();
240: while (e.hasMoreElements())
241: {
242: Object name = e.nextElement();
243: attrs[i++] = name;
244: attrs[i++] = a.getAttribute(name);
245: }
246: }
247: }
248:
249: public SmallAttributeSet(Object [] a)
250: {
251: if (a == null)
252: attrs = new Object[0];
253: else
254: {
255: attrs = new Object[a.length];
256: System.arraycopy(a, 0, attrs, 0, a.length);
257: }
258: }
259:
260: public Object clone()
261: {
262: return new SmallAttributeSet(this.attrs);
263: }
264:
265: public boolean containsAttribute(Object name, Object value)
266: {
267: for (int i = 0; i < attrs.length; i += 2)
268: {
269: if (attrs[i].equals(name) &&
270: attrs[i+1].equals(value))
271: return true;
272: }
273: return false;
274: }
275:
276: public boolean containsAttributes(AttributeSet a)
277: {
278: Enumeration e = a.getAttributeNames();
279: while (e.hasMoreElements())
280: {
281: Object name = e.nextElement();
282: Object val = a.getAttribute(name);
283: if (!containsAttribute(name, val))
284: return false;
285: }
286: return true;
287: }
288:
289: public AttributeSet copyAttributes()
290: {
291: return (AttributeSet) clone();
292: }
293:
294: public boolean equals(Object obj)
295: {
296: return
297: (obj instanceof AttributeSet)
298: && this.isEqual((AttributeSet)obj);
299: }
300:
301: public Object getAttribute(Object key)
302: {
303: for (int i = 0; i < attrs.length; i += 2)
304: {
305: if (attrs[i].equals(key))
306: return attrs[i+1];
307: }
308:
309:
310:
311: if (!(key.equals(ResolveAttribute)))
312: {
313: Object p = getResolveParent();
314: if (p != null && p instanceof AttributeSet)
315: return (((AttributeSet)p).getAttribute(key));
316: }
317:
318: return null;
319: }
320:
321: public int getAttributeCount()
322: {
323: return attrs.length / 2;
324: }
325:
326: public Enumeration getAttributeNames()
327: {
328: return new Enumeration()
329: {
330: int i = 0;
331: public boolean hasMoreElements()
332: {
333: return i < attrs.length;
334: }
335: public Object nextElement()
336: {
337: i += 2;
338: return attrs[i-2];
339: }
340: };
341: }
342:
343: public AttributeSet getResolveParent()
344: {
345: return (AttributeSet) getAttribute(ResolveAttribute);
346: }
347:
348: public int hashCode()
349: {
350: return java.util.Arrays.asList(attrs).hashCode();
351: }
352:
353: public boolean isDefined(Object key)
354: {
355: for (int i = 0; i < attrs.length; i += 2)
356: {
357: if (attrs[i].equals(key))
358: return true;
359: }
360: return false;
361: }
362:
363: public boolean isEqual(AttributeSet attr)
364: {
365: return getAttributeCount() == attr.getAttributeCount()
366: && this.containsAttributes(attr);
367: }
368:
369: public String toString()
370: {
371: StringBuffer sb = new StringBuffer();
372: sb.append("[StyleContext.SmallattributeSet:");
373: for (int i = 0; i < attrs.length - 1; ++i)
374: {
375: sb.append(" (");
376: sb.append(attrs[i].toString());
377: sb.append("=");
378: sb.append(attrs[i+1].toString());
379: sb.append(")");
380: }
381: sb.append("]");
382: return sb.toString();
383: }
384: }
385:
386:
387:
388:
389:
390:
391:
392:
393:
394:
397: public static final String DEFAULT_STYLE = "default";
398:
399:
402: NamedStyle defaultStyle = new NamedStyle(DEFAULT_STYLE, null);
403:
404: static Hashtable sharedAttributeSets = new Hashtable();
405: static Hashtable sharedFonts = new Hashtable();
406:
407: static StyleContext defaultStyleContext = new StyleContext();
408: static final int compressionThreshold = 9;
409:
410:
413: private static Hashtable staticAttributeKeys = new Hashtable();
414:
415: EventListenerList listenerList;
416: Hashtable styleTable;
417:
418:
422: public StyleContext()
423: {
424: listenerList = new EventListenerList();
425: styleTable = new Hashtable();
426: styleTable.put(DEFAULT_STYLE, defaultStyle);
427: }
428:
429: protected SmallAttributeSet createSmallAttributeSet(AttributeSet a)
430: {
431: return new SmallAttributeSet(a);
432: }
433:
434: protected MutableAttributeSet createLargeAttributeSet(AttributeSet a)
435: {
436: return new SimpleAttributeSet(a);
437: }
438:
439: public void addChangeListener(ChangeListener listener)
440: {
441: listenerList.add(ChangeListener.class, listener);
442: }
443:
444: public void removeChangeListener(ChangeListener listener)
445: {
446: listenerList.remove(ChangeListener.class, listener);
447: }
448:
449: public ChangeListener[] getChangeListeners()
450: {
451: return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
452: }
453:
454: public Style addStyle(String name, Style parent)
455: {
456: Style newStyle = new NamedStyle(name, parent);
457: if (name != null)
458: styleTable.put(name, newStyle);
459: return newStyle;
460: }
461:
462: public void removeStyle(String name)
463: {
464: styleTable.remove(name);
465: }
466:
467:
477: public Style getStyle(String name)
478: {
479: return (Style) styleTable.get(name);
480: }
481:
482:
486: public Enumeration getStyleNames()
487: {
488: return styleTable.keys();
489: }
490:
491:
492:
493:
494:
495:
496:
497:
498:
499:
500:
501:
502:
503:
504:
505:
506: private static class SimpleFontSpec
507: {
508: String family;
509: int style;
510: int size;
511: public SimpleFontSpec(String family,
512: int style,
513: int size)
514: {
515: this.family = family;
516: this.style = style;
517: this.size = size;
518: }
519: public boolean equals(Object obj)
520: {
521: return (obj != null)
522: && (obj instanceof SimpleFontSpec)
523: && (((SimpleFontSpec)obj).family.equals(this.family))
524: && (((SimpleFontSpec)obj).style == this.style)
525: && (((SimpleFontSpec)obj).size == this.size);
526: }
527: public int hashCode()
528: {
529: return family.hashCode() + style + size;
530: }
531: }
532:
533: public Font getFont(AttributeSet attr)
534: {
535: String family = StyleConstants.getFontFamily(attr);
536: int style = Font.PLAIN;
537: if (StyleConstants.isBold(attr))
538: style += Font.BOLD;
539: if (StyleConstants.isItalic(attr))
540: style += Font.ITALIC;
541: int size = StyleConstants.getFontSize(attr);
542: return getFont(family, style, size);
543: }
544:
545: public Font getFont(String family, int style, int size)
546: {
547: SimpleFontSpec spec = new SimpleFontSpec(family, style, size);
548: if (sharedFonts.containsKey(spec))
549: return (Font) sharedFonts.get(spec);
550: else
551: {
552: Font tmp = new Font(family, style, size);
553: sharedFonts.put(spec, tmp);
554: return tmp;
555: }
556: }
557:
558: public FontMetrics getFontMetrics(Font f)
559: {
560: return Toolkit.getDefaultToolkit().getFontMetrics(f);
561: }
562:
563: public Color getForeground(AttributeSet a)
564: {
565: return StyleConstants.getForeground(a);
566: }
567:
568: public Color getBackground(AttributeSet a)
569: {
570: return StyleConstants.getBackground(a);
571: }
572:
573: protected int getCompressionThreshold()
574: {
575: return compressionThreshold;
576: }
577:
578: public static StyleContext getDefaultStyleContext()
579: {
580: return defaultStyleContext;
581: }
582:
583: public AttributeSet addAttribute(AttributeSet old, Object name, Object value)
584: {
585: if (old instanceof MutableAttributeSet)
586: {
587: ((MutableAttributeSet)old).addAttribute(name, value);
588: return old;
589: }
590: else
591: {
592: MutableAttributeSet mutable = createLargeAttributeSet(old);
593: mutable.addAttribute(name, value);
594: if (mutable.getAttributeCount() >= getCompressionThreshold())
595: return mutable;
596: else
597: {
598: SmallAttributeSet small = createSmallAttributeSet(mutable);
599: if (sharedAttributeSets.containsKey(small))
600: small = (SmallAttributeSet) sharedAttributeSets.get(small);
601: else
602: sharedAttributeSets.put(small,small);
603: return small;
604: }
605: }
606: }
607:
608: public AttributeSet addAttributes(AttributeSet old, AttributeSet attributes)
609: {
610: if (old instanceof MutableAttributeSet)
611: {
612: ((MutableAttributeSet)old).addAttributes(attributes);
613: return old;
614: }
615: else
616: {
617: MutableAttributeSet mutable = createLargeAttributeSet(old);
618: mutable.addAttributes(attributes);
619: if (mutable.getAttributeCount() >= getCompressionThreshold())
620: return mutable;
621: else
622: {
623: SmallAttributeSet small = createSmallAttributeSet(mutable);
624: if (sharedAttributeSets.containsKey(small))
625: small = (SmallAttributeSet) sharedAttributeSets.get(small);
626: else
627: sharedAttributeSets.put(small,small);
628: return small;
629: }
630: }
631: }
632:
633: public AttributeSet getEmptySet()
634: {
635: AttributeSet e = createSmallAttributeSet(null);
636: if (sharedAttributeSets.containsKey(e))
637: e = (AttributeSet) sharedAttributeSets.get(e);
638: else
639: sharedAttributeSets.put(e, e);
640: return e;
641: }
642:
643: public void reclaim(AttributeSet attributes)
644: {
645: if (sharedAttributeSets.containsKey(attributes))
646: sharedAttributeSets.remove(attributes);
647: }
648:
649: public AttributeSet removeAttribute(AttributeSet old, Object name)
650: {
651: if (old instanceof MutableAttributeSet)
652: {
653: ((MutableAttributeSet)old).removeAttribute(name);
654: if (old.getAttributeCount() < getCompressionThreshold())
655: {
656: SmallAttributeSet small = createSmallAttributeSet(old);
657: if (!sharedAttributeSets.containsKey(small))
658: sharedAttributeSets.put(small,small);
659: old = (AttributeSet) sharedAttributeSets.get(small);
660: }
661: return old;
662: }
663: else
664: {
665: MutableAttributeSet mutable = createLargeAttributeSet(old);
666: mutable.removeAttribute(name);
667: SmallAttributeSet small = createSmallAttributeSet(mutable);
668: if (sharedAttributeSets.containsKey(small))
669: small = (SmallAttributeSet) sharedAttributeSets.get(small);
670: else
671: sharedAttributeSets.put(small,small);
672: return small;
673: }
674: }
675:
676: public AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes)
677: {
678: return removeAttributes(old, attributes.getAttributeNames());
679: }
680:
681: public AttributeSet removeAttributes(AttributeSet old, Enumeration names)
682: {
683: if (old instanceof MutableAttributeSet)
684: {
685: ((MutableAttributeSet)old).removeAttributes(names);
686: if (old.getAttributeCount() < getCompressionThreshold())
687: {
688: SmallAttributeSet small = createSmallAttributeSet(old);
689: if (!sharedAttributeSets.containsKey(small))
690: sharedAttributeSets.put(small,small);
691: old = (AttributeSet) sharedAttributeSets.get(small);
692: }
693: return old;
694: }
695: else
696: {
697: MutableAttributeSet mutable = createLargeAttributeSet(old);
698: mutable.removeAttributes(names);
699: SmallAttributeSet small = createSmallAttributeSet(mutable);
700: if (sharedAttributeSets.containsKey(small))
701: small = (SmallAttributeSet) sharedAttributeSets.get(small);
702: else
703: sharedAttributeSets.put(small,small);
704: return small;
705: }
706: }
707:
708:
714: public static Object getStaticAttribute(Object key)
715: {
716: if (key == null)
717: return null;
718: return staticAttributeKeys.get(key);
719: }
720:
721:
728: public static Object getStaticAttributeKey(Object key)
729: {
730: return key.getClass().getName() + "." + key.toString();
731: }
732:
733:
745: public static void readAttributeSet(ObjectInputStream in, MutableAttributeSet a)
746: throws ClassNotFoundException, IOException
747: {
748: if (in == null || a == null)
749: return;
750:
751: Object key = in.readObject();
752: Object val = in.readObject();
753: while (key != null && val != null)
754: {
755: Object staticKey = staticAttributeKeys.get(key);
756: Object staticVal = staticAttributeKeys.get(val);
757:
758: if (staticKey != null)
759: key = staticKey;
760: if (staticVal != null)
761: val = staticVal;
762:
763: a.addAttribute(key, val);
764: key = in.readObject();
765: val = in.readObject();
766: }
767: }
768:
769:
778: public static void writeAttributeSet(ObjectOutputStream out, AttributeSet a)
779: throws IOException
780: {
781: Enumeration e = a.getAttributeNames();
782: while (e.hasMoreElements())
783: {
784: Object oldKey = e.nextElement();
785: Object newKey = getStaticAttribute(oldKey);
786: Object key = (newKey == null) ? oldKey : newKey;
787:
788: out.writeObject(key);
789: out.writeObject(a.getAttribute(oldKey));
790: }
791: out.writeObject(null);
792: out.writeObject(null);
793: }
794:
795:
804: public void readAttributes(ObjectInputStream in, MutableAttributeSet a)
805: throws ClassNotFoundException, IOException
806: {
807: readAttributeSet(in, a);
808: }
809:
810:
818: public void writeAttributes(ObjectOutputStream out, AttributeSet a)
819: throws IOException
820: {
821: writeAttributeSet(out, a);
822: }
823:
824:
834: public static void registerStaticAttributeKey(Object key)
835: {
836: if (key != null)
837: staticAttributeKeys.put(key.getClass().getName() + "." + key.toString(),
838: key);
839: }
840: }