summaryrefslogtreecommitdiff
path: root/src/com/android/inputmethod/pinyin/SoftKeyToggle.java
blob: 89ff2fe6f3ecf60669fdc9bd41207989eed016c6 (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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * 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.android.inputmethod.pinyin;

import android.graphics.drawable.Drawable;

/**
 * Class for soft keys which defined in the keyboard xml file. A soft key can be
 * a basic key or a toggling key.
 * 
 * @see com.android.inputmethod.pinyin.SoftKey
 */
public class SoftKeyToggle extends SoftKey {
    /**
     * The current state number is stored in the lowest 8 bits of mKeyMask, this
     * mask is used to get the state number. If the current state is 0, the
     * normal state is enabled; if the current state is more than 0, a toggle
     * state in the toggle state chain will be enabled.
     */
    private static final int KEYMASK_TOGGLE_STATE = 0x000000ff;

    private ToggleState mToggleState;

    public int getToggleStateId() {
        return (mKeyMask & KEYMASK_TOGGLE_STATE);
    }

    // The state id should be valid, and less than 255.
    // If resetIfNotFound is true and there is no such toggle state with the
    // given id, the key state will be reset.
    // If the key state is newly changed (enabled to the given state, or
    // reseted) and needs re-draw, return true.
    public boolean enableToggleState(int stateId, boolean resetIfNotFound) {
        int oldStateId = (mKeyMask & KEYMASK_TOGGLE_STATE);
        if (oldStateId == stateId) return false;

        mKeyMask &= (~KEYMASK_TOGGLE_STATE);
        if (stateId > 0) {
            mKeyMask |= (KEYMASK_TOGGLE_STATE & stateId);
            if (getToggleState() == null) {
                mKeyMask &= (~KEYMASK_TOGGLE_STATE);
                if (!resetIfNotFound && oldStateId > 0) {
                    mKeyMask |= (KEYMASK_TOGGLE_STATE & oldStateId);
                }
                return resetIfNotFound;
            } else {
                return true;
            }
        } else {
            return true;
        }
    }

    // The state id should be valid, and less than 255.
    // If resetIfNotFound is true and there is no such toggle state with the
    // given id, the key state will be reset.
    // If the key state is newly changed and needs re-draw, return true.
    public boolean disableToggleState(int stateId, boolean resetIfNotFound) {
        int oldStateId = (mKeyMask & KEYMASK_TOGGLE_STATE);
        if (oldStateId == stateId) {
            mKeyMask &= (~KEYMASK_TOGGLE_STATE);
            return stateId != 0;
        }

        if (resetIfNotFound) {
            mKeyMask &= (~KEYMASK_TOGGLE_STATE);
            return oldStateId != 0;
        }
        return false;
    }

    // Clear any toggle state. If the key needs re-draw, return true.
    public boolean disableAllToggleStates() {
        int oldStateId = (mKeyMask & KEYMASK_TOGGLE_STATE);
        mKeyMask &= (~KEYMASK_TOGGLE_STATE);
        return oldStateId != 0;
    }

    @Override
    public Drawable getKeyIcon() {
        ToggleState state = getToggleState();
        if (null != state) return state.mKeyIcon;
        return super.getKeyIcon();
    }

    @Override
    public Drawable getKeyIconPopup() {
        ToggleState state = getToggleState();
        if (null != state) {
            if (null != state.mKeyIconPopup) {
                return state.mKeyIconPopup;
            } else {
                return state.mKeyIcon;
            }
        }
        return super.getKeyIconPopup();
    }

    @Override
    public int getKeyCode() {
        ToggleState state = getToggleState();
        if (null != state) return state.mKeyCode;
        return mKeyCode;
    }

    @Override
    public String getKeyLabel() {
        ToggleState state = getToggleState();
        if (null != state) return state.mKeyLabel;
        return mKeyLabel;
    }

    @Override
    public Drawable getKeyBg() {
        ToggleState state = getToggleState();
        if (null != state && null != state.mKeyType) {
            return state.mKeyType.mKeyBg;
        }
        return mKeyType.mKeyBg;
    }

    @Override
    public Drawable getKeyHlBg() {
        ToggleState state = getToggleState();
        if (null != state && null != state.mKeyType) {
            return state.mKeyType.mKeyHlBg;
        }
        return mKeyType.mKeyHlBg;
    }

    @Override
    public int getColor() {
        ToggleState state = getToggleState();
        if (null != state && null != state.mKeyType) {
            return state.mKeyType.mColor;
        }
        return mKeyType.mColor;
    }

    @Override
    public int getColorHl() {
        ToggleState state = getToggleState();
        if (null != state && null != state.mKeyType) {
            return state.mKeyType.mColorHl;
        }
        return mKeyType.mColorHl;
    }

    @Override
    public int getColorBalloon() {
        ToggleState state = getToggleState();
        if (null != state && null != state.mKeyType) {
            return state.mKeyType.mColorBalloon;
        }
        return mKeyType.mColorBalloon;
    }

    @Override
    public boolean isKeyCodeKey() {
        ToggleState state = getToggleState();
        if (null != state) {
            if (state.mKeyCode > 0) return true;
            return false;
        }
        return super.isKeyCodeKey();
    }

    @Override
    public boolean isUserDefKey() {
        ToggleState state = getToggleState();
        if (null != state) {
            if (state.mKeyCode < 0) return true;
            return false;
        }
        return super.isUserDefKey();
    }

    @Override
    public boolean isUniStrKey() {
        ToggleState state = getToggleState();
        if (null != state) {
            if (null != state.mKeyLabel && state.mKeyCode == 0) {
                return true;
            }
            return false;
        }
        return super.isUniStrKey();
    }

    @Override
    public boolean needBalloon() {
        ToggleState state = getToggleState();
        if (null != state) {
            return (state.mIdAndFlags & KEYMASK_BALLOON) != 0;
        }
        return super.needBalloon();
    }

    @Override
    public boolean repeatable() {
        ToggleState state = getToggleState();
        if (null != state) {
            return (state.mIdAndFlags & KEYMASK_REPEAT) != 0;
        }
        return super.repeatable();
    }

    @Override
    public void changeCase(boolean lowerCase) {
        ToggleState state = getToggleState();
        if (null != state && null != state.mKeyLabel) {
            if (lowerCase)
                state.mKeyLabel = state.mKeyLabel.toLowerCase();
            else
                state.mKeyLabel = state.mKeyLabel.toUpperCase();
        }
    }

    public ToggleState createToggleState() {
        return new ToggleState();
    }

    public boolean setToggleStates(ToggleState rootState) {
        if (null == rootState) return false;
        mToggleState = rootState;
        return true;
    }

    private ToggleState getToggleState() {
        int stateId = (mKeyMask & KEYMASK_TOGGLE_STATE);
        if (0 == stateId) return null;

        ToggleState state = mToggleState;
        while ((null != state)
                && (state.mIdAndFlags & KEYMASK_TOGGLE_STATE) != stateId) {
            state = state.mNextState;
        }
        return state;
    }

    public class ToggleState {
        // The id should be bigger than 0;
        private int mIdAndFlags;
        public SoftKeyType mKeyType;
        public int mKeyCode;
        public Drawable mKeyIcon;
        public Drawable mKeyIconPopup;
        public String mKeyLabel;
        public ToggleState mNextState;

        public void setStateId(int stateId) {
            mIdAndFlags |= (stateId & KEYMASK_TOGGLE_STATE);
        }

        public void setStateFlags(boolean repeat, boolean balloon) {
            if (repeat) {
                mIdAndFlags |= KEYMASK_REPEAT;
            } else {
                mIdAndFlags &= (~KEYMASK_REPEAT);
            }

            if (balloon) {
                mIdAndFlags |= KEYMASK_BALLOON;
            } else {
                mIdAndFlags &= (~KEYMASK_BALLOON);
            }
        }
    }
}