1333 lines · 47.6 KB · Java
RawDownload
/* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package javax.swing.plaf.synth; import java.awt.Color;import java.awt.Component;import java.awt.Font;import java.awt.Graphics;import java.awt.Image;import java.awt.Insets;import java.awt.Toolkit;import java.io.BufferedInputStream;import java.io.IOException;import java.io.InputStream;import java.net.MalformedURLException;import java.net.URL;import java.net.URLClassLoader;import java.text.ParseException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Locale;import java.util.Map;import java.util.StringTokenizer;import java.util.regex.PatternSyntaxException; import javax.swing.ImageIcon;import javax.swing.JSplitPane;import javax.swing.SwingConstants;import javax.swing.UIDefaults;import javax.swing.plaf.ColorUIResource;import javax.swing.plaf.DimensionUIResource;import javax.swing.plaf.FontUIResource;import javax.swing.plaf.InsetsUIResource;import javax.swing.plaf.UIResource;import javax.xml.parsers.ParserConfigurationException;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes;import org.xml.sax.InputSource;import org.xml.sax.Locator;import org.xml.sax.SAXException;import org.xml.sax.SAXParseException;import org.xml.sax.helpers.DefaultHandler; import com.sun.beans.decoder.DocumentHandler; class SynthParser extends DefaultHandler {    //    // Known element names    //    private static final String ELEMENT_SYNTH = "synth";    private static final String ELEMENT_STYLE = "style";    private static final String ELEMENT_STATE = "state";    private static final String ELEMENT_FONT = "font";    private static final String ELEMENT_COLOR = "color";    private static final String ELEMENT_IMAGE_PAINTER = "imagePainter";    private static final String ELEMENT_PAINTER = "painter";    private static final String ELEMENT_PROPERTY = "property";    private static final String ELEMENT_SYNTH_GRAPHICS = "graphicsUtils";    private static final String ELEMENT_IMAGE_ICON = "imageIcon";    private static final String ELEMENT_BIND = "bind";    private static final String ELEMENT_BIND_KEY = "bindKey";    private static final String ELEMENT_INSETS = "insets";    private static final String ELEMENT_OPAQUE = "opaque";    private static final String ELEMENT_DEFAULTS_PROPERTY =                                        "defaultsProperty";    private static final String ELEMENT_INPUT_MAP = "inputMap";     //    // Known attribute names    //    private static final String ATTRIBUTE_ACTION = "action";    private static final String ATTRIBUTE_ID = "id";    private static final String ATTRIBUTE_IDREF = "idref";    private static final String ATTRIBUTE_CLONE = "clone";    private static final String ATTRIBUTE_VALUE = "value";    private static final String ATTRIBUTE_NAME = "name";    private static final String ATTRIBUTE_STYLE = "style";    private static final String ATTRIBUTE_SIZE = "size";    private static final String ATTRIBUTE_TYPE = "type";    private static final String ATTRIBUTE_TOP = "top";    private static final String ATTRIBUTE_LEFT = "left";    private static final String ATTRIBUTE_BOTTOM = "bottom";    private static final String ATTRIBUTE_RIGHT = "right";    private static final String ATTRIBUTE_KEY = "key";    private static final String ATTRIBUTE_SOURCE_INSETS = "sourceInsets";    private static final String ATTRIBUTE_DEST_INSETS = "destinationInsets";    private static final String ATTRIBUTE_PATH = "path";    private static final String ATTRIBUTE_STRETCH = "stretch";    private static final String ATTRIBUTE_PAINT_CENTER = "paintCenter";    private static final String ATTRIBUTE_METHOD = "method";    private static final String ATTRIBUTE_DIRECTION = "direction";    private static final String ATTRIBUTE_CENTER = "center";     /**     * Lazily created, used for anything we don't understand.     */    private DocumentHandler _handler;     /**     * Indicates the depth of how many elements we've encountered but don't     * understand. This is used when forwarding to beans persistance to know     * when we hsould stop forwarding.     */    private int _depth;     /**     * Factory that new styles are added to.     */    private DefaultSynthStyleFactory _factory;     /**     * Array of state infos for the current style. These are pushed to the     * style when </style> is received.     */    private List<ParsedSynthStyle.StateInfo> _stateInfos;     /**     * Current style.     */    private ParsedSynthStyle _style;     /**     * Current state info.     */    private ParsedSynthStyle.StateInfo _stateInfo;     /**     * Bindings for the current InputMap     */    private List<String> _inputMapBindings;     /**     * ID for the input map. This is cached as     * the InputMap is created AFTER the inputMapProperty has ended.     */    private String _inputMapID;     /**     * Object references outside the scope of persistance.     */    private Map<String,Object> _mapping;     /**     * Based URL used to resolve paths.     */    private URL _urlResourceBase;     /**     * Based class used to resolve paths.     */    private Class<?> _classResourceBase;     /**     * List of ColorTypes. This is populated in startColorType.     */    private List<ColorType> _colorTypes;     /**     * defaultsPropertys are placed here.     */    private Map<String, Object> _defaultsMap;     /**     * List of SynthStyle.Painters that will be applied to the current style.     */    private List<ParsedSynthStyle.PainterInfo> _stylePainters;     /**     * List of SynthStyle.Painters that will be applied to the current state.     */    private List<ParsedSynthStyle.PainterInfo> _statePainters;     SynthParser() {        _mapping = new HashMap<String,Object>();        _stateInfos = new ArrayList<ParsedSynthStyle.StateInfo>();        _colorTypes = new ArrayList<ColorType>();        _inputMapBindings = new ArrayList<String>();        _stylePainters = new ArrayList<ParsedSynthStyle.PainterInfo>();        _statePainters = new ArrayList<ParsedSynthStyle.PainterInfo>();    }     /**     * Parses a set of styles from <code>inputStream</code>, adding the     * resulting styles to the passed in DefaultSynthStyleFactory.     * Resources are resolved either from a URL or from a Class. When calling     * this method, one of the URL or the Class must be null but not both at     * the same time.     *     * @param inputStream XML document containing the styles to read     * @param factory DefaultSynthStyleFactory that new styles are added to     * @param urlResourceBase the URL used to resolve any resources, such as Images     * @param classResourceBase the Class used to resolve any resources, such as Images     * @param defaultsMap Map that UIDefaults properties are placed in     */    public void parse(InputStream inputStream,                      DefaultSynthStyleFactory factory,                      URL urlResourceBase, Class<?> classResourceBase,                      Map<String, Object> defaultsMap)                      throws ParseException, IllegalArgumentException {        if (inputStream == null || factory == null ||            (urlResourceBase == null && classResourceBase == null)) {            throw new IllegalArgumentException(                "You must supply an InputStream, StyleFactory and Class or URL");        }         assert(!(urlResourceBase != null && classResourceBase != null));         _factory = factory;        _classResourceBase = classResourceBase;        _urlResourceBase = urlResourceBase;        _defaultsMap = defaultsMap;        try {            try {                SAXParser saxParser = SAXParserFactory.newInstance().                                                   newSAXParser();                saxParser.parse(new BufferedInputStream(inputStream), this);            } catch (ParserConfigurationException e) {                throw new ParseException("Error parsing: " + e, 0);            }            catch (SAXException se) {                throw new ParseException("Error parsing: " + se + " " +                                         se.getException(), 0);            }            catch (IOException ioe) {                throw new ParseException("Error parsing: " + ioe, 0);            }        } finally {            reset();        }    }     /**     * Returns the path to a resource.     */    private URL getResource(String path) {        if (_classResourceBase != null) {            return _classResourceBase.getResource(path);        } else {            try {                return new URL(_urlResourceBase, path);            } catch (MalformedURLException mue) {                return null;            }        }    }     /**     * Clears our internal state.     */    private void reset() {        _handler = null;        _depth = 0;        _mapping.clear();        _stateInfos.clear();        _colorTypes.clear();        _statePainters.clear();        _stylePainters.clear();    }     /**     * Returns true if we are forwarding to persistance.     */    private boolean isForwarding() {        return (_depth > 0);    }     /**     * Handles beans persistance.     */    private DocumentHandler getHandler() {        if (_handler == null) {            _handler = new DocumentHandler();            if (_urlResourceBase != null) {                // getHandler() is never called before parse() so it is safe                // to create a URLClassLoader with _resourceBase.                //                // getResource(".") is called to ensure we have the directory                // containing the resources in the case the resource base is a                // .class file.                URL[] urls = new URL[] { getResource(".") };                ClassLoader parent = Thread.currentThread().getContextClassLoader();                ClassLoader urlLoader = new URLClassLoader(urls, parent);                _handler.setClassLoader(urlLoader);            } else {                _handler.setClassLoader(_classResourceBase.getClassLoader());            }             for (String key : _mapping.keySet()) {                _handler.setVariable(key, _mapping.get(key));            }        }        return _handler;    }     /**     * If <code>value</code> is an instance of <code>type</code> it is     * returned, otherwise a SAXException is thrown.     */    private Object checkCast(Object value, Class type) throws SAXException {        if (!type.isInstance(value)) {            throw new SAXException("Expected type " + type + " got " +                                   value.getClass());        }        return value;    }     /**     * Returns an object created with id=key. If the object is not of     * type type, this will throw an exception.     */    private Object lookup(String key, Class type) throws SAXException {        Object value;        if (_handler != null) {            if (_handler.hasVariable(key)) {                return checkCast(_handler.getVariable(key), type);            }        }        value = _mapping.get(key);        if (value == null) {            throw new SAXException("ID " + key + " has not been defined");        }        return checkCast(value, type);    }     /**     * Registers an object by name. This will throw an exception if an     * object has already been registered under the given name.     */    private void register(String key, Object value) throws SAXException {        if (key != null) {            if (_mapping.get(key) != null ||                     (_handler != null && _handler.hasVariable(key))) {                throw new SAXException("ID " + key + " is already defined");            }            if (_handler != null) {                _handler.setVariable(key, value);            }            else {                _mapping.put(key, value);            }        }    }     /**     * Convenience method to return the next int, or throw if there are no     * more valid ints.     */    private int nextInt(StringTokenizer tok, String errorMsg) throws                   SAXException {        if (!tok.hasMoreTokens()) {            throw new SAXException(errorMsg);        }        try {            return Integer.parseInt(tok.nextToken());        } catch (NumberFormatException nfe) {            throw new SAXException(errorMsg);        }    }     /**     * Convenience method to return an Insets object.     */    private Insets parseInsets(String insets, String errorMsg) throws                        SAXException {        StringTokenizer tokenizer = new StringTokenizer(insets);        return new Insets(nextInt(tokenizer, errorMsg),                          nextInt(tokenizer, errorMsg),                          nextInt(tokenizer, errorMsg),                          nextInt(tokenizer, errorMsg));    }       //    // The following methods are invoked from startElement/stopElement    //     private void startStyle(Attributes attributes) throws SAXException {        String id = null;         _style = null;        for(int i = attributes.getLength() - 1; i >= 0; i--) {            String key = attributes.getQName(i);            if (key.equals(ATTRIBUTE_CLONE)) {                _style = (ParsedSynthStyle)((ParsedSynthStyle)lookup(                         attributes.getValue(i), ParsedSynthStyle.class)).                         clone();            }            else if (key.equals(ATTRIBUTE_ID)) {                id = attributes.getValue(i);            }        }        if (_style == null) {            _style = new ParsedSynthStyle();        }        register(id, _style);    }     private void endStyle() {        int size = _stylePainters.size();        if (size > 0) {            _style.setPainters(_stylePainters.toArray(new ParsedSynthStyle.PainterInfo[size]));            _stylePainters.clear();        }        size = _stateInfos.size();        if (size > 0) {            _style.setStateInfo(_stateInfos.toArray(new ParsedSynthStyle.StateInfo[size]));            _stateInfos.clear();        }        _style = null;    }     private void startState(Attributes attributes) throws SAXException {        ParsedSynthStyle.StateInfo stateInfo = null;        int state = 0;        String id = null;         _stateInfo = null;        for(int i = attributes.getLength() - 1; i >= 0; i--) {            String key = attributes.getQName(i);            if (key.equals(ATTRIBUTE_ID)) {                id = attributes.getValue(i);            }            else if (key.equals(ATTRIBUTE_IDREF)) {                _stateInfo = (ParsedSynthStyle.StateInfo)lookup(                   attributes.getValue(i), ParsedSynthStyle.StateInfo.class);            }            else if (key.equals(ATTRIBUTE_CLONE)) {                _stateInfo = (ParsedSynthStyle.StateInfo)((ParsedSynthStyle.                             StateInfo)lookup(attributes.getValue(i),                             ParsedSynthStyle.StateInfo.class)).clone();            }            else if (key.equals(ATTRIBUTE_VALUE)) {                StringTokenizer tokenizer = new StringTokenizer(                                   attributes.getValue(i));                while (tokenizer.hasMoreTokens()) {                    String stateString = tokenizer.nextToken().toUpperCase().                                                   intern();                    if (stateString == "ENABLED") {                        state |= SynthConstants.ENABLED;                    }                    else if (stateString == "MOUSE_OVER") {                        state |= SynthConstants.MOUSE_OVER;                    }                    else if (stateString == "PRESSED") {                        state |= SynthConstants.PRESSED;                    }                    else if (stateString == "DISABLED") {                        state |= SynthConstants.DISABLED;                    }                    else if (stateString == "FOCUSED") {                        state |= SynthConstants.FOCUSED;                    }                    else if (stateString == "SELECTED") {                        state |= SynthConstants.SELECTED;                    }                    else if (stateString == "DEFAULT") {                        state |= SynthConstants.DEFAULT;                    }                    else if (stateString != "AND") {                        throw new SAXException("Unknown state: " + state);                    }                }            }        }        if (_stateInfo == null) {            _stateInfo = new ParsedSynthStyle.StateInfo();        }        _stateInfo.setComponentState(state);        register(id, _stateInfo);        _stateInfos.add(_stateInfo);    }     private void endState() {        int size = _statePainters.size();

Lines 1–500 of 1333.