CursorAnchorInfoCompatWrapper.java revision de12c1bf49efb6ac9b7127933eebb08956488ace
1/*
2 * Copyright (C) 2014 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 com.android.inputmethod.compat;
18
19import android.graphics.Matrix;
20import android.graphics.RectF;
21
22import com.android.inputmethod.annotations.UsedForTesting;
23
24@UsedForTesting
25public final class CursorAnchorInfoCompatWrapper {
26
27    /**
28     * The insertion marker or character bounds have at least one visible region.
29     */
30    public static final int FLAG_HAS_VISIBLE_REGION = 0x01;
31
32    /**
33     * The insertion marker or character bounds have at least one invisible (clipped) region.
34     */
35    public static final int FLAG_HAS_INVISIBLE_REGION = 0x02;
36
37    /**
38     * The insertion marker or character bounds is placed at right-to-left (RTL) character.
39     */
40    public static final int FLAG_IS_RTL = 0x04;
41
42    // Note that CursorAnchorInfo has been introduced in API level XX (Build.VERSION_CODE.LXX).
43    private static final CompatUtils.ClassWrapper sCursorAnchorInfoClass;
44    private static final CompatUtils.ToIntMethodWrapper sGetSelectionStartMethod;
45    private static final CompatUtils.ToIntMethodWrapper sGetSelectionEndMethod;
46    private static final CompatUtils.ToObjectMethodWrapper<RectF> sGetCharacterBoundsMethod;
47    private static final CompatUtils.ToIntMethodWrapper sGetCharacterBoundsFlagsMethod;
48    private static final CompatUtils.ToObjectMethodWrapper<CharSequence> sGetComposingTextMethod;
49    private static final CompatUtils.ToIntMethodWrapper sGetComposingTextStartMethod;
50    private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerBaselineMethod;
51    private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerBottomMethod;
52    private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerHorizontalMethod;
53    private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerTopMethod;
54    private static final CompatUtils.ToObjectMethodWrapper<Matrix> sGetMatrixMethod;
55    private static final CompatUtils.ToIntMethodWrapper sGetInsertionMarkerFlagsMethod;
56
57    private static int INVALID_TEXT_INDEX = -1;
58    static {
59        sCursorAnchorInfoClass = CompatUtils.getClassWrapper(
60                "android.view.inputmethod.CursorAnchorInfo");
61        sGetSelectionStartMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
62                "getSelectionStart", INVALID_TEXT_INDEX);
63        sGetSelectionEndMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
64                "getSelectionEnd", INVALID_TEXT_INDEX);
65        sGetCharacterBoundsMethod = sCursorAnchorInfoClass.getMethod(
66                "getCharacterBounds", (RectF)null, int.class);
67        sGetCharacterBoundsFlagsMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
68                "getCharacterBoundsFlags", 0, int.class);
69        sGetComposingTextMethod = sCursorAnchorInfoClass.getMethod(
70                "getComposingText", (CharSequence)null);
71        sGetComposingTextStartMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
72                "getComposingTextStart", INVALID_TEXT_INDEX);
73        sGetInsertionMarkerBaselineMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
74                "getInsertionMarkerBaseline", 0.0f);
75        sGetInsertionMarkerBottomMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
76                "getInsertionMarkerBottom", 0.0f);
77        sGetInsertionMarkerHorizontalMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
78                "getInsertionMarkerHorizontal", 0.0f);
79        sGetInsertionMarkerTopMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
80                "getInsertionMarkerTop", 0.0f);
81        sGetMatrixMethod = sCursorAnchorInfoClass.getMethod("getMatrix", (Matrix)null);
82        sGetInsertionMarkerFlagsMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
83                "getInsertionMarkerFlags", 0);
84    }
85
86    @UsedForTesting
87    public boolean isAvailable() {
88        return sCursorAnchorInfoClass.exists() && mInstance != null;
89    }
90
91    private Object mInstance;
92
93    private CursorAnchorInfoCompatWrapper(final Object instance) {
94        mInstance = instance;
95    }
96
97    @UsedForTesting
98    public static CursorAnchorInfoCompatWrapper fromObject(final Object instance) {
99        if (!sCursorAnchorInfoClass.exists()) {
100            return new CursorAnchorInfoCompatWrapper(null);
101        }
102        return new CursorAnchorInfoCompatWrapper(instance);
103    }
104
105    private static final class FakeHolder {
106        static CursorAnchorInfoCompatWrapper sInstance = new CursorAnchorInfoCompatWrapper(null);
107    }
108
109    @UsedForTesting
110    public static CursorAnchorInfoCompatWrapper getFake() {
111        return FakeHolder.sInstance;
112    }
113
114    public int getSelectionStart() {
115        return sGetSelectionStartMethod.invoke(mInstance);
116    }
117
118    public int getSelectionEnd() {
119        return sGetSelectionEndMethod.invoke(mInstance);
120    }
121
122    public CharSequence getComposingText() {
123        return sGetComposingTextMethod.invoke(mInstance);
124    }
125
126    public int getComposingTextStart() {
127        return sGetComposingTextStartMethod.invoke(mInstance);
128    }
129
130    public Matrix getMatrix() {
131        return sGetMatrixMethod.invoke(mInstance);
132    }
133
134    public RectF getCharacterBounds(final int index) {
135        return sGetCharacterBoundsMethod.invoke(mInstance, index);
136    }
137
138    public int getCharacterBoundsFlags(final int index) {
139        return sGetCharacterBoundsFlagsMethod.invoke(mInstance, index);
140    }
141
142    public float getInsertionMarkerBaseline() {
143        return sGetInsertionMarkerBaselineMethod.invoke(mInstance);
144    }
145
146    public float getInsertionMarkerBottom() {
147        return sGetInsertionMarkerBottomMethod.invoke(mInstance);
148    }
149
150    public float getInsertionMarkerHorizontal() {
151        return sGetInsertionMarkerHorizontalMethod.invoke(mInstance);
152    }
153
154    public float getInsertionMarkerTop() {
155        return sGetInsertionMarkerTopMethod.invoke(mInstance);
156    }
157
158    public int getInsertionMarkerFlags() {
159        return sGetInsertionMarkerFlagsMethod.invoke(mInstance);
160    }
161}
162