package idv.Zero.KerKerInput; import java.util.ArrayList; import java.util.List; import android.util.Log; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.PopupWindow; import android.widget.TextView; public class CandidatesView extends View { private List<CharSequence> _cands; private Paint _pntText; private Drawable _drwHighlighted, _divider; private KerKerInputCore _core; private int _wordWidth = 34; private PopupWindow _winPreview; private TextView _txtPreview; private int _lastTouchedX; private int OUT_OF_BOUND = -1; private int[] _candIdxToX; private int[] _candIdxToWidth; private int[] _candIdxToPage; private int _scrollX; private int _currentCandidate; private int scrollStartCandID; private int _currentPage; public CandidatesView(Context c, AttributeSet attrs) { super(c, attrs); _drwHighlighted = c.getResources().getDrawable(R.drawable.highlight); _divider = c.getResources().getDrawable(R.drawable.divider); _cands = new ArrayList<CharSequence>(); _candIdxToX = new int[0]; _candIdxToWidth = new int[0]; _candIdxToPage = new int[0]; _currentPage = 0; _pntText = new Paint(); _pntText.setColor(Color.WHITE); _pntText.setAntiAlias(true); _pntText.setTextSize(24); _pntText.setStrokeWidth(0); setHorizontalFadingEdgeEnabled(true); setHorizontalScrollBarEnabled(false); setVerticalScrollBarEnabled(false); _lastTouchedX = OUT_OF_BOUND; scrollStartCandID = 0; } public void initPopup() { Context c = _core.getFrontend(); _winPreview = new PopupWindow(c); _winPreview.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); _winPreview.setBackgroundDrawable(null); _txtPreview = (TextView) _core.getInflater().inflate(R.layout.candidates_preview, null); _winPreview.setContentView(_txtPreview); } public void setCandidates(List<CharSequence> lst) { _cands = lst; _candIdxToX = new int[lst.size()]; _candIdxToWidth = new int[lst.size()]; _candIdxToPage = new int[lst.size()]; _currentPage = 0; scrollStartCandID = 0; invalidate(); Log.i("CandidateView", lst.toString()); } public void setCore(KerKerInputCore core) { _core = core; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int x = 0, page = 0; int y = (int) (getHeight() + _pntText.getTextSize() - _pntText.descent()) / 2; int count = _cands.size(); _divider.setBounds(0, 0, _divider.getIntrinsicWidth(), getHeight()); for(int i=0;i<count;i++) { CharSequence cand = _cands.get(i); float textWidth = _pntText.measureText(cand.toString()); float cellWidth = textWidth + 2; if (cellWidth < _wordWidth) cellWidth = _wordWidth; _candIdxToWidth[i] = (int)textWidth; _candIdxToX[i] = x; _candIdxToPage[i] = page; // FIXME: Failed if single candidate's textWidth > getWidth() if (x + textWidth > getWidth()) { page++; x = 0; i--; continue; } if (i < scrollStartCandID || page != _currentPage) { x += cellWidth + _divider.getIntrinsicWidth(); continue; } canvas.translate(x, 0); if (isCandSelected(x, x + (int)cellWidth)) { _drwHighlighted.setBounds(0, 0, (int)cellWidth, getHeight()); _drwHighlighted.draw(canvas); showPopup(i); } canvas.drawText(cand.toString(), (cellWidth-textWidth)/2, y, _pntText); canvas.translate(cellWidth, 0); _divider.draw(canvas); canvas.translate(-cellWidth, 0); canvas.translate(-x, 0); x += cellWidth + _divider.getIntrinsicWidth(); } _core.getCurrentInputMethod().setTotalPages(page + 1); } private boolean isCandSelected(int x, int xe) { if (_lastTouchedX >= x && _lastTouchedX <= xe) return true; else return false; } @Override public boolean onTouchEvent(MotionEvent me) { if (me.getAction() == MotionEvent.ACTION_UP || me.getAction() == MotionEvent.ACTION_OUTSIDE) { if (me.getAction() == MotionEvent.ACTION_UP) commitCandidates(); hidePopup(); } else if (me.getAction() == MotionEvent.ACTION_DOWN || me.getAction() == MotionEvent.ACTION_MOVE) _lastTouchedX = (int) me.getX(); invalidate(); return true; } private void commitCandidates() { if (_currentCandidate == OUT_OF_BOUND) return; _core.commitCandidate(_currentCandidate); } private void showPopup(int candIndex) { _currentCandidate = candIndex; CharSequence str = _cands.get(candIndex); _txtPreview.setText(str); _txtPreview.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); int wordWidth = (int)(_pntText.measureText(str.toString())); int popupWidth = wordWidth + _txtPreview.getPaddingLeft() + _txtPreview.getPaddingRight(); int popupHeight = _txtPreview.getMeasuredHeight(); int popupX = _candIdxToX[candIndex] - _scrollX + (popupWidth - _wordWidth) / 2 + 8; // 8? int popupY = -popupHeight; int[] offset = new int[2]; getLocationInWindow(offset); popupY += offset[1]; if (_winPreview.isShowing()) _winPreview.update(popupX, popupY, popupWidth, popupHeight); else { _winPreview.setWidth(popupWidth); _winPreview.setHeight(popupHeight); _winPreview.showAtLocation(this, Gravity.NO_GRAVITY, popupX, popupY); } _txtPreview.setVisibility(VISIBLE); } private void hidePopup() { _winPreview.dismiss(); _lastTouchedX = OUT_OF_BOUND; _currentCandidate = OUT_OF_BOUND; } public void prevPage() { if (_currentPage == 0) return; _currentPage--; while(scrollStartCandID >= 0 && _candIdxToPage[scrollStartCandID] > _currentPage - 1) scrollStartCandID--; scrollStartCandID++; _core.getCurrentInputMethod().setCurrentPage(_currentPage); } public void nextPage() { _currentPage++; while(scrollStartCandID < _cands.size() && _candIdxToPage[scrollStartCandID] < _currentPage) scrollStartCandID++; if (scrollStartCandID == _cands.size()) { scrollStartCandID--; prevPage(); } _core.getCurrentInputMethod().setCurrentPage(_currentPage); } }