2 * Copyright (C) 2008,2009 OMRON SOFTWARE Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.hiroshica.android.input.nicownn2;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.lang.Math;
23 import android.content.Context;
24 import android.content.SharedPreferences;
25 import android.preference.PreferenceManager;
26 import android.content.res.Configuration;
27 import android.content.res.Resources;
28 import android.media.MediaPlayer;
29 import android.os.AsyncTask;
30 import android.os.SystemClock;
31 import android.os.Vibrator;
32 import android.text.TextUtils;
33 import android.text.TextPaint;
34 import android.text.SpannableString;
35 import android.text.Spanned;
36 import android.text.style.ImageSpan;
37 import android.text.style.DynamicDrawableSpan;
38 import android.util.Log;
39 import android.util.DisplayMetrics;
40 import android.view.Gravity;
41 import android.view.MotionEvent;
42 import android.view.View;
43 import android.view.ViewGroup;
44 import android.view.View.OnClickListener;
45 import android.view.View.OnLongClickListener;
46 import android.view.View.OnTouchListener;
47 import android.view.GestureDetector;
48 import android.view.LayoutInflater;
49 import android.widget.Button;
50 import android.widget.LinearLayout;
51 import android.widget.ScrollView;
52 import android.widget.HorizontalScrollView;
53 import android.widget.TextView;
54 import android.widget.EditText;
55 import android.widget.RelativeLayout;
56 import android.graphics.drawable.Drawable;
59 * The default candidates view manager class using {@link EditText}.
61 * @author Copyright (C) 2009 OMRON SOFTWARE CO., LTD. All Rights Reserved.
63 public class TextCandidatesViewManager implements CandidatesViewManager, GestureDetector.OnGestureListener {
64 /** Height of a line */
65 public static final int LINE_HEIGHT = 34;
67 public static final int LINE_NUM_1LINE = 1;
68 public static final int LINE_NUM_2LINE = 2;
69 public static final int LINE_NUM_MAX = 2;
71 /** Number of lines to display (Portrait) */
72 //public static final int LINE_NUM_PORTRAIT = 1;
73 /** Number of lines to display (Landscape) */
74 //public static final int LINE_NUM_LANDSCAPE = 1;
77 private static final int DISPLAY_LINE_MAX_COUNT = 1000;
78 /** Width of the view */
79 private static final int CANDIDATE_MINIMUM_WIDTH = 48;
80 /** Height of the view */
81 //private static final int CANDIDATE_MINIMUM_HEIGHT = 42;
83 * candidate-line height
85 private static final HashMap<String, Integer> candidateViewKeyHeight = new HashMap<String, Integer>() {
89 private static final long serialVersionUID = 1L;
91 put("candidateview_value_0", 0);
92 put("candidateview_value_1", 1);
93 put("candidateview_value_2", 2);
95 private static int mCandidateViewHeightIndex = 0;
96 public static int candidateViewDataTable[] = { 42, 51, 60 };
98 /** Maximum number of displaying candidates par one line (full view mode) */
99 private static final int FULL_VIEW_DIV = 5;
101 /** Body view of the candidates list */
102 private ViewGroup mViewBody;
103 /** Scroller of {@code mViewBodyText} */
104 private ScrollView mViewBodyVScroll;
105 private HorizontalScrollView mViewBodyHScroll;
107 private boolean mIsScroll;
108 /** Base of {@code mViewCandidateList1st}, {@code mViewCandidateList2nd} */
109 private ViewGroup mViewCandidateBase;
110 /** The view of the scaling up candidate */
111 private View mViewScaleUp;
112 /** Layout for the candidates list on normal view */
113 private LinearLayout mViewCandidateList1st;
114 /** Layout for the candidates list on full view */
115 private RelativeLayout mViewCandidateList2nd;
117 /** {@link NicoWnn} instance using this manager */
118 private NicoWnn mWnn;
119 /** View type (VIEW_TYPE_NORMAL or VIEW_TYPE_FULL or VIEW_TYPE_CLOSE) */
120 private int mViewType;
121 /** Portrait display({@code true}) or landscape({@code false}) */
122 private boolean mPortrait;
124 /** Width of the view */
126 /** Height of the view */
127 private int mViewHeight;
128 /** Whether hide the view if there is no candidates */
129 private boolean mAutoHideMode;
130 /** The converter to be get candidates from and notice the selected candidate to. */
131 public WnnEngine mConverter;
132 /** Vibrator for touch vibration */
133 private Vibrator mVibrator = null;
134 /** MediaPlayer for click sound */
135 private MediaPlayer mSound = null;
137 /** Number of candidates displaying */
140 int[] mWnnLineCount = new int[LINE_NUM_MAX];
141 int[] mWnnLineCountMax = new int[LINE_NUM_MAX];
142 private int[] mWnnLineOffset = new int[LINE_NUM_MAX];
144 /** portrait/landscape line */
145 private static final HashMap<String, Integer> lineModeTable = new HashMap<String, Integer>() {/**
148 private static final long serialVersionUID = 1L;
157 private int mLineMode;
158 private int mPortraitLine;
159 private int mLandscapeLine;
161 private boolean mNoSpace;
163 /** get last id of topline */
164 private int mToplineLastId;
166 private int mTotalLastId;
167 /** List of candidates */
168 private ArrayList<WnnWord> mWnnWordArray;
169 private ArrayList<Integer> mWnnWordTextLength;
170 private ArrayList<Integer> mWnnWordOccupyCount;
172 /** Gesture detector */
173 private GestureDetector mGestureDetector;
174 /** The word pressed */
175 private WnnWord mWord;
176 /** Number of lines displayed */
177 private int mLineCount = 1;
179 /** {@code true} if the candidate delete state is selected */
180 private boolean mIsScaleUp = false;
182 /** {@code true} if the full screen mode is selected */
183 private boolean mIsFullView = false;
185 private boolean mIsCreateFullView = false;
187 private boolean mIsLockHScroll = false;
189 private int mTargetScrollWidth;
191 /** The event object for "touch" */
192 private MotionEvent mMotionEvent = null;
194 /** {@code true} if there are more candidates to display. */
195 private boolean mCanReadMore = false;
196 /** Width of {@code mReadMoreButton} */
197 private int mTextColor = 0;
198 /** Template object for each candidate and normal/full view change button */
199 private TextView mViewCandidateTemplate;
200 /** Number of candidates in full view */
201 private int mFullViewWordCount;
202 /** Number of candidates in the current line (in full view) */
203 private int mFullViewOccupyCount;
204 /** View of the previous candidate (in full view) */
205 private TextView mFullViewPrevView;
206 /** Id of the top line view (in full view) */
207 private int mFullViewPrevLineTopId;
208 /** Layout of the previous candidate (in full view) */
209 private RelativeLayout.LayoutParams mFullViewPrevParams;
210 /** Whether all candidates is displayed */
211 private boolean mCreateCandidateDone;
212 /** general infomation about a display */
213 private static final DisplayMetrics mMetrics = new DisplayMetrics();
216 private TextCandidateTask mCandidateTask = null;
217 private boolean mIsActiveTask = false;
218 private boolean mIsCancelTask = false;
220 // docomo emoji hashmap
221 private static final HashMap<String, Integer> DOCOMO_EMOJI_TABLE = new HashMap<String, Integer>() {/**
224 private static final long serialVersionUID = 1L;
227 put("\uE63E", R.drawable.docomo_1); put("\uE63F", R.drawable.docomo_2); put("\uE640", R.drawable.docomo_3); put("\uE641", R.drawable.docomo_4);
228 put("\uE642", R.drawable.docomo_5); put("\uE643", R.drawable.docomo_6); put("\uE644", R.drawable.docomo_7); put("\uE645", R.drawable.docomo_8);
229 put("\uE646", R.drawable.docomo_9); put("\uE647", R.drawable.docomo_10); put("\uE648", R.drawable.docomo_11); put("\uE649", R.drawable.docomo_12);
230 put("\uE64A", R.drawable.docomo_13); put("\uE64B", R.drawable.docomo_14); put("\uE64C", R.drawable.docomo_15); put("\uE64D", R.drawable.docomo_16);
231 put("\uE64E", R.drawable.docomo_17); put("\uE64F", R.drawable.docomo_18); put("\uE650", R.drawable.docomo_19); put("\uE651", R.drawable.docomo_20);
232 put("\uE652", R.drawable.docomo_21); put("\uE653", R.drawable.docomo_22); put("\uE654", R.drawable.docomo_23); put("\uE655", R.drawable.docomo_24);
233 put("\uE656", R.drawable.docomo_25); put("\uE657", R.drawable.docomo_26); put("\uE658", R.drawable.docomo_27); put("\uE659", R.drawable.docomo_28);
234 put("\uE65A", R.drawable.docomo_29); put("\uE65B", R.drawable.docomo_30); put("\uE65C", R.drawable.docomo_31); put("\uE65D", R.drawable.docomo_32);
235 put("\uE65E", R.drawable.docomo_33); put("\uE65F", R.drawable.docomo_34); put("\uE660", R.drawable.docomo_35); put("\uE661", R.drawable.docomo_36);
236 put("\uE662", R.drawable.docomo_37); put("\uE663", R.drawable.docomo_38); put("\uE664", R.drawable.docomo_39); put("\uE665", R.drawable.docomo_40);
237 put("\uE666", R.drawable.docomo_41); put("\uE667", R.drawable.docomo_42); put("\uE668", R.drawable.docomo_43); put("\uE669", R.drawable.docomo_44);
238 put("\uE66A", R.drawable.docomo_45); put("\uE66B", R.drawable.docomo_46); put("\uE66C", R.drawable.docomo_47); put("\uE66D", R.drawable.docomo_48);
239 put("\uE66E", R.drawable.docomo_49); put("\uE66F", R.drawable.docomo_50); put("\uE670", R.drawable.docomo_51); put("\uE671", R.drawable.docomo_52);
240 put("\uE672", R.drawable.docomo_53); put("\uE673", R.drawable.docomo_54); put("\uE674", R.drawable.docomo_55); put("\uE675", R.drawable.docomo_56);
241 put("\uE676", R.drawable.docomo_57); put("\uE677", R.drawable.docomo_58); put("\uE678", R.drawable.docomo_59); put("\uE679", R.drawable.docomo_60);
242 put("\uE67A", R.drawable.docomo_61); put("\uE67B", R.drawable.docomo_62); put("\uE67C", R.drawable.docomo_63); put("\uE67D", R.drawable.docomo_64);
243 put("\uE67E", R.drawable.docomo_65); put("\uE67F", R.drawable.docomo_66); put("\uE680", R.drawable.docomo_67); put("\uE681", R.drawable.docomo_68);
244 put("\uE682", R.drawable.docomo_69); put("\uE683", R.drawable.docomo_70); put("\uE684", R.drawable.docomo_71); put("\uE685", R.drawable.docomo_72);
245 put("\uE686", R.drawable.docomo_73); put("\uE687", R.drawable.docomo_74); put("\uE688", R.drawable.docomo_75); put("\uE689", R.drawable.docomo_76);
246 put("\uE68A", R.drawable.docomo_77); put("\uE68B", R.drawable.docomo_78); put("\uE68C", R.drawable.docomo_79); put("\uE68D", R.drawable.docomo_80);
247 put("\uE68E", R.drawable.docomo_81); put("\uE68F", R.drawable.docomo_82); put("\uE690", R.drawable.docomo_83); put("\uE691", R.drawable.docomo_84);
248 put("\uE692", R.drawable.docomo_85); put("\uE693", R.drawable.docomo_86); put("\uE694", R.drawable.docomo_87); put("\uE695", R.drawable.docomo_88);
249 put("\uE696", R.drawable.docomo_89); put("\uE697", R.drawable.docomo_90); put("\uE698", R.drawable.docomo_91); put("\uE699", R.drawable.docomo_92);
250 put("\uE69A", R.drawable.docomo_93); put("\uE69B", R.drawable.docomo_94); put("\uE69C", R.drawable.docomo_95); put("\uE69D", R.drawable.docomo_96);
251 put("\uE69E", R.drawable.docomo_97); put("\uE69F", R.drawable.docomo_98); put("\uE6A0", R.drawable.docomo_99); put("\uE6A1", R.drawable.docomo_100);
252 put("\uE6A2", R.drawable.docomo_101); put("\uE6A3", R.drawable.docomo_102); put("\uE6A4", R.drawable.docomo_103); put("\uE6A5", R.drawable.docomo_104);
253 put("\uE6CE", R.drawable.docomo_105); put("\uE6CF", R.drawable.docomo_106); put("\uE6D0", R.drawable.docomo_107); put("\uE6D1", R.drawable.docomo_108);
254 put("\uE6D2", R.drawable.docomo_109); put("\uE6D3", R.drawable.docomo_110); put("\uE6D4", R.drawable.docomo_111); put("\uE6D5", R.drawable.docomo_112);
255 put("\uE6D6", R.drawable.docomo_113); put("\uE6D7", R.drawable.docomo_114); put("\uE6D8", R.drawable.docomo_115); put("\uE6D9", R.drawable.docomo_116);
256 put("\uE6DA", R.drawable.docomo_117); put("\uE6DB", R.drawable.docomo_118); put("\uE6DC", R.drawable.docomo_119); put("\uE6DD", R.drawable.docomo_120);
257 put("\uE6DE", R.drawable.docomo_121); put("\uE6DF", R.drawable.docomo_122); put("\uE6E0", R.drawable.docomo_123); put("\uE6E1", R.drawable.docomo_124);
258 put("\uE6E2", R.drawable.docomo_125); put("\uE6E3", R.drawable.docomo_126); put("\uE6E4", R.drawable.docomo_127); put("\uE6E5", R.drawable.docomo_128);
259 put("\uE6E6", R.drawable.docomo_129); put("\uE6E7", R.drawable.docomo_130); put("\uE6E8", R.drawable.docomo_131); put("\uE6E9", R.drawable.docomo_132);
260 put("\uE6EA", R.drawable.docomo_133); put("\uE6EB", R.drawable.docomo_134); put("\uE70B", R.drawable.docomo_135); put("\uE6EC", R.drawable.docomo_136);
261 put("\uE6ED", R.drawable.docomo_137); put("\uE6EE", R.drawable.docomo_138); put("\uE6EF", R.drawable.docomo_139); put("\uE6F0", R.drawable.docomo_140);
262 put("\uE6F1", R.drawable.docomo_141); put("\uE6F2", R.drawable.docomo_142); put("\uE6F3", R.drawable.docomo_143); put("\uE6F4", R.drawable.docomo_144);
263 put("\uE6F5", R.drawable.docomo_145); put("\uE6F6", R.drawable.docomo_146); put("\uE6F7", R.drawable.docomo_147); put("\uE6F8", R.drawable.docomo_148);
264 put("\uE6F9", R.drawable.docomo_149); put("\uE6FA", R.drawable.docomo_150); put("\uE6FB", R.drawable.docomo_151); put("\uE6FC", R.drawable.docomo_152);
265 put("\uE6FD", R.drawable.docomo_153); put("\uE6FE", R.drawable.docomo_154); put("\uE6FF", R.drawable.docomo_155); put("\uE700", R.drawable.docomo_156);
266 put("\uE701", R.drawable.docomo_157); put("\uE702", R.drawable.docomo_158); put("\uE703", R.drawable.docomo_159); put("\uE704", R.drawable.docomo_160);
267 put("\uE705", R.drawable.docomo_161); put("\uE706", R.drawable.docomo_162); put("\uE707", R.drawable.docomo_163); put("\uE708", R.drawable.docomo_164);
268 put("\uE709", R.drawable.docomo_165); put("\uE70A", R.drawable.docomo_166); put("\uE6AC", R.drawable.docomo_167); put("\uE6AD", R.drawable.docomo_168);
269 put("\uE6AE", R.drawable.docomo_169); put("\uE6B1", R.drawable.docomo_170); put("\uE6B2", R.drawable.docomo_171); put("\uE6B3", R.drawable.docomo_172);
270 put("\uE6B7", R.drawable.docomo_173); put("\uE6B8", R.drawable.docomo_174); put("\uE6B9", R.drawable.docomo_175); put("\uE6BA", R.drawable.docomo_176);
271 put("\uE70C", R.drawable.docomo_ex1); put("\uE70D", R.drawable.docomo_ex2); put("\uE70E", R.drawable.docomo_ex3); put("\uE70F", R.drawable.docomo_ex4);
272 put("\uE710", R.drawable.docomo_ex5); put("\uE711", R.drawable.docomo_ex6); put("\uE712", R.drawable.docomo_ex7); put("\uE713", R.drawable.docomo_ex8);
273 put("\uE714", R.drawable.docomo_ex9); put("\uE715", R.drawable.docomo_ex10); put("\uE716", R.drawable.docomo_ex11); put("\uE717", R.drawable.docomo_ex12);
274 put("\uE718", R.drawable.docomo_ex13); put("\uE719", R.drawable.docomo_ex14); put("\uE71A", R.drawable.docomo_ex15); put("\uE71B", R.drawable.docomo_ex16);
275 put("\uE71C", R.drawable.docomo_ex17); put("\uE71D", R.drawable.docomo_ex18); put("\uE71E", R.drawable.docomo_ex19); put("\uE71F", R.drawable.docomo_ex20);
276 put("\uE720", R.drawable.docomo_ex21); put("\uE721", R.drawable.docomo_ex22); put("\uE722", R.drawable.docomo_ex23); put("\uE723", R.drawable.docomo_ex24);
277 put("\uE724", R.drawable.docomo_ex25); put("\uE725", R.drawable.docomo_ex26); put("\uE726", R.drawable.docomo_ex27); put("\uE727", R.drawable.docomo_ex28);
278 put("\uE728", R.drawable.docomo_ex29); put("\uE729", R.drawable.docomo_ex30); put("\uE72A", R.drawable.docomo_ex31); put("\uE72B", R.drawable.docomo_ex32);
279 put("\uE72C", R.drawable.docomo_ex33); put("\uE72D", R.drawable.docomo_ex34); put("\uE72E", R.drawable.docomo_ex35); put("\uE72F", R.drawable.docomo_ex36);
280 put("\uE730", R.drawable.docomo_ex37); put("\uE731", R.drawable.docomo_ex38); put("\uE732", R.drawable.docomo_ex39); put("\uE733", R.drawable.docomo_ex40);
281 put("\uE734", R.drawable.docomo_ex41); put("\uE735", R.drawable.docomo_ex42); put("\uE736", R.drawable.docomo_ex43); put("\uE737", R.drawable.docomo_ex44);
282 put("\uE738", R.drawable.docomo_ex45); put("\uE739", R.drawable.docomo_ex46); put("\uE73A", R.drawable.docomo_ex47); put("\uE73B", R.drawable.docomo_ex48);
283 put("\uE73C", R.drawable.docomo_ex49); put("\uE73D", R.drawable.docomo_ex50); put("\uE73E", R.drawable.docomo_ex51); put("\uE73F", R.drawable.docomo_ex52);
284 put("\uE740", R.drawable.docomo_ex53); put("\uE741", R.drawable.docomo_ex54); put("\uE742", R.drawable.docomo_ex55); put("\uE743", R.drawable.docomo_ex56);
285 put("\uE744", R.drawable.docomo_ex57); put("\uE745", R.drawable.docomo_ex58); put("\uE746", R.drawable.docomo_ex59); put("\uE747", R.drawable.docomo_ex60);
286 put("\uE748", R.drawable.docomo_ex61); put("\uE749", R.drawable.docomo_ex62); put("\uE74A", R.drawable.docomo_ex63); put("\uE74B", R.drawable.docomo_ex64);
287 put("\uE74C", R.drawable.docomo_ex65); put("\uE74D", R.drawable.docomo_ex66); put("\uE74E", R.drawable.docomo_ex67); put("\uE74F", R.drawable.docomo_ex68);
288 put("\uE750", R.drawable.docomo_ex69); put("\uE751", R.drawable.docomo_ex70); put("\uE752", R.drawable.docomo_ex71); put("\uE753", R.drawable.docomo_ex72);
289 put("\uE754", R.drawable.docomo_ex73); put("\uE755", R.drawable.docomo_ex74); put("\uE756", R.drawable.docomo_ex75); put("\uE757", R.drawable.docomo_ex76);
292 /** Event listener for touching a candidate */
293 private OnTouchListener mCandidateOnTouch = new OnTouchListener() {
294 public boolean onTouch(View v, MotionEvent event) {
295 if (mMotionEvent != null) {
299 if ((event.getAction() == MotionEvent.ACTION_UP)
300 && (v instanceof TextView)) {
301 Drawable d = v.getBackground();
303 d.setState(new int[] {});
307 mMotionEvent = event;
308 boolean ret = mWnn.onEvent(new NicoWnnEvent(NicoWnnEvent.CANDIDATE_VIEW_TOUCH));
315 /** Event listener for clicking a candidate */
316 private OnClickListener mCandidateOnClick = new OnClickListener() {
317 public void onClick(View v) {
322 if (v instanceof TextView) {
323 checkCandidateTask();
324 TextView text = (TextView)v;
325 int wordcount = text.getId() - 1;
327 word = mWnnWordArray.get(wordcount);
328 selectCandidate(word);
333 /** Event listener for long-clicking a candidate */
334 private OnLongClickListener mCandidateOnLongClick = new OnLongClickListener() {
335 public boolean onLongClick(View v) {
336 if (mViewScaleUp == null) {
344 Drawable d = v.getBackground();
346 if(d.getState().length == 0){
351 int wordcount = ((TextView)v).getId() - 1;
352 mWord = mWnnWordArray.get(wordcount);
353 setViewScaleUp(true, mWord);
363 public TextCandidatesViewManager() {
370 * @param displayLimit The limit of display
372 public TextCandidatesViewManager(int displayLimit) {
373 this.mWnnWordArray = new ArrayList<WnnWord>();
374 this.mWnnWordTextLength = new ArrayList<Integer>();
375 this.mWnnWordOccupyCount = new ArrayList<Integer>();
376 this.mAutoHideMode = true;
377 this.mIsActiveTask = false;
378 mMetrics.setToDefaults();
382 * Set auto-hide mode.
383 * @param hide {@code true} if the view will hidden when no candidate exists;
384 * {@code false} if the view is always shown.
386 public void setAutoHide(boolean hide) {
387 mAutoHideMode = hide;
390 /** @see CandidatesViewManager */
391 public View initView(NicoWnn parent, int width, int height) {
393 mViewWidth = Math.round((float)width / mMetrics.density);
394 mViewHeight = Math.round((float)height / mMetrics.density);
396 (parent.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE);
403 SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(parent);
405 mLineMode = lineModeTable.get(pref.getString("nico_candidate_mode", "1_1"));
406 if (0 == mLineMode) {
410 if (1 == mLineMode) {
414 if (2 == mLineMode) {
418 if (3 == mLineMode) {
422 mNoSpace = pref.getBoolean("nospace_candidate", false);
423 // candidate line height
424 mCandidateViewHeightIndex = candidateViewKeyHeight.get(pref.getString("candidateview_height_mode", "candidateview_value_0"));
427 Resources r = mWnn.getResources();
429 LayoutInflater inflater = parent.getLayoutInflater();
430 mViewBody = (ViewGroup)inflater.inflate(R.layout.candidates, null);
432 mViewBodyVScroll = (ScrollView)mViewBody.findViewById(R.id.candview_scroll);
433 mViewBodyVScroll.setOnTouchListener(mCandidateOnTouch);
435 mViewBodyHScroll = (HorizontalScrollView)mViewBody.findViewById(R.id.candview_hscroll);
436 mViewBodyHScroll.setOnTouchListener(mCandidateOnTouch);
437 mIsLockHScroll = false;
439 mViewCandidateBase = (ViewGroup)mViewBody.findViewById(R.id.candview_base);
441 mViewCandidateList1st = (LinearLayout)mViewBody.findViewById(R.id.candidates_1st_view);
442 mViewCandidateList1st.setOnTouchListener(mCandidateOnTouch);
443 mViewCandidateList1st.setOnClickListener(mCandidateOnClick);
445 mViewCandidateList2nd = (RelativeLayout)mViewBody.findViewById(R.id.candidates_2nd_view);
446 mViewCandidateList2nd.setOnTouchListener(mCandidateOnTouch);
447 mViewCandidateList2nd.setOnClickListener(mCandidateOnClick);
449 // create first textView
450 for (int iI = 0; iI < LINE_NUM_MAX; ++iI) {
451 LinearLayout lineView = new LinearLayout(mViewBodyVScroll.getContext());
452 lineView.setOrientation(LinearLayout.HORIZONTAL);
453 LinearLayout.LayoutParams layoutParams =
454 new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
455 ViewGroup.LayoutParams.WRAP_CONTENT);
456 lineView.setLayoutParams(layoutParams);
457 lineView.setGravity(Gravity.LEFT);
459 lineView.setMinimumHeight(getCandidateMinimumHeight());
460 mViewCandidateList1st.addView(lineView);
463 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(getCandidateMinimumWidth(), getCandidateMinimumHeight());
464 params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
465 params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
467 TextView textView = createCandidateView();
468 //textView.setLayoutParams(params);
469 mViewCandidateList2nd.addView(textView);
470 mViewCandidateTemplate = textView;
472 mTextColor = r.getColor(R.color.candidate_text);
474 setViewType(CandidatesViewManager.VIEW_TYPE_CLOSE);
476 mGestureDetector = new GestureDetector(this);
478 View scaleUp = (View)inflater.inflate(R.layout.candidate_scale_up, null);
479 mViewScaleUp = scaleUp;
482 Button b = (Button)scaleUp.findViewById(R.id.candidate_select);
483 b.setOnClickListener(new View.OnClickListener() {
484 public void onClick(View v) {
485 selectCandidate(mWord);
490 b = (Button)scaleUp.findViewById(R.id.candidate_cancel);
491 b.setOnClickListener(new View.OnClickListener() {
492 public void onClick(View v) {
493 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
494 mWnn.onEvent(new NicoWnnEvent(NicoWnnEvent.UPDATE_CANDIDATE));
501 /** @see CandidatesViewManager#getCurrentView */
502 public View getCurrentView() {
506 /** @see CandidatesViewManager#setViewType */
507 public void setViewType(int type) {
508 boolean readMore = setViewLayout(type);
511 if (false == mIsCreateFullView) {
512 mCanReadMore = false;
513 mFullViewWordCount = 0;
514 mFullViewOccupyCount = 0;
515 mFullViewPrevLineTopId = 0;
516 mCreateCandidateDone = false;
523 mIsLockHScroll = false;
525 displayCandidates(this.mConverter, false, -1);
526 mIsCreateFullView = true;
529 visibleFullCandidate();
532 if (type == CandidatesViewManager.VIEW_TYPE_NORMAL) {
535 if (mDisplayEndOffset > 0) {
536 int maxLine = getMaxLine();
537 displayCandidates(this.mConverter, false, maxLine);
542 if (mViewBody.isShown()) {
543 mWnn.setCandidatesViewShown(false);
550 * Set the view layout
552 * @param type View type
553 * @return {@code true} if display is updated; {@code false} if otherwise
555 private boolean setViewLayout(int type) {
557 setViewScaleUp(false, null);
560 case CandidatesViewManager.VIEW_TYPE_CLOSE:
561 checkCandidateTask();
562 mViewCandidateBase.setMinimumHeight(-1);
563 //mIsLockHScroll = false;
566 case CandidatesViewManager.VIEW_TYPE_NORMAL:
567 clearNormalCandidates();
568 mViewBodyVScroll.scrollTo(0, 0);
569 if (false == mIsLockHScroll) {
570 //mViewBodyHScroll.scrollTo(0, 0);
572 mViewCandidateList1st.setVisibility(View.VISIBLE);
573 LinearLayout candidateList = mViewCandidateList1st;
574 for (int iI = 0; iI < LINE_NUM_MAX; ++iI) {
575 LinearLayout lineView = (LinearLayout)candidateList.getChildAt(iI);
576 if (iI < getMaxLine()) {
577 lineView.setVisibility(View.VISIBLE);
580 lineView.setVisibility(View.GONE);
583 mViewCandidateList2nd.setVisibility(View.GONE);
584 mViewCandidateBase.setMinimumHeight(-1);
585 int line = getMaxLine();
586 int minheight = (getCandidateMinimumHeight() * line);
587 if (false == mNoSpace) {
588 minheight += ((getCandidateMinimumHeight()/3) * 2);
590 mViewCandidateList1st.setMinimumHeight(minheight);
593 case CandidatesViewManager.VIEW_TYPE_FULL:
595 mViewCandidateList1st.setVisibility(View.GONE);
596 mViewCandidateList2nd.setVisibility(View.VISIBLE);
597 mViewCandidateList2nd.setMinimumHeight(mViewHeight);
598 mViewCandidateBase.setMinimumHeight(mViewHeight);
603 /** @see CandidatesViewManager#getViewType */
604 public int getViewType() {
609 public void setFullView() {
611 mIsScroll = false; // reset scroll flag
612 mWnn.onEvent(new NicoWnnEvent(NicoWnnEvent.LIST_CANDIDATES_FULL));
615 /** @see CandidatesViewManager#displayCandidates */
616 public void displayCandidates(WnnEngine converter) {
617 SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mWnn);
624 mLineMode = lineModeTable.get(pref.getString("nico_candidate_mode", "1_1"));
625 if (0 == mLineMode) {
629 else if (1 == mLineMode) {
633 else if (2 == mLineMode) {
637 else if (3 == mLineMode) {
641 mNoSpace = pref.getBoolean("nospace_candidate", false);
642 // candidate line height
643 mCandidateViewHeightIndex = candidateViewKeyHeight.get(pref.getString("candidateview_height_mode", "candidateview_value_0"));
645 mCanReadMore = false;
647 mFullViewWordCount = 0;
648 mFullViewOccupyCount = 0;
649 mFullViewPrevLineTopId = 0;
650 mCreateCandidateDone = false;
651 mIsCreateFullView = false;
655 mConverter = converter;
657 createWnnWordArray();
659 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
660 /* create normalview */
661 display1stCandidates(mConverter, mViewWidth);
662 mTargetScrollWidth = mViewWidth / 2;
663 mViewBodyHScroll.scrollTo(0, 0);
664 mIsLockHScroll = false;
665 /* create background normalview */
666 startCandidateTask();
671 private void startCandidateTask() {
672 int viewWidth = mViewWidth * 1000;
673 mCandidateTask = new TextCandidateTask(this);
674 if (null != mCandidateTask) {
675 mIsActiveTask = true;
676 mIsCancelTask = false;
677 mCandidateTask.execute(viewWidth);
683 public void checkCandidateTask() {
684 if (null != mCandidateTask) {
685 mCandidateTask.cancel(true);
686 mCandidateTask = null;
692 public void hideCandidateTask() {
694 if (null != mCandidateTask) {
695 mCandidateTask.cancel(true);
699 } catch (Exception e) {
702 //SystemClock.sleep(20);
703 if (true == mIsCancelTask) {
708 mCandidateTask = null;
714 public void cancelTask() {
715 mIsCancelTask = true;
720 synchronized private void createWnnWordArray() {
721 //private void createWnnWordArray() {
722 WnnEngine converter = mConverter;
723 if (null == converter) {
726 WnnWord result = null;
728 int indentWidth = mViewWidth / FULL_VIEW_DIV;
729 int maxindex = DISPLAY_LINE_MAX_COUNT * FULL_VIEW_DIV;
732 result = converter.getNextCandidate();
733 if (result == null) {
736 int textLength = measureText(result.candidate, 0, result.candidate.length());
737 int occupyCount = Math.min((textLength + indentWidth) / indentWidth, FULL_VIEW_DIV);
738 int textWidth = indentWidth * occupyCount;
740 mWnnWordArray.add(index, result);
741 mWnnWordTextLength.add(index, textWidth);
742 mWnnWordOccupyCount.add(index, occupyCount);
743 maxWidth += textWidth;
745 } while (index < maxindex);
747 /* split wnnword tables */
749 int size = mWnnWordArray.size();
750 int maxline = getMaxLine();
751 int halfWidth = (maxWidth / maxline);
756 halfWidth = Math.max(halfWidth, maxWidth - halfWidth);
757 for (iI = 0; iI < size; ++iI, ++divsize) {
758 if (halfWidth <= calcWidth) {
761 calcWidth += mWnnWordTextLength.get(iI);
763 for (iI = 0; iI < maxline; ++iI) {
764 mWnnLineCount[iI] = 0;
765 mWnnLineOffset[iI] = offset;
766 mWnnLineCountMax[iI] = divsize;
768 divsize = mWnnWordArray.size() - divsize;
772 /** @see CandidatesViewManager#getMaxLine */
774 int maxLine = (mPortrait) ? mPortraitLine : mLandscapeLine;
780 //synchronized private void display1stCandidates(WnnEngine converter, int width) {
781 private void display1stCandidates(WnnEngine converter, int width) {
782 if (converter == null) {
786 WnnWord result = null;
787 int maxline = getMaxLine();
795 for (iI = 0; iI < maxline; ++iI) {
796 wordcount = mWnnLineCount[iI];
797 size = mWnnLineCountMax[iI];
798 offset = mWnnLineOffset[iI];
801 LinearLayout candidateList = mViewCandidateList1st;
802 LinearLayout lineView = (LinearLayout)candidateList.getChildAt(iI);
803 while (wordcount < size) {
804 calcid = wordcount + offset;
805 result = mWnnWordArray.get(calcid);
806 calcwidth += mWnnWordTextLength.get(calcid);
807 set1stCandidate(wordcount, calcid, result, mWnnWordTextLength.get(calcid), mWnnWordOccupyCount.get(calcid), lineView);
809 if (calcwidth >= width) {
813 mWordCount += wordcount;
814 mWnnLineCount[iI] = wordcount;
816 m1stWordCount = mWordCount;
818 if (mWordCount < 1) { /* no candidates */
820 mWnn.setCandidatesViewShown(false);
823 mCanReadMore = false;
825 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
831 if (!(mViewBody.isShown())) {
832 mWnn.setCandidatesViewShown(true);
838 public int calc1stCandidates(int line, int width) {
839 if (false == mIsActiveTask) {
848 wordcount = mWnnLineCount[line];
849 size = mWnnLineCountMax[line];
850 offset = mWnnLineOffset[line];
851 while(calcwidth < width) {
852 if (wordcount >= size) {
855 calcid = wordcount + offset;
856 WnnWord wnnword = null;
858 wnnword = mWnnWordArray.get(calcid);
859 } catch (Exception e) {
860 mWnnLineCount[line] = mWnnLineCountMax[line];
863 calcwidth += mWnnWordTextLength.get(calcid);
871 public boolean display1stCandidates(int line, int width) {
872 if (false == mIsActiveTask) {
875 boolean result = false;
882 wordcount = mWnnLineCount[line];
883 size = mWnnLineCountMax[line];
884 offset = mWnnLineOffset[line];
885 LinearLayout candidateList = mViewCandidateList1st;
886 LinearLayout lineView = (LinearLayout)candidateList.getChildAt(line);
887 while(calcwidth < width) {
888 if (wordcount >= size) {
892 calcid = wordcount + offset;
893 WnnWord wnnword = null;
895 wnnword = mWnnWordArray.get(calcid);
896 } catch (Exception e) {
897 mWnnLineCount[line] = mWnnLineCountMax[line];
900 calcwidth += mWnnWordTextLength.get(calcid);
901 set1stCandidate(wordcount, calcid, wnnword, mWnnWordTextLength.get(calcid), mWnnWordOccupyCount.get(calcid), lineView);
904 mWnnLineCount[line] = wordcount;
910 public void invalidate1stView() {
911 int maxLine = getMaxLine();
912 LinearLayout lineView = (LinearLayout)mViewCandidateList1st.getChildAt(0);
914 for (int iI = 0; iI < maxLine; ++iI) {
915 lineView = (LinearLayout)mViewCandidateList1st.getChildAt(iI);
916 int getwidth = lineView.getWidth();
917 if (width < getwidth) {
921 int getx = mViewBodyHScroll.getScrollX();
922 int gety = mViewBodyHScroll.getScrollY();
923 mViewCandidateList1st.invalidate();
924 mViewBodyHScroll.scrollTo(getx, gety);
929 public void display1stLastSetup() {
930 m1stWordCount = mWordCount;
931 mIsActiveTask = false;
934 * Display the candidates.
936 * @param converter {@link WnnEngine} which holds candidates.
937 * @param dispFirst Whether it is the first time displaying the candidates
938 * @param maxLine The maximum number of displaying lines
940 //synchronized private void displayCandidates(WnnEngine converter, boolean dispFirst, int maxLine) {
941 private void displayCandidates(WnnEngine converter, boolean dispFirst, int maxLine) {
942 if (converter == null) {
945 boolean isBreak = false;
948 WnnWord result = null;
949 int size = mWnnWordArray.size();
950 while (mWordCount < size) {
951 result = mWnnWordArray.get(mWordCount);
952 setCandidate(result, mWnnWordTextLength.get(mWordCount), mWnnWordOccupyCount.get(mWordCount));
953 if (dispFirst && (maxLine < mLineCount)) {
960 if (!isBreak && !mCreateCandidateDone) {
961 /* align left if necessary */
963 mCreateCandidateDone = true;
966 if (mWordCount < 1) { /* no candidates */
968 mWnn.setCandidatesViewShown(false);
971 mCanReadMore = false;
973 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
976 if (!(mViewBody.isShown())) {
977 mWnn.setCandidatesViewShown(true);
985 private void set1stCandidate(int viewindex, int inid, WnnWord word, int textLength, int occupyCount, LinearLayout lineView) {
987 int indentWidth = mViewWidth / FULL_VIEW_DIV;
989 //int width = indentWidth * occupyCount;
990 int width = textLength;
991 int height = getCandidateMinimumHeight();
992 boolean iscreate = false;
993 textView = (TextView) lineView.getChildAt(viewindex);
994 if (textView == null) {
995 textView = createCandidateView();
999 int textId = inid + 1;
1000 textView.setWidth(width);
1001 textView.setHeight(height);
1002 textView.setText(word.candidate);
1003 textView.setTextColor(mTextColor);
1004 textView.setId(textId);
1005 textView.setVisibility(View.VISIBLE);
1006 textView.setPressed(false);
1007 textView.setEllipsize(TextUtils.TruncateAt.END);
1009 textView.setOnClickListener(mCandidateOnClick);
1010 textView.setOnLongClickListener(mCandidateOnLongClick);
1011 textView.setBackgroundResource(R.drawable.cand_back);
1013 textView.setOnTouchListener(mCandidateOnTouch);
1015 checkImageSpan(textView, word);
1016 if (true == iscreate) {
1017 lineView.addView(textView);
1021 * Add a candidate into the list.
1022 * @param word A candidate word
1024 private void setCandidate(WnnWord word, int textLength, int occupyCount) {
1026 int indentWidth = mViewWidth / FULL_VIEW_DIV;
1028 RelativeLayout layout = mViewCandidateList2nd;
1030 int width = indentWidth * occupyCount;
1031 int height = getCandidateMinimumHeight();
1032 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width, height);
1034 if (mFullViewPrevLineTopId == 0) {
1035 params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
1037 params.addRule(RelativeLayout.BELOW, mFullViewPrevLineTopId);
1040 if (mFullViewOccupyCount == 0) {
1041 params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
1043 params.addRule(RelativeLayout.RIGHT_OF, (mWordCount));
1046 textView = (TextView) layout.getChildAt(mFullViewWordCount);
1047 if (textView == null) {
1048 textView = createCandidateView();
1049 textView.setLayoutParams(params);
1051 mViewCandidateList2nd.addView(textView);
1053 mViewCandidateList2nd.updateViewLayout(textView, params);
1055 int textId = mWordCount+1;
1057 mFullViewOccupyCount += occupyCount;
1058 mFullViewWordCount++;
1059 mFullViewPrevView = textView;
1060 mFullViewPrevParams = params;
1062 textView.setText(word.candidate);
1063 textView.setTextColor(mTextColor);
1064 textView.setId(textId);
1065 textView.setVisibility(View.VISIBLE);
1066 textView.setPressed(false);
1067 textView.setEllipsize(TextUtils.TruncateAt.END);
1069 textView.setOnClickListener(mCandidateOnClick);
1070 textView.setOnLongClickListener(mCandidateOnLongClick);
1071 textView.setBackgroundResource(R.drawable.cand_back);
1073 textView.setOnTouchListener(mCandidateOnTouch);
1075 checkImageSpan(textView, word);
1077 mTotalLastId = textId;
1079 if (FULL_VIEW_DIV < (mFullViewOccupyCount + occupyCount)) {
1080 if (FULL_VIEW_DIV != mFullViewOccupyCount) {
1081 mFullViewPrevParams.width += (FULL_VIEW_DIV - mFullViewOccupyCount) * indentWidth;
1082 mViewCandidateList2nd.updateViewLayout(mFullViewPrevView, mFullViewPrevParams);
1084 if (getMaxLine() >= mLineCount) {
1085 mToplineLastId = textId;
1093 private void checkImageSpan(TextView textView, WnnWord word) {
1094 ImageSpan span = null;
1095 if (word.candidate.equals(" ")) {
1096 span = new ImageSpan(mWnn, R.drawable.word_half_space, DynamicDrawableSpan.ALIGN_BASELINE);
1097 } else if (word.candidate.equals("\u3000" /* full-width space */)) {
1098 span = new ImageSpan(mWnn, R.drawable.word_full_space, DynamicDrawableSpan.ALIGN_BASELINE);
1100 // check docomo emoji
1101 Integer getres = getDocomoEmojiRes(word);
1102 if (null != getres) {
1103 span = new ImageSpan(mWnn, getres.intValue(), DynamicDrawableSpan.ALIGN_BASELINE);
1106 SpannableString spannable = new SpannableString(" ");
1107 spannable.setSpan(span, 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
1108 textView.setText(spannable);
1112 * Create a view for a candidate.
1115 public TextView createCandidateView() {
1116 TextView text = new TextView(mViewBodyVScroll.getContext());
1117 text.setTextSize(20);
1118 text.setBackgroundResource(R.drawable.cand_back);
1119 text.setGravity(Gravity.CENTER);
1120 text.setSingleLine();
1121 text.setPadding(1, 1, 1, 1);
1122 text.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
1123 ViewGroup.LayoutParams.WRAP_CONTENT,
1125 text.setMinHeight(getCandidateMinimumHeight());
1126 text.setMinimumWidth(getCandidateMinimumWidth());
1131 * Clear the list of the normal candidate view.
1133 private void clearNormalViewCandidate() {
1134 LinearLayout candidateList = mViewCandidateList1st;
1135 int lineNum = candidateList.getChildCount();
1136 for (int i = 0; i < lineNum; i++) {
1137 LinearLayout lineView = (LinearLayout)candidateList.getChildAt(i);
1138 int size = lineView.getChildCount();
1139 for (int j = 0; j < size; j++) {
1140 View v = lineView.getChildAt(j);
1141 v.setVisibility(View.GONE);
1146 /** @see CandidatesViewManager#clearCandidates */
1147 public void clearCandidates() {
1149 checkCandidateTask();
1150 clearNormalViewCandidate();
1152 RelativeLayout layout2nd = mViewCandidateList2nd;
1153 size = layout2nd.getChildCount();
1154 for (int i = 0; i < size; i++) {
1155 View v = layout2nd.getChildAt(i);
1156 v.setVisibility(View.GONE);
1164 mWnnWordArray.clear();
1165 mWnnWordTextLength.clear();
1166 mWnnWordOccupyCount.clear();
1168 mIsFullView = false;
1169 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
1170 if (mAutoHideMode) {
1171 setViewLayout(CandidatesViewManager.VIEW_TYPE_CLOSE);
1174 if (mAutoHideMode && mViewBody.isShown()) {
1175 mWnn.setCandidatesViewShown(false);
1177 mCanReadMore = false;
1179 /** clear normalCandidate */
1180 private void clearNormalCandidates() {
1181 if (false == mIsCreateFullView) {
1184 if (mTotalLastId > mToplineLastId) {
1185 mCanReadMore = true;
1189 /** view fullCandidate */
1190 private void visibleFullCandidate() {
1191 if (false == mIsCreateFullView) {
1194 RelativeLayout layout = mViewCandidateList2nd;
1195 int size = layout.getChildCount();
1196 if (size > mTotalLastId) {
1197 size = mTotalLastId;
1199 for (int i = 0; i < size; i++) {
1200 View v = layout.getChildAt(i);
1201 v.setVisibility(View.VISIBLE);
1203 if (mTotalLastId != 0) {
1204 mCanReadMore = false;
1207 /** @see CandidatesViewManager#setPreferences */
1208 public void setPreferences(SharedPreferences pref) {
1210 if (pref.getBoolean("key_vibration", false)) {
1211 mVibrator = (Vibrator)mWnn.getSystemService(Context.VIBRATOR_SERVICE);
1215 if (pref.getBoolean("key_sound", false)) {
1216 mSound = MediaPlayer.create(mWnn, R.raw.type);
1220 } catch (Exception ex) {
1221 Log.d("iwnn", "NO VIBRATOR");
1226 * Process {@code OpenWnnEvent.CANDIDATE_VIEW_TOUCH} event.
1228 * @return {@code true} if event is processed; {@code false} if otherwise
1230 public boolean onTouchSync() {
1231 return mGestureDetector.onTouchEvent(mMotionEvent);
1235 * Select a candidate.
1237 * This method notices the selected word to {@link NicoWnn}.
1239 * @param word The selected word
1241 private void selectCandidate(WnnWord word) {
1242 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
1243 if (mVibrator != null) {
1244 try { mVibrator.vibrate(30); } catch (Exception ex) { }
1246 if (mSound != null) {
1247 try { mSound.seekTo(0); mSound.start(); } catch (Exception ex) { }
1249 mIsLockHScroll = true;
1250 mWnn.onEvent(new NicoWnnEvent(NicoWnnEvent.SELECT_CANDIDATE, word));
1253 /** @see android.view.GestureDetector.OnGestureListener#onDown */
1254 public boolean onDown(MotionEvent arg0) {
1258 /** @see android.view.GestureDetector.OnGestureListener#onFling */
1259 public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) {
1263 boolean consumed = false;
1266 if (arg0 != null && arg1 != null) {
1267 gety = (int)(arg1.getY() - arg0.getY());
1273 //if (arg3 < (float)-(getCandidateMinimumHeight() * 10)) {
1274 if (gety < -(getCandidateMinimumHeight() * 2)) {
1275 if ((mViewType == CandidatesViewManager.VIEW_TYPE_NORMAL) && mCanReadMore) {
1276 if (mVibrator != null) {
1277 try { mVibrator.vibrate(30); } catch (Exception ex) { }
1280 mIsScroll = false; // reset scroll flag
1281 mWnn.onEvent(new NicoWnnEvent(NicoWnnEvent.LIST_CANDIDATES_FULL));
1285 //else if (arg3 > (float)getCandidateMinimumHeight()) {
1286 else if (gety > (getCandidateMinimumHeight() * 1)) {
1287 if ((mViewBodyVScroll.getScrollY() == 0) && (true == mIsFullView)) {
1288 if (true == mIsScroll) {
1292 if (mVibrator != null) {
1293 try { mVibrator.vibrate(30); } catch (Exception ex) { }
1295 mIsFullView = false;
1296 mWnn.onEvent(new NicoWnnEvent(NicoWnnEvent.LIST_CANDIDATES_NORMAL));
1303 /** @see android.view.GestureDetector.OnGestureListener#onLongPress */
1304 public void onLongPress(MotionEvent arg0) {
1308 /** @see android.view.GestureDetector.OnGestureListener#onScroll */
1309 public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) {
1310 if (mViewBodyVScroll.getScrollY() != 0) {
1315 /** @see android.view.GestureDetector.OnGestureListener#onShowPress */
1316 public void onShowPress(MotionEvent arg0) {
1319 /** @see android.view.GestureDetector.OnGestureListener#onSingleTapUp */
1320 public boolean onSingleTapUp(MotionEvent arg0) {
1325 * Retrieve the width of string to draw.
1327 * @param text The string
1328 * @param start The start position (specified by the number of character)
1329 * @param end The end position (specified by the number of character)
1330 * @return The width of string to draw
1332 public int measureText(CharSequence text, int start, int end) {
1333 TextPaint paint = mViewCandidateTemplate.getPaint();
1334 int getwidth = Math.max((int)paint.measureText(text, start, end), CANDIDATE_MINIMUM_WIDTH);
1335 //int getwidth = Math.max((int)(end - start) * 40, CANDIDATE_MINIMUM_WIDTH);
1340 * Switch list/enlarge view mode.
1341 * @param up {@code true}:enlarge, {@code false}:list
1342 * @param word The candidate word to be enlarged.
1344 private void setViewScaleUp(boolean up, WnnWord word) {
1345 if (up == mIsScaleUp || (mViewScaleUp == null)) {
1349 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
1350 mViewCandidateList1st.setVisibility(View.GONE);
1351 mViewCandidateList2nd.setVisibility(View.GONE);
1352 mViewCandidateBase.setMinimumHeight(-1);
1353 mViewCandidateBase.addView(mViewScaleUp);
1354 TextView text = (TextView)mViewScaleUp.findViewById(R.id.candidate_scale_up_text);
1355 text.setText(word.candidate);
1356 checkImageSpan(text, word);
1358 Resources r = mViewBodyVScroll.getContext().getResources();
1359 text.setTextSize(r.getDimensionPixelSize(R.dimen.candidate_delete_word_size_landscape));
1365 mViewCandidateBase.removeView(mViewScaleUp);
1370 * Create a layout for the next line.
1372 private void createNextLine() {
1373 mFullViewOccupyCount = 0;
1374 mFullViewPrevLineTopId = mFullViewPrevView.getId();
1379 * @return the minimum width of a candidate view.
1381 public static int getCandidateMinimumWidth() {
1382 //return (int)(CANDIDATE_MINIMUM_WIDTH * mMetrics.density);
1383 return (int)(CANDIDATE_MINIMUM_WIDTH);
1387 * @return the minimum height of a candidate view.
1389 public static int getCandidateMinimumHeight() {
1390 //return (int)((float)candidateViewDataTable[mCandidateViewHeightIndex] * mMetrics.density);
1391 return (int)((float)candidateViewDataTable[mCandidateViewHeightIndex]);
1395 * get docomo-emoji resource
1397 private Integer getDocomoEmojiRes(WnnWord word) {
1398 return DOCOMO_EMOJI_TABLE.get(word.candidate);