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;
18
19/**
20 * InputFilters can be attached to {@link Editable}s to constrain the
21 * changes that can be made to them.
22 */
23public interface InputFilter
24{
25    /**
26     * This method is called when the buffer is going to replace the
27     * range <code>dstart &hellip; dend</code> of <code>dest</code>
28     * with the new text from the range <code>start &hellip; end</code>
29     * of <code>source</code>.  Return the CharSequence that you would
30     * like to have placed there instead, including an empty string
31     * if appropriate, or <code>null</code> to accept the original
32     * replacement.  Be careful to not to reject 0-length replacements,
33     * as this is what happens when you delete text.  Also beware that
34     * you should not attempt to make any changes to <code>dest</code>
35     * from this method; you may only examine it for context.
36     *
37     * Note: If <var>source</var> is an instance of {@link Spanned} or
38     * {@link Spannable}, the span objects in the <var>source</var> should be
39     * copied into the filtered result (i.e. the non-null return value).
40     * {@link TextUtils#copySpansFrom} can be used for convenience.
41     */
42    public CharSequence filter(CharSequence source, int start, int end,
43                               Spanned dest, int dstart, int dend);
44
45    /**
46     * This filter will capitalize all the lower case letters that are added
47     * through edits.
48     */
49    public static class AllCaps implements InputFilter {
50        public CharSequence filter(CharSequence source, int start, int end,
51                                   Spanned dest, int dstart, int dend) {
52            for (int i = start; i < end; i++) {
53                if (Character.isLowerCase(source.charAt(i))) {
54                    char[] v = new char[end - start];
55                    TextUtils.getChars(source, start, end, v, 0);
56                    String s = new String(v).toUpperCase();
57
58                    if (source instanceof Spanned) {
59                        SpannableString sp = new SpannableString(s);
60                        TextUtils.copySpansFrom((Spanned) source,
61                                                start, end, null, sp, 0);
62                        return sp;
63                    } else {
64                        return s;
65                    }
66                }
67            }
68
69            return null; // keep original
70        }
71    }
72
73    /**
74     * This filter will constrain edits not to make the length of the text
75     * greater than the specified length.
76     */
77    public static class LengthFilter implements InputFilter {
78        private final int mMax;
79
80        public LengthFilter(int max) {
81            mMax = max;
82        }
83
84        public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
85                int dstart, int dend) {
86            int keep = mMax - (dest.length() - (dend - dstart));
87            if (keep <= 0) {
88                return "";
89            } else if (keep >= end - start) {
90                return null; // keep original
91            } else {
92                keep += start;
93                if (Character.isHighSurrogate(source.charAt(keep - 1))) {
94                    --keep;
95                    if (keep == start) {
96                        return "";
97                    }
98                }
99                return source.subSequence(start, keep);
100            }
101        }
102
103        /**
104         * @return the maximum length enforced by this input filter
105         */
106        public int getMax() {
107            return mMax;
108        }
109    }
110}
111