CursorAnchorInfoCompatWrapper.java revision deff9495f771a54b8ea55e07e0d44a0302ea9e10
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 24import java.lang.reflect.Method; 25 26@UsedForTesting 27public final class CursorAnchorInfoCompatWrapper { 28 // Note that CursorAnchorInfo has been introduced in API level XX (Build.VERSION_CODE.LXX). 29 private static Class<?> getCursorAnchorInfoClass() { 30 try { 31 return Class.forName("android.view.inputmethod.CursorAnchorInfo"); 32 } catch (ClassNotFoundException e) { 33 return null; 34 } 35 } 36 private static final Class<?> CLASS; 37 private static final Method METHOD_GET_CHARACTER_RECT; 38 private static final Method METHOD_GET_CHARACTER_RECT_FLAGS; 39 private static final Method METHOD_GET_COMPOSING_TEXT; 40 private static final Method METHOD_GET_COMPOSING_TEXT_START; 41 private static final Method METHOD_GET_MATRIX; 42 static { 43 CLASS = getCursorAnchorInfoClass(); 44 METHOD_GET_CHARACTER_RECT = CompatUtils.getMethod(CLASS, "getCharacterRect", int.class); 45 METHOD_GET_CHARACTER_RECT_FLAGS = CompatUtils.getMethod(CLASS, "getCharacterRectFlags", 46 int.class); 47 METHOD_GET_COMPOSING_TEXT = CompatUtils.getMethod(CLASS, "getComposingText"); 48 METHOD_GET_COMPOSING_TEXT_START = CompatUtils.getMethod(CLASS, "getComposingTextStart"); 49 METHOD_GET_MATRIX = CompatUtils.getMethod(CLASS, "getMatrix"); 50 } 51 52 @UsedForTesting 53 public static boolean isAvailable() { 54 return CLASS != null; 55 } 56 57 public static final int CHARACTER_RECT_TYPE_MASK = 0x0f; 58 59 /** 60 * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor did not specify any type of this 61 * character. Editor authors should not use this flag. 62 */ 63 public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0; 64 65 /** 66 * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely visible. 67 */ 68 public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; 69 70 /** 71 * Type for {@link #CHARACTER_RECT_TYPE_MASK}: some area of the character is invisible. 72 */ 73 public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2; 74 75 /** 76 * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely invisible. 77 */ 78 public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; 79 80 /** 81 * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor gave up to calculate the rectangle 82 * for this character. Input method authors should ignore the returned rectangle. 83 */ 84 public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4; 85 86 private Object mInstance; 87 88 private CursorAnchorInfoCompatWrapper(final Object instance) { 89 mInstance = instance; 90 } 91 92 @UsedForTesting 93 public static CursorAnchorInfoCompatWrapper fromObject(final Object instance) { 94 if (!isAvailable()) { 95 return new CursorAnchorInfoCompatWrapper(null); 96 } 97 return new CursorAnchorInfoCompatWrapper(instance); 98 } 99 100 private static final class FakeHolder { 101 static CursorAnchorInfoCompatWrapper sInstance = new CursorAnchorInfoCompatWrapper(null); 102 } 103 104 @UsedForTesting 105 public static CursorAnchorInfoCompatWrapper getFake() { 106 return FakeHolder.sInstance; 107 } 108 109 public CharSequence getComposingText() { 110 return (CharSequence) CompatUtils.invoke(mInstance, null, METHOD_GET_COMPOSING_TEXT); 111 } 112 113 private static int COMPOSING_TEXT_START_DEFAULT = -1; 114 public int getComposingTextStart() { 115 if (mInstance == null || METHOD_GET_COMPOSING_TEXT_START == null) { 116 return COMPOSING_TEXT_START_DEFAULT; 117 } 118 return (int) CompatUtils.invoke(mInstance, null, METHOD_GET_COMPOSING_TEXT_START); 119 } 120 121 public Matrix getMatrix() { 122 return (Matrix) CompatUtils.invoke(mInstance, null, METHOD_GET_MATRIX); 123 } 124 125 public RectF getCharacterRect(final int index) { 126 return (RectF) CompatUtils.invoke(mInstance, null, METHOD_GET_CHARACTER_RECT, index); 127 } 128 129 public int getCharacterRectFlags(final int index) { 130 if (mInstance == null || METHOD_GET_CHARACTER_RECT_FLAGS == null) { 131 return CHARACTER_RECT_TYPE_UNSPECIFIED; 132 } 133 return (int) CompatUtils.invoke(mInstance, null, METHOD_GET_CHARACTER_RECT_FLAGS, index); 134 } 135} 136