23 * questions.
24 */
25 package javax.swing.plaf.synth;
26
27 import java.awt.Color;
28 import java.awt.Component;
29 import java.awt.Font;
30 import java.awt.Graphics;
31 import java.awt.Image;
32 import java.awt.Insets;
33 import java.awt.Toolkit;
34 import java.io.BufferedInputStream;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.net.MalformedURLException;
38 import java.net.URL;
39 import java.net.URLClassLoader;
40 import java.text.ParseException;
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.Locale;
44 import java.util.Map;
45 import java.util.StringTokenizer;
46 import java.util.regex.PatternSyntaxException;
47
48 import javax.swing.ImageIcon;
49 import javax.swing.JSplitPane;
50 import javax.swing.SwingConstants;
51 import javax.swing.UIDefaults;
52 import javax.swing.plaf.ColorUIResource;
53 import javax.swing.plaf.DimensionUIResource;
54 import javax.swing.plaf.FontUIResource;
55 import javax.swing.plaf.InsetsUIResource;
56 import javax.swing.plaf.UIResource;
57 import javax.xml.parsers.ParserConfigurationException;
58 import javax.xml.parsers.SAXParser;
59 import javax.xml.parsers.SAXParserFactory;
60
61 import org.xml.sax.AttributeList;
62 import org.xml.sax.HandlerBase;
121 * Lazily created, used for anything we don't understand.
122 */
123 private ObjectHandler _handler;
124
125 /**
126 * Indicates the depth of how many elements we've encountered but don't
127 * understand. This is used when forwarding to beans persistance to know
128 * when we hsould stop forwarding.
129 */
130 private int _depth;
131
132 /**
133 * Factory that new styles are added to.
134 */
135 private DefaultSynthStyleFactory _factory;
136
137 /**
138 * Array of state infos for the current style. These are pushed to the
139 * style when </style> is received.
140 */
141 private java.util.List _stateInfos;
142
143 /**
144 * Current style.
145 */
146 private ParsedSynthStyle _style;
147
148 /**
149 * Current state info.
150 */
151 private ParsedSynthStyle.StateInfo _stateInfo;
152
153 /**
154 * Bindings for the current InputMap
155 */
156 private java.util.List _inputMapBindings;
157
158 /**
159 * ID for the input map. This is cached as
160 * the InputMap is created AFTER the inputMapProperty has ended.
161 */
162 private String _inputMapID;
163
164 /**
165 * Object references outside the scope of persistance.
166 */
167 private Map<String,Object> _mapping;
168
169 /**
170 * Based URL used to resolve paths.
171 */
172 private URL _urlResourceBase;
173
174 /**
175 * Based class used to resolve paths.
176 */
177 private Class<?> _classResourceBase;
178
179 /**
180 * List of ColorTypes. This is populated in startColorType.
181 */
182 private java.util.List _colorTypes;
183
184 /**
185 * defaultsPropertys are placed here.
186 */
187 private Map _defaultsMap;
188
189 /**
190 * List of SynthStyle.Painters that will be applied to the current style.
191 */
192 private java.util.List _stylePainters;
193
194 /**
195 * List of SynthStyle.Painters that will be applied to the current state.
196 */
197 private java.util.List _statePainters;
198
199 SynthParser() {
200 _mapping = new HashMap<String,Object>();
201 _stateInfos = new ArrayList();
202 _colorTypes = new ArrayList();
203 _inputMapBindings = new ArrayList();
204 _stylePainters = new ArrayList();
205 _statePainters = new ArrayList();
206 }
207
208 /**
209 * Parses a set of styles from <code>inputStream</code>, adding the
210 * resulting styles to the passed in DefaultSynthStyleFactory.
211 * Resources are resolved either from a URL or from a Class. When calling
212 * this method, one of the URL or the Class must be null but not both at
213 * the same time.
214 *
215 * @param inputStream XML document containing the styles to read
216 * @param factory DefaultSynthStyleFactory that new styles are added to
217 * @param urlResourceBase the URL used to resolve any resources, such as Images
218 * @param classResourceBase the Class used to resolve any resources, such as Images
219 * @param defaultsMap Map that UIDefaults properties are placed in
220 */
221 public void parse(InputStream inputStream,
222 DefaultSynthStyleFactory factory,
223 URL urlResourceBase, Class<?> classResourceBase,
224 Map defaultsMap)
225 throws ParseException, IllegalArgumentException {
226 if (inputStream == null || factory == null ||
227 (urlResourceBase == null && classResourceBase == null)) {
228 throw new IllegalArgumentException(
229 "You must supply an InputStream, StyleFactory and Class or URL");
230 }
231
232 assert(!(urlResourceBase != null && classResourceBase != null));
233
234 _factory = factory;
235 _classResourceBase = classResourceBase;
236 _urlResourceBase = urlResourceBase;
237 _defaultsMap = defaultsMap;
238 try {
239 try {
240 SAXParser saxParser = SAXParserFactory.newInstance().
241 newSAXParser();
242 saxParser.parse(new BufferedInputStream(inputStream), this);
243 } catch (ParserConfigurationException e) {
244 throw new ParseException("Error parsing: " + e, 0);
318 return _handler;
319 }
320
321 /**
322 * If <code>value</code> is an instance of <code>type</code> it is
323 * returned, otherwise a SAXException is thrown.
324 */
325 private Object checkCast(Object value, Class type) throws SAXException {
326 if (!type.isInstance(value)) {
327 throw new SAXException("Expected type " + type + " got " +
328 value.getClass());
329 }
330 return value;
331 }
332
333 /**
334 * Returns an object created with id=key. If the object is not of
335 * type type, this will throw an exception.
336 */
337 private Object lookup(String key, Class type) throws SAXException {
338 Object value = null;
339 if (_handler != null) {
340 if ((value = _handler.lookup(key)) != null) {
341 return checkCast(value, type);
342 }
343 }
344 value = _mapping.get(key);
345 if (value == null) {
346 throw new SAXException("ID " + key + " has not been defined");
347 }
348 return checkCast(value, type);
349 }
350
351 /**
352 * Registers an object by name. This will throw an exception if an
353 * object has already been registered under the given name.
354 */
355 private void register(String key, Object value) throws SAXException {
356 if (key != null) {
357 if (_mapping.get(key) != null ||
358 (_handler != null && _handler.lookup(key) != null)) {
408 for(int i = attributes.getLength() - 1; i >= 0; i--) {
409 String key = attributes.getName(i);
410 if (key.equals(ATTRIBUTE_CLONE)) {
411 _style = (ParsedSynthStyle)((ParsedSynthStyle)lookup(
412 attributes.getValue(i), ParsedSynthStyle.class)).
413 clone();
414 }
415 else if (key.equals(ATTRIBUTE_ID)) {
416 id = attributes.getValue(i);
417 }
418 }
419 if (_style == null) {
420 _style = new ParsedSynthStyle();
421 }
422 register(id, _style);
423 }
424
425 private void endStyle() throws SAXException {
426 int size = _stylePainters.size();
427 if (size > 0) {
428 _style.setPainters((ParsedSynthStyle.PainterInfo[])
429 _stylePainters.toArray(new ParsedSynthStyle.
430 PainterInfo[size]));
431 _stylePainters.clear();
432 }
433 size = _stateInfos.size();
434 if (size > 0) {
435 _style.setStateInfo((ParsedSynthStyle.StateInfo[])_stateInfos.
436 toArray(new ParsedSynthStyle.StateInfo[size]));
437 _stateInfos.clear();
438 }
439 _style = null;
440 }
441
442 private void startState(AttributeList attributes) throws SAXException {
443 ParsedSynthStyle.StateInfo stateInfo = null;
444 int state = 0;
445 String id = null;
446
447 _stateInfo = null;
448 for(int i = attributes.getLength() - 1; i >= 0; i--) {
449 String key = attributes.getName(i);
450 if (key.equals(ATTRIBUTE_ID)) {
451 id = attributes.getValue(i);
452 }
453 else if (key.equals(ATTRIBUTE_IDREF)) {
454 _stateInfo = (ParsedSynthStyle.StateInfo)lookup(
455 attributes.getValue(i), ParsedSynthStyle.StateInfo.class);
456 }
486 else if (stateString == "DEFAULT") {
487 state |= SynthConstants.DEFAULT;
488 }
489 else if (stateString != "AND") {
490 throw new SAXException("Unknown state: " + state);
491 }
492 }
493 }
494 }
495 if (_stateInfo == null) {
496 _stateInfo = new ParsedSynthStyle.StateInfo();
497 }
498 _stateInfo.setComponentState(state);
499 register(id, _stateInfo);
500 _stateInfos.add(_stateInfo);
501 }
502
503 private void endState() throws SAXException {
504 int size = _statePainters.size();
505 if (size > 0) {
506 _stateInfo.setPainters((ParsedSynthStyle.PainterInfo[])
507 _statePainters.toArray(new ParsedSynthStyle.
508 PainterInfo[size]));
509 _statePainters.clear();
510 }
511 _stateInfo = null;
512 }
513
514 private void startFont(AttributeList attributes) throws SAXException {
515 Font font = null;
516 int style = Font.PLAIN;
517 int size = 0;
518 String id = null;
519 String name = null;
520
521 for(int i = attributes.getLength() - 1; i >= 0; i--) {
522 String key = attributes.getName(i);
523 if (key.equals(ATTRIBUTE_ID)) {
524 id = attributes.getValue(i);
525 }
526 else if (key.equals(ATTRIBUTE_IDREF)) {
527 font = (Font)lookup(attributes.getValue(i), Font.class);
528 }
669 get(typeClass), ColorType.class));
670 } catch (NoSuchFieldException nsfe) {
671 throw new SAXException("Unable to find color type: " +
672 typeName);
673 } catch (IllegalAccessException iae) {
674 throw new SAXException("Unable to find color type: " +
675 typeName);
676 }
677 }
678 }
679 }
680 if (color == null) {
681 throw new SAXException("color: you must specificy a value");
682 }
683 register(id, color);
684 if (_stateInfo != null && _colorTypes.size() > 0) {
685 Color[] colors = _stateInfo.getColors();
686 int max = 0;
687 for (int counter = _colorTypes.size() - 1; counter >= 0;
688 counter--) {
689 max = Math.max(max, ((ColorType)_colorTypes.get(counter)).
690 getID());
691 }
692 if (colors == null || colors.length <= max) {
693 Color[] newColors = new Color[max + 1];
694 if (colors != null) {
695 System.arraycopy(colors, 0, newColors, 0, colors.length);
696 }
697 colors = newColors;
698 }
699 for (int counter = _colorTypes.size() - 1; counter >= 0;
700 counter--) {
701 colors[((ColorType)_colorTypes.get(counter)).getID()] = color;
702 }
703 _stateInfo.setColors(colors);
704 }
705 }
706
707 private void startProperty(AttributeList attributes,
708 Object property) throws SAXException {
709 Object value = null;
710 Object key = null;
711 // Type of the value: 0=idref, 1=boolean, 2=dimension, 3=insets,
712 // 4=integer,5=string
713 int iType = 0;
714 String aValue = null;
715
716 for(int i = attributes.getLength() - 1; i >= 0; i--) {
717 String aName = attributes.getName(i);
718 if (aName.equals(ATTRIBUTE_TYPE)) {
719 String type = attributes.getValue(i).toUpperCase();
720 if (type.equals("IDREF")) {
721 iType = 0;
722 }
723 else if (type.equals("BOOLEAN")) {
724 iType = 1;
725 }
726 else if (type.equals("DIMENSION")) {
727 iType = 2;
728 }
729 else if (type.equals("INSETS")) {
730 iType = 3;
1012 throw new SAXException("property: you must specify a path");
1013 }
1014 if (center && (sourceInsets != null || destInsets != null ||
1015 paintCenterSpecified || stretchSpecified)) {
1016 throw new SAXException("The attributes: sourceInsets, " +
1017 "destinationInsets, paintCenter and stretch " +
1018 " are not legal when center is true");
1019 }
1020 painter = new ImagePainter(!stretch, paintCenter,
1021 sourceInsets, destInsets, getResource(path), center);
1022 }
1023 register(id, painter);
1024 if (_stateInfo != null) {
1025 addPainterOrMerge(_statePainters, method, painter, direction);
1026 }
1027 else if (_style != null) {
1028 addPainterOrMerge(_stylePainters, method, painter, direction);
1029 }
1030 }
1031
1032 private void addPainterOrMerge(java.util.List painters, String method,
1033 SynthPainter painter, int direction) {
1034 ParsedSynthStyle.PainterInfo painterInfo;
1035 painterInfo = new ParsedSynthStyle.PainterInfo(method,
1036 painter,
1037 direction);
1038
1039 for (Object infoObject: painters) {
1040 ParsedSynthStyle.PainterInfo info;
1041 info = (ParsedSynthStyle.PainterInfo) infoObject;
1042
1043 if (painterInfo.equalsPainter(info)) {
1044 info.addPainter(painter);
1045 return;
1046 }
1047 }
1048
1049 painters.add(painterInfo);
1050 }
1051
1052 private void startImageIcon(AttributeList attributes) throws SAXException {
|
23 * questions.
24 */
25 package javax.swing.plaf.synth;
26
27 import java.awt.Color;
28 import java.awt.Component;
29 import java.awt.Font;
30 import java.awt.Graphics;
31 import java.awt.Image;
32 import java.awt.Insets;
33 import java.awt.Toolkit;
34 import java.io.BufferedInputStream;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.net.MalformedURLException;
38 import java.net.URL;
39 import java.net.URLClassLoader;
40 import java.text.ParseException;
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.List;
44 import java.util.Locale;
45 import java.util.Map;
46 import java.util.StringTokenizer;
47 import java.util.regex.PatternSyntaxException;
48
49 import javax.swing.ImageIcon;
50 import javax.swing.JSplitPane;
51 import javax.swing.SwingConstants;
52 import javax.swing.UIDefaults;
53 import javax.swing.plaf.ColorUIResource;
54 import javax.swing.plaf.DimensionUIResource;
55 import javax.swing.plaf.FontUIResource;
56 import javax.swing.plaf.InsetsUIResource;
57 import javax.swing.plaf.UIResource;
58 import javax.xml.parsers.ParserConfigurationException;
59 import javax.xml.parsers.SAXParser;
60 import javax.xml.parsers.SAXParserFactory;
61
62 import org.xml.sax.AttributeList;
63 import org.xml.sax.HandlerBase;
122 * Lazily created, used for anything we don't understand.
123 */
124 private ObjectHandler _handler;
125
126 /**
127 * Indicates the depth of how many elements we've encountered but don't
128 * understand. This is used when forwarding to beans persistance to know
129 * when we hsould stop forwarding.
130 */
131 private int _depth;
132
133 /**
134 * Factory that new styles are added to.
135 */
136 private DefaultSynthStyleFactory _factory;
137
138 /**
139 * Array of state infos for the current style. These are pushed to the
140 * style when </style> is received.
141 */
142 private List<ParsedSynthStyle.StateInfo> _stateInfos;
143
144 /**
145 * Current style.
146 */
147 private ParsedSynthStyle _style;
148
149 /**
150 * Current state info.
151 */
152 private ParsedSynthStyle.StateInfo _stateInfo;
153
154 /**
155 * Bindings for the current InputMap
156 */
157 private List<String> _inputMapBindings;
158
159 /**
160 * ID for the input map. This is cached as
161 * the InputMap is created AFTER the inputMapProperty has ended.
162 */
163 private String _inputMapID;
164
165 /**
166 * Object references outside the scope of persistance.
167 */
168 private Map<String,Object> _mapping;
169
170 /**
171 * Based URL used to resolve paths.
172 */
173 private URL _urlResourceBase;
174
175 /**
176 * Based class used to resolve paths.
177 */
178 private Class<?> _classResourceBase;
179
180 /**
181 * List of ColorTypes. This is populated in startColorType.
182 */
183 private List<ColorType> _colorTypes;
184
185 /**
186 * defaultsPropertys are placed here.
187 */
188 private Map<String, Object> _defaultsMap;
189
190 /**
191 * List of SynthStyle.Painters that will be applied to the current style.
192 */
193 private List<ParsedSynthStyle.PainterInfo> _stylePainters;
194
195 /**
196 * List of SynthStyle.Painters that will be applied to the current state.
197 */
198 private List<ParsedSynthStyle.PainterInfo> _statePainters;
199
200 SynthParser() {
201 _mapping = new HashMap<String,Object>();
202 _stateInfos = new ArrayList<ParsedSynthStyle.StateInfo>();
203 _colorTypes = new ArrayList<ColorType>();
204 _inputMapBindings = new ArrayList<String>();
205 _stylePainters = new ArrayList<ParsedSynthStyle.PainterInfo>();
206 _statePainters = new ArrayList<ParsedSynthStyle.PainterInfo>();
207 }
208
209 /**
210 * Parses a set of styles from <code>inputStream</code>, adding the
211 * resulting styles to the passed in DefaultSynthStyleFactory.
212 * Resources are resolved either from a URL or from a Class. When calling
213 * this method, one of the URL or the Class must be null but not both at
214 * the same time.
215 *
216 * @param inputStream XML document containing the styles to read
217 * @param factory DefaultSynthStyleFactory that new styles are added to
218 * @param urlResourceBase the URL used to resolve any resources, such as Images
219 * @param classResourceBase the Class used to resolve any resources, such as Images
220 * @param defaultsMap Map that UIDefaults properties are placed in
221 */
222 public void parse(InputStream inputStream,
223 DefaultSynthStyleFactory factory,
224 URL urlResourceBase, Class<?> classResourceBase,
225 Map<String, Object> defaultsMap)
226 throws ParseException, IllegalArgumentException {
227 if (inputStream == null || factory == null ||
228 (urlResourceBase == null && classResourceBase == null)) {
229 throw new IllegalArgumentException(
230 "You must supply an InputStream, StyleFactory and Class or URL");
231 }
232
233 assert(!(urlResourceBase != null && classResourceBase != null));
234
235 _factory = factory;
236 _classResourceBase = classResourceBase;
237 _urlResourceBase = urlResourceBase;
238 _defaultsMap = defaultsMap;
239 try {
240 try {
241 SAXParser saxParser = SAXParserFactory.newInstance().
242 newSAXParser();
243 saxParser.parse(new BufferedInputStream(inputStream), this);
244 } catch (ParserConfigurationException e) {
245 throw new ParseException("Error parsing: " + e, 0);
319 return _handler;
320 }
321
322 /**
323 * If <code>value</code> is an instance of <code>type</code> it is
324 * returned, otherwise a SAXException is thrown.
325 */
326 private Object checkCast(Object value, Class type) throws SAXException {
327 if (!type.isInstance(value)) {
328 throw new SAXException("Expected type " + type + " got " +
329 value.getClass());
330 }
331 return value;
332 }
333
334 /**
335 * Returns an object created with id=key. If the object is not of
336 * type type, this will throw an exception.
337 */
338 private Object lookup(String key, Class type) throws SAXException {
339 Object value;
340 if (_handler != null) {
341 if ((value = _handler.lookup(key)) != null) {
342 return checkCast(value, type);
343 }
344 }
345 value = _mapping.get(key);
346 if (value == null) {
347 throw new SAXException("ID " + key + " has not been defined");
348 }
349 return checkCast(value, type);
350 }
351
352 /**
353 * Registers an object by name. This will throw an exception if an
354 * object has already been registered under the given name.
355 */
356 private void register(String key, Object value) throws SAXException {
357 if (key != null) {
358 if (_mapping.get(key) != null ||
359 (_handler != null && _handler.lookup(key) != null)) {
409 for(int i = attributes.getLength() - 1; i >= 0; i--) {
410 String key = attributes.getName(i);
411 if (key.equals(ATTRIBUTE_CLONE)) {
412 _style = (ParsedSynthStyle)((ParsedSynthStyle)lookup(
413 attributes.getValue(i), ParsedSynthStyle.class)).
414 clone();
415 }
416 else if (key.equals(ATTRIBUTE_ID)) {
417 id = attributes.getValue(i);
418 }
419 }
420 if (_style == null) {
421 _style = new ParsedSynthStyle();
422 }
423 register(id, _style);
424 }
425
426 private void endStyle() throws SAXException {
427 int size = _stylePainters.size();
428 if (size > 0) {
429 _style.setPainters(_stylePainters.toArray(new ParsedSynthStyle.PainterInfo[size]));
430 _stylePainters.clear();
431 }
432 size = _stateInfos.size();
433 if (size > 0) {
434 _style.setStateInfo(_stateInfos.toArray(new ParsedSynthStyle.StateInfo[size]));
435 _stateInfos.clear();
436 }
437 _style = null;
438 }
439
440 private void startState(AttributeList attributes) throws SAXException {
441 ParsedSynthStyle.StateInfo stateInfo = null;
442 int state = 0;
443 String id = null;
444
445 _stateInfo = null;
446 for(int i = attributes.getLength() - 1; i >= 0; i--) {
447 String key = attributes.getName(i);
448 if (key.equals(ATTRIBUTE_ID)) {
449 id = attributes.getValue(i);
450 }
451 else if (key.equals(ATTRIBUTE_IDREF)) {
452 _stateInfo = (ParsedSynthStyle.StateInfo)lookup(
453 attributes.getValue(i), ParsedSynthStyle.StateInfo.class);
454 }
484 else if (stateString == "DEFAULT") {
485 state |= SynthConstants.DEFAULT;
486 }
487 else if (stateString != "AND") {
488 throw new SAXException("Unknown state: " + state);
489 }
490 }
491 }
492 }
493 if (_stateInfo == null) {
494 _stateInfo = new ParsedSynthStyle.StateInfo();
495 }
496 _stateInfo.setComponentState(state);
497 register(id, _stateInfo);
498 _stateInfos.add(_stateInfo);
499 }
500
501 private void endState() throws SAXException {
502 int size = _statePainters.size();
503 if (size > 0) {
504 _stateInfo.setPainters(_statePainters.toArray(new ParsedSynthStyle.PainterInfo[size]));
505 _statePainters.clear();
506 }
507 _stateInfo = null;
508 }
509
510 private void startFont(AttributeList attributes) throws SAXException {
511 Font font = null;
512 int style = Font.PLAIN;
513 int size = 0;
514 String id = null;
515 String name = null;
516
517 for(int i = attributes.getLength() - 1; i >= 0; i--) {
518 String key = attributes.getName(i);
519 if (key.equals(ATTRIBUTE_ID)) {
520 id = attributes.getValue(i);
521 }
522 else if (key.equals(ATTRIBUTE_IDREF)) {
523 font = (Font)lookup(attributes.getValue(i), Font.class);
524 }
665 get(typeClass), ColorType.class));
666 } catch (NoSuchFieldException nsfe) {
667 throw new SAXException("Unable to find color type: " +
668 typeName);
669 } catch (IllegalAccessException iae) {
670 throw new SAXException("Unable to find color type: " +
671 typeName);
672 }
673 }
674 }
675 }
676 if (color == null) {
677 throw new SAXException("color: you must specificy a value");
678 }
679 register(id, color);
680 if (_stateInfo != null && _colorTypes.size() > 0) {
681 Color[] colors = _stateInfo.getColors();
682 int max = 0;
683 for (int counter = _colorTypes.size() - 1; counter >= 0;
684 counter--) {
685 max = Math.max(max, _colorTypes.get(counter).getID());
686 }
687 if (colors == null || colors.length <= max) {
688 Color[] newColors = new Color[max + 1];
689 if (colors != null) {
690 System.arraycopy(colors, 0, newColors, 0, colors.length);
691 }
692 colors = newColors;
693 }
694 for (int counter = _colorTypes.size() - 1; counter >= 0;
695 counter--) {
696 colors[_colorTypes.get(counter).getID()] = color;
697 }
698 _stateInfo.setColors(colors);
699 }
700 }
701
702 private void startProperty(AttributeList attributes,
703 Object property) throws SAXException {
704 Object value = null;
705 String key = null;
706 // Type of the value: 0=idref, 1=boolean, 2=dimension, 3=insets,
707 // 4=integer,5=string
708 int iType = 0;
709 String aValue = null;
710
711 for(int i = attributes.getLength() - 1; i >= 0; i--) {
712 String aName = attributes.getName(i);
713 if (aName.equals(ATTRIBUTE_TYPE)) {
714 String type = attributes.getValue(i).toUpperCase();
715 if (type.equals("IDREF")) {
716 iType = 0;
717 }
718 else if (type.equals("BOOLEAN")) {
719 iType = 1;
720 }
721 else if (type.equals("DIMENSION")) {
722 iType = 2;
723 }
724 else if (type.equals("INSETS")) {
725 iType = 3;
1007 throw new SAXException("property: you must specify a path");
1008 }
1009 if (center && (sourceInsets != null || destInsets != null ||
1010 paintCenterSpecified || stretchSpecified)) {
1011 throw new SAXException("The attributes: sourceInsets, " +
1012 "destinationInsets, paintCenter and stretch " +
1013 " are not legal when center is true");
1014 }
1015 painter = new ImagePainter(!stretch, paintCenter,
1016 sourceInsets, destInsets, getResource(path), center);
1017 }
1018 register(id, painter);
1019 if (_stateInfo != null) {
1020 addPainterOrMerge(_statePainters, method, painter, direction);
1021 }
1022 else if (_style != null) {
1023 addPainterOrMerge(_stylePainters, method, painter, direction);
1024 }
1025 }
1026
1027 private void addPainterOrMerge(List<ParsedSynthStyle.PainterInfo> painters, String method,
1028 SynthPainter painter, int direction) {
1029 ParsedSynthStyle.PainterInfo painterInfo;
1030 painterInfo = new ParsedSynthStyle.PainterInfo(method,
1031 painter,
1032 direction);
1033
1034 for (Object infoObject: painters) {
1035 ParsedSynthStyle.PainterInfo info;
1036 info = (ParsedSynthStyle.PainterInfo) infoObject;
1037
1038 if (painterInfo.equalsPainter(info)) {
1039 info.addPainter(painter);
1040 return;
1041 }
1042 }
1043
1044 painters.add(painterInfo);
1045 }
1046
1047 private void startImageIcon(AttributeList attributes) throws SAXException {
|