SuggestionStripView.java revision ae5c736e37973e26b201d45ff6c139862a6e05cf
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/* 2e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka * Copyright (C) 2010 The Android Open Source Project 3e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka * 4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of 6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at 7e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka * 8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka * 10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under 14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License. 15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 17923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpackage com.android.inputmethod.latin; 18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context; 2066a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasaniimport android.content.res.Resources; 2108a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaokaimport android.content.res.TypedArray; 226f7218627eda110a8454053f8ecb7b80edfdc8cesatokimport android.graphics.Color; 23923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.graphics.Typeface; 24e583371b13ebd9aa336d0883e8c174ae4918c758Tadashi G. Takaokaimport android.graphics.drawable.Drawable; 25e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.os.Message; 26522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaokaimport android.text.Spannable; 27522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaokaimport android.text.SpannableString; 28e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.text.Spanned; 29b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaokaimport android.text.TextPaint; 30e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.text.TextUtils; 3155b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaokaimport android.text.style.BackgroundColorSpan; 32522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaokaimport android.text.style.CharacterStyle; 3355b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaokaimport android.text.style.ForegroundColorSpan; 3474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaokaimport android.text.style.StyleSpan; 35522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaokaimport android.text.style.UnderlineSpan; 36923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.AttributeSet; 37923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.Gravity; 38923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.LayoutInflater; 39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View; 40e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.view.View.OnClickListener; 41ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaokaimport android.view.View.OnLongClickListener; 42e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.view.ViewGroup; 43e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.widget.LinearLayout; 44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.widget.PopupWindow; 45923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.widget.TextView; 46923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 47a7eed902f1b0d6871d416412b3c6f91163fa2578Tadashi G. Takaokaimport com.android.inputmethod.compat.FrameLayoutCompatUtils; 48f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaokaimport com.android.inputmethod.compat.LinearLayoutCompatUtils; 49ddb61ea461b920d87be4ad78c8a36eec1013b965Tadashi G. Takaokaimport com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; 50ddb61ea461b920d87be4ad78c8a36eec1013b965Tadashi G. Takaoka 51179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaokaimport java.util.ArrayList; 526f7218627eda110a8454053f8ecb7b80edfdc8cesatokimport java.util.List; 53179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka 54ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaokapublic class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener { 55c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka public interface Listener { 56c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka public boolean addWordToDictionary(String word); 57c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka public void pickSuggestionManually(int index, CharSequence word); 58c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka } 59c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka 6086e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}. 6186e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka private static final int MAX_SUGGESTIONS = 18; 6274b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka private static final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT; 633118277dd47492089761c0ed1097abaeb376395cTadashi G. Takaoka private static final int MATCH_PARENT = ViewGroup.LayoutParams.MATCH_PARENT; 64923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 658553b5ec315660ab53dd9234e64e1e39ea09ec0fJean Chalard private static final boolean DBG = LatinImeLogger.sDBG; 666f7218627eda110a8454053f8ecb7b80edfdc8cesatok 6774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka private final ViewGroup mCandidatesStrip; 6886e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka private ViewGroup mCandidatesPane; 6986e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka private ViewGroup mCandidatesPaneContainer; 7086e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka private View mKeyboardView; 7174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 721e273fa6d1e8babfebebbbe331d87d3854755e7fTadashi G. Takaoka private final ArrayList<TextView> mWords = new ArrayList<TextView>(); 732442e779857e7eda253aadcb1c4dff5ccb3e53f4Tadashi G. Takaoka private final ArrayList<TextView> mInfos = new ArrayList<TextView>(); 74ddb61ea461b920d87be4ad78c8a36eec1013b965Tadashi G. Takaoka private final ArrayList<View> mDividers = new ArrayList<View>(); 7574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 7682411d47ba7e8133ed2390c6920945e139a738cesatok private final PopupWindow mPreviewPopup; 7782411d47ba7e8133ed2390c6920945e139a738cesatok private final TextView mPreviewText; 7866a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani 79717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka private final View mTouchToSave; 80717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka private final TextView mWordToSave; 81717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka 82c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka private Listener mListener; 837e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka private SuggestedWords mSuggestions = SuggestedWords.EMPTY; 8455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka private boolean mShowingAutoCorrectionInverted; 85e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka private boolean mShowingAddToDictionary; 866a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 87d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private final SuggestionsStripParams mStripParams; 88d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private final SuggestionsPaneParams mPaneParams; 89ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka private static final float MIN_TEXT_XSCALE = 0.70f; 90b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka 914f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa private final UiHandler mHandler = new UiHandler(this); 9255b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka 934f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa private static class UiHandler extends StaticInnerHandlerWrapper<CandidateView> { 9455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka private static final int MSG_HIDE_PREVIEW = 0; 9555b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka private static final int MSG_UPDATE_SUGGESTION = 1; 9655b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka 9755b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka private static final long DELAY_HIDE_PREVIEW = 1000; 9855b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka private static final long DELAY_UPDATE_SUGGESTION = 300; 9955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka 1004f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public UiHandler(CandidateView outerInstance) { 1014f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa super(outerInstance); 1024f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa } 1034f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa 104e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka @Override 105e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka public void dispatchMessage(Message msg) { 1064f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final CandidateView candidateView = getOuterInstance(); 107e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka switch (msg.what) { 108e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka case MSG_HIDE_PREVIEW: 1094f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa candidateView.hidePreview(); 110e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka break; 11155b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka case MSG_UPDATE_SUGGESTION: 1124f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa candidateView.updateSuggestions(); 11355b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka break; 114e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka } 115e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka } 11655b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka 11755b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka public void postHidePreview() { 11855b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka cancelHidePreview(); 11955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_HIDE_PREVIEW), DELAY_HIDE_PREVIEW); 12055b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 12155b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka 12255b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka public void cancelHidePreview() { 12355b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka removeMessages(MSG_HIDE_PREVIEW); 12455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 12555b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka 1269fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka public void postUpdateSuggestions() { 12755b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka cancelUpdateSuggestions(); 1289fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION), 12955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka DELAY_UPDATE_SUGGESTION); 13055b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 13155b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka 13255b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka public void cancelUpdateSuggestions() { 13355b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTION); 13455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 13555b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka 13655b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka public void cancelAllMessages() { 13755b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka cancelHidePreview(); 13855b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka cancelUpdateSuggestions(); 13955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 140e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 141179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka 142d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private static class CandidateViewParams { 14374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka public final int mPadding; 14474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka public final int mDividerWidth; 14574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka public final int mDividerHeight; 14616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka public final int mCandidateStripHeight; 14716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka 14816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka protected final List<TextView> mWords; 14916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka protected final List<View> mDividers; 15016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka protected final List<TextView> mInfos; 151d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 15216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka protected CandidateViewParams(List<TextView> words, List<View> dividers, 153ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka List<TextView> infos) { 15416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka mWords = words; 15516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka mDividers = dividers; 15616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka mInfos = infos; 15716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka 15816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final TextView word = words.get(0); 15916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final View divider = dividers.get(0); 160d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka mPadding = word.getCompoundPaddingLeft() + word.getCompoundPaddingRight(); 161d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka divider.measure(WRAP_CONTENT, MATCH_PARENT); 162d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka mDividerWidth = divider.getMeasuredWidth(); 163d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka mDividerHeight = divider.getMeasuredHeight(); 16416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka 16516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final Resources res = word.getResources(); 16616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka mCandidateStripHeight = res.getDimensionPixelOffset(R.dimen.candidate_strip_height); 167d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 168d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 169d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 170d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private static class SuggestionsPaneParams extends CandidateViewParams { 17116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka public SuggestionsPaneParams(List<TextView> words, List<View> dividers, 172ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka List<TextView> infos) { 173ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka super(words, dividers, infos); 17416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 17516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka 17616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka public int layout(SuggestedWords suggestions, ViewGroup paneView, int from, int textColor, 17716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka int paneWidth) { 17816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int count = Math.min(mWords.size(), suggestions.size()); 17916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka View centeringFrom = null, lastView = null; 18016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka int x = 0, y = 0; 18116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka for (int index = from; index < count; index++) { 18216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int pos = index; 18316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final TextView word = mWords.get(pos); 18416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final View divider = mDividers.get(pos); 18516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final TextPaint paint = word.getPaint(); 18616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka word.setTextColor(textColor); 18716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final CharSequence styled = suggestions.getWord(pos); 18816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka 18916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final TextView info; 19016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (DBG) { 19116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final CharSequence debugInfo = getDebugInfo(suggestions, index); 19216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (debugInfo != null) { 19316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka info = mInfos.get(index); 19416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka info.setText(debugInfo); 19516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } else { 19616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka info = null; 19716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 19816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } else { 19916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka info = null; 20016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 20116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka 20216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final CharSequence text; 20316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final float scaleX; 20416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka paint.setTextScaleX(1.0f); 20516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int textWidth = getTextWidth(styled, paint); 20616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka int available = paneWidth - x - mPadding; 20716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (textWidth >= available) { 20816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka // Needs new row, centering previous row. 20916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka centeringCandidates(paneView, centeringFrom, lastView, x, paneWidth); 21016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka x = 0; 21116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka y += mCandidateStripHeight; 21216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 21316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (x != 0) { 21416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka // Add divider if this isn't the left most suggestion in current row. 21516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka paneView.addView(divider); 21616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka FrameLayoutCompatUtils.placeViewAt(divider, x, y 21716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka + (mCandidateStripHeight - mDividerHeight) / 2, mDividerWidth, 21816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka mDividerHeight); 21916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka x += mDividerWidth; 22016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 22116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka available = paneWidth - x - mPadding; 22216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka text = getEllipsizedText(styled, available, paint); 22316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka scaleX = paint.getTextScaleX(); 22416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka word.setText(text); 22516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka word.setTextScaleX(scaleX); 22616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka paneView.addView(word); 22716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka lastView = word; 22816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (x == 0) 22916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka centeringFrom = word; 23016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka word.measure(WRAP_CONTENT, 23116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka MeasureSpec.makeMeasureSpec(mCandidateStripHeight, MeasureSpec.EXACTLY)); 23216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int width = word.getMeasuredWidth(); 23316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int height = word.getMeasuredHeight(); 23416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka FrameLayoutCompatUtils.placeViewAt(word, x, y + (mCandidateStripHeight - height) 23516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka / 2, width, height); 23616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka x += width; 23716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (info != null) { 23816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka paneView.addView(info); 23916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka lastView = info; 24016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka info.measure(WRAP_CONTENT, WRAP_CONTENT); 24116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int infoWidth = info.getMeasuredWidth(); 24216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka FrameLayoutCompatUtils.placeViewAt(info, x - infoWidth, y, infoWidth, 24316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka info.getMeasuredHeight()); 24416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 24516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 24616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (x != 0) { 24716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka // Centering last candidates row. 24816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka centeringCandidates(paneView, centeringFrom, lastView, x, paneWidth); 24916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 25016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka 25116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka return count - from; 252d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 253d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 254d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 255d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private static class SuggestionsStripParams extends CandidateViewParams { 256d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private static final int DEFAULT_CANDIDATE_COUNT_IN_STRIP = 3; 25760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka private static final int DEFAULT_CENTER_CANDIDATE_PERCENTILE = 40; 258d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private static final int PUNCTUATIONS_IN_STRIP = 6; 259d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 260d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private final int mColorTypedWord; 261d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private final int mColorAutoCorrect; 262d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private final int mColorSuggestedCandidate; 263d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private final int mCandidateCountInStrip; 26460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka private final float mCenterCandidateWeight; 26560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka private final int mCenterCandidateIndex; 266ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka private final Drawable mMoreCandidateHint; 267d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 268d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD); 269d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan(); 270d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private final CharacterStyle mInvertedForegroundColorSpan; 271d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private final CharacterStyle mInvertedBackgroundColorSpan; 272d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private static final int AUTO_CORRECT_BOLD = 0x01; 273d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private static final int AUTO_CORRECT_UNDERLINE = 0x02; 274d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private static final int AUTO_CORRECT_INVERT = 0x04; 275d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 27616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka private final TextPaint mPaint; 27774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka private final int mAutoCorrectHighlight; 27874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 279d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private final ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>(); 28074b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 281ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka public boolean mMoreSuggestionsAvailable; 282ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka 283d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka public SuggestionsStripParams(Context context, AttributeSet attrs, int defStyle, 284ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka List<TextView> words, List<View> dividers, List<TextView> infos) { 285ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka super(words, dividers, infos); 286d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka final TypedArray a = context.obtainStyledAttributes( 287d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka attrs, R.styleable.CandidateView, defStyle, R.style.CandidateViewStyle); 288d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka mAutoCorrectHighlight = a.getInt(R.styleable.CandidateView_autoCorrectHighlight, 0); 289d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka mColorTypedWord = a.getColor(R.styleable.CandidateView_colorTypedWord, 0); 290d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka mColorAutoCorrect = a.getColor(R.styleable.CandidateView_colorAutoCorrect, 0); 291d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka mColorSuggestedCandidate = a.getColor(R.styleable.CandidateView_colorSuggested, 0); 292d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka mCandidateCountInStrip = a.getInt( 293d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka R.styleable.CandidateView_candidateCountInStrip, 294d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka DEFAULT_CANDIDATE_COUNT_IN_STRIP); 29560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka mCenterCandidateWeight = a.getInt( 29660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka R.styleable.CandidateView_centerCandidatePercentile, 29760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka DEFAULT_CENTER_CANDIDATE_PERCENTILE) / 100.0f; 298d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka a.recycle(); 299d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 30060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka mCenterCandidateIndex = mCandidateCountInStrip / 2; 301ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka final Resources res = context.getResources(); 302ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka mMoreCandidateHint = res.getDrawable(R.drawable.more_suggestions_hint); 30360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka 304d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka mInvertedForegroundColorSpan = new ForegroundColorSpan(mColorTypedWord ^ 0x00ffffff); 305d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka mInvertedBackgroundColorSpan = new BackgroundColorSpan(mColorTypedWord); 306d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 30774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mPaint = new TextPaint(); 308ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka final float textSize = res.getDimension(R.dimen.candidate_text_size); 30974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mPaint.setTextSize(textSize); 31074b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka } 31174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 31216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka public int getTextColor() { 31316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka return mColorTypedWord; 314d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 315d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 31616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka private CharSequence getStyledCandidateWord(CharSequence word, boolean isAutoCorrect) { 317d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka if (!isAutoCorrect) 318d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka return word; 319d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka final int len = word.length(); 320d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka final Spannable spannedWord = new SpannableString(word); 321d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka if ((mAutoCorrectHighlight & AUTO_CORRECT_BOLD) != 0) 322d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka spannedWord.setSpan(BOLD_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 323d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka if ((mAutoCorrectHighlight & AUTO_CORRECT_UNDERLINE) != 0) 324d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka spannedWord.setSpan(UNDERLINE_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 325d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka return spannedWord; 326d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 327d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 32860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka private static boolean willAutoCorrect(SuggestedWords suggestions) { 32960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka return !suggestions.mTypedWordValid && suggestions.mHasMinimalSuggestion; 33060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } 33160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka 33260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka private int getWordPosition(int index, SuggestedWords suggestions) { 33360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka // TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more 33460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka // suggestions. 33560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final int centerPos = willAutoCorrect(suggestions) ? 1 : 0; 33660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka if (index == mCenterCandidateIndex) { 33760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka return centerPos; 33860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } else if (index == centerPos) { 33960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka return mCenterCandidateIndex; 34060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } else { 341d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka return index; 342d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 343d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 344d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 34560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka private int getCandidateTextColor(int index, SuggestedWords suggestions, int pos) { 346d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka // TODO: Need to revisit this logic with bigram suggestions 347d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka final boolean isSuggestedCandidate = (pos != 0); 348d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 349d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka final int color; 35060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka if (index == mCenterCandidateIndex && willAutoCorrect(suggestions)) { 351d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka color = mColorAutoCorrect; 352d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } else if (isSuggestedCandidate) { 353d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka color = mColorSuggestedCandidate; 354d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } else { 355d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka color = mColorTypedWord; 356d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 35760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka 35860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final SuggestedWordInfo info = (pos < suggestions.size()) 35960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka ? suggestions.getInfo(pos) : null; 360d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka if (info != null && info.isPreviousSuggestedWord()) { 361d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka return applyAlpha(color, 0.5f); 362d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } else { 363d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka return color; 364d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 365d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 366d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 367d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka private static int applyAlpha(final int color, final float alpha) { 368d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka final int newAlpha = (int)(Color.alpha(color) * alpha); 369d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka return Color.argb(newAlpha, Color.red(color), Color.green(color), Color.blue(color)); 370d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 371d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 372d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka public CharSequence getInvertedText(CharSequence text) { 373d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka if ((mAutoCorrectHighlight & AUTO_CORRECT_INVERT) == 0) 374d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka return null; 375d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka final int len = text.length(); 376d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka final Spannable word = new SpannableString(text); 377d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka word.setSpan(mInvertedBackgroundColorSpan, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 378d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka word.setSpan(mInvertedForegroundColorSpan, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 379d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka return word; 380d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 381d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka 38216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka public int layout(SuggestedWords suggestions, ViewGroup stripView, ViewGroup paneView, 38316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka int stripWidth) { 38460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka if (suggestions.isPunctuationSuggestions()) { 38560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka return layoutPunctuationSuggestions(suggestions, stripView); 38660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } 38760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka 38860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final int countInStrip = mCandidateCountInStrip; 38960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka setupTexts(suggestions, countInStrip); 39060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka 39160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka int x = 0; 39260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka for (int index = 0; index < countInStrip; index++) { 39360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final int pos = getWordPosition(index, suggestions); 39460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka 39560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka if (index != 0) { 39660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final View divider = mDividers.get(pos); 39760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka // Add divider if this isn't the left most suggestion in candidate strip. 39860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka stripView.addView(divider); 39960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } 40060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka 40116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final CharSequence styled = mTexts.get(pos); 40260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final TextView word = mWords.get(pos); 403ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka if (index == mCenterCandidateIndex && suggestions.size() > countInStrip) { 404ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka // TODO: This "more suggestions hint" should have nicely designed icon. 405ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka word.setCompoundDrawablesWithIntrinsicBounds( 406ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka null, null, null, mMoreCandidateHint); 407ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka mMoreSuggestionsAvailable = true; 408ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka } else { 409ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka word.setCompoundDrawables(null, null, null, null); 410ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka mMoreSuggestionsAvailable = false; 411ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka } 412ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka 41360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka // Disable this candidate if the suggestion is null or empty. 41460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka word.setEnabled(!TextUtils.isEmpty(styled)); 41560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka word.setTextColor(getCandidateTextColor(index, suggestions, pos)); 416ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka final int width = getCandidateWidth(index, stripWidth); 41760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final CharSequence text = getEllipsizedText(styled, width, word.getPaint()); 41860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final float scaleX = word.getTextScaleX(); 41960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka word.setText(text); // TextView.setText() resets text scale x to 1.0. 42060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka word.setTextScaleX(scaleX); 42160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka stripView.addView(word); 42260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka setLayoutWeight(word, getCandidateWeight(index), mCandidateStripHeight); 42316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka 42416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (DBG) { 42560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final CharSequence debugInfo = getDebugInfo(suggestions, pos); 42616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (debugInfo != null) { 42760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final TextView info = mInfos.get(pos); 42816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka info.setText(debugInfo); 42916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka paneView.addView(info); 43016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka info.measure(WRAP_CONTENT, WRAP_CONTENT); 43160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final int infoWidth = info.getMeasuredWidth(); 43216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int y = info.getMeasuredHeight(); 43360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka FrameLayoutCompatUtils.placeViewAt(info, x, 0, infoWidth, y); 43460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka x += infoWidth * 2; 43516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 43660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } 43716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 43816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka 43960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka return countInStrip; 44016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 44116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka 44260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka private int getCandidateWidth(int index, int maxWidth) { 44360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final int paddings = mPadding * mCandidateCountInStrip; 44460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final int dividers = mDividerWidth * (mCandidateCountInStrip - 1); 44560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final int availableWidth = maxWidth - paddings - dividers; 44660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka return (int)(availableWidth * getCandidateWeight(index)); 44760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } 44874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 44960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka private float getCandidateWeight(int index) { 45060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka if (index == mCenterCandidateIndex) { 45160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka return mCenterCandidateWeight; 45260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } else { 45360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka // TODO: Revisit this for cases of 5 or more suggestions 45460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka return (1.0f - mCenterCandidateWeight) / (mCandidateCountInStrip - 1); 45574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka } 45674b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka } 45774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 45860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka private void setupTexts(SuggestedWords suggestions, int countInStrip) { 45974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mTexts.clear(); 46060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final int count = Math.min(suggestions.size(), countInStrip); 46160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka for (int pos = 0; pos < count; pos++) { 46260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final CharSequence word = suggestions.getWord(pos); 46360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final boolean isAutoCorrect = pos == 1 && willAutoCorrect(suggestions); 464d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka final CharSequence styled = getStyledCandidateWord(word, isAutoCorrect); 46574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mTexts.add(styled); 46674b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka } 46760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka for (int pos = count; pos < countInStrip; pos++) { 46860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka // Make this inactive for touches in layout(). 46960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka mTexts.add(null); 47060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } 47174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka } 47274b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 47360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka private int layoutPunctuationSuggestions(SuggestedWords suggestions, ViewGroup stripView) { 47460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final int countInStrip = Math.min(suggestions.size(), PUNCTUATIONS_IN_STRIP); 47560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka for (int index = 0; index < countInStrip; index++) { 47660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka if (index != 0) { 47760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka // Add divider if this isn't the left most suggestion in candidate strip. 47860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka stripView.addView(mDividers.get(index)); 47960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } 48060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka 48160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final TextView word = mWords.get(index); 48260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka word.setEnabled(true); 48360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka word.setTextColor(mColorTypedWord); 48460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final CharSequence text = suggestions.getWord(index); 48560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka word.setText(text); 48660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka word.setTextScaleX(1.0f); 487ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka word.setCompoundDrawables(null, null, null, null); 48860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka stripView.addView(word); 48960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka setLayoutWeight(word, 1.0f, mCandidateStripHeight); 49060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } 491ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka mMoreSuggestionsAvailable = false; 49260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka return countInStrip; 49374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka } 49474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka } 49574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 496923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 497923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Construct a CandidateView for showing suggested words for completion. 498923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @param context 499923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @param attrs 500923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 501923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public CandidateView(Context context, AttributeSet attrs) { 50208a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka this(context, attrs, R.attr.candidateViewStyle); 50308a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka } 50408a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka 50508a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka public CandidateView(Context context, AttributeSet attrs, int defStyle) { 506f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka // Note: Up to version 10 (Gingerbread) of the API, LinearLayout doesn't have 3-argument 507f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka // constructor. 508f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka // TODO: Call 3-argument constructor, super(context, attrs, defStyle), when we abandon 509f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka // backward compatibility with the version 10 or earlier of the API. 510f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka super(context, attrs); 511f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka if (defStyle != R.attr.candidateViewStyle) { 512f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka throw new IllegalArgumentException( 513f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka "can't accept defStyle other than R.attr.candidayeViewStyle: defStyle=" 514f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka + defStyle); 515f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka } 516f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka setBackgroundDrawable(LinearLayoutCompatUtils.getBackgroundDrawable( 517f921129f9b1083ac9d7d7be8c94701bdf6435b47Tadashi G. Takaoka context, attrs, defStyle, R.style.CandidateViewStyle)); 518923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 51916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final LayoutInflater inflater = LayoutInflater.from(context); 52086e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka inflater.inflate(R.layout.candidates_strip, this); 52186e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka 52286e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka mPreviewPopup = new PopupWindow(context); 523e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka mPreviewText = (TextView) inflater.inflate(R.layout.candidate_preview, null); 524e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mPreviewPopup.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT, 525e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka ViewGroup.LayoutParams.WRAP_CONTENT); 526923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPreviewPopup.setContentView(mPreviewText); 527923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPreviewPopup.setBackgroundDrawable(null); 528923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 52974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mCandidatesStrip = (ViewGroup)findViewById(R.id.candidates_strip); 53060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka for (int pos = 0; pos < MAX_SUGGESTIONS; pos++) { 53174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka final TextView word = (TextView)inflater.inflate(R.layout.candidate_word, null); 53260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka word.setTag(pos); 5332442e779857e7eda253aadcb1c4dff5ccb3e53f4Tadashi G. Takaoka word.setOnClickListener(this); 534ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka word.setOnLongClickListener(this); 5352442e779857e7eda253aadcb1c4dff5ccb3e53f4Tadashi G. Takaoka mWords.add(word); 536a1aab83a24e74cb0fad4b1c1e59b18d23ecbdad3Tadashi G. Takaoka final View divider = inflater.inflate(R.layout.candidate_divider, null); 53760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka divider.setTag(pos); 538a1aab83a24e74cb0fad4b1c1e59b18d23ecbdad3Tadashi G. Takaoka divider.setOnClickListener(this); 539a1aab83a24e74cb0fad4b1c1e59b18d23ecbdad3Tadashi G. Takaoka mDividers.add(divider); 54074b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mInfos.add((TextView)inflater.inflate(R.layout.candidate_info, null)); 541c9716b28ce438e06b5cacc07fc002944bcbe24a0Tadashi G. Takaoka } 542179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka 543717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka mTouchToSave = findViewById(R.id.touch_to_save); 544717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka mWordToSave = (TextView)findViewById(R.id.word_to_save); 545717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka mWordToSave.setOnClickListener(this); 546717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka 547ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka mStripParams = new SuggestionsStripParams(context, attrs, defStyle, mWords, mDividers, 548ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka mInfos); 549ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka mPaneParams = new SuggestionsPaneParams(mWords, mDividers, mInfos); 550923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 551c9716b28ce438e06b5cacc07fc002944bcbe24a0Tadashi G. Takaoka 552923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 553c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka * A connection back to the input method. 554923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @param listener 555923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 55686e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka public void setListener(Listener listener, View inputView) { 557c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka mListener = listener; 55886e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka mKeyboardView = inputView.findViewById(R.id.keyboard_view); 559a7eed902f1b0d6871d416412b3c6f91163fa2578Tadashi G. Takaoka mCandidatesPane = FrameLayoutCompatUtils.getPlacer( 560a7eed902f1b0d6871d416412b3c6f91163fa2578Tadashi G. Takaoka (ViewGroup)inputView.findViewById(R.id.candidates_pane)); 56186e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka mCandidatesPane.setOnClickListener(this); 56286e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka mCandidatesPaneContainer = (ViewGroup)inputView.findViewById( 56386e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka R.id.candidates_pane_container); 564923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 565923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 5667e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public void setSuggestions(SuggestedWords suggestions) { 5679fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (suggestions == null) 568a15e45ef45931ba46678b39c159518d8aa2d4d65Tadashi G. Takaoka return; 5699fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mSuggestions = suggestions; 57055b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka if (mShowingAutoCorrectionInverted) { 5719fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 57255b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } else { 5739fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka updateSuggestions(); 57455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 57555b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 57655b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka 5779fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka private void updateSuggestions() { 578e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka clear(); 57986e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka closeCandidatesPane(); 58016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (mSuggestions.size() == 0) 58174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka return; 58274b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 58316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int width = getWidth(); 58416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int countInStrip = mStripParams.layout( 58516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka mSuggestions, mCandidatesStrip, mCandidatesPane, width); 58616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int countInPane = mPaneParams.layout( 58716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka mSuggestions, mCandidatesPane, countInStrip, mStripParams.getTextColor(), width); 58816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 58974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 59016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka private static CharSequence getDebugInfo(SuggestedWords suggestions, int pos) { 59160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka if (DBG && pos < suggestions.size()) { 59216713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final SuggestedWordInfo wordInfo = suggestions.getInfo(pos); 59316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (wordInfo != null) { 59416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final CharSequence debugInfo = wordInfo.getDebugString(); 59516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka if (!TextUtils.isEmpty(debugInfo)) { 59616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka return debugInfo; 597d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka } 5982442e779857e7eda253aadcb1c4dff5ccb3e53f4Tadashi G. Takaoka } 59986e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka } 60016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka return null; 60186e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka } 60286e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka 6033118277dd47492089761c0ed1097abaeb376395cTadashi G. Takaoka private static void setLayoutWeight(View v, float weight, int height) { 60474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka final ViewGroup.LayoutParams lp = v.getLayoutParams(); 60574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka if (lp instanceof LinearLayout.LayoutParams) { 60674b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka final LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp; 60774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka llp.weight = weight; 60874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka llp.width = 0; 6093118277dd47492089761c0ed1097abaeb376395cTadashi G. Takaoka llp.height = height; 61074b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka } 61174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka } 61274b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 61316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka private static void centeringCandidates(ViewGroup parent, View from, View to, int width, 61416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka int parentWidth) { 61516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int fromIndex = parent.indexOfChild(from); 61616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int toIndex = parent.indexOfChild(to); 61716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final int offset = (parentWidth - width) / 2; 61886e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka for (int index = fromIndex; index <= toIndex; index++) { 61916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka offsetMargin(parent.getChildAt(index), offset, 0); 62086e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka } 62186e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka } 62286e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka 62386e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka private static void offsetMargin(View v, int dx, int dy) { 624862e05a8f0aa03ddc4582d5bf68a3201f348cf1dTadashi G. Takaoka if (v == null) 625862e05a8f0aa03ddc4582d5bf68a3201f348cf1dTadashi G. Takaoka return; 6262442e779857e7eda253aadcb1c4dff5ccb3e53f4Tadashi G. Takaoka final ViewGroup.LayoutParams lp = v.getLayoutParams(); 62786e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka if (lp instanceof ViewGroup.MarginLayoutParams) { 6282442e779857e7eda253aadcb1c4dff5ccb3e53f4Tadashi G. Takaoka final ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp; 62986e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka mlp.setMargins(mlp.leftMargin + dx, mlp.topMargin + dy, 0, 0); 63086e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka } 63186e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka } 63286e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka 63374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka private static CharSequence getEllipsizedText(CharSequence text, int maxWidth, 63474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka TextPaint paint) { 63574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka paint.setTextScaleX(1.0f); 63674b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka final int width = getTextWidth(text, paint); 63760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka if (width <= maxWidth) { 63860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka return text; 63960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka } 64060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka final float scaleX = maxWidth / (float)width; 641b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka if (scaleX >= MIN_TEXT_XSCALE) { 64274b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka paint.setTextScaleX(scaleX); 64374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka return text; 644b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka } 645b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka 64674b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka // Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To get 64760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka // squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE). 64874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka final CharSequence ellipsized = TextUtils.ellipsize( 64974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka text, paint, maxWidth / MIN_TEXT_XSCALE, TextUtils.TruncateAt.MIDDLE); 65074b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka paint.setTextScaleX(MIN_TEXT_XSCALE); 65174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka return ellipsized; 652b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka } 653b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka 65474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka private static int getTextWidth(CharSequence text, TextPaint paint) { 655b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka if (TextUtils.isEmpty(text)) return 0; 656fe9b65afa84530d17dd82c770c19de763a50cb58Tadashi G. Takaoka final Typeface savedTypeface = paint.getTypeface(); 65774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka paint.setTypeface(getTextTypeface(text)); 658b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka final int len = text.length(); 659b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka final float[] widths = new float[len]; 660b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka final int count = paint.getTextWidths(text, 0, len, widths); 661fe9b65afa84530d17dd82c770c19de763a50cb58Tadashi G. Takaoka int width = 0; 662b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka for (int i = 0; i < count; i++) { 663fe9b65afa84530d17dd82c770c19de763a50cb58Tadashi G. Takaoka width += Math.round(widths[i] + 0.5f); 664b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka } 665fe9b65afa84530d17dd82c770c19de763a50cb58Tadashi G. Takaoka paint.setTypeface(savedTypeface); 666fe9b65afa84530d17dd82c770c19de763a50cb58Tadashi G. Takaoka return width; 667b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka } 668b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka 66974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka private static Typeface getTextTypeface(CharSequence text) { 67074b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka if (!(text instanceof SpannableString)) 67174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka return Typeface.DEFAULT; 67274b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 67374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka final SpannableString ss = (SpannableString)text; 67474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka final StyleSpan[] styles = ss.getSpans(0, text.length(), StyleSpan.class); 67574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka if (styles.length == 0) 67674b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka return Typeface.DEFAULT; 67774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 67874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka switch (styles[0].getStyle()) { 67974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka case Typeface.BOLD: return Typeface.DEFAULT_BOLD; 68074b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka // TODO: BOLD_ITALIC, ITALIC case? 68174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka default: return Typeface.DEFAULT; 682b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka } 683b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka } 684b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka 68586e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka private void expandCandidatesPane() { 68686e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka mCandidatesPaneContainer.setMinimumHeight(mKeyboardView.getMeasuredHeight()); 68774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mCandidatesPaneContainer.setVisibility(VISIBLE); 68874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mKeyboardView.setVisibility(GONE); 68986e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka } 690e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka 69186e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka private void closeCandidatesPane() { 69274b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mCandidatesPaneContainer.setVisibility(GONE); 69374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mKeyboardView.setVisibility(VISIBLE); 694923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 695923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 69655b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka public void onAutoCorrectionInverted(CharSequence autoCorrectedWord) { 697d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka final CharSequence inverted = mStripParams.getInvertedText(autoCorrectedWord); 698d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka if (inverted == null) 69955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka return; 7001e273fa6d1e8babfebebbbe331d87d3854755e7fTadashi G. Takaoka final TextView tv = mWords.get(1); 701d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka tv.setText(inverted); 70255b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka mShowingAutoCorrectionInverted = true; 70355b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 70455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka 705b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani public boolean isShowingAddToDictionaryHint() { 706b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani return mShowingAddToDictionary; 707b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 708b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 70966a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani public void showAddToDictionaryHint(CharSequence word) { 710717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka mWordToSave.setText(word); 71166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani mShowingAddToDictionary = true; 71274b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mCandidatesStrip.setVisibility(GONE); 71374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mTouchToSave.setVisibility(VISIBLE); 71466a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 71566a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani 7166558253160e2039c87f424bd814f402ecd31de3bKen Wakasa public boolean dismissAddToDictionaryHint() { 7176558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (!mShowingAddToDictionary) return false; 7186558253160e2039c87f424bd814f402ecd31de3bKen Wakasa clear(); 7196558253160e2039c87f424bd814f402ecd31de3bKen Wakasa return true; 7206558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 7216558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 7227e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public SuggestedWords getSuggestions() { 723979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return mSuggestions; 724979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 725979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 726923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void clear() { 72766a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani mShowingAddToDictionary = false; 72855b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka mShowingAutoCorrectionInverted = false; 72974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mTouchToSave.setVisibility(GONE); 7301bd62a56211db2933eb5dd735c108e610111d6fbKen Wakasa mCandidatesStrip.setVisibility(VISIBLE); 73174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka mCandidatesStrip.removeAllViews(); 73286e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka mCandidatesPane.removeAllViews(); 73388110d1799146943c627916ffaa94bbc4dd6f2aeTadashi G. Takaoka closeCandidatesPane(); 734923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 735923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 7366ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani private void hidePreview() { 737179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka mPreviewPopup.dismiss(); 7386ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani } 739e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka 740e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka private void showPreview(int index, CharSequence word) { 741e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka if (TextUtils.isEmpty(word)) 742e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka return; 743e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka 744e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka final TextView previewText = mPreviewText; 745d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka previewText.setTextColor(mStripParams.mColorTypedWord); 746e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka previewText.setText(word); 747e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka previewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 748e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 749f20eb55d4f8063f89c6c0abb3af3029fe23cb845Tadashi G. Takaoka View v = mWords.get(index); 750e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka final int[] offsetInWindow = new int[2]; 751e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka v.getLocationInWindow(offsetInWindow); 752e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka final int posX = offsetInWindow[0]; 753e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka final int posY = offsetInWindow[1] - previewText.getMeasuredHeight(); 754e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka final PopupWindow previewPopup = mPreviewPopup; 755e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka if (previewPopup.isShowing()) { 756e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka previewPopup.update(posX, posY, previewPopup.getWidth(), previewPopup.getHeight()); 757e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka } else { 758e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka previewPopup.showAtLocation(this, Gravity.NO_GRAVITY, posX, posY); 759923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 760e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka previewText.setVisibility(VISIBLE); 76155b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka mHandler.postHidePreview(); 762923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 763fcba53ef7c874a4685c12c01404c91b779cae1e8Tadashi G. Takaoka 764e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka private void addToDictionary(CharSequence word) { 765c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka if (mListener.addWordToDictionary(word.toString())) { 766e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka showPreview(0, getContext().getString(R.string.added_word, word)); 767e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka } 768e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka } 769e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka 770e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka @Override 771ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka public boolean onLongClick(View view) { 772ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka if (mStripParams.mMoreSuggestionsAvailable) { 773ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka expandCandidatesPane(); 774ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka return true; 775ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka } 776ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka return false; 777ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka } 778ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka 779ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka @Override 780e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka public void onClick(View view) { 781717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka if (view == mWordToSave) { 782717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka addToDictionary(((TextView)view).getText()); 783717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka clear(); 784717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka return; 785717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka } 786717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka 787ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka if (view == mCandidatesPane) { 788ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka closeCandidatesPane(); 789ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka return; 790ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka } 791ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka 79286e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka final Object tag = view.getTag(); 79386e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka if (!(tag instanceof Integer)) 79486e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka return; 79586e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka final int index = (Integer) tag; 79637deb112c727dfed5e94d054cf5f00f5d60c8120Tadashi G. Takaoka if (index >= mSuggestions.size()) 79737deb112c727dfed5e94d054cf5f00f5d60c8120Tadashi G. Takaoka return; 79886e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka 79937deb112c727dfed5e94d054cf5f00f5d60c8120Tadashi G. Takaoka final CharSequence word = mSuggestions.getWord(index); 800717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka mListener.pickSuggestionManually(index, word); 80186e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka // Because some punctuation letters are not treated as word separator depending on locale, 80286e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka // {@link #setSuggestions} might not be called and candidates pane left opened. 80386e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka closeCandidatesPane(); 804923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 80582411d47ba7e8133ed2390c6920945e139a738cesatok 8066ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani @Override 8076ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani public void onDetachedFromWindow() { 8086ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani super.onDetachedFromWindow(); 80955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka mHandler.cancelAllMessages(); 8106ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani hidePreview(); 8116ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani } 812923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 813