summaryrefslogtreecommitdiff
path: root/selfbraille/WriteData.java
blob: 3c16502b5e6e41534d7244e5244b8436fe370dbe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
 * Copyright (C) 2012 Google Inc.
 *
 * 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.
 */

package com.googlecode.eyesfree.braille.selfbraille;

import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;

/**
 * Represents what should be shown on the braille display for a
 * part of the accessibility node tree.
 */
public class WriteData implements Parcelable {

    private static final String PROP_SELECTION_START = "selectionStart";
    private static final String PROP_SELECTION_END = "selectionEnd";

    private AccessibilityNodeInfo mAccessibilityNodeInfo;
    private CharSequence mText;
    private Bundle mProperties = Bundle.EMPTY;

    /**
     * Returns a new {@link WriteData} instance for the given {@code view}.
     */
    public static WriteData forView(View view) {
        AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain(view);
        WriteData writeData = new WriteData();
        writeData.mAccessibilityNodeInfo = node;
        return writeData;
    }

    public AccessibilityNodeInfo getAccessibilityNodeInfo() {
        return mAccessibilityNodeInfo;
    }

    /**
     * Sets the text to be displayed when the accessibility node associated
     * with this instance has focus.  If this method is not called (or
     * {@code text} is {@code null}), this client relinquishes control over
     * this node.
     */
    public WriteData setText(CharSequence text) {
        mText = text;
        return this;
    }

    public CharSequence getText() {
        return mText;
    }

    /**
     * Sets the start position in the text of a text selection or cursor that
     * should be marked on the display.  A negative value (the default) means
     * no selection will be added.
     */
    public WriteData setSelectionStart(int v) {
        writableProperties().putInt(PROP_SELECTION_START, v);
        return this;
    }

    /**
     * @see {@link #setSelectionStart}.
     */
    public int getSelectionStart() {
        return mProperties.getInt(PROP_SELECTION_START, -1);
    }

    /**
     * Sets the end of the text selection to be marked on the display.  This
     * value should only be non-negative if the selection start is
     * non-negative.  If this value is <= the selection start, the selection
     * is a cursor.  Otherwise, the selection covers the range from
     * start(inclusive) to end (exclusive).
     *
     * @see {@link android.text.Selection}.
     */
    public WriteData setSelectionEnd(int v) {
        writableProperties().putInt(PROP_SELECTION_END, v);
        return this;
    }

    /**
     * @see {@link #setSelectionEnd}.
     */
    public int getSelectionEnd() {
        return mProperties.getInt(PROP_SELECTION_END, -1);
    }

    private Bundle writableProperties() {
        if (mProperties == Bundle.EMPTY) {
            mProperties = new Bundle();
        }
        return mProperties;
    }

    /**
     * Checks constraints on the fields that must be satisfied before sending
     * this instance to the self braille service.
     * @throws IllegalStateException
     */
    public void validate() throws IllegalStateException {
        if (mAccessibilityNodeInfo == null) {
            throw new IllegalStateException(
                "Accessibility node info can't be null");
        }
        int selectionStart = getSelectionStart();
        int selectionEnd = getSelectionEnd();
        if (mText == null) {
            if (selectionStart > 0 || selectionEnd > 0) {
                throw new IllegalStateException(
                    "Selection can't be set without text");
            }
        } else {
            if (selectionStart < 0 && selectionEnd >= 0) {
                throw new IllegalStateException(
                    "Selection end without start");
            }
            int textLength = mText.length();
            if (selectionStart > textLength || selectionEnd > textLength) {
                throw new IllegalStateException("Selection out of bounds");
            }
        }
    }

    // For Parcelable support.

    public static final Parcelable.Creator<WriteData> CREATOR =
        new Parcelable.Creator<WriteData>() {
            @Override
            public WriteData createFromParcel(Parcel in) {
                return new WriteData(in);
            }

            @Override
            public WriteData[] newArray(int size) {
                return new WriteData[size];
            }
        };

    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * {@inheritDoc}
     * <strong>Note:</strong> The {@link AccessibilityNodeInfo} will be
     * recycled by this method, don't try to use this more than once.
     */
    @Override
    public void writeToParcel(Parcel out, int flags) {
        mAccessibilityNodeInfo.writeToParcel(out, flags);
        // The above call recycles the node, so make sure we don't use it
        // anymore.
        mAccessibilityNodeInfo = null;
        out.writeString(mText.toString());
        out.writeBundle(mProperties);
    }

    private WriteData() {
    }

    private WriteData(Parcel in) {
        mAccessibilityNodeInfo =
                AccessibilityNodeInfo.CREATOR.createFromParcel(in);
        mText = in.readString();
        mProperties = in.readBundle();
    }
}