blob: c8291f1bb26bf231a2de8bfa153f9c5bdcf88f89 [file] [log] [blame]
/*
* Copyright (C) 2008,2009 OMRON SOFTWARE Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jp.co.omronsoft.openwnn;
import java.util.ArrayList;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.media.MediaPlayer;
import android.os.Vibrator;
import android.text.TextUtils;
import android.text.TextPaint;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ImageSpan;
import android.text.style.DynamicDrawableSpan;
import android.util.Log;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.ImageView;
import android.graphics.drawable.Drawable;
/**
* The default candidates view manager class using {@link EditText}.
*
* @author Copyright (C) 2009 OMRON SOFTWARE CO., LTD. All Rights Reserved.
*/
public class TextCandidatesViewManager implements CandidatesViewManager, GestureDetector.OnGestureListener {
/** Height of a line */
public static final int LINE_HEIGHT = 34;
/** Number of lines to display (Portrait) */
public static final int LINE_NUM_PORTRAIT = 2;
/** Number of lines to display (Landscape) */
public static final int LINE_NUM_LANDSCAPE = 1;
/** Maximum lines */
private static final int DISPLAY_LINE_MAX_COUNT = 1000;
/** Width of the view */
private static final int CANDIDATE_MINIMUM_WIDTH = 48;
/** Height of the view */
private static final int CANDIDATE_MINIMUM_HEIGHT = 35;
/** Align the candidate left if the width of the string exceeds this threshold */
private static final int CANDIDATE_LEFT_ALIGN_THRESHOLD = 120;
/** Maximum number of displaying candidates par one line (full view mode) */
private static final int FULL_VIEW_DIV = 4;
/** Body view of the candidates list */
private ViewGroup mViewBody;
/** Scroller of {@code mViewBodyText} */
private ScrollView mViewBodyScroll;
/** Base of {@code mViewCandidateList1st}, {@code mViewCandidateList2nd} */
private ViewGroup mViewCandidateBase;
/** Button displayed bottom of the view when there are more candidates. */
private ImageView mReadMoreButton;
/** The view of the scaling up candidate */
private View mViewScaleUp;
/** Layout for the candidates list on normal view */
private LinearLayout mViewCandidateList1st;
/** Layout for the candidates list on full view */
private RelativeLayout mViewCandidateList2nd;
/** {@link OpenWnn} instance using this manager */
private OpenWnn mWnn;
/** View type (VIEW_TYPE_NORMAL or VIEW_TYPE_FULL or VIEW_TYPE_CLOSE) */
private int mViewType;
/** Portrait display({@code true}) or landscape({@code false}) */
private boolean mPortrait;
/** Width of the view */
private int mViewWidth;
/** Height of the view */
private int mViewHeight;
/** Whether hide the view if there is no candidates */
private boolean mAutoHideMode;
/** The converter to be get candidates from and notice the selected candidate to. */
private WnnEngine mConverter;
/** Limitation of displaying candidates */
private int mDisplayLimit;
/** Vibrator for touch vibration */
private Vibrator mVibrator = null;
/** MediaPlayer for click sound */
private MediaPlayer mSound = null;
/** Number of candidates displaying */
private int mWordCount;
/** List of candidates */
private ArrayList<WnnWord> mWnnWordArray;
/** Gesture detector */
private GestureDetector mGestureDetector;
/** The word pressed */
private WnnWord mWord;
/** Character width of the candidate area */
private int mLineLength = 0;
/** Number of lines displayed */
private int mLineCount = 1;
/** {@code true} if the candidate delete state is selected */
private boolean mIsScaleUp = false;
/** {@code true} if the full screen mode is selected */
private boolean mIsFullView = false;
/** The event object for "touch" */
private MotionEvent mMotionEvent = null;
/** The offset when the candidates is flowed out the candidate window */
private int mDisplayEndOffset = 0;
/** {@code true} if there are more candidates to display. */
private boolean mCanReadMore = false;
/** Width of {@code mReadMoreButton} */
private int mReadMoreButtonWidth = 0;
/** Color of the candidates */
private int mTextColor = 0;
/** Template object for each candidate and normal/full view change button */
private TextView mViewCandidateTemplate;
/** Number of candidates in full view */
private int mFullViewWordCount;
/** Number of candidates in the current line (in full view) */
private int mFullViewOccupyCount;
/** View of the previous candidate (in full view) */
private TextView mFullViewPrevView;
/** Id of the top line view (in full view) */
private int mFullViewPrevLineTopId;
/** Layout of the previous candidate (in full view) */
private RelativeLayout.LayoutParams mFullViewPrevParams;
/** Whether all candidates is displayed */
private boolean mCreateCandidateDone;
/** Number of lines in normal view */
private int mNormalViewWordCountOfLine;
/** general infomation about a display */
private final DisplayMetrics mMetrics = new DisplayMetrics();
/** Event listener for touching a candidate */
private OnTouchListener mCandidateOnTouch = new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (mMotionEvent != null) {
return true;
}
if ((event.getAction() == MotionEvent.ACTION_UP)
&& (v instanceof TextView)) {
Drawable d = v.getBackground();
if (d != null) {
d.setState(new int[] {});
}
}
mMotionEvent = event;
boolean ret = mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CANDIDATE_VIEW_TOUCH));
mMotionEvent = null;
return ret;
}
};
/** Event listener for clicking a candidate */
private OnClickListener mCandidateOnClick = new OnClickListener() {
public void onClick(View v) {
if (!v.isShown()) {
return;
}
if (v instanceof TextView) {
TextView text = (TextView)v;
int wordcount = text.getId();
WnnWord word = null;
word = mWnnWordArray.get(wordcount);
selectCandidate(word);
}
}
};
/** Event listener for long-clicking a candidate */
private OnLongClickListener mCandidateOnLongClick = new OnLongClickListener() {
public boolean onLongClick(View v) {
if (mViewScaleUp == null) {
return false;
}
if (!v.isShown()) {
return true;
}
Drawable d = v.getBackground();
if (d != null) {
if(d.getState().length == 0){
return true;
}
}
int wordcount = ((TextView)v).getId();
mWord = mWnnWordArray.get(wordcount);
setViewScaleUp(true, mWord);
return true;
}
};
/**
* Constructor
*/
public TextCandidatesViewManager() {
this(-1);
}
/**
* Constructor
*
* @param displayLimit The limit of display
*/
public TextCandidatesViewManager(int displayLimit) {
this.mDisplayLimit = displayLimit;
this.mWnnWordArray = new ArrayList<WnnWord>();
this.mAutoHideMode = true;
mMetrics.setToDefaults();
}
/**
* Set auto-hide mode.
* @param hide {@code true} if the view will hidden when no candidate exists;
* {@code false} if the view is always shown.
*/
public void setAutoHide(boolean hide) {
mAutoHideMode = hide;
}
/** @see CandidatesViewManager */
public View initView(OpenWnn parent, int width, int height) {
mWnn = parent;
mViewWidth = width;
mViewHeight = height;
mPortrait =
(parent.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE);
Resources r = mWnn.getResources();
LayoutInflater inflater = parent.getLayoutInflater();
mViewBody = (ViewGroup)inflater.inflate(R.layout.candidates, null);
mViewBodyScroll = (ScrollView)mViewBody.findViewById(R.id.candview_scroll);
mViewBodyScroll.setOnTouchListener(mCandidateOnTouch);
mViewCandidateBase = (ViewGroup)mViewBody.findViewById(R.id.candview_base);
createNormalCandidateView();
mViewCandidateList2nd = (RelativeLayout)mViewBody.findViewById(R.id.candidates_2nd_view);
mReadMoreButtonWidth = r.getDrawable(R.drawable.cand_up).getMinimumWidth();
mTextColor = r.getColor(R.color.candidate_text);
mReadMoreButton = (ImageView)mViewBody.findViewById(R.id.read_more_text);
mReadMoreButton.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (mIsFullView) {
mReadMoreButton.setImageResource(R.drawable.cand_down_press);
} else {
mReadMoreButton.setImageResource(R.drawable.cand_up_press);
}
break;
case MotionEvent.ACTION_UP:
if (mIsFullView) {
mReadMoreButton.setImageResource(R.drawable.cand_down);
} else {
mReadMoreButton.setImageResource(R.drawable.cand_up);
}
break;
default:
break;
}
return false;
}
});
mReadMoreButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (!v.isShown()) {
return;
}
if (mIsFullView) {
mIsFullView = false;
mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.LIST_CANDIDATES_NORMAL));
} else {
mIsFullView = true;
mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.LIST_CANDIDATES_FULL));
}
}
});
setViewType(CandidatesViewManager.VIEW_TYPE_CLOSE);
mGestureDetector = new GestureDetector(this);
View scaleUp = (View)inflater.inflate(R.layout.candidate_scale_up, null);
mViewScaleUp = scaleUp;
/* select button */
Button b = (Button)scaleUp.findViewById(R.id.candidate_select);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
selectCandidate(mWord);
}
});
/* cancel button */
b = (Button)scaleUp.findViewById(R.id.candidate_cancel);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.UPDATE_CANDIDATE));
}
});
return mViewBody;
}
/**
* Create the normal candidate view
*/
private void createNormalCandidateView() {
mViewCandidateList1st = (LinearLayout)mViewBody.findViewById(R.id.candidates_1st_view);
mViewCandidateList1st.setOnTouchListener(mCandidateOnTouch);
mViewCandidateList1st.setOnClickListener(mCandidateOnClick);
int line = getMaxLine();
int width = mViewWidth;
for (int i = 0; i < line; i++) {
LinearLayout lineView = new LinearLayout(mViewBodyScroll.getContext());
lineView.setOrientation(LinearLayout.HORIZONTAL);
LinearLayout.LayoutParams layoutParams =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
lineView.setLayoutParams(layoutParams);
for (int j = 0; j < (width / getCandidateMinimumWidth()); j++) {
TextView tv = createCandidateView();
lineView.addView(tv);
}
if (i == 0) {
TextView tv = createCandidateView();
layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.weight = 0;
layoutParams.gravity = Gravity.RIGHT;
tv.setLayoutParams(layoutParams);
lineView.addView(tv);
mViewCandidateTemplate = tv;
}
mViewCandidateList1st.addView(lineView);
}
}
/** @see CandidatesViewManager#getCurrentView */
public View getCurrentView() {
return mViewBody;
}
/** @see CandidatesViewManager#setViewType */
public void setViewType(int type) {
boolean readMore = setViewLayout(type);
if (readMore) {
displayCandidates(this.mConverter, false, -1);
} else {
if (type == CandidatesViewManager.VIEW_TYPE_NORMAL) {
mIsFullView = false;
if (mDisplayEndOffset > 0) {
int maxLine = getMaxLine();
displayCandidates(this.mConverter, false, maxLine);
} else {
setReadMore();
}
} else {
if (mViewBody.isShown()) {
mWnn.setCandidatesViewShown(false);
}
}
}
}
/**
* Set the view layout
*
* @param type View type
* @return {@code true} if display is updated; {@code false} if otherwise
*/
private boolean setViewLayout(int type) {
mViewType = type;
setViewScaleUp(false, null);
switch (type) {
case CandidatesViewManager.VIEW_TYPE_CLOSE:
mViewCandidateBase.setMinimumHeight(-1);
return false;
case CandidatesViewManager.VIEW_TYPE_NORMAL:
mViewBodyScroll.scrollTo(0, 0);
mViewCandidateList1st.setVisibility(View.VISIBLE);
mViewCandidateList2nd.setVisibility(View.GONE);
mViewCandidateBase.setMinimumHeight(-1);
int line = (mPortrait) ? LINE_NUM_PORTRAIT : LINE_NUM_LANDSCAPE;
mViewCandidateList1st.setMinimumHeight(getCandidateMinimumHeight() * line);
return false;
case CandidatesViewManager.VIEW_TYPE_FULL:
default:
mViewCandidateList2nd.setVisibility(View.VISIBLE);
mViewCandidateBase.setMinimumHeight(mViewHeight);
return true;
}
}
/** @see CandidatesViewManager#getViewType */
public int getViewType() {
return mViewType;
}
/** @see CandidatesViewManager#displayCandidates */
public void displayCandidates(WnnEngine converter) {
mCanReadMore = false;
mDisplayEndOffset = 0;
mIsFullView = false;
mFullViewWordCount = 0;
mFullViewOccupyCount = 0;
mFullViewPrevLineTopId = 0;
mCreateCandidateDone = false;
mNormalViewWordCountOfLine = 0;
clearCandidates();
mConverter = converter;
setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
mViewCandidateTemplate.setVisibility(View.VISIBLE);
mViewCandidateTemplate.setBackgroundResource(R.drawable.cand_back);
displayCandidates(converter, true, getMaxLine());
}
/** @see CandidatesViewManager#getMaxLine */
private int getMaxLine() {
int maxLine = (mPortrait) ? LINE_NUM_PORTRAIT : LINE_NUM_LANDSCAPE;
return maxLine;
}
/**
* Display the candidates.
*
* @param converter {@link WnnEngine} which holds candidates.
* @param dispFirst Whether it is the first time displaying the candidates
* @param maxLine The maximum number of displaying lines
*/
synchronized private void displayCandidates(WnnEngine converter, boolean dispFirst, int maxLine) {
if (converter == null) {
return;
}
/* Concatenate the candidates already got and the last one in dispFirst mode */
int displayLimit = mDisplayLimit;
boolean isHistorySequence = false;
boolean isBreak = false;
/* Get candidates */
WnnWord result = null;
while ((displayLimit == -1 || mWordCount < displayLimit)) {
result = converter.getNextCandidate();
if (result == null) {
break;
}
setCandidate(false, result);
if (dispFirst && (maxLine < mLineCount)) {
mCanReadMore = true;
isBreak = true;
break;
}
}
if (!isBreak && !mCreateCandidateDone) {
/* align left if necessary */
createNextLine();
mCreateCandidateDone = true;
}
if (mWordCount < 1) { /* no candidates */
if (mAutoHideMode) {
mWnn.setCandidatesViewShown(false);
return;
} else {
mCanReadMore = false;
mIsFullView = false;
setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
}
}
setReadMore();
if (!(mViewBody.isShown())) {
mWnn.setCandidatesViewShown(true);
}
return;
}
/**
* Add a candidate into the list.
* @param isCategory {@code true}:caption of category, {@code false}:normal word
* @param word A candidate word
*/
private void setCandidate(boolean isCategory, WnnWord word) {
int textLength = measureText(word.candidate, 0, word.candidate.length());
TextView template = mViewCandidateTemplate;
textLength += template.getPaddingLeft() + template.getPaddingRight();
int maxWidth = mViewWidth;
TextView textView;
if (mIsFullView || getMaxLine() < mLineCount) {
/* Full view */
int indentWidth = mViewWidth / FULL_VIEW_DIV;
int occupyCount = Math.min((textLength + indentWidth) / indentWidth, FULL_VIEW_DIV);
if (isCategory) {
occupyCount = FULL_VIEW_DIV;
}
if (FULL_VIEW_DIV < (mFullViewOccupyCount + occupyCount)) {
if (FULL_VIEW_DIV != mFullViewOccupyCount) {
mFullViewPrevParams.width += (FULL_VIEW_DIV - mFullViewOccupyCount) * indentWidth;
mViewCandidateList2nd.updateViewLayout(mFullViewPrevView, mFullViewPrevParams);
}
mFullViewOccupyCount = 0;
mFullViewPrevLineTopId = mFullViewPrevView.getId();
mLineCount++;
}
RelativeLayout layout = mViewCandidateList2nd;
int width = indentWidth * occupyCount;
int height = getCandidateMinimumHeight();
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width, height);
if (mFullViewPrevLineTopId == 0) {
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
} else {
params.addRule(RelativeLayout.BELOW, mFullViewPrevLineTopId);
}
if (mFullViewOccupyCount == 0) {
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
} else {
params.addRule(RelativeLayout.RIGHT_OF, (mWordCount - 1));
}
textView = (TextView) layout.getChildAt(mFullViewWordCount);
if (textView == null) {
textView = createCandidateView();
textView.setLayoutParams(params);
mViewCandidateList2nd.addView(textView);
} else {
mViewCandidateList2nd.updateViewLayout(textView, params);
}
mFullViewOccupyCount += occupyCount;
mFullViewWordCount++;
mFullViewPrevView = textView;
mFullViewPrevParams = params;
} else {
textLength = Math.max(textLength, getCandidateMinimumWidth());
/* Normal view */
int nextEnd = mLineLength + textLength;
if (mLineCount == 1) {
maxWidth -= getCandidateMinimumWidth();
}
if ((maxWidth < nextEnd) && (mWordCount != 0)) {
createNextLine();
if (getMaxLine() < mLineCount) {
mLineLength = 0;
/* Call this method again to add the candidate in the full view */
setCandidate(isCategory, word);
return;
}
mLineLength = textLength;
} else {
mLineLength = nextEnd;
}
LinearLayout lineView = (LinearLayout) mViewCandidateList1st.getChildAt(mLineCount - 1);
textView = (TextView) lineView.getChildAt(mNormalViewWordCountOfLine);
if (isCategory) {
if (mLineCount == 1) {
mViewCandidateTemplate.setBackgroundDrawable(null);
}
mLineLength += CANDIDATE_LEFT_ALIGN_THRESHOLD;
}
mNormalViewWordCountOfLine++;
}
textView.setText(word.candidate);
textView.setTextColor(mTextColor);
textView.setId(mWordCount);
textView.setVisibility(View.VISIBLE);
textView.setPressed(false);
if (isCategory) {
textView.setOnClickListener(null);
textView.setOnLongClickListener(null);
textView.setBackgroundDrawable(null);
} else {
textView.setOnClickListener(mCandidateOnClick);
textView.setOnLongClickListener(mCandidateOnLongClick);
textView.setBackgroundResource(R.drawable.cand_back);
}
textView.setOnTouchListener(mCandidateOnTouch);
if (maxWidth < textLength) {
textView.setEllipsize(TextUtils.TruncateAt.END);
} else {
textView.setEllipsize(null);
}
ImageSpan span = null;
if (word.candidate.equals(" ")) {
span = new ImageSpan(mWnn, R.drawable.word_half_space,
DynamicDrawableSpan.ALIGN_BASELINE);
} else if (word.candidate.equals("\u3000" /* full-width space */)) {
span = new ImageSpan(mWnn, R.drawable.word_full_space,
DynamicDrawableSpan.ALIGN_BASELINE);
}
if (span != null) {
SpannableString spannable = new SpannableString(" ");
spannable.setSpan(span, 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannable);
}
mWnnWordArray.add(mWordCount, word);
mWordCount++;
}
/**
* Create a view for a candidate.
* @return the view
*/
private TextView createCandidateView() {
TextView text = new TextView(mViewBodyScroll.getContext());
text.setTextSize(20);
text.setBackgroundResource(R.drawable.cand_back);
text.setGravity(Gravity.CENTER);
text.setSingleLine();
text.setPadding(4, 4, 4, 4);
text.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
1.0f));
text.setMinHeight(getCandidateMinimumHeight());
text.setMinimumWidth(getCandidateMinimumWidth());
return text;
}
/**
* Display {@code mReadMoreText} if there are more candidates.
*/
private void setReadMore() {
if (mIsScaleUp) {
mReadMoreButton.setVisibility(View.GONE);
mViewCandidateTemplate.setVisibility(View.GONE);
return;
}
if (mIsFullView) {
mReadMoreButton.setVisibility(View.VISIBLE);
mReadMoreButton.setImageResource(R.drawable.cand_down);
} else {
if (mCanReadMore) {
mReadMoreButton.setVisibility(View.VISIBLE);
mReadMoreButton.setImageResource(R.drawable.cand_up);
} else {
mReadMoreButton.setVisibility(View.GONE);
mViewCandidateTemplate.setVisibility(View.GONE);
}
}
}
/**
* Clear the list of the normal candidate view.
*/
private void clearNormalViewCandidate() {
LinearLayout candidateList = mViewCandidateList1st;
int lineNum = candidateList.getChildCount();
for (int i = 0; i < lineNum; i++) {
LinearLayout lineView = (LinearLayout)candidateList.getChildAt(i);
int size = lineView.getChildCount();
for (int j = 0; j < size; j++) {
View v = lineView.getChildAt(j);
v.setVisibility(View.GONE);
}
}
}
/** @see CandidatesViewManager#clearCandidates */
public void clearCandidates() {
clearNormalViewCandidate();
RelativeLayout layout = mViewCandidateList2nd;
int size = layout.getChildCount();
for (int i = 0; i < size; i++) {
View v = layout.getChildAt(i);
v.setVisibility(View.GONE);
}
mLineCount = 1;
mWordCount = 0;
mWnnWordArray.clear();
mLineLength = 0;
mIsFullView = false;
setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
if (mAutoHideMode) {
setViewLayout(CandidatesViewManager.VIEW_TYPE_CLOSE);
}
if (mAutoHideMode && mViewBody.isShown()) {
mWnn.setCandidatesViewShown(false);
}
mCanReadMore = false;
setReadMore();
}
/** @see CandidatesViewManager#setPreferences */
public void setPreferences(SharedPreferences pref) {
try {
if (pref.getBoolean("key_vibration", false)) {
mVibrator = (Vibrator)mWnn.getSystemService(Context.VIBRATOR_SERVICE);
} else {
mVibrator = null;
}
if (pref.getBoolean("key_sound", false)) {
mSound = MediaPlayer.create(mWnn, R.raw.type);
} else {
mSound = null;
}
} catch (Exception ex) {
Log.d("iwnn", "NO VIBRATOR");
}
}
/**
* Process {@code OpenWnnEvent.CANDIDATE_VIEW_TOUCH} event.
*
* @return {@code true} if event is processed; {@code false} if otherwise
*/
public boolean onTouchSync() {
return mGestureDetector.onTouchEvent(mMotionEvent);
}
/**
* Select a candidate.
* <br>
* This method notices the selected word to {@link OpenWnn}.
*
* @param word The selected word
*/
private void selectCandidate(WnnWord word) {
setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
if (mVibrator != null) {
try { mVibrator.vibrate(30); } catch (Exception ex) { }
}
if (mSound != null) {
try { mSound.seekTo(0); mSound.start(); } catch (Exception ex) { }
}
mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.SELECT_CANDIDATE, word));
}
/** @see android.view.GestureDetector.OnGestureListener#onDown */
public boolean onDown(MotionEvent arg0) {
return false;
}
/** @see android.view.GestureDetector.OnGestureListener#onFling */
public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) {
if (mIsScaleUp) {
return false;
}
boolean consumed = false;
if (arg1 != null && arg0 != null && arg1.getY() < arg0.getY()) {
if ((mViewType == CandidatesViewManager.VIEW_TYPE_NORMAL) && mCanReadMore) {
if (mVibrator != null) {
try { mVibrator.vibrate(30); } catch (Exception ex) { }
}
mIsFullView = true;
mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.LIST_CANDIDATES_FULL));
consumed = true;
}
} else {
if (mViewBodyScroll.getScrollY() == 0) {
if (mVibrator != null) {
try { mVibrator.vibrate(30); } catch (Exception ex) { }
}
mIsFullView = false;
mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.LIST_CANDIDATES_NORMAL));
consumed = true;
}
}
return consumed;
}
/** @see android.view.GestureDetector.OnGestureListener#onLongPress */
public void onLongPress(MotionEvent arg0) {
return;
}
/** @see android.view.GestureDetector.OnGestureListener#onScroll */
public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) {
return false;
}
/** @see android.view.GestureDetector.OnGestureListener#onShowPress */
public void onShowPress(MotionEvent arg0) {
}
/** @see android.view.GestureDetector.OnGestureListener#onSingleTapUp */
public boolean onSingleTapUp(MotionEvent arg0) {
return false;
}
/**
* Retrieve the width of string to draw.
*
* @param text The string
* @param start The start position (specified by the number of character)
* @param end The end position (specified by the number of character)
* @return The width of string to draw
*/
public int measureText(CharSequence text, int start, int end) {
TextPaint paint = mViewCandidateTemplate.getPaint();
return (int)paint.measureText(text, start, end);
}
/**
* Switch list/enlarge view mode.
* @param up {@code true}:enlarge, {@code false}:list
* @param word The candidate word to be enlarged.
*/
private void setViewScaleUp(boolean up, WnnWord word) {
if (up == mIsScaleUp || (mViewScaleUp == null)) {
return;
}
if (up) {
setViewLayout(CandidatesViewManager.VIEW_TYPE_NORMAL);
mViewCandidateList1st.setVisibility(View.GONE);
mViewCandidateBase.setMinimumHeight(-1);
mViewCandidateBase.addView(mViewScaleUp);
TextView text = (TextView)mViewScaleUp.findViewById(R.id.candidate_scale_up_text);
text.setText(word.candidate);
if (!mPortrait) {
Resources r = mViewBodyScroll.getContext().getResources();
text.setTextSize(r.getDimensionPixelSize(R.dimen.candidate_delete_word_size_landscape));
}
mIsScaleUp = true;
setReadMore();
} else {
mIsScaleUp = false;
mViewCandidateBase.removeView(mViewScaleUp);
}
}
/**
* Create a layout for the next line.
*/
private void createNextLine() {
int lineCount = mLineCount;
if (mIsFullView || getMaxLine() < lineCount) {
/* Full view */
mFullViewOccupyCount = 0;
mFullViewPrevLineTopId = mFullViewPrevView.getId();
} else {
/* Normal view */
LinearLayout lineView = (LinearLayout) mViewCandidateList1st.getChildAt(lineCount - 1);
float weight = 0;
if (mLineLength < CANDIDATE_LEFT_ALIGN_THRESHOLD) {
if (lineCount == 1) {
mViewCandidateTemplate.setVisibility(View.GONE);
}
} else {
weight = 1.0f;
}
LinearLayout.LayoutParams params
= new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
weight);
int child = lineView.getChildCount();
for (int i = 0; i < child; i++) {
View view = lineView.getChildAt(i);
if (view != mViewCandidateTemplate) {
view.setLayoutParams(params);
}
}
mLineLength = 0;
mNormalViewWordCountOfLine = 0;
}
mLineCount++;
}
/**
* @return the minimum width of a candidate view.
*/
private int getCandidateMinimumWidth() {
return (int)(CANDIDATE_MINIMUM_WIDTH * mMetrics.density);
}
/**
* @return the minimum height of a candidate view.
*/
private int getCandidateMinimumHeight() {
return (int)(CANDIDATE_MINIMUM_HEIGHT * mMetrics.density);
}
}