Package com.rim.samples.device.accessibilitydemo.customcomponentsdemo

Source Code of com.rim.samples.device.accessibilitydemo.customcomponentsdemo.TextComponent$TextComponentStringTokenizer

/*
* TextComponent.java
*
* Copyright � 1998-2011 Research In Motion Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Note: For the sake of simplicity, this sample application may not leverage
* resource bundles and resource strings.  However, it is STRONGLY recommended
* that application developers make use of the localization features available
* within the BlackBerry development platform to ensure a seamless application
* experience across a variety of languages and geographies.  For more information
* on localizing your application, please refer to the BlackBerry Java Development
* Environment Development Guide associated with this release.
*/

package com.rim.samples.device.accessibilitydemo.customcomponentsdemo;

import java.util.Vector;

import net.rim.device.api.system.Display;
import net.rim.device.api.ui.AccessibleEventDispatcher;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.accessibility.AccessibleContext;
import net.rim.device.api.ui.accessibility.AccessibleRole;
import net.rim.device.api.ui.accessibility.AccessibleState;
import net.rim.device.api.ui.accessibility.AccessibleTable;
import net.rim.device.api.ui.accessibility.AccessibleText;
import net.rim.device.api.ui.accessibility.AccessibleValue;
import net.rim.device.api.ui.text.TextFilter;

/**
* Sample implementation for a textual accessible UI component. Provides the
* screen reader application with the text data contained in the the custom
* field and information about changes to the textual data. This field's text is
* split up into lines and words
*/
public final class TextComponent extends Field implements AccessibleContext,
        AccessibleText {
    private final String _text;
    private int _state;

    // Lines and words are stored in Vectors so that a line or word at a given
    // index can be returned by the AccessibleText.getAtIndex() method.
    private Vector _lines; // Contains the text split into lines based on
                           // component's width
    private Vector _words; // Contains the text split into words based on
                           // whitespaces

    /**
     * Constructs a new TextComponent
     *
     * @param text
     *            The text to be displayed by this component
     */
    public TextComponent(final String text) {
        super(Field.FOCUSABLE);

        _text = text;
    }

    // *********************** Field implementation ****************************

    /**
     * @see Field#getAccessibleContext()
     */
    public AccessibleContext getAccessibleContext() {
        return this;
    }

    /**
     * @see Field#getPreferredWidth()
     */
    public int getPreferredWidth() {
        return Display.getWidth();
    }

    /**
     * @see Field#getPreferredHeight()
     */
    public int getPreferredHeight() {
        return Math.max(20, _lines.size() * 30);
    }

    /**
     * @see Field#layout(int, int)
     */
    protected void layout(final int width, final int height) {
        // Split text into lines based on the given width
        final StringBuffer currentLine = new StringBuffer();
        final Font font = getFont();
        _lines = new Vector();
        _words = new Vector();

        // Add words one by one and form lines
        final TextComponentStringTokenizer tokenizer =
                new TextComponentStringTokenizer(_text);
        while (tokenizer.hasMoreTokens()) {
            final String word = tokenizer.nextToken();
            _words.addElement(word);

            if (font.getAdvance(currentLine.toString() + word) < width) {
                // Current word still fits into the line, add it
                currentLine.append(word);
            } else {
                // The word doesn't fit, make a new line
                _lines.addElement(currentLine.toString());
                currentLine.setLength(0);
                currentLine.append(word);
            }
        }

        if (currentLine.length() > 0) {
            _lines.addElement(currentLine.toString());
        }

        setExtent(getPreferredWidth(), getPreferredHeight());
    }

    /**
     * @see Field#onFocus(int)
     */
    protected void onFocus(final int direction) {
        super.onFocus(direction);

        // Update accessible state and notify screen reader
        final int oldState = _state;
        _state = _state | AccessibleState.FOCUSED;
        AccessibleEventDispatcher.dispatchAccessibleEvent(
                AccessibleContext.ACCESSIBLE_STATE_CHANGED, new Integer(
                        oldState), new Integer(_state), this);
    }

    /**
     * @see Field#onFocus(int)
     */
    protected void onUnfocus() {
        super.onUnfocus();

        // Update accessible state and notify screen reader
        final int oldState = _state;
        _state = _state & ~AccessibleState.FOCUSED;
        AccessibleEventDispatcher.dispatchAccessibleEvent(
                AccessibleContext.ACCESSIBLE_STATE_CHANGED, new Integer(
                        oldState), new Integer(_state), this);
    }

    /**
     * @see Field#paint(Graphics)
     */
    protected void paint(final Graphics graphics) {
        int y = 0;
        final int fontHeight = graphics.getFont().getHeight();

        // Paint text line by line.
        final int linesCount = _lines.size();
        for (int i = 0; i < linesCount; i++) {
            graphics.drawText((String) _lines.elementAt(i), 0, y);
            y += fontHeight;
        }
    }

    // ******************** AccessibleContext implementation *******************

    /**
     * @see AccessibleContext#getAccessibleText()
     */
    public AccessibleText getAccessibleText() {
        // The component implements AccessibleText
        return this;
    }

    /**
     * @see AccessibleContext#getAccessibleName()
     */
    public String getAccessibleName() {
        // The name of the sample component,
        // will be read by the reader.
        return " My Text Field ";
    }

    /**
     * @see AccessibleContext#getAccessibleParent()
     */
    public AccessibleContext getAccessibleParent() {
        // Return manager where text component is added
        final Manager manager = getManager();
        return manager != null ? manager.getAccessibleContext() : null;
    }

    /**
     * @see AccessibleContext#getAccessibleRole()
     */
    public int getAccessibleRole() {
        // Component serves as a text field.
        return AccessibleRole.TEXT_FIELD;
    }

    /**
     * @see AccessibleContext#getAccessibleStateSet()
     */
    public int getAccessibleStateSet() {
        // Text component can be focused but not edited
        final boolean focused = isFocus();

        if (focused) {
            return AccessibleState.FOCUSED | AccessibleState.FOCUSABLE;
        } else {
            return AccessibleState.FOCUSABLE;
        }
    }

    /**
     * @see AccessibleContext#isAccessibleStateSet(int)
     */
    public boolean isAccessibleStateSet(final int state) {
        return (state & getAccessibleStateSet()) != 0;
    }

    /**
     * @see AccessibleContext#getAccessibleChildAt(int)
     */
    public AccessibleContext getAccessibleChildAt(final int index) {
        // Text field doesn't have any children
        return null;
    }

    /**
     * @see AccessibleContext#getAccessibleChildCount()
     */
    public int getAccessibleChildCount() {
        // Text field doesn't have any children
        return 0;
    }

    /**
     * @see AccessibleContext#getAccessibleSelectionAt(int)
     */
    public AccessibleContext getAccessibleSelectionAt(final int index) {
        // Text field doesn't have any children
        return null;
    }

    /**
     * @see AccessibleContext#getAccessibleSelectionCount()
     */
    public int getAccessibleSelectionCount() {
        // Text field doesn't have any children
        return 0;
    }

    /**
     * @see AccessibleContext#getAccessibleTable()
     */
    public AccessibleTable getAccessibleTable() {
        // This is a text component, not a table
        return null;
    }

    /**
     * @see AccessibleContext#getAccessibleValue()
     */
    public AccessibleValue getAccessibleValue() {
        // This is a text component, no numerical values
        return null;
    }

    /**
     * @see AccessibleContext#isAccessibleChildSelected(int)
     */
    public boolean isAccessibleChildSelected(final int index) {
        // Text field doesn't have any children
        return false;
    }

    // ******************** AccessibleText implementation *******************

    /**
     * @see AccessibleText#getAtIndex(int, int)
     */
    public String getAtIndex(final int part, final int index) {
        // Return character, line or word at the given index
        switch (part) {
        case AccessibleText.CHAR:
            return String.valueOf(_text.charAt(index));

        case AccessibleText.LINE:
            return (String) _lines.elementAt(index);

        case AccessibleText.WORD:
            return (String) _words.elementAt(index);
        }

        return null;
    }

    /**
     * @see AccessibleText#getCaretPosition()
     */
    public int getCaretPosition() {
        // Our text component is not editable and doesn't support caret
        // navigation
        return 0;
    }

    /**
     * @see AccessibleText#getCharCount()
     */
    public int getCharCount() {
        // Number of characters
        return _text.length();
    }

    /**
     * @see AccessibleText#getInputFilterStyle()
     */
    public int getInputFilterStyle() {
        return TextFilter.DEFAULT;
    }

    /**
     * @see AccessibleText#getLineCount()
     */
    public int getLineCount() {
        // Number of lines in the component, based on current width
        return _lines.size();
    }

    /**
     * @see AccessibleText#getSelectionEnd()
     */
    public int getSelectionEnd() {
        // Text component doesn't have text selection feature
        return 0;
    }

    /**
     * @see AccessibleText#getSelectionStart()
     */
    public int getSelectionStart() {
        // Text component doesn't have text selection feature
        return 0;
    }

    /**
     * @see AccessibleText#getSelectionText()
     */
    public String getSelectionText() {
        // Text component doesn't have text selection feature
        return _text;
    }

    /**
     * @see AccessibleText#getWholeText()
     */
    public String getWholeText() {
        // Return the whole text
        return _text;
    }

    /**
     * A string tokenizer class used by the TextComponent class
     */
    private static final class TextComponentStringTokenizer {
        private int _currentPosition;
        private int _newPosition;
        private final int _maxPosition;
        private final String _str;
        private final String _delimiter;
        private boolean _delimsChanged;

        /**
         * Constructor
         *
         * @param str
         *            The string to be parsed
         * @param delim
         *            The delimiters to split the string on
         * @param returnDelims
         *            Flag indicating whether to return the delimiters as tokens
         */
        private TextComponentStringTokenizer(final String str) {
            // Initialize members
            _currentPosition = 0;
            _newPosition = -1;
            _str = str;
            _maxPosition = _str.length();
            _delimiter = " ";
        }

        /**
         * Tests if there are more tokens available from this tokenizer's string
         *
         * @return True if there is at least one token in the string after the
         *         current position, otherwise false
         */
        boolean hasMoreTokens() {
            return _currentPosition < _maxPosition;
        }

        /**
         * Returns the next token from this string tokenizer
         *
         * @return The next token from this string tokenizer
         */
        String nextToken() {
            _currentPosition =
                    _newPosition >= 0 && !_delimsChanged ? _newPosition
                            : _currentPosition;
            _delimsChanged = false;
            _newPosition = -1;

            if (_currentPosition >= _maxPosition) {
                return null;
            }
            final int start = _currentPosition;
            _currentPosition = scanToken(_currentPosition);
            return _str.substring(start, _currentPosition);
        }

        /**
         * Returns the end position of the next token
         *
         * @param startPos
         *            Start position of the token
         * @return The end position of the next token
         */
        private int scanToken(final int startPos) {
            int position = startPos;
            while (position < _maxPosition) {
                final char c = _str.charAt(position);

                if (_delimiter.indexOf(c) >= 0) {
                    break;
                }
                ++position;
            }
            if (startPos == position) {
                final char c = _str.charAt(position);

                if (_delimiter.indexOf(c) >= 0) {
                    ++position;
                }
            }
            return position;
        }
    }
}
TOP

Related Classes of com.rim.samples.device.accessibilitydemo.customcomponentsdemo.TextComponent$TextComponentStringTokenizer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.