package net.toload.main.hd.candidate;
import java.util.List;
import net.toload.main.hd.R;
import net.toload.main.hd.global.Mapping;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ScrollView;
public class CandidateExpandedView extends CandidateView {
private final boolean DEBUG = false;
private final String TAG = "CandidateExpandedView";
private static final int MAX_SUGGESTIONS = 200;
private CandidateView mCandidateView;
private List<Mapping> mSuggestions;
//private int mVerticalPadding;
private int mTouchX = OUT_OF_BOUNDS;
private int mTouchY = OUT_OF_BOUNDS;
private int mSelRow; //Jeremy '11,8,28
private int mSelCol; //Jeremy '11,8,28
//private int mScrollY;
private int[][] mWordX = new int[MAX_SUGGESTIONS][MAX_SUGGESTIONS];
private int[][] mWordWidth = new int[MAX_SUGGESTIONS][MAX_SUGGESTIONS];
private int[] mRowSize = new int[MAX_SUGGESTIONS];
private int[] mRowStartingIndex = new int[MAX_SUGGESTIONS];
private int mRows=0;
private int mHeight; // built own mHeight and get from resources.
private int mTotalHeight;
private ScrollView mParentScroolView;
public CandidateExpandedView(Context context, AttributeSet attrs) {
super(context, attrs);
//this.mGestureDetector = null;
//mVerticalPadding =(int)( context.getResources()
// .getDimensionPixelSize(R.dimen.candidate_vertical_padding) *mLIMEPref.getFontSize());
mHeight = (int) (context.getResources().
getDimensionPixelSize(R.dimen.candidate_stripe_height) *mLIMEPref.getFontSize());
}
public void setParentScrollView(ScrollView v){
mParentScroolView = v;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desireWidth = resolveSize(mCandidateView.getWidth(), widthMeasureSpec);
int desiredHeight = resolveSize(mTotalHeight, heightMeasureSpec);
// Maximum possible width and desired height
setMeasuredDimension(desireWidth, desiredHeight);
}
@Override
protected void onDraw(Canvas canvas) {
if(mSuggestions == null) return;
if(DEBUG)
Log.i(TAG, "OnDraw() mSuggestions.size:" + mSuggestions.size());
//mTotalWidth = 0;
if (mBgPadding == null) {
mBgPadding = new Rect(0, 0, 0, 0);
if (getBackground() != null) {
getBackground().getPadding(mBgPadding);
}
}
if(DEBUG)
Log.i(TAG, "OnDraw():mBgPadding.Top=" + mBgPadding.top
+", mBgPadding.Right=" + mBgPadding.right);
final int height = mHeight;
final Rect bgPadding = mBgPadding;
final Paint paint = mPaint;
final Paint npaint = nPaint;
// Update mSelectedIndex from touch x and y;
if(mTouchX!=OUT_OF_BOUNDS && mTouchY!=OUT_OF_BOUNDS ){
//Jeremy '11,8,23 mTouchY is already relative to view origin, no need to add mScrollY
mSelRow =(int) (mTouchY )// + mScrollY)
/ (height + mVerticalPadding);
for(int i=0; i<mRowSize[mSelRow]; i++){
if (mTouchX >= mWordX[mSelRow][i] && mTouchX < mWordX[mSelRow][i]+ mWordWidth[mSelRow][i] ){
mSelectedIndex = mRowStartingIndex[mSelRow] +i;
mSelCol = i;
break;
}
}
if(DEBUG)
Log.i(TAG, "onDraw(): new mSelectedIndex =" + mSelectedIndex
+ ", mSelRow=" + mSelRow
+ ", mSelCol=" + mSelCol);
}
// Paint all the suggestions and lines.
if (canvas != null) {
// Calculate column and row of mSelectedIndex
/*int selRow =0;
int selCol = mSelectedIndex;
if(mSelectedIndex >= mRowSize[0]){
for(int i=0; i < mRows+1; i++){
//if(DEBUG)
Log.i(TAG, "onDraw(): mRowStartingIndex[" +i +"]=" + mRowStartingIndex[i]);
selRow = i;
if(mSelectedIndex < mRowStartingIndex[i]+ mRowSize[i] ) break;
}
//selRow = i;
selCol = mSelectedIndex - mRowStartingIndex[selRow];
}*/
if(DEBUG)
Log.i(TAG, "onDraw(): mSelectedIndex=" + mSelectedIndex + " at row:" + mSelRow + ", column:" + mSelCol);
// Draw highlight on SelectedIndex
// 29/Aug/2011, Art just ignore if there is an error.
try{
if (canvas != null && mSelectedIndex >=0) {
canvas.translate(mWordX[mSelRow][mSelCol], mSelRow * (height+ mVerticalPadding));
mSelectionHighlight.setBounds(0, bgPadding.top, mWordWidth[mSelRow][mSelCol], height);
mSelectionHighlight.draw(canvas);
canvas.translate(-mWordX[mSelRow][mSelCol], -mSelRow * (height+ mVerticalPadding));
}
}catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}
int y = (int) (((height - mPaint.getTextSize()) / 2) - mPaint.ascent());
int index = 0; //index in mSuggestions
for (int i = 0; i < mRows; i++) {
if(i!=0) y += height + mVerticalPadding;
for(int j = 0; j < mRowSize[i]; j++){
String suggestion = mSuggestions.get(index).getWord();
index++;
//if(DEBUG)
// Log.i(TAG, "Candidateview:OnDraw():index:" + index + " Drawing:" + suggestion );
if(mSuggestions.get(i).isDictionary()){
//npaint.setColor(mColorRecommended);
paint.setColor(mColorDictionary);
}else{
npaint.setColor(mColorOther);
if(i == 0 && j==0){
if(mSelectedIndex == 0) paint.setColor(mColorInverted);
else paint.setColor(mColorRecommended);
} else
paint.setColor(mColorOther);
}
canvas.drawText(suggestion, mWordX[i][j] + X_GAP, y, paint);
paint.setColor(mColorOther);
float lineX = mWordX[i][j] + mWordWidth[i][j] + 0.5f;
canvas.drawLine(lineX, bgPadding.top + (height + mVerticalPadding)*i, lineX,
(height + mVerticalPadding)*(i+1) - mVerticalPadding + 1, paint);
paint.setFakeBoldText(false);
}
}
}
}
public void setParentCandidateView(CandidateView v){
mCandidateView =v;
}
public void prepareLayout()
{
if(DEBUG)
Log.i(TAG, "prepareLayout()");
if(mSuggestions == null || mSuggestions.size()==0) return;
if(DEBUG)
Log.i(TAG, "prepareLayout():mSuggestions.size()" + mSuggestions.size());
updateFontSize();
final int height = mHeight;
final Paint paint = mPaint;
int x = 0;
int row=0;
int indexInRow=0;
mRowStartingIndex[0]=0;
final int count = mCount;
for (int i = 0; i < count; i++) {
//if(DEBUG)
// Log.i(TAG, "prepareLayout():updating:" + i +", indexInRox=" + indexInRow );
String suggestion = mSuggestions.get(i).getWord();
float textWidth = paint.measureText(suggestion);
final int wordWidth = (int) textWidth + X_GAP * 2;
if(x + wordWidth > mScreenWidth){
mRowSize[row]=indexInRow;
row++;
mRowStartingIndex[row] = i;
indexInRow =0;
x=0;
if(DEBUG)
Log.i(TAG, "prepareLayout():mRowSize[" + (row-1) +"]=" + mRowSize[row-1] );
if(DEBUG)
Log.i(TAG, "prepareLayout():mRowStartingIndex[" + row +"]=" + mRowStartingIndex[row] );
}
mWordX[row][indexInRow] = x;
mWordWidth[row][indexInRow] = wordWidth;
x += wordWidth;
if(DEBUG)
Log.i(TAG, "prepareLayout():mWorx[" + row +"][" +indexInRow +"]=" + mWordX[row][indexInRow] );
if(DEBUG)
Log.i(TAG, "prepareLayout():mWordWidth[" + row +"][" +indexInRow +"]=" + mWordWidth[row][indexInRow] );
if(i== count-1){
mRowSize[row]=indexInRow +1;
if(DEBUG)
Log.i(TAG, "prepareLayout():mRowSize[" + (row) +"]=" + mRowSize[row] );
}
indexInRow++;
}
//mTotalWidth = x;
mRows = row+1;
mTotalHeight = (height + mVerticalPadding) * (mRows);
if(DEBUG)
Log.i(TAG, "prepareLayout(): mRows=" + mRows + ", mTotalHeight=" + mTotalHeight);
}
@Override
public void setSuggestions(List<Mapping> suggestions) {
if(DEBUG) Log.i(TAG, "setSuggestions(), suggestions.size()=" + suggestions.size());
if(mCandidateView!=null && mCandidateView.mSuggestions!=null){
mSuggestions = mCandidateView.mSuggestions;
mCount = mCandidateView.mCount;
mSelectedIndex = mCandidateView.mSelectedIndex;
mTouchX = OUT_OF_BOUNDS;
mTouchY = OUT_OF_BOUNDS;
if(mSelectedIndex==-1){
mSelCol = -1;
mSelRow = -1;
}else{
mSelCol = mSelectedIndex;
mSelRow = 0;
}
}
prepareLayout();
requestLayout();
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent me) {
if(DEBUG)
Log.i(TAG, "onTouchEvent(): x =" + me.getX() + ", y=" + me.getY()
+ ", ScroolY=" +mParentScroolView.getScrollY() );
int action = me.getAction();
int x = (int) me.getX();
int y = (int) me.getY();
mTouchX = x;
mTouchY = y;
//mScrollY = mParentScroolView.getScrollY();
switch (action) {
case MotionEvent.ACTION_DOWN:
if(DEBUG) Log.i(TAG, "onTouchEvent(), Action_DONW");
invalidate();
break;
case MotionEvent.ACTION_MOVE:
if(DEBUG) Log.i(TAG, "onTouchEvent(), Action_MOVE");
invalidate();
break;
case MotionEvent.ACTION_UP:
if(DEBUG) Log.i(TAG, "onTouchEvent(), Action_UP");
//invalidate();
mCandidateView.takeSelectedSuggestion(true);//takeSuggstionAtIndex(mSelectedIndex);
break;
}
return true;
}
private void scrollToRow(int row){
int selY = row*(mHeight + mVerticalPadding);
int scrollY = mParentScroolView.getScrollY();
int scrollHeight = mParentScroolView.getHeight();
if(DEBUG) Log.i(TAG, "scrollToRow(), row=" + row
+ ", selected row y=" + selY
+ ", ScrollViewHeight" + scrollHeight
+ ", ScollY="+scrollY);
if(selY < scrollY || selY > (scrollY + scrollHeight))
mParentScroolView.scrollTo(0, row*((mHeight + mVerticalPadding)));
}
@Override
public void selectNext() {
if (mSuggestions == null) return;
if(mSelectedIndex == -1){
mSelectedIndex=0;
mSelRow=0;
mSelCol=0;
}else if(mSelectedIndex < mCount-1){
mSelectedIndex++;
if(mSelectedIndex >= mRowStartingIndex[mSelRow] + mRowSize[mSelRow]){
mSelRow++;
mSelCol=0;
scrollToRow(mSelRow);
}else
mSelCol++;
invalidate();
}
}
@Override
public void selectPrev() {
if (mSuggestions == null) return;
if(mSelectedIndex > 0) {
mSelectedIndex--;
if(mSelectedIndex < mRowStartingIndex[mSelRow] ){
mSelRow--;
mSelCol = mRowSize[mSelRow]-1;
scrollToRow(mSelRow);
}else
mSelCol--;
invalidate();
}
}
@Override
public void selectNextRow() {
if (mSuggestions == null) return;
if(mSelRow < mRows-1){
mSelRow ++;
if(DEBUG)
Log.i(TAG,"selectNextRow(): newRow=" + mSelRow
+ ", mSelCol=" + mSelCol
+ ", mRowStartingIndex[mSelRow]=" + mRowStartingIndex[mSelRow]
+ ", + mRowSize[mSelRow]" + + mRowSize[mSelRow]);
if(mSelCol > mRowSize[mSelRow]-1)
mSelCol = mRowSize[mSelRow]-1;
else if(mSelCol == -1)
mSelCol =0;
mSelectedIndex = mRowStartingIndex[mSelRow] + mSelCol;
scrollToRow(mSelRow);
invalidate();
}
}
@Override
public void selectPrevRow() {
if (mSuggestions == null) return;
if(mSelRow >0) {
mSelRow--;
if(mSelCol > mRowSize[mSelRow]-1)
mSelCol = mRowSize[mSelRow]-1;
mSelectedIndex = mRowStartingIndex[mSelRow] + mSelCol;
scrollToRow(mSelRow);
invalidate();
}
}
}