BaseKeyListener.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.text.method;
18
19import android.view.KeyEvent;
20import android.view.View;
21import android.text.*;
22import android.text.method.TextKeyListener.Capitalize;
23import android.widget.TextView;
24
25public abstract class BaseKeyListener
26extends MetaKeyKeyListener
27implements KeyListener {
28    /* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
29
30    /**
31     * Performs the action that happens when you press the DEL key in
32     * a TextView.  If there is a selection, deletes the selection;
33     * otherwise, DEL alone deletes the character before the cursor,
34     * if any;
35     * ALT+DEL deletes everything on the line the cursor is on.
36     *
37     * @return true if anything was deleted; false otherwise.
38     */
39    public boolean backspace(View view, Editable content, int keyCode,
40                             KeyEvent event) {
41        int selStart, selEnd;
42        boolean result = true;
43
44        {
45            int a = Selection.getSelectionStart(content);
46            int b = Selection.getSelectionEnd(content);
47
48            selStart = Math.min(a, b);
49            selEnd = Math.max(a, b);
50        }
51
52        if (selStart != selEnd) {
53            content.delete(selStart, selEnd);
54        } else if (altBackspace(view, content, keyCode, event)) {
55            result = true;
56        } else {
57            int to = TextUtils.getOffsetBefore(content, selEnd);
58
59            if (to != selEnd) {
60                content.delete(Math.min(to, selEnd), Math.max(to, selEnd));
61            }
62            else {
63                result = false;
64            }
65        }
66
67        if (result)
68            adjustMetaAfterKeypress(content);
69
70        return result;
71    }
72
73    private boolean altBackspace(View view, Editable content, int keyCode,
74                                 KeyEvent event) {
75        if (getMetaState(content, META_ALT_ON) != 1) {
76            return false;
77        }
78
79        if (!(view instanceof TextView)) {
80            return false;
81        }
82
83        Layout layout = ((TextView) view).getLayout();
84
85        if (layout == null) {
86            return false;
87        }
88
89        int l = layout.getLineForOffset(Selection.getSelectionStart(content));
90        int start = layout.getLineStart(l);
91        int end = layout.getLineEnd(l);
92
93        if (end == start) {
94            return false;
95        }
96
97        content.delete(start, end);
98        return true;
99    }
100
101    static int makeTextContentType(Capitalize caps, boolean autoText) {
102        int contentType = InputType.TYPE_CLASS_TEXT;
103        switch (caps) {
104            case CHARACTERS:
105                contentType |= InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
106                break;
107            case WORDS:
108                contentType |= InputType.TYPE_TEXT_FLAG_CAP_WORDS;
109                break;
110            case SENTENCES:
111                contentType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
112                break;
113        }
114        if (autoText) {
115            contentType |= InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
116        }
117        return contentType;
118    }
119
120    public boolean onKeyDown(View view, Editable content,
121                             int keyCode, KeyEvent event) {
122        if (keyCode == KeyEvent.KEYCODE_DEL) {
123            backspace(view, content, keyCode, event);
124            return true;
125        }
126
127        return super.onKeyDown(view, content, keyCode, event);
128    }
129
130    /**
131     * Base implementation handles ACTION_MULTIPLE KEYCODE_UNKNOWN by inserting
132     * the event's text into the content.
133     */
134    public boolean onKeyOther(View view, Editable content, KeyEvent event) {
135        if (event.getAction() != KeyEvent.ACTION_MULTIPLE
136                || event.getKeyCode() != KeyEvent.KEYCODE_UNKNOWN) {
137            // Not something we are interested in.
138            return false;
139        }
140
141        int selStart, selEnd;
142
143        {
144            int a = Selection.getSelectionStart(content);
145            int b = Selection.getSelectionEnd(content);
146
147            selStart = Math.min(a, b);
148            selEnd = Math.max(a, b);
149        }
150
151        CharSequence text = event.getCharacters();
152        if (text == null) {
153            return false;
154        }
155
156        content.replace(selStart, selEnd, text);
157        return true;
158    }
159}
160
161