3058 lines · 108.8 KB · Java
RawDownload
/* * Copyright (c) 2000, 2008, 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.text.html; import java.awt.*;import java.awt.event.*;import java.beans.*;import java.util.*;import javax.swing.*;import javax.swing.event.*;import javax.swing.text.*;import javax.accessibility.*;import java.text.BreakIterator; /* * The AccessibleHTML class provide information about the contents * of a HTML document to assistive technologies. * * @author  Lynn Monsanto */class AccessibleHTML implements Accessible {     /**     * The editor.     */    private JEditorPane editor;    /**     * Current model.     */    private Document model;    /**     * DocumentListener installed on the current model.     */    private DocumentListener docListener;    /**     * PropertyChangeListener installed on the editor     */    private PropertyChangeListener propChangeListener;    /**     * The root ElementInfo for the document     */    private ElementInfo rootElementInfo;    /*     * The root accessible context for the document     */    private RootHTMLAccessibleContext rootHTMLAccessibleContext;     public AccessibleHTML(JEditorPane pane) {        editor = pane;        propChangeListener = new PropertyChangeHandler();        setDocument(editor.getDocument());         docListener = new DocumentHandler();    }     /**     * Sets the document.     */    private void setDocument(Document document) {        if (model != null) {            model.removeDocumentListener(docListener);        }        if (editor != null) {            editor.removePropertyChangeListener(propChangeListener);        }        this.model = document;        if (model != null) {            if (rootElementInfo != null) {                rootElementInfo.invalidate(false);            }            buildInfo();            model.addDocumentListener(docListener);        }        else {            rootElementInfo = null;        }        if (editor != null) {            editor.addPropertyChangeListener(propChangeListener);        }    }     /**     * Returns the Document currently presenting information for.     */    private Document getDocument() {        return model;    }     /**     * Returns the JEditorPane providing information for.     */    private JEditorPane getTextComponent() {        return editor;    }     /**     * Returns the ElementInfo representing the root Element.     */    private ElementInfo getRootInfo() {        return rootElementInfo;    }     /**     * Returns the root <code>View</code> associated with the current text     * component.     */    private View getRootView() {        return getTextComponent().getUI().getRootView(getTextComponent());    }     /**     * Returns the bounds the root View will be rendered in.     */    private Rectangle getRootEditorRect() {        Rectangle alloc = getTextComponent().getBounds();        if ((alloc.width > 0) && (alloc.height > 0)) {            alloc.x = alloc.y = 0;            Insets insets = editor.getInsets();            alloc.x += insets.left;            alloc.y += insets.top;            alloc.width -= insets.left + insets.right;            alloc.height -= insets.top + insets.bottom;            return alloc;        }        return null;    }     /**     * If possible acquires a lock on the Document.  If a lock has been     * obtained a key will be retured that should be passed to     * <code>unlock</code>.     */    private Object lock() {        Document document = getDocument();         if (document instanceof AbstractDocument) {            ((AbstractDocument)document).readLock();            return document;        }        return null;    }     /**     * Releases a lock previously obtained via <code>lock</code>.     */    private void unlock(Object key) {        if (key != null) {            ((AbstractDocument)key).readUnlock();        }    }     /**     * Rebuilds the information from the current info.     */    private void buildInfo() {        Object lock = lock();         try {            Document doc = getDocument();            Element root = doc.getDefaultRootElement();             rootElementInfo = new ElementInfo(root);            rootElementInfo.validate();        } finally {            unlock(lock);        }    }     /*     * Create an ElementInfo subclass based on the passed in Element.     */    ElementInfo createElementInfo(Element e, ElementInfo parent) {        AttributeSet attrs = e.getAttributes();         if (attrs != null) {            Object name = attrs.getAttribute(StyleConstants.NameAttribute);             if (name == HTML.Tag.IMG) {                return new IconElementInfo(e, parent);            }            else if (name == HTML.Tag.CONTENT || name == HTML.Tag.CAPTION) {                return new TextElementInfo(e, parent);            }            else if (name == HTML.Tag.TABLE) {                return new TableElementInfo(e, parent);            }        }        return null;    }     /**     * Returns the root AccessibleContext for the document     */    public AccessibleContext getAccessibleContext() {        if (rootHTMLAccessibleContext == null) {            rootHTMLAccessibleContext =                new RootHTMLAccessibleContext(rootElementInfo);        }        return rootHTMLAccessibleContext;    }     /*     * The roow AccessibleContext for the document     */    private class RootHTMLAccessibleContext extends HTMLAccessibleContext {         public RootHTMLAccessibleContext(ElementInfo elementInfo) {            super(elementInfo);        }         /**         * Gets the accessibleName property of this object.  The accessibleName         * property of an object is a localized String that designates the purpose         * of the object.  For example, the accessibleName property of a label         * or button might be the text of the label or button itself.  In the         * case of an object that doesn't display its name, the accessibleName         * should still be set.  For example, in the case of a text field used         * to enter the name of a city, the accessibleName for the en_US locale         * could be 'city.'         *         * @return the localized name of the object; null if this         * object does not have a name         *         * @see #setAccessibleName         */        public String getAccessibleName() {            if (model != null) {                return (String)model.getProperty(Document.TitleProperty);            } else {                return null;            }        }         /**         * Gets the accessibleDescription property of this object.  If this         * property isn't set, returns the content type of this         * <code>JEditorPane</code> instead (e.g. "plain/text", "html/text").         *         * @return the localized description of the object; <code>null</code>         *      if this object does not have a description         *         * @see #setAccessibleName         */        public String getAccessibleDescription() {            return editor.getContentType();        }         /**         * Gets the role of this object.  The role of the object is the generic         * purpose or use of the class of this object.  For example, the role         * of a push button is AccessibleRole.PUSH_BUTTON.  The roles in         * AccessibleRole are provided so component developers can pick from         * a set of predefined roles.  This enables assistive technologies to         * provide a consistent interface to various tweaked subclasses of         * components (e.g., use AccessibleRole.PUSH_BUTTON for all components         * that act like a push button) as well as distinguish between sublasses         * that behave differently (e.g., AccessibleRole.CHECK_BOX for check boxes         * and AccessibleRole.RADIO_BUTTON for radio buttons).         * <p>Note that the AccessibleRole class is also extensible, so         * custom component developers can define their own AccessibleRole's         * if the set of predefined roles is inadequate.         *         * @return an instance of AccessibleRole describing the role of the object         * @see AccessibleRole         */        public AccessibleRole getAccessibleRole() {            return AccessibleRole.TEXT;        }    }     /*     * Base AccessibleContext class for HTML elements     */    protected abstract class HTMLAccessibleContext extends AccessibleContext        implements Accessible, AccessibleComponent {         protected ElementInfo elementInfo;         public HTMLAccessibleContext(ElementInfo elementInfo) {            this.elementInfo = elementInfo;        }         // begin AccessibleContext implementation ...        public AccessibleContext getAccessibleContext() {            return this;        }         /**         * Gets the state set of this object.         *         * @return an instance of AccessibleStateSet describing the states         * of the object         * @see AccessibleStateSet         */        public AccessibleStateSet getAccessibleStateSet() {            AccessibleStateSet states = new AccessibleStateSet();            Component comp = getTextComponent();             if (comp.isEnabled()) {                states.add(AccessibleState.ENABLED);            }            if (comp instanceof JTextComponent &&                ((JTextComponent)comp).isEditable()) {                 states.add(AccessibleState.EDITABLE);                states.add(AccessibleState.FOCUSABLE);            }            if (comp.isVisible()) {                states.add(AccessibleState.VISIBLE);            }            if (comp.isShowing()) {                states.add(AccessibleState.SHOWING);            }            return states;        }         /**         * Gets the 0-based index of this object in its accessible parent.         *         * @return the 0-based index of this object in its parent; -1 if this         * object does not have an accessible parent.         *         * @see #getAccessibleParent         * @see #getAccessibleChildrenCount         * @see #getAccessibleChild         */        public int getAccessibleIndexInParent() {            return elementInfo.getIndexInParent();        }         /**         * Returns the number of accessible children of the object.         *         * @return the number of accessible children of the object.         */        public int getAccessibleChildrenCount() {            return elementInfo.getChildCount();        }         /**         * Returns the specified Accessible child of the object.  The Accessible         * children of an Accessible object are zero-based, so the first child         * of an Accessible child is at index 0, the second child is at index 1,         * and so on.         *         * @param i zero-based index of child         * @return the Accessible child of the object         * @see #getAccessibleChildrenCount         */        public Accessible getAccessibleChild(int i) {            ElementInfo childInfo = elementInfo.getChild(i);            if (childInfo != null && childInfo instanceof Accessible) {                return (Accessible)childInfo;            } else {                return null;            }        }         /**         * Gets the locale of the component. If the component does not have a         * locale, then the locale of its parent is returned.         *         * @return this component's locale.  If this component does not have         * a locale, the locale of its parent is returned.         *         * @exception IllegalComponentStateException         * If the Component does not have its own locale and has not yet been         * added to a containment hierarchy such that the locale can be         * determined from the containing parent.         */        public Locale getLocale() throws IllegalComponentStateException {            return editor.getLocale();        }        // ... end AccessibleContext implementation         // begin AccessibleComponent implementation ...        public AccessibleComponent getAccessibleComponent() {            return this;        }         /**         * Gets the background color of this object.         *         * @return the background color, if supported, of the object;         * otherwise, null         * @see #setBackground         */        public Color getBackground() {            return getTextComponent().getBackground();        }         /**         * Sets the background color of this object.         *         * @param c the new Color for the background         * @see #setBackground         */        public void setBackground(Color c) {            getTextComponent().setBackground(c);        }         /**         * Gets the foreground color of this object.         *         * @return the foreground color, if supported, of the object;         * otherwise, null         * @see #setForeground         */        public Color getForeground() {            return getTextComponent().getForeground();        }         /**         * Sets the foreground color of this object.         *         * @param c the new Color for the foreground         * @see #getForeground         */        public void setForeground(Color c) {            getTextComponent().setForeground(c);        }         /**         * Gets the Cursor of this object.         *         * @return the Cursor, if supported, of the object; otherwise, null         * @see #setCursor         */        public Cursor getCursor() {            return getTextComponent().getCursor();        }         /**         * Sets the Cursor of this object.         *         * @param cursor the new Cursor for the object         * @see #getCursor         */        public void setCursor(Cursor cursor) {            getTextComponent().setCursor(cursor);        }         /**         * Gets the Font of this object.         *         * @return the Font,if supported, for the object; otherwise, null         * @see #setFont         */        public Font getFont() {            return getTextComponent().getFont();        }         /**         * Sets the Font of this object.         *         * @param f the new Font for the object         * @see #getFont         */        public void setFont(Font f) {            getTextComponent().setFont(f);        }         /**         * Gets the FontMetrics of this object.         *         * @param f the Font         * @return the FontMetrics, if supported, the object; otherwise, null         * @see #getFont         */        public FontMetrics getFontMetrics(Font f) {            return getTextComponent().getFontMetrics(f);        }         /**         * Determines if the object is enabled.  Objects that are enabled         * will also have the AccessibleState.ENABLED state set in their         * AccessibleStateSets.

Lines 1–500 of 3058.