231 lines
9.9 KiB
Java
231 lines
9.9 KiB
Java
|
/*
|
||
|
* Copyright (C) 2011 The Android Open Source Project
|
||
|
*
|
||
|
* 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 com.android.inputmethod.latin.suggestions;
|
||
|
|
||
|
import android.content.res.Resources;
|
||
|
import android.graphics.Paint;
|
||
|
import android.graphics.drawable.Drawable;
|
||
|
import android.text.TextUtils;
|
||
|
|
||
|
import com.android.inputmethod.keyboard.Key;
|
||
|
import com.android.inputmethod.keyboard.Keyboard;
|
||
|
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
||
|
import com.android.inputmethod.keyboard.KeyboardView;
|
||
|
import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
|
||
|
import com.android.inputmethod.keyboard.internal.KeyboardParams;
|
||
|
import com.android.inputmethod.latin.LatinImeLogger;
|
||
|
import com.android.inputmethod.latin.R;
|
||
|
import com.android.inputmethod.latin.SuggestedWords;
|
||
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||
|
|
||
|
public class MoreSuggestions extends Keyboard {
|
||
|
public static final int SUGGESTION_CODE_BASE = 1024;
|
||
|
|
||
|
private MoreSuggestions(Builder.MoreSuggestionsParam params) {
|
||
|
super(params);
|
||
|
}
|
||
|
|
||
|
public static class Builder extends KeyboardBuilder<Builder.MoreSuggestionsParam> {
|
||
|
private static final boolean DBG = LatinImeLogger.sDBG;
|
||
|
|
||
|
private final MoreSuggestionsView mPaneView;
|
||
|
private SuggestedWords mSuggestions;
|
||
|
private int mFromPos;
|
||
|
private int mToPos;
|
||
|
|
||
|
public static class MoreSuggestionsParam extends KeyboardParams {
|
||
|
private final int[] mWidths = new int[SuggestionsView.MAX_SUGGESTIONS];
|
||
|
private final int[] mRowNumbers = new int[SuggestionsView.MAX_SUGGESTIONS];
|
||
|
private final int[] mColumnOrders = new int[SuggestionsView.MAX_SUGGESTIONS];
|
||
|
private final int[] mNumColumnsInRow = new int[SuggestionsView.MAX_SUGGESTIONS];
|
||
|
private static final int MAX_COLUMNS_IN_ROW = 3;
|
||
|
private int mNumRows;
|
||
|
public Drawable mDivider;
|
||
|
public int mDividerWidth;
|
||
|
|
||
|
public int layout(SuggestedWords suggestions, int fromPos, int maxWidth, int minWidth,
|
||
|
int maxRow, KeyboardView view) {
|
||
|
clearKeys();
|
||
|
final Paint paint = new Paint();
|
||
|
paint.setAntiAlias(true);
|
||
|
final Resources res = view.getContext().getResources();
|
||
|
mDivider = res.getDrawable(R.drawable.more_suggestions_divider);
|
||
|
// TODO: Drawable itself should has an alpha value.
|
||
|
mDivider.setAlpha(128);
|
||
|
mDividerWidth = mDivider.getIntrinsicWidth();
|
||
|
final int padding = (int) res.getDimension(
|
||
|
R.dimen.more_suggestions_key_horizontal_padding);
|
||
|
|
||
|
int row = 0;
|
||
|
int pos = fromPos, rowStartPos = fromPos;
|
||
|
final int size = Math.min(suggestions.size(), SuggestionsView.MAX_SUGGESTIONS);
|
||
|
while (pos < size) {
|
||
|
final CharSequence word = suggestions.getWord(pos);
|
||
|
// TODO: Should take care of text x-scaling.
|
||
|
mWidths[pos] = (int)view.getDefaultLabelWidth(word, paint) + padding;
|
||
|
final int numColumn = pos - rowStartPos + 1;
|
||
|
final int columnWidth =
|
||
|
(maxWidth - mDividerWidth * (numColumn - 1)) / numColumn;
|
||
|
if (numColumn > MAX_COLUMNS_IN_ROW
|
||
|
|| !fitInWidth(rowStartPos, pos + 1, columnWidth)) {
|
||
|
if ((row + 1) >= maxRow) {
|
||
|
break;
|
||
|
}
|
||
|
mNumColumnsInRow[row] = pos - rowStartPos;
|
||
|
rowStartPos = pos;
|
||
|
row++;
|
||
|
}
|
||
|
mColumnOrders[pos] = pos - rowStartPos;
|
||
|
mRowNumbers[pos] = row;
|
||
|
pos++;
|
||
|
}
|
||
|
mNumColumnsInRow[row] = pos - rowStartPos;
|
||
|
mNumRows = row + 1;
|
||
|
mBaseWidth = mOccupiedWidth = Math.max(
|
||
|
minWidth, calcurateMaxRowWidth(fromPos, pos));
|
||
|
mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight + mVerticalGap;
|
||
|
return pos - fromPos;
|
||
|
}
|
||
|
|
||
|
private boolean fitInWidth(int startPos, int endPos, int width) {
|
||
|
for (int pos = startPos; pos < endPos; pos++) {
|
||
|
if (mWidths[pos] > width)
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private int calcurateMaxRowWidth(int startPos, int endPos) {
|
||
|
int maxRowWidth = 0;
|
||
|
int pos = startPos;
|
||
|
for (int row = 0; row < mNumRows; row++) {
|
||
|
final int numColumnInRow = mNumColumnsInRow[row];
|
||
|
int maxKeyWidth = 0;
|
||
|
while (pos < endPos && mRowNumbers[pos] == row) {
|
||
|
maxKeyWidth = Math.max(maxKeyWidth, mWidths[pos]);
|
||
|
pos++;
|
||
|
}
|
||
|
maxRowWidth = Math.max(maxRowWidth,
|
||
|
maxKeyWidth * numColumnInRow + mDividerWidth * (numColumnInRow - 1));
|
||
|
}
|
||
|
return maxRowWidth;
|
||
|
}
|
||
|
|
||
|
private static final int[][] COLUMN_ORDER_TO_NUMBER = {
|
||
|
{ 0, },
|
||
|
{ 1, 0, },
|
||
|
{ 2, 0, 1},
|
||
|
};
|
||
|
|
||
|
public int getNumColumnInRow(int pos) {
|
||
|
return mNumColumnsInRow[mRowNumbers[pos]];
|
||
|
}
|
||
|
|
||
|
public int getColumnNumber(int pos) {
|
||
|
final int columnOrder = mColumnOrders[pos];
|
||
|
final int numColumn = getNumColumnInRow(pos);
|
||
|
return COLUMN_ORDER_TO_NUMBER[numColumn - 1][columnOrder];
|
||
|
}
|
||
|
|
||
|
public int getX(int pos) {
|
||
|
final int columnNumber = getColumnNumber(pos);
|
||
|
return columnNumber * (getWidth(pos) + mDividerWidth);
|
||
|
}
|
||
|
|
||
|
public int getY(int pos) {
|
||
|
final int row = mRowNumbers[pos];
|
||
|
return (mNumRows -1 - row) * mDefaultRowHeight + mTopPadding;
|
||
|
}
|
||
|
|
||
|
public int getWidth(int pos) {
|
||
|
final int numColumnInRow = getNumColumnInRow(pos);
|
||
|
return (mOccupiedWidth - mDividerWidth * (numColumnInRow - 1)) / numColumnInRow;
|
||
|
}
|
||
|
|
||
|
public void markAsEdgeKey(Key key, int pos) {
|
||
|
final int row = mRowNumbers[pos];
|
||
|
if (row == 0)
|
||
|
key.markAsBottomEdge(this);
|
||
|
if (row == mNumRows - 1)
|
||
|
key.markAsTopEdge(this);
|
||
|
|
||
|
final int numColumnInRow = mNumColumnsInRow[row];
|
||
|
final int column = getColumnNumber(pos);
|
||
|
if (column == 0)
|
||
|
key.markAsLeftEdge(this);
|
||
|
if (column == numColumnInRow - 1)
|
||
|
key.markAsRightEdge(this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Builder(MoreSuggestionsView paneView) {
|
||
|
super(paneView.getContext(), new MoreSuggestionsParam());
|
||
|
mPaneView = paneView;
|
||
|
}
|
||
|
|
||
|
public Builder layout(SuggestedWords suggestions, int fromPos, int maxWidth,
|
||
|
int minWidth, int maxRow) {
|
||
|
final Keyboard keyboard = KeyboardSwitcher.getInstance().getLatinKeyboard();
|
||
|
final int xmlId = R.xml.kbd_suggestions_pane_template;
|
||
|
load(keyboard.mId.cloneWithNewXml(xmlId));
|
||
|
mParams.mVerticalGap = mParams.mTopPadding = keyboard.mVerticalGap / 2;
|
||
|
|
||
|
final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow,
|
||
|
mPaneView);
|
||
|
mFromPos = fromPos;
|
||
|
mToPos = fromPos + count;
|
||
|
mSuggestions = suggestions;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
private static String getDebugInfo(SuggestedWords suggestions, int pos) {
|
||
|
if (!DBG) return null;
|
||
|
final SuggestedWordInfo wordInfo = suggestions.getInfo(pos);
|
||
|
if (wordInfo == null) return null;
|
||
|
final String info = wordInfo.getDebugString();
|
||
|
if (TextUtils.isEmpty(info)) return null;
|
||
|
return info;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public MoreSuggestions build() {
|
||
|
final MoreSuggestionsParam params = mParams;
|
||
|
for (int pos = mFromPos; pos < mToPos; pos++) {
|
||
|
final int x = params.getX(pos);
|
||
|
final int y = params.getY(pos);
|
||
|
final int width = params.getWidth(pos);
|
||
|
final String word = mSuggestions.getWord(pos).toString();
|
||
|
final String info = getDebugInfo(mSuggestions, pos);
|
||
|
final int index = pos + SUGGESTION_CODE_BASE;
|
||
|
final Key key = new Key(
|
||
|
params, word, info, null, index, null, x, y, width,
|
||
|
params.mDefaultRowHeight);
|
||
|
params.markAsEdgeKey(key, pos);
|
||
|
params.onAddKey(key);
|
||
|
final int columnNumber = params.getColumnNumber(pos);
|
||
|
final int numColumnInRow = params.getNumColumnInRow(pos);
|
||
|
if (columnNumber < numColumnInRow - 1) {
|
||
|
final Key.Spacer spacer = new Key.Spacer(params, params.mDivider, x + width, y,
|
||
|
params.mDividerWidth, params.mDefaultRowHeight);
|
||
|
params.onAddKey(spacer);
|
||
|
}
|
||
|
}
|
||
|
return new MoreSuggestions(params);
|
||
|
}
|
||
|
}
|
||
|
}
|