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 jp.co.omronsoft.openwnn;
19 import java.util.ArrayList;
20 import android.content.Context;
21 import android.content.SharedPreferences;
22 import android.content.res.Configuration;
23 import android.content.res.Resources;
24 import android.media.MediaPlayer;
25 import android.os.Vibrator;
26 import android.text.TextUtils;
27 import android.text.TextPaint;
28 import android.text.SpannableString;
29 import android.text.Spanned;
30 import android.text.style.ImageSpan;
31 import android.text.style.DynamicDrawableSpan;
32 import android.util.Log;
33 import android.util.DisplayMetrics;
34 import android.view.Gravity;
35 import android.view.MotionEvent;
36 import android.view.View;
37 import android.view.ViewGroup;
38 import android.view.View.OnClickListener;
39 import android.view.View.OnLongClickListener;
40 import android.view.View.OnTouchListener;
41 import android.view.GestureDetector;
42 import android.view.LayoutInflater;
43 import android.widget.Button;
44 import android.widget.LinearLayout;
45 import android.widget.ScrollView;
46 import android.widget.TextView;
47 import android.widget.EditText;
48 import android.widget.AbsoluteLayout;
49 import android.widget.ImageView;
50 import android.graphics.drawable.Drawable;
53 * The default candidates view manager class using {@link EditText}.
55 * @author Copyright (C) 2009 OMRON SOFTWARE CO., LTD. All Rights Reserved.
57 public class TextCandidatesViewManager implements CandidatesViewManager, GestureDetector.OnGestureListener {
58 /** Height of a line */
59 public static final int LINE_HEIGHT = 34;
60 /** Number of lines to display (Portrait) */
61 public static final int LINE_NUM_PORTRAIT = 2;
62 /** Number of lines to display (Landscape) */
63 public static final int LINE_NUM_LANDSCAPE = 1;
66 private static final int DISPLAY_LINE_MAX_COUNT = 1000;
67 /** Width of the view */
68 private static final int CANDIDATE_MINIMUM_WIDTH = 48;
69 /** Height of the view */
70 private static final int CANDIDATE_MINIMUM_HEIGHT = 35;
71 /** Align the candidate left if the width of the string exceeds this threshold */
72 private static final int CANDIDATE_LEFT_ALIGN_THRESHOLD = 120;
73 /** Maximum number of displaying candidates par one line (full view mode) */
74 private static final int FULL_VIEW_DIV = 4;
76 /** Body view of the candidates list */
77 private ViewGroup mViewBody;
78 /** Scroller of {@code mViewBodyText} */
79 private ScrollView mViewBodyScroll;
80 /** Base of {@code mViewCandidateList1st}, {@code mViewCandidateList2nd} */
81 private ViewGroup mViewCandidateBase;
82 /** Button displayed bottom of the view when there are more candidates. */
83 private ImageView mReadMoreButton;
84 /** The view of the scaling up candidate */
85 private View mViewScaleUp;
86 /** Layout for the candidates list on normal view */
87 private LinearLayout mViewCandidateList1st;
88 /** Layout for the candidates list on full view */
89 private AbsoluteLayout mViewCandidateList2nd;
90 /** {@link OpenWnn} instance using this manager */
92 /** View type (VIEW_TYPE_NORMAL or VIEW_TYPE_FULL or VIEW_TYPE_CLOSE) */
93 private int mViewType;
94 /** Portrait display({@code true}) or landscape({@code false}) */
95 private boolean mPortrait;
97 /** Width of the view */
98 private int mViewWidth;
99 /** Height of the view */
100 private int mViewHeight;
101 /** Minimum width of a candidate (density support) */
102 private int mCandidateMinimumWidth;
103 /** Maximum width of a candidate (density support) */
104 private int mCandidateMinimumHeight;
106 /** Whether hide the view if there is no candidates */
107 private boolean mAutoHideMode;
108 /** The converter to be get candidates from and notice the selected candidate to. */
109 private WnnEngine mConverter;
110 /** Limitation of displaying candidates */
111 private int mDisplayLimit;
113 /** Vibrator for touch vibration */
114 private Vibrator mVibrator = null;
115 /** MediaPlayer for click sound */
116 private MediaPlayer mSound = null;
118 /** Number of candidates displaying */
119 private int mWordCount;
120 /** List of candidates */
121 private ArrayList<WnnWord> mWnnWordArray;
123 /** Gesture detector */
124 private GestureDetector mGestureDetector;
125 /** The word pressed */
126 private WnnWord mWord;
127 /** Character width of the candidate area */
128 private int mLineLength = 0;
129 /** Number of lines displayed */
130 private int mLineCount = 1;
132 /** {@code true} if the candidate delete state is selected */
133 private boolean mIsScaleUp = false;
135 /** {@code true} if the full screen mode is selected */
136 private boolean mIsFullView = false;
138 /** The event object for "touch" */
139 private MotionEvent mMotionEvent = null;
141 /** The offset when the candidates is flowed out the candidate window */
142 private int mDisplayEndOffset = 0;
143 /** {@code true} if there are more candidates to display. */
144 private boolean mCanReadMore = false;
145 /** Width of {@code mReadMoreButton} */
146 private int mReadMoreButtonWidth = 0;
147 /** Color of the candidates */
148 private int mTextColor = 0;
149 /** Template object for each candidate and normal/full view change button */
150 private TextView mViewCandidateTemplate;
151 /** Number of candidates in full view */
152 private int mFullViewWordCount;
153 /** Number of candidates in the current line (in full view) */
154 private int mFullViewOccupyCount;
155 /** View of the previous candidate (in full view) */
156 private TextView mFullViewPrevView;
157 /** Id of the top line view (in full view) */
158 private int mFullViewPrevLineTopId;
159 /** Layout of the previous candidate (in full view) */
160 private ViewGroup.LayoutParams mFullViewPrevParams;
161 /** Whether all candidates is displayed */
162 private boolean mCreateCandidateDone;
163 /** Number of lines in normal view */
164 private int mNormalViewWordCountOfLine;
165 /** general infomation about a display */
166 private final DisplayMetrics mMetrics = new DisplayMetrics();
168 /** Event listener for touching a candidate */
169 private OnTouchListener mCandidateOnTouch = new OnTouchListener() {
170 public boolean onTouch(View v, MotionEvent event) {
171 if (mMotionEvent != null) {
175 if ((event.getAction() == MotionEvent.ACTION_UP)
176 && (v instanceof TextView)) {
177 Drawable d = v.getBackground();
179 d.setState(new int[] {});
183 mMotionEvent = event;
184 boolean ret = mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CANDIDATE_VIEW_TOUCH));
191 /** Event listener for clicking a candidate */
192 private OnClickListener mCandidateOnClick = new OnClickListener() {
193 public void onClick(View v) {
198 if (v instanceof TextView) {
199 TextView text = (TextView)v;
200 int wordcount = text.getId();
202 word = mWnnWordArray.get(wordcount);
203 selectCandidate(word);
208 /** Event listener for long-clicking a candidate */
209 private OnLongClickListener mCandidateOnLongClick = new OnLongClickListener() {
210 public boolean onLongClick(View v) {
211 if (mViewScaleUp == null) {
219 Drawable d = v.getBackground();
221 if(d.getState().length == 0){
226 int wordcount = ((TextView)v).getId();
227 mWord = mWnnWordArray.get(wordcount);
228 setViewScaleUp(true, mWord);
238 public TextCandidatesViewManager() {
245 * @param displayLimit The limit of display
247 public TextCandidatesViewManager(int displayLimit) {
248 this.mDisplayLimit = displayLimit;
249 this.mWnnWordArray = new ArrayList<WnnWord>();
250 this.mAutoHideMode = true;
251 mMetrics.setToDefaults();
255 * Set auto-hide mode.
256 * @param hide {@code true} if the view will hidden when no candidate exists;
257 * {@code false} if the view is always shown.
259 public void setAutoHide(boolean hide) {
260 mAutoHideMode = hide;
263 /** @see CandidatesViewManager */
264 public View initView(OpenWnn parent, int width, int height) {
267 mViewHeight = height;
268 mCandidateMinimumWidth = (int)(CANDIDATE_MINIMUM_WIDTH * mMetrics.density);
269 mCandidateMinimumHeight = (int)(CANDIDATE_MINIMUM_HEIGHT * mMetrics.density);
271 (parent.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE);
273 Resources r = mWnn.getResources();
275 LayoutInflater inflater = parent.getLayoutInflater();
276 mViewBody = (ViewGroup)inflater.inflate(R.layout.candidates, null);
278 mViewBodyScroll = (ScrollView)mViewBody.findViewById(R.id.candview_scroll);
279 mViewBodyScroll.setOnTouchListener(mCandidateOnTouch);
281 mViewCandidateBase = (ViewGroup)mViewBody.findViewById(R.id.candview_base);
283 createNormalCandidateView();
284 mViewCandidateList2nd = (AbsoluteLayout)mViewBody.findViewById(R.id.candidates_2nd_view);
286 mReadMoreButtonWidth = r.getDrawable(R.drawable.cand_up).getMinimumWidth();
288 mTextColor = r.getColor(R.color.candidate_text);
290 mReadMoreButton = (ImageView)mViewBody.findViewById(R.id.read_more_text);
291 mReadMoreButton.setOnTouchListener(new View.OnTouchListener() {
292 public boolean onTouch(View v, MotionEvent event) {
293 switch (event.getAction()) {
294 case MotionEvent.ACTION_DOWN:
296 mReadMoreButton.setImageResource(R.drawable.cand_down_press);
298 mReadMoreButton.setImageResource(R.drawable.cand_up_press);
301 case MotionEvent.ACTION_UP:
303 mReadMoreButton.setImageResource(R.drawable.cand_down);
305 mReadMoreButton.setImageResource(R.drawable.cand_up);
314 mReadMoreButton.setOnClickListener(new View.OnClickListener() {
315 public void onClick(View v) {
322 mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.LIST_CANDIDATES_NORMAL));
325 mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.LIST_CANDIDATES_FULL));
330 setViewType(CandidatesViewManager.VIEW_TYPE_CLOSE);
332 mGestureDetector = new GestureDetector(this);
334 View scaleUp = (View)inflater.inflate(R.layout.candidate_scale_up, null);
335 mViewScaleUp = scaleUp;
338 Button b = (Button)scaleUp.findViewById(R.id.candidate_select);
339 b.setOnClickListener(new View.OnClickListener() {
340 public void onClick(View v) {
341 selectCandidate(mWord);
346 b = (Button)scaleUp.findViewById(R.id.candidate_cancel);
347 b.setOnClickListener(new View.OnClickListener() {
348 public void onClick(View v) {
349 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
350 mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.UPDATE_CANDIDATE));
358 * Create the normal candidate view
360 private void createNormalCandidateView() {
361 mViewCandidateList1st = (LinearLayout)mViewBody.findViewById(R.id.candidates_1st_view);
362 mViewCandidateList1st.setOnTouchListener(mCandidateOnTouch);
363 mViewCandidateList1st.setOnClickListener(mCandidateOnClick);
365 int line = getMaxLine();
366 int width = mViewWidth;
367 for (int i = 0; i < line; i++) {
368 LinearLayout lineView = new LinearLayout(mViewBodyScroll.getContext());
369 lineView.setOrientation(LinearLayout.HORIZONTAL);
370 LinearLayout.LayoutParams layoutParams =
371 new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
372 ViewGroup.LayoutParams.WRAP_CONTENT);
373 lineView.setLayoutParams(layoutParams);
374 for (int j = 0; j < (width / getCandidateMinimumWidth()); j++) {
375 TextView tv = createCandidateView();
376 lineView.addView(tv);
380 TextView tv = createCandidateView();
381 layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
382 ViewGroup.LayoutParams.WRAP_CONTENT);
383 layoutParams.weight = 0;
384 layoutParams.gravity = Gravity.RIGHT;
385 tv.setLayoutParams(layoutParams);
387 lineView.addView(tv);
388 mViewCandidateTemplate = tv;
390 mViewCandidateList1st.addView(lineView);
394 /** @see CandidatesViewManager#getCurrentView */
395 public View getCurrentView() {
399 /** @see CandidatesViewManager#setViewType */
400 public void setViewType(int type) {
401 boolean readMore = setViewLayout(type);
404 displayCandidates(this.mConverter, false, -1);
406 if (type == CandidatesViewManager.VIEW_TYPE_NORMAL) {
408 if (mDisplayEndOffset > 0) {
409 int maxLine = getMaxLine();
410 displayCandidates(this.mConverter, false, maxLine);
415 if (mViewBody.isShown()) {
416 mWnn.setCandidatesViewShown(false);
423 * Set the view layout
425 * @param type View type
426 * @return {@code true} if display is updated; {@code false} if otherwise
428 private boolean setViewLayout(int type) {
430 setViewScaleUp(false, null);
433 case CandidatesViewManager.VIEW_TYPE_CLOSE:
434 mViewCandidateBase.setMinimumHeight(-1);
437 case CandidatesViewManager.VIEW_TYPE_NORMAL:
438 mViewBodyScroll.scrollTo(0, 0);
439 mViewCandidateList1st.setVisibility(View.VISIBLE);
440 mViewCandidateList2nd.setVisibility(View.GONE);
441 mViewCandidateBase.setMinimumHeight(-1);
442 int line = (mPortrait) ? LINE_NUM_PORTRAIT : LINE_NUM_LANDSCAPE;
443 mViewCandidateList1st.setMinimumHeight(getCandidateMinimumHeight() * line);
446 case CandidatesViewManager.VIEW_TYPE_FULL:
448 mViewCandidateList2nd.setVisibility(View.VISIBLE);
449 mViewCandidateBase.setMinimumHeight(mViewHeight);
454 /** @see CandidatesViewManager#getViewType */
455 public int getViewType() {
459 /** @see CandidatesViewManager#displayCandidates */
460 public void displayCandidates(WnnEngine converter) {
462 mCanReadMore = false;
463 mDisplayEndOffset = 0;
465 mFullViewWordCount = 0;
466 mFullViewOccupyCount = 0;
467 mFullViewPrevLineTopId = 0;
468 mCreateCandidateDone = false;
469 mNormalViewWordCountOfLine = 0;
472 mConverter = converter;
473 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
475 mViewCandidateTemplate.setVisibility(View.VISIBLE);
476 mViewCandidateTemplate.setBackgroundResource(R.drawable.cand_back);
478 displayCandidates(converter, true, getMaxLine());
481 /** @see CandidatesViewManager#getMaxLine */
482 private int getMaxLine() {
483 int maxLine = (mPortrait) ? LINE_NUM_PORTRAIT : LINE_NUM_LANDSCAPE;
488 * Display the candidates.
490 * @param converter {@link WnnEngine} which holds candidates.
491 * @param dispFirst Whether it is the first time displaying the candidates
492 * @param maxLine The maximum number of displaying lines
494 synchronized private void displayCandidates(WnnEngine converter, boolean dispFirst, int maxLine) {
495 if (converter == null) {
499 /* Concatenate the candidates already got and the last one in dispFirst mode */
500 int displayLimit = mDisplayLimit;
502 boolean isHistorySequence = false;
503 boolean isBreak = false;
506 WnnWord result = null;
507 while ((displayLimit == -1 || mWordCount < displayLimit)) {
508 result = converter.getNextCandidate();
510 if (result == null) {
514 setCandidate(false, result);
516 if (dispFirst && (maxLine < mLineCount)) {
523 if (!isBreak && !mCreateCandidateDone) {
524 /* align left if necessary */
526 mCreateCandidateDone = true;
529 if (mWordCount < 1) { /* no candidates */
531 mWnn.setCandidatesViewShown(false);
534 mCanReadMore = false;
536 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
542 if (!(mViewBody.isShown())) {
543 mWnn.setCandidatesViewShown(true);
549 * Add a candidate into the list.
550 * @param isCategory {@code true}:caption of category, {@code false}:normal word
551 * @param word A candidate word
553 private void setCandidate(boolean isCategory, WnnWord word) {
554 int textLength = measureText(word.candidate, 0, word.candidate.length());
555 TextView template = mViewCandidateTemplate;
556 textLength += template.getPaddingLeft() + template.getPaddingRight();
557 int maxWidth = mViewWidth;
560 if (mIsFullView || getMaxLine() < mLineCount) {
562 int indentWidth = mViewWidth / FULL_VIEW_DIV;
563 int occupyCount = Math.min((textLength + indentWidth) / indentWidth, FULL_VIEW_DIV);
565 occupyCount = FULL_VIEW_DIV;
568 if (FULL_VIEW_DIV < (mFullViewOccupyCount + occupyCount)) {
569 if (FULL_VIEW_DIV != mFullViewOccupyCount) {
570 mFullViewPrevParams.width += (FULL_VIEW_DIV - mFullViewOccupyCount) * indentWidth;
571 mViewCandidateList2nd.updateViewLayout(mFullViewPrevView, mFullViewPrevParams);
573 mFullViewOccupyCount = 0;
574 mFullViewPrevLineTopId = mFullViewPrevView.getId();
578 ViewGroup layout = mViewCandidateList2nd;
580 int width = indentWidth * occupyCount;
581 int height = getCandidateMinimumHeight();
584 ViewGroup.LayoutParams params = buildLayoutParams(mViewCandidateList2nd, width, height);
586 textView = (TextView) layout.getChildAt(mFullViewWordCount);
587 if (textView == null) {
588 textView = createCandidateView();
589 textView.setLayoutParams(params);
591 mViewCandidateList2nd.addView(textView);
593 mViewCandidateList2nd.updateViewLayout(textView, params);
596 mFullViewOccupyCount += occupyCount;
597 mFullViewWordCount++;
598 mFullViewPrevView = textView;
599 mFullViewPrevParams = params;
602 textLength = Math.max(textLength, getCandidateMinimumWidth());
605 int nextEnd = mLineLength + textLength;
606 if (mLineCount == 1) {
607 maxWidth -= getCandidateMinimumWidth();
610 if ((maxWidth < nextEnd) && (mWordCount != 0)) {
612 if (getMaxLine() < mLineCount) {
614 /* Call this method again to add the candidate in the full view */
615 setCandidate(isCategory, word);
619 mLineLength = textLength;
621 mLineLength = nextEnd;
624 LinearLayout lineView = (LinearLayout) mViewCandidateList1st.getChildAt(mLineCount - 1);
625 textView = (TextView) lineView.getChildAt(mNormalViewWordCountOfLine);
628 if (mLineCount == 1) {
629 mViewCandidateTemplate.setBackgroundDrawable(null);
631 mLineLength += CANDIDATE_LEFT_ALIGN_THRESHOLD;
634 mNormalViewWordCountOfLine++;
637 textView.setText(word.candidate);
638 textView.setTextColor(mTextColor);
639 textView.setId(mWordCount);
640 textView.setVisibility(View.VISIBLE);
641 textView.setPressed(false);
644 textView.setOnClickListener(null);
645 textView.setOnLongClickListener(null);
646 textView.setBackgroundDrawable(null);
648 textView.setOnClickListener(mCandidateOnClick);
649 textView.setOnLongClickListener(mCandidateOnLongClick);
650 textView.setBackgroundResource(R.drawable.cand_back);
652 textView.setOnTouchListener(mCandidateOnTouch);
654 if (maxWidth < textLength) {
655 textView.setEllipsize(TextUtils.TruncateAt.END);
657 textView.setEllipsize(null);
660 ImageSpan span = null;
661 if (word.candidate.equals(" ")) {
662 span = new ImageSpan(mWnn, R.drawable.word_half_space,
663 DynamicDrawableSpan.ALIGN_BASELINE);
664 } else if (word.candidate.equals("\u3000" /* full-width space */)) {
665 span = new ImageSpan(mWnn, R.drawable.word_full_space,
666 DynamicDrawableSpan.ALIGN_BASELINE);
670 SpannableString spannable = new SpannableString(" ");
671 spannable.setSpan(span, 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
672 textView.setText(spannable);
675 mWnnWordArray.add(mWordCount, word);
680 * Create AbsoluteLayout.LayoutParams
681 * @param layout AbsoluteLayout
684 * @return ViewGroup.LayoutParams
686 private ViewGroup.LayoutParams buildLayoutParams(AbsoluteLayout layout, int width, int height) {
688 int indentWidth = mViewWidth / FULL_VIEW_DIV;
689 int x = indentWidth * mFullViewOccupyCount;
690 int nomalLine = (mPortrait) ? LINE_NUM_PORTRAIT : LINE_NUM_LANDSCAPE;
691 int y = getCandidateMinimumHeight() * (mLineCount - nomalLine - 1);
692 ViewGroup.LayoutParams params
693 = new AbsoluteLayout.LayoutParams(width, height, x, y);
704 * Create a view for a candidate.
707 private TextView createCandidateView() {
708 TextView text = new TextView(mViewBodyScroll.getContext());
709 text.setTextSize(20);
710 text.setBackgroundResource(R.drawable.cand_back);
711 text.setGravity(Gravity.CENTER);
712 text.setSingleLine();
713 text.setPadding(4, 4, 4, 4);
714 text.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
715 ViewGroup.LayoutParams.WRAP_CONTENT,
717 text.setMinHeight(getCandidateMinimumHeight());
718 text.setMinimumWidth(getCandidateMinimumWidth());
723 * Display {@code mReadMoreText} if there are more candidates.
725 private void setReadMore() {
727 mReadMoreButton.setVisibility(View.GONE);
728 mViewCandidateTemplate.setVisibility(View.GONE);
733 mReadMoreButton.setVisibility(View.VISIBLE);
734 mReadMoreButton.setImageResource(R.drawable.cand_down);
737 mReadMoreButton.setVisibility(View.VISIBLE);
738 mReadMoreButton.setImageResource(R.drawable.cand_up);
740 mReadMoreButton.setVisibility(View.GONE);
741 mViewCandidateTemplate.setVisibility(View.GONE);
747 * Clear the list of the normal candidate view.
749 private void clearNormalViewCandidate() {
750 LinearLayout candidateList = mViewCandidateList1st;
751 int lineNum = candidateList.getChildCount();
752 for (int i = 0; i < lineNum; i++) {
754 LinearLayout lineView = (LinearLayout)candidateList.getChildAt(i);
755 int size = lineView.getChildCount();
756 for (int j = 0; j < size; j++) {
757 View v = lineView.getChildAt(j);
758 v.setVisibility(View.GONE);
763 /** @see CandidatesViewManager#clearCandidates */
764 public void clearCandidates() {
765 clearNormalViewCandidate();
767 ViewGroup layout = mViewCandidateList2nd;
768 int size = layout.getChildCount();
769 for (int i = 0; i < size; i++) {
770 View v = layout.getChildAt(i);
771 v.setVisibility(View.GONE);
776 mWnnWordArray.clear();
781 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
783 setViewLayout(CandidatesViewManager.VIEW_TYPE_CLOSE);
786 if (mAutoHideMode && mViewBody.isShown()) {
787 mWnn.setCandidatesViewShown(false);
789 mCanReadMore = false;
793 /** @see CandidatesViewManager#setPreferences */
794 public void setPreferences(SharedPreferences pref) {
796 if (pref.getBoolean("key_vibration", false)) {
797 mVibrator = (Vibrator)mWnn.getSystemService(Context.VIBRATOR_SERVICE);
801 if (pref.getBoolean("key_sound", false)) {
802 mSound = MediaPlayer.create(mWnn, R.raw.type);
806 } catch (Exception ex) {
807 Log.d("iwnn", "NO VIBRATOR");
812 * Process {@code OpenWnnEvent.CANDIDATE_VIEW_TOUCH} event.
814 * @return {@code true} if event is processed; {@code false} if otherwise
816 public boolean onTouchSync() {
817 return mGestureDetector.onTouchEvent(mMotionEvent);
821 * Select a candidate.
823 * This method notices the selected word to {@link OpenWnn}.
825 * @param word The selected word
827 private void selectCandidate(WnnWord word) {
828 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
829 if (mVibrator != null) {
830 try { mVibrator.vibrate(30); } catch (Exception ex) { }
832 if (mSound != null) {
833 try { mSound.seekTo(0); mSound.start(); } catch (Exception ex) { }
835 mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.SELECT_CANDIDATE, word));
838 /** @see android.view.GestureDetector.OnGestureListener#onDown */
839 public boolean onDown(MotionEvent arg0) {
843 /** @see android.view.GestureDetector.OnGestureListener#onFling */
844 public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) {
849 boolean consumed = false;
850 if (arg1 != null && arg0 != null && arg1.getY() < arg0.getY()) {
851 if ((mViewType == CandidatesViewManager.VIEW_TYPE_NORMAL) && mCanReadMore) {
852 if (mVibrator != null) {
853 try { mVibrator.vibrate(30); } catch (Exception ex) { }
856 mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.LIST_CANDIDATES_FULL));
860 if (mViewBodyScroll.getScrollY() == 0) {
861 if (mVibrator != null) {
862 try { mVibrator.vibrate(30); } catch (Exception ex) { }
865 mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.LIST_CANDIDATES_NORMAL));
873 /** @see android.view.GestureDetector.OnGestureListener#onLongPress */
874 public void onLongPress(MotionEvent arg0) {
878 /** @see android.view.GestureDetector.OnGestureListener#onScroll */
879 public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) {
883 /** @see android.view.GestureDetector.OnGestureListener#onShowPress */
884 public void onShowPress(MotionEvent arg0) {
887 /** @see android.view.GestureDetector.OnGestureListener#onSingleTapUp */
888 public boolean onSingleTapUp(MotionEvent arg0) {
893 * Retrieve the width of string to draw.
895 * @param text The string
896 * @param start The start position (specified by the number of character)
897 * @param end The end position (specified by the number of character)
898 * @return The width of string to draw
900 public int measureText(CharSequence text, int start, int end) {
901 if (end - start < 3) {
902 return getCandidateMinimumWidth();
905 TextPaint paint = mViewCandidateTemplate.getPaint();
906 return (int)paint.measureText(text, start, end);
910 * Switch list/enlarge view mode.
911 * @param up {@code true}:enlarge, {@code false}:list
912 * @param word The candidate word to be enlarged.
914 private void setViewScaleUp(boolean up, WnnWord word) {
915 if (up == mIsScaleUp || (mViewScaleUp == null)) {
920 setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
921 mViewCandidateList1st.setVisibility(View.GONE);
922 mViewCandidateBase.setMinimumHeight(-1);
923 mViewCandidateBase.addView(mViewScaleUp);
924 TextView text = (TextView)mViewScaleUp.findViewById(R.id.candidate_scale_up_text);
925 text.setText(word.candidate);
927 Resources r = mViewBodyScroll.getContext().getResources();
928 text.setTextSize(r.getDimensionPixelSize(R.dimen.candidate_delete_word_size_landscape));
935 mViewCandidateBase.removeView(mViewScaleUp);
940 * Create a layout for the next line.
942 private void createNextLine() {
943 int lineCount = mLineCount;
944 if (mIsFullView || getMaxLine() < lineCount) {
946 mFullViewOccupyCount = 0;
947 mFullViewPrevLineTopId = mFullViewPrevView.getId();
950 LinearLayout lineView = (LinearLayout) mViewCandidateList1st.getChildAt(lineCount - 1);
952 if (mLineLength < CANDIDATE_LEFT_ALIGN_THRESHOLD) {
953 if (lineCount == 1) {
954 mViewCandidateTemplate.setVisibility(View.GONE);
960 LinearLayout.LayoutParams params
961 = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
962 ViewGroup.LayoutParams.WRAP_CONTENT,
965 int child = lineView.getChildCount();
966 for (int i = 0; i < child; i++) {
967 View view = lineView.getChildAt(i);
969 if (view != mViewCandidateTemplate) {
970 view.setLayoutParams(params);
975 mNormalViewWordCountOfLine = 0;
981 * @return the minimum width of a candidate view.
983 private int getCandidateMinimumWidth() {
984 return mCandidateMinimumWidth;
988 * @return the minimum height of a candidate view.
990 private int getCandidateMinimumHeight() {
991 return mCandidateMinimumHeight;