am 23574d12: LatinIME portion of "green plus" feature.
* commit '23574d1231296e090e6efb41a50c7885a116ddb4': LatinIME portion of "green plus" feature.main
commit
311ebf3397
|
@ -33,30 +33,6 @@
|
||||||
android:soundEffectsEnabled="false" />
|
android:soundEffectsEnabled="false" />
|
||||||
<!-- Provide audio and haptic feedback by ourselves based on the keyboard settings.
|
<!-- Provide audio and haptic feedback by ourselves based on the keyboard settings.
|
||||||
We just need to ignore the system's audio and haptic feedback settings. -->
|
We just need to ignore the system's audio and haptic feedback settings. -->
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/add_to_dictionary_strip"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginLeft="@dimen/config_suggestions_strip_horizontal_margin"
|
|
||||||
android:layout_marginRight="@dimen/config_suggestions_strip_horizontal_margin"
|
|
||||||
android:hapticFeedbackEnabled="false"
|
|
||||||
android:soundEffectsEnabled="false">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/word_to_save"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
style="?attr/suggestionWordStyle" />
|
|
||||||
<include
|
|
||||||
android:id="@+id/word_to_save_divider"
|
|
||||||
layout="@layout/suggestion_divider" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/hint_add_to_dictionary"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center_vertical|start"
|
|
||||||
style="?attr/suggestionWordStyle" />
|
|
||||||
</LinearLayout>
|
|
||||||
<!-- Provide audio and haptic feedback by ourselves based on the keyboard settings.
|
<!-- Provide audio and haptic feedback by ourselves based on the keyboard settings.
|
||||||
We just need to ignore the system's audio and haptic feedback settings. -->
|
We just need to ignore the system's audio and haptic feedback settings. -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
/*
|
|
||||||
**
|
|
||||||
** Copyright 2014, 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.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
<!-- The extra margin in dp around the hit area of the commit/add-to-dictionary indicator -->
|
|
||||||
<integer name="text_decorator_hit_area_margin_in_dp">
|
|
||||||
4
|
|
||||||
</integer>
|
|
||||||
|
|
||||||
<!-- Background color to be used to highlight the target text when the add-to-dictionary
|
|
||||||
indicator is visible. -->
|
|
||||||
<color name="text_decorator_add_to_dictionary_indicator_text_highlight_color">
|
|
||||||
#D1E7B7
|
|
||||||
</color>
|
|
||||||
|
|
||||||
<!-- Foreground color of the commit indicator. -->
|
|
||||||
<color name="text_decorator_add_to_dictionary_indicator_background_color">
|
|
||||||
#4EB848
|
|
||||||
</color>
|
|
||||||
|
|
||||||
<!-- Foreground color of the add-to-dictionary indicator. -->
|
|
||||||
<color name="text_decorator_add_to_dictionary_indicator_foreground_color">
|
|
||||||
#FFFFFF
|
|
||||||
</color>
|
|
||||||
|
|
||||||
<!-- Viewport size of "text_decorator_add_to_dictionary_indicator_path". -->
|
|
||||||
<integer name="text_decorator_add_to_dictionary_indicator_path_size">
|
|
||||||
480
|
|
||||||
</integer>
|
|
||||||
|
|
||||||
<!-- Coordinates of the closed path to be used to render the add-to-dictionary indicator.
|
|
||||||
The format is: X[0], Y[0], X[1], Y[1], ..., X[N-1], Y[N-1] -->
|
|
||||||
<integer-array name="text_decorator_add_to_dictionary_indicator_path">
|
|
||||||
<item>380</item>
|
|
||||||
<item>260</item>
|
|
||||||
<item>260</item>
|
|
||||||
<item>260</item>
|
|
||||||
<item>260</item>
|
|
||||||
<item>380</item>
|
|
||||||
<item>220</item>
|
|
||||||
<item>380</item>
|
|
||||||
<item>220</item>
|
|
||||||
<item>260</item>
|
|
||||||
<item>100</item>
|
|
||||||
<item>260</item>
|
|
||||||
<item>100</item>
|
|
||||||
<item>220</item>
|
|
||||||
<item>220</item>
|
|
||||||
<item>220</item>
|
|
||||||
<item>220</item>
|
|
||||||
<item>100</item>
|
|
||||||
<item>260</item>
|
|
||||||
<item>100</item>
|
|
||||||
<item>260</item>
|
|
||||||
<item>220</item>
|
|
||||||
<item>380</item>
|
|
||||||
<item>220</item>
|
|
||||||
</integer-array>
|
|
||||||
</resources>
|
|
|
@ -127,7 +127,6 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions,
|
||||||
mKeyboardTextsSet.setLocale(mRichImm.getCurrentSubtypeLocales()[0], mThemeContext);
|
mKeyboardTextsSet.setLocale(mRichImm.getCurrentSubtypeLocales()[0], mThemeContext);
|
||||||
} catch (KeyboardLayoutSetException e) {
|
} catch (KeyboardLayoutSetException e) {
|
||||||
Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause());
|
Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,372 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 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.keyboard;
|
|
||||||
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.RectF;
|
|
||||||
import android.inputmethodservice.InputMethodService;
|
|
||||||
import android.os.Message;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.inputmethod.CursorAnchorInfo;
|
|
||||||
|
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
|
||||||
import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
|
|
||||||
import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A controller class of the add-to-dictionary indicator (a.k.a. TextDecorator). This class
|
|
||||||
* is designed to be independent of UI subsystems such as {@link View}. All the UI related
|
|
||||||
* operations are delegated to {@link TextDecoratorUi} via {@link TextDecoratorUiOperator}.
|
|
||||||
*/
|
|
||||||
public class TextDecorator {
|
|
||||||
private static final String TAG = TextDecorator.class.getSimpleName();
|
|
||||||
private static final boolean DEBUG = false;
|
|
||||||
|
|
||||||
private static final int INVALID_CURSOR_INDEX = -1;
|
|
||||||
|
|
||||||
private static final int MODE_MONITOR = 0;
|
|
||||||
private static final int MODE_WAITING_CURSOR_INDEX = 1;
|
|
||||||
private static final int MODE_SHOWING_INDICATOR = 2;
|
|
||||||
|
|
||||||
private int mMode = MODE_MONITOR;
|
|
||||||
|
|
||||||
private String mLastComposingText = null;
|
|
||||||
private boolean mHasRtlCharsInLastComposingText = false;
|
|
||||||
private RectF mComposingTextBoundsForLastComposingText = new RectF();
|
|
||||||
|
|
||||||
private boolean mIsFullScreenMode = false;
|
|
||||||
private String mWaitingWord = null;
|
|
||||||
private int mWaitingCursorStart = INVALID_CURSOR_INDEX;
|
|
||||||
private int mWaitingCursorEnd = INVALID_CURSOR_INDEX;
|
|
||||||
@Nullable
|
|
||||||
private CursorAnchorInfoCompatWrapper mCursorAnchorInfoWrapper = null;
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private final Listener mListener;
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private TextDecoratorUiOperator mUiOperator = EMPTY_UI_OPERATOR;
|
|
||||||
|
|
||||||
public interface Listener {
|
|
||||||
/**
|
|
||||||
* Called when the user clicks the indicator to add the word into the dictionary.
|
|
||||||
* @param word the word which the user clicked on.
|
|
||||||
*/
|
|
||||||
void onClickComposingTextToAddToDictionary(final String word);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextDecorator(@Nullable final Listener listener) {
|
|
||||||
mListener = (listener != null) ? listener : EMPTY_LISTENER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the UI operator for {@link TextDecorator}. Any user visible operations will be
|
|
||||||
* delegated to the associated UI operator.
|
|
||||||
* @param uiOperator the UI operator to be associated.
|
|
||||||
*/
|
|
||||||
public void setUiOperator(@Nonnull final TextDecoratorUiOperator uiOperator) {
|
|
||||||
mUiOperator.disposeUi();
|
|
||||||
mUiOperator = uiOperator;
|
|
||||||
mUiOperator.setOnClickListener(getOnClickHandler());
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Runnable mDefaultOnClickHandler = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
onClickIndicator();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@UsedForTesting
|
|
||||||
final Runnable getOnClickHandler() {
|
|
||||||
return mDefaultOnClickHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the "Add to dictionary" indicator and associates it with associating the given word.
|
|
||||||
*
|
|
||||||
* @param word the word which should be associated with the indicator. This object will be
|
|
||||||
* passed back in {@link Listener#onClickComposingTextToAddToDictionary(String)}.
|
|
||||||
* @param selectionStart the cursor index (inclusive) when the indicator should be displayed.
|
|
||||||
* @param selectionEnd the cursor index (exclusive) when the indicator should be displayed.
|
|
||||||
*/
|
|
||||||
public void showAddToDictionaryIndicator(final String word, final int selectionStart,
|
|
||||||
final int selectionEnd) {
|
|
||||||
mWaitingWord = word;
|
|
||||||
mWaitingCursorStart = selectionStart;
|
|
||||||
mWaitingCursorEnd = selectionEnd;
|
|
||||||
mMode = MODE_WAITING_CURSOR_INDEX;
|
|
||||||
layoutLater();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Must be called when the input method is about changing to for from the full screen mode.
|
|
||||||
* @param fullScreenMode {@code true} if the input method is entering the full screen mode.
|
|
||||||
* {@code false} is the input method is finishing the full screen mode.
|
|
||||||
*/
|
|
||||||
public void notifyFullScreenMode(final boolean fullScreenMode) {
|
|
||||||
final boolean fullScreenModeChanged = (mIsFullScreenMode != fullScreenMode);
|
|
||||||
mIsFullScreenMode = fullScreenMode;
|
|
||||||
if (fullScreenModeChanged) {
|
|
||||||
layoutLater();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets previous requests and makes indicator invisible.
|
|
||||||
*/
|
|
||||||
public void reset() {
|
|
||||||
mWaitingWord = null;
|
|
||||||
mMode = MODE_MONITOR;
|
|
||||||
mWaitingCursorStart = INVALID_CURSOR_INDEX;
|
|
||||||
mWaitingCursorEnd = INVALID_CURSOR_INDEX;
|
|
||||||
cancelLayoutInternalExpectedly("Resetting internal state.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Must be called when the {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}
|
|
||||||
* is called.
|
|
||||||
*
|
|
||||||
* <p>CAVEAT: Currently the input method author is responsible for ignoring
|
|
||||||
* {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} called in full screen
|
|
||||||
* mode.</p>
|
|
||||||
* @param info the compatibility wrapper object for the received {@link CursorAnchorInfo}.
|
|
||||||
*/
|
|
||||||
public void onUpdateCursorAnchorInfo(@Nullable final CursorAnchorInfoCompatWrapper info) {
|
|
||||||
mCursorAnchorInfoWrapper = info;
|
|
||||||
// Do not use layoutLater() to minimize the latency.
|
|
||||||
layoutImmediately();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancelLayoutInternalUnexpectedly(final String message) {
|
|
||||||
mUiOperator.hideUi();
|
|
||||||
Log.d(TAG, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancelLayoutInternalExpectedly(final String message) {
|
|
||||||
mUiOperator.hideUi();
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void layoutLater() {
|
|
||||||
mLayoutInvalidator.invalidateLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void layoutImmediately() {
|
|
||||||
// Clear pending layout requests.
|
|
||||||
mLayoutInvalidator.cancelInvalidateLayout();
|
|
||||||
layoutMain();
|
|
||||||
}
|
|
||||||
|
|
||||||
void layoutMain() {
|
|
||||||
final CursorAnchorInfoCompatWrapper info = mCursorAnchorInfoWrapper;
|
|
||||||
|
|
||||||
if (info == null) {
|
|
||||||
cancelLayoutInternalExpectedly("CursorAnchorInfo isn't available.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Matrix matrix = info.getMatrix();
|
|
||||||
if (matrix == null) {
|
|
||||||
cancelLayoutInternalUnexpectedly("Matrix is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
final CharSequence composingText = info.getComposingText();
|
|
||||||
if (!TextUtils.isEmpty(composingText)) {
|
|
||||||
final int composingTextStart = info.getComposingTextStart();
|
|
||||||
final int lastCharRectIndex = composingTextStart + composingText.length() - 1;
|
|
||||||
final RectF lastCharRect = info.getCharacterBounds(lastCharRectIndex);
|
|
||||||
final int lastCharRectFlags = info.getCharacterBoundsFlags(lastCharRectIndex);
|
|
||||||
final boolean hasInvisibleRegionInLastCharRect =
|
|
||||||
(lastCharRectFlags & CursorAnchorInfoCompatWrapper.FLAG_HAS_INVISIBLE_REGION)
|
|
||||||
!= 0;
|
|
||||||
if (lastCharRect == null || matrix == null || hasInvisibleRegionInLastCharRect) {
|
|
||||||
mUiOperator.hideUi();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that the following layout information is fragile, and must be invalidated
|
|
||||||
// even when surrounding text next to the composing text is changed because it can
|
|
||||||
// affect how the composing text is rendered.
|
|
||||||
// TODO: Investigate if we can change the input logic to make the target text
|
|
||||||
// composing state so that we can retrieve the character bounds reliably.
|
|
||||||
final String composingTextString = composingText.toString();
|
|
||||||
final float top = lastCharRect.top;
|
|
||||||
final float bottom = lastCharRect.bottom;
|
|
||||||
float left = lastCharRect.left;
|
|
||||||
float right = lastCharRect.right;
|
|
||||||
boolean useRtlLayout = false;
|
|
||||||
for (int i = composingText.length() - 1; i >= 0; --i) {
|
|
||||||
final int characterIndex = composingTextStart + i;
|
|
||||||
final RectF characterBounds = info.getCharacterBounds(characterIndex);
|
|
||||||
final int characterBoundsFlags = info.getCharacterBoundsFlags(characterIndex);
|
|
||||||
if (characterBounds == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (characterBounds.top != top) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (characterBounds.bottom != bottom) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((characterBoundsFlags & CursorAnchorInfoCompatWrapper.FLAG_IS_RTL) != 0) {
|
|
||||||
// This is for both RTL text and bi-directional text. RTL languages usually mix
|
|
||||||
// RTL characters with LTR characters and in this case we should display the
|
|
||||||
// indicator on the left, while in LTR languages that normally never happens.
|
|
||||||
// TODO: Try to come up with a better algorithm.
|
|
||||||
useRtlLayout = true;
|
|
||||||
}
|
|
||||||
left = Math.min(characterBounds.left, left);
|
|
||||||
right = Math.max(characterBounds.right, right);
|
|
||||||
}
|
|
||||||
mLastComposingText = composingTextString;
|
|
||||||
mHasRtlCharsInLastComposingText = useRtlLayout;
|
|
||||||
mComposingTextBoundsForLastComposingText.set(left, top, right, bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
final int selectionStart = info.getSelectionStart();
|
|
||||||
final int selectionEnd = info.getSelectionEnd();
|
|
||||||
switch (mMode) {
|
|
||||||
case MODE_MONITOR:
|
|
||||||
mUiOperator.hideUi();
|
|
||||||
return;
|
|
||||||
case MODE_WAITING_CURSOR_INDEX:
|
|
||||||
if (selectionStart != mWaitingCursorStart || selectionEnd != mWaitingCursorEnd) {
|
|
||||||
mUiOperator.hideUi();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mMode = MODE_SHOWING_INDICATOR;
|
|
||||||
break;
|
|
||||||
case MODE_SHOWING_INDICATOR:
|
|
||||||
if (selectionStart != mWaitingCursorStart || selectionEnd != mWaitingCursorEnd) {
|
|
||||||
mUiOperator.hideUi();
|
|
||||||
mMode = MODE_MONITOR;
|
|
||||||
mWaitingCursorStart = INVALID_CURSOR_INDEX;
|
|
||||||
mWaitingCursorEnd = INVALID_CURSOR_INDEX;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cancelLayoutInternalUnexpectedly("Unexpected internal mode=" + mMode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TextUtils.equals(mLastComposingText, mWaitingWord)) {
|
|
||||||
cancelLayoutInternalUnexpectedly("mLastComposingText doesn't match mWaitingWord");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((info.getInsertionMarkerFlags() &
|
|
||||||
CursorAnchorInfoCompatWrapper.FLAG_HAS_INVISIBLE_REGION) != 0) {
|
|
||||||
mUiOperator.hideUi();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mUiOperator.layoutUi(matrix, mComposingTextBoundsForLastComposingText,
|
|
||||||
mHasRtlCharsInLastComposingText);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onClickIndicator() {
|
|
||||||
if (mMode != MODE_SHOWING_INDICATOR) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mListener.onClickComposingTextToAddToDictionary(mWaitingWord);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final LayoutInvalidator mLayoutInvalidator = new LayoutInvalidator(this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used for managing pending layout tasks for {@link TextDecorator#layoutLater()}.
|
|
||||||
*/
|
|
||||||
private static final class LayoutInvalidator {
|
|
||||||
private final HandlerImpl mHandler;
|
|
||||||
public LayoutInvalidator(@Nonnull final TextDecorator ownerInstance) {
|
|
||||||
mHandler = new HandlerImpl(ownerInstance);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int MSG_LAYOUT = 0;
|
|
||||||
|
|
||||||
private static final class HandlerImpl
|
|
||||||
extends LeakGuardHandlerWrapper<TextDecorator> {
|
|
||||||
public HandlerImpl(@Nonnull final TextDecorator ownerInstance) {
|
|
||||||
super(ownerInstance);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleMessage(final Message msg) {
|
|
||||||
final TextDecorator owner = getOwnerInstance();
|
|
||||||
if (owner == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (msg.what) {
|
|
||||||
case MSG_LAYOUT:
|
|
||||||
owner.layoutMain();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Puts a layout task into the scheduler. Does nothing if one or more layout tasks are
|
|
||||||
* already scheduled.
|
|
||||||
*/
|
|
||||||
public void invalidateLayout() {
|
|
||||||
if (!mHandler.hasMessages(MSG_LAYOUT)) {
|
|
||||||
mHandler.obtainMessage(MSG_LAYOUT).sendToTarget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the pending layout tasks.
|
|
||||||
*/
|
|
||||||
public void cancelInvalidateLayout() {
|
|
||||||
mHandler.removeMessages(MSG_LAYOUT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private final static Listener EMPTY_LISTENER = new Listener() {
|
|
||||||
@Override
|
|
||||||
public void onClickComposingTextToAddToDictionary(final String word) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private final static TextDecoratorUiOperator EMPTY_UI_OPERATOR = new TextDecoratorUiOperator() {
|
|
||||||
@Override
|
|
||||||
public void disposeUi() {
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void hideUi() {
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void setOnClickListener(Runnable listener) {
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void layoutUi(Matrix matrix, RectF composingTextBounds, boolean useRtlLayout) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,262 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 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.keyboard;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.Path;
|
|
||||||
import android.graphics.RectF;
|
|
||||||
import android.graphics.drawable.ColorDrawable;
|
|
||||||
import android.inputmethodservice.InputMethodService;
|
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.ViewGroup.LayoutParams;
|
|
||||||
import android.view.ViewParent;
|
|
||||||
import android.widget.PopupWindow;
|
|
||||||
import android.widget.RelativeLayout;
|
|
||||||
|
|
||||||
import com.android.inputmethod.latin.R;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used as the UI component of {@link TextDecorator}.
|
|
||||||
*/
|
|
||||||
public final class TextDecoratorUi implements TextDecoratorUiOperator {
|
|
||||||
private static final boolean VISUAL_DEBUG = false;
|
|
||||||
private static final int VISUAL_DEBUG_HIT_AREA_COLOR = 0x80ff8000;
|
|
||||||
|
|
||||||
private final RelativeLayout mLocalRootView;
|
|
||||||
private final AddToDictionaryIndicatorView mAddToDictionaryIndicatorView;
|
|
||||||
private final PopupWindow mTouchEventWindow;
|
|
||||||
private final View mTouchEventWindowClickListenerView;
|
|
||||||
private final float mHitAreaMarginInPixels;
|
|
||||||
private final RectF mDisplayRect;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This constructor is designed to be called from {@link InputMethodService#setInputView(View)}.
|
|
||||||
* Other usages are not supported.
|
|
||||||
*
|
|
||||||
* @param context the context of the input method.
|
|
||||||
* @param inputView the view that is passed to {@link InputMethodService#setInputView(View)}.
|
|
||||||
*/
|
|
||||||
public TextDecoratorUi(final Context context, final View inputView) {
|
|
||||||
final Resources resources = context.getResources();
|
|
||||||
final int hitAreaMarginInDP = resources.getInteger(
|
|
||||||
R.integer.text_decorator_hit_area_margin_in_dp);
|
|
||||||
mHitAreaMarginInPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
|
||||||
hitAreaMarginInDP, resources.getDisplayMetrics());
|
|
||||||
final DisplayMetrics displayMetrics = resources.getDisplayMetrics();
|
|
||||||
mDisplayRect = new RectF(0.0f, 0.0f, displayMetrics.widthPixels,
|
|
||||||
displayMetrics.heightPixels);
|
|
||||||
|
|
||||||
mLocalRootView = new RelativeLayout(context);
|
|
||||||
mLocalRootView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
|
|
||||||
LayoutParams.MATCH_PARENT));
|
|
||||||
// TODO: Use #setBackground(null) for API Level >= 16.
|
|
||||||
mLocalRootView.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
|
||||||
|
|
||||||
final ViewGroup contentView = getContentView(inputView);
|
|
||||||
mAddToDictionaryIndicatorView = new AddToDictionaryIndicatorView(context);
|
|
||||||
mLocalRootView.addView(mAddToDictionaryIndicatorView);
|
|
||||||
if (contentView != null) {
|
|
||||||
contentView.addView(mLocalRootView);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This popup window is used to avoid the limitation that the input method is not able to
|
|
||||||
// observe the touch events happening outside of InputMethodService.Insets#touchableRegion.
|
|
||||||
// We don't use this popup window for rendering the UI for performance reasons though.
|
|
||||||
mTouchEventWindow = new PopupWindow(context);
|
|
||||||
if (VISUAL_DEBUG) {
|
|
||||||
mTouchEventWindow.setBackgroundDrawable(new ColorDrawable(VISUAL_DEBUG_HIT_AREA_COLOR));
|
|
||||||
} else {
|
|
||||||
mTouchEventWindow.setBackgroundDrawable(null);
|
|
||||||
}
|
|
||||||
mTouchEventWindowClickListenerView = new View(context);
|
|
||||||
mTouchEventWindow.setContentView(mTouchEventWindowClickListenerView);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void disposeUi() {
|
|
||||||
if (mLocalRootView != null) {
|
|
||||||
final ViewParent parent = mLocalRootView.getParent();
|
|
||||||
if (parent != null && parent instanceof ViewGroup) {
|
|
||||||
((ViewGroup) parent).removeView(mLocalRootView);
|
|
||||||
}
|
|
||||||
mLocalRootView.removeAllViews();
|
|
||||||
}
|
|
||||||
if (mTouchEventWindow != null) {
|
|
||||||
mTouchEventWindow.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void hideUi() {
|
|
||||||
mAddToDictionaryIndicatorView.setVisibility(View.GONE);
|
|
||||||
mTouchEventWindow.dismiss();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final RectF getIndicatorBoundsInScreenCoordinates(final Matrix matrix,
|
|
||||||
final RectF composingTextBounds, final boolean showAtLeftSide) {
|
|
||||||
final float indicatorSize = composingTextBounds.height();
|
|
||||||
final RectF indicatorBounds;
|
|
||||||
if (showAtLeftSide) {
|
|
||||||
indicatorBounds = new RectF(composingTextBounds.left - indicatorSize,
|
|
||||||
composingTextBounds.top, composingTextBounds.left,
|
|
||||||
composingTextBounds.top + indicatorSize);
|
|
||||||
} else {
|
|
||||||
indicatorBounds = new RectF(composingTextBounds.right, composingTextBounds.top,
|
|
||||||
composingTextBounds.right + indicatorSize,
|
|
||||||
composingTextBounds.top + indicatorSize);
|
|
||||||
}
|
|
||||||
matrix.mapRect(indicatorBounds);
|
|
||||||
return indicatorBounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void layoutUi(final Matrix matrix, final RectF composingTextBounds,
|
|
||||||
final boolean useRtlLayout) {
|
|
||||||
RectF indicatorBoundsInScreenCoordinates = getIndicatorBoundsInScreenCoordinates(matrix,
|
|
||||||
composingTextBounds, useRtlLayout /* showAtLeftSide */);
|
|
||||||
if (indicatorBoundsInScreenCoordinates.left < mDisplayRect.left ||
|
|
||||||
mDisplayRect.right < indicatorBoundsInScreenCoordinates.right) {
|
|
||||||
// The indicator is clipped by the screen. Show the indicator at the opposite side.
|
|
||||||
indicatorBoundsInScreenCoordinates = getIndicatorBoundsInScreenCoordinates(matrix,
|
|
||||||
composingTextBounds, !useRtlLayout /* showAtLeftSide */);
|
|
||||||
}
|
|
||||||
|
|
||||||
mAddToDictionaryIndicatorView.setBounds(indicatorBoundsInScreenCoordinates);
|
|
||||||
|
|
||||||
final RectF hitAreaBoundsInScreenCoordinates = new RectF();
|
|
||||||
matrix.mapRect(hitAreaBoundsInScreenCoordinates, composingTextBounds);
|
|
||||||
hitAreaBoundsInScreenCoordinates.union(indicatorBoundsInScreenCoordinates);
|
|
||||||
hitAreaBoundsInScreenCoordinates.inset(-mHitAreaMarginInPixels, -mHitAreaMarginInPixels);
|
|
||||||
|
|
||||||
final int[] originScreen = new int[2];
|
|
||||||
mLocalRootView.getLocationOnScreen(originScreen);
|
|
||||||
final int viewOriginX = originScreen[0];
|
|
||||||
final int viewOriginY = originScreen[1];
|
|
||||||
mAddToDictionaryIndicatorView.setX(indicatorBoundsInScreenCoordinates.left - viewOriginX);
|
|
||||||
mAddToDictionaryIndicatorView.setY(indicatorBoundsInScreenCoordinates.top - viewOriginY);
|
|
||||||
mAddToDictionaryIndicatorView.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
if (mTouchEventWindow.isShowing()) {
|
|
||||||
mTouchEventWindow.update((int)hitAreaBoundsInScreenCoordinates.left - viewOriginX,
|
|
||||||
(int)hitAreaBoundsInScreenCoordinates.top - viewOriginY,
|
|
||||||
(int)hitAreaBoundsInScreenCoordinates.width(),
|
|
||||||
(int)hitAreaBoundsInScreenCoordinates.height());
|
|
||||||
} else {
|
|
||||||
mTouchEventWindow.setWidth((int)hitAreaBoundsInScreenCoordinates.width());
|
|
||||||
mTouchEventWindow.setHeight((int)hitAreaBoundsInScreenCoordinates.height());
|
|
||||||
mTouchEventWindow.showAtLocation(mLocalRootView, Gravity.NO_GRAVITY,
|
|
||||||
(int)hitAreaBoundsInScreenCoordinates.left - viewOriginX,
|
|
||||||
(int)hitAreaBoundsInScreenCoordinates.top - viewOriginY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setOnClickListener(final Runnable listener) {
|
|
||||||
mTouchEventWindowClickListenerView.setOnClickListener(new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(final View arg0) {
|
|
||||||
listener.run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class IndicatorView extends View {
|
|
||||||
private final Path mPath;
|
|
||||||
private final Path mTmpPath = new Path();
|
|
||||||
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
||||||
private final Matrix mMatrix = new Matrix();
|
|
||||||
private final int mBackgroundColor;
|
|
||||||
private final int mForegroundColor;
|
|
||||||
private final RectF mBounds = new RectF();
|
|
||||||
public IndicatorView(Context context, final int pathResourceId,
|
|
||||||
final int sizeResourceId, final int backgroundColorResourceId,
|
|
||||||
final int foregroundColroResourceId) {
|
|
||||||
super(context);
|
|
||||||
final Resources resources = context.getResources();
|
|
||||||
mPath = createPath(resources, pathResourceId, sizeResourceId);
|
|
||||||
mBackgroundColor = resources.getColor(backgroundColorResourceId);
|
|
||||||
mForegroundColor = resources.getColor(foregroundColroResourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBounds(final RectF rect) {
|
|
||||||
mBounds.set(rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDraw(Canvas canvas) {
|
|
||||||
mPaint.setColor(mBackgroundColor);
|
|
||||||
mPaint.setStyle(Paint.Style.FILL);
|
|
||||||
canvas.drawRect(0.0f, 0.0f, mBounds.width(), mBounds.height(), mPaint);
|
|
||||||
|
|
||||||
mMatrix.reset();
|
|
||||||
mMatrix.postScale(mBounds.width(), mBounds.height());
|
|
||||||
mPath.transform(mMatrix, mTmpPath);
|
|
||||||
mPaint.setColor(mForegroundColor);
|
|
||||||
canvas.drawPath(mTmpPath, mPaint);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Path createPath(final Resources resources, final int pathResourceId,
|
|
||||||
final int sizeResourceId) {
|
|
||||||
final int size = resources.getInteger(sizeResourceId);
|
|
||||||
final float normalizationFactor = 1.0f / size;
|
|
||||||
final int[] array = resources.getIntArray(pathResourceId);
|
|
||||||
|
|
||||||
final Path path = new Path();
|
|
||||||
for (int i = 0; i < array.length; i += 2) {
|
|
||||||
if (i == 0) {
|
|
||||||
path.moveTo(array[i] * normalizationFactor, array[i + 1] * normalizationFactor);
|
|
||||||
} else {
|
|
||||||
path.lineTo(array[i] * normalizationFactor, array[i + 1] * normalizationFactor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
path.close();
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ViewGroup getContentView(final View view) {
|
|
||||||
final View rootView = view.getRootView();
|
|
||||||
if (rootView == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ViewGroup windowContentView = (ViewGroup)rootView.findViewById(android.R.id.content);
|
|
||||||
if (windowContentView == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return windowContentView;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class AddToDictionaryIndicatorView extends TextDecoratorUi.IndicatorView {
|
|
||||||
public AddToDictionaryIndicatorView(final Context context) {
|
|
||||||
super(context, R.array.text_decorator_add_to_dictionary_indicator_path,
|
|
||||||
R.integer.text_decorator_add_to_dictionary_indicator_path_size,
|
|
||||||
R.color.text_decorator_add_to_dictionary_indicator_background_color,
|
|
||||||
R.color.text_decorator_add_to_dictionary_indicator_foreground_color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 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.keyboard;
|
|
||||||
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.RectF;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This interface defines how UI operations required for {@link TextDecorator} are delegated to
|
|
||||||
* the actual UI implementation class.
|
|
||||||
*/
|
|
||||||
public interface TextDecoratorUiOperator {
|
|
||||||
/**
|
|
||||||
* Called to notify that the UI is ready to be disposed.
|
|
||||||
*/
|
|
||||||
void disposeUi();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the UI should become invisible.
|
|
||||||
*/
|
|
||||||
void hideUi();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to set the new click handler.
|
|
||||||
* @param onClickListener the callback object whose {@link Runnable#run()} should be called when
|
|
||||||
* the indicator is clicked.
|
|
||||||
*/
|
|
||||||
void setOnClickListener(final Runnable onClickListener);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the layout should be updated.
|
|
||||||
* @param matrix The matrix that transforms the local coordinates into the screen coordinates.
|
|
||||||
* @param composingTextBounds The bounding box of the composing text, in local coordinates.
|
|
||||||
* @param useRtlLayout {@code true} if the indicator should be optimized for RTL layout.
|
|
||||||
*/
|
|
||||||
void layoutUi(final Matrix matrix, final RectF composingTextBounds, final boolean useRtlLayout);
|
|
||||||
}
|
|
|
@ -259,7 +259,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPageScrolled(final int position, final float positionOffset,
|
public void onPageScrolled(final int position, final float positionOffset,
|
||||||
final int positionOffsetPixels) {
|
final int positionOffsetPixels) {
|
||||||
mEmojiPalettesAdapter.onPageScrolled();
|
mEmojiPalettesAdapter.onPageScrolled();
|
||||||
final Pair<Integer, Integer> newPos =
|
final Pair<Integer, Integer> newPos =
|
||||||
mEmojiCategory.getCategoryIdAndPageIdFromPagePosition(position);
|
mEmojiCategory.getCategoryIdAndPageIdFromPagePosition(position);
|
||||||
|
@ -358,7 +358,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setupAlphabetKey(final TextView alphabetKey, final String label,
|
private static void setupAlphabetKey(final TextView alphabetKey, final String label,
|
||||||
final KeyDrawParams params) {
|
final KeyDrawParams params) {
|
||||||
alphabetKey.setText(label);
|
alphabetKey.setText(label);
|
||||||
alphabetKey.setTextColor(params.mFunctionalTextColor);
|
alphabetKey.setTextColor(params.mFunctionalTextColor);
|
||||||
alphabetKey.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mLabelSize);
|
alphabetKey.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mLabelSize);
|
||||||
|
@ -366,7 +366,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startEmojiPalettes(final String switchToAlphaLabel,
|
public void startEmojiPalettes(final String switchToAlphaLabel,
|
||||||
final KeyVisualAttributes keyVisualAttr, final KeyboardIconsSet iconSet) {
|
final KeyVisualAttributes keyVisualAttr, final KeyboardIconsSet iconSet) {
|
||||||
final int deleteIconResId = iconSet.getIconResourceId(KeyboardIconsSet.NAME_DELETE_KEY);
|
final int deleteIconResId = iconSet.getIconResourceId(KeyboardIconsSet.NAME_DELETE_KEY);
|
||||||
if (deleteIconResId != 0) {
|
if (deleteIconResId != 0) {
|
||||||
mDeleteKey.setImageResource(deleteIconResId);
|
mDeleteKey.setImageResource(deleteIconResId);
|
||||||
|
@ -427,4 +427,4 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
|
||||||
mTabHost.setCurrentTab(newTabId);
|
mTabHost.setCurrentTab(newTabId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -124,10 +124,6 @@ public interface DictionaryFacilitator {
|
||||||
void waitForLoadingDictionariesForTesting(final long timeout, final TimeUnit unit)
|
void waitForLoadingDictionariesForTesting(final long timeout, final TimeUnit unit)
|
||||||
throws InterruptedException;
|
throws InterruptedException;
|
||||||
|
|
||||||
boolean isUserDictionaryEnabled();
|
|
||||||
|
|
||||||
void addWordToUserDictionary(final Context context, final String word);
|
|
||||||
|
|
||||||
void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
|
void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
|
||||||
@Nonnull final NgramContext ngramContext, final int timeStampInSeconds,
|
@Nonnull final NgramContext ngramContext, final int timeStampInSeconds,
|
||||||
final boolean blockPotentiallyOffensive);
|
final boolean blockPotentiallyOffensive);
|
||||||
|
|
|
@ -73,7 +73,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
|
||||||
|
|
||||||
private DictionaryGroup[] mDictionaryGroups = new DictionaryGroup[] { new DictionaryGroup() };
|
private DictionaryGroup[] mDictionaryGroups = new DictionaryGroup[] { new DictionaryGroup() };
|
||||||
private DictionaryGroup mMostProbableDictionaryGroup = mDictionaryGroups[0];
|
private DictionaryGroup mMostProbableDictionaryGroup = mDictionaryGroups[0];
|
||||||
private boolean mIsUserDictEnabled = false;
|
|
||||||
private volatile CountDownLatch mLatchForWaitingLoadingMainDictionaries = new CountDownLatch(0);
|
private volatile CountDownLatch mLatchForWaitingLoadingMainDictionaries = new CountDownLatch(0);
|
||||||
// To synchronize assigning mDictionaryGroup to ensure closing dictionaries.
|
// To synchronize assigning mDictionaryGroup to ensure closing dictionaries.
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
|
@ -458,7 +457,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
|
||||||
oldDictionaryGroups = mDictionaryGroups;
|
oldDictionaryGroups = mDictionaryGroups;
|
||||||
mDictionaryGroups = newDictionaryGroups;
|
mDictionaryGroups = newDictionaryGroups;
|
||||||
mMostProbableDictionaryGroup = newDictionaryGroups[0];
|
mMostProbableDictionaryGroup = newDictionaryGroups[0];
|
||||||
mIsUserDictEnabled = UserBinaryDictionary.isEnabled(context);
|
|
||||||
if (hasAtLeastOneUninitializedMainDictionary()) {
|
if (hasAtLeastOneUninitializedMainDictionary()) {
|
||||||
asyncReloadUninitializedMainDictionaries(context, newLocales, listener);
|
asyncReloadUninitializedMainDictionaries(context, newLocales, listener);
|
||||||
}
|
}
|
||||||
|
@ -629,19 +627,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUserDictionaryEnabled() {
|
|
||||||
return mIsUserDictEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addWordToUserDictionary(final Context context, final String word) {
|
|
||||||
final Locale locale = getMostProbableLocale();
|
|
||||||
if (locale == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: add a toast telling what language this is being added to?
|
|
||||||
UserBinaryDictionary.addWordToUserDictionary(context, locale, word);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
|
public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
|
||||||
@Nonnull final NgramContext ngramContext, final int timeStampInSeconds,
|
@Nonnull final NgramContext ngramContext, final int timeStampInSeconds,
|
||||||
final boolean blockPotentiallyOffensive) {
|
final boolean blockPotentiallyOffensive) {
|
||||||
|
|
|
@ -20,7 +20,6 @@ import static com.android.inputmethod.latin.common.Constants.ImeOption.FORCE_ASC
|
||||||
import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
|
import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
|
||||||
import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
|
import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -32,13 +31,11 @@ import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.inputmethodservice.InputMethodService;
|
import android.inputmethodservice.InputMethodService;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Debug;
|
import android.os.Debug;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.PrintWriterPrinter;
|
import android.util.PrintWriterPrinter;
|
||||||
import android.util.Printer;
|
import android.util.Printer;
|
||||||
|
@ -47,18 +44,14 @@ import android.view.Gravity;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup.LayoutParams;
|
import android.view.ViewGroup.LayoutParams;
|
||||||
import android.view.ViewTreeObserver;
|
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.inputmethod.CompletionInfo;
|
import android.view.inputmethod.CompletionInfo;
|
||||||
import android.view.inputmethod.CursorAnchorInfo;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.view.inputmethod.InputMethodSubtype;
|
import android.view.inputmethod.InputMethodSubtype;
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.android.inputmethod.accessibility.AccessibilityUtils;
|
import com.android.inputmethod.accessibility.AccessibilityUtils;
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
|
|
||||||
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
|
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
|
||||||
import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils;
|
import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils;
|
||||||
import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater;
|
import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater;
|
||||||
|
@ -72,7 +65,6 @@ import com.android.inputmethod.keyboard.KeyboardActionListener;
|
||||||
import com.android.inputmethod.keyboard.KeyboardId;
|
import com.android.inputmethod.keyboard.KeyboardId;
|
||||||
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
||||||
import com.android.inputmethod.keyboard.MainKeyboardView;
|
import com.android.inputmethod.keyboard.MainKeyboardView;
|
||||||
import com.android.inputmethod.keyboard.TextDecoratorUi;
|
|
||||||
import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
|
import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import com.android.inputmethod.latin.common.Constants;
|
import com.android.inputmethod.latin.common.Constants;
|
||||||
|
@ -90,8 +82,6 @@ import com.android.inputmethod.latin.suggestions.SuggestionStripView;
|
||||||
import com.android.inputmethod.latin.suggestions.SuggestionStripViewAccessor;
|
import com.android.inputmethod.latin.suggestions.SuggestionStripViewAccessor;
|
||||||
import com.android.inputmethod.latin.touchinputconsumer.GestureConsumer;
|
import com.android.inputmethod.latin.touchinputconsumer.GestureConsumer;
|
||||||
import com.android.inputmethod.latin.utils.ApplicationUtils;
|
import com.android.inputmethod.latin.utils.ApplicationUtils;
|
||||||
import com.android.inputmethod.latin.utils.CapsModeUtils;
|
|
||||||
import com.android.inputmethod.latin.utils.CursorAnchorInfoUtils;
|
|
||||||
import com.android.inputmethod.latin.utils.DialogUtils;
|
import com.android.inputmethod.latin.utils.DialogUtils;
|
||||||
import com.android.inputmethod.latin.utils.ImportantNoticeUtils;
|
import com.android.inputmethod.latin.utils.ImportantNoticeUtils;
|
||||||
import com.android.inputmethod.latin.utils.IntentUtils;
|
import com.android.inputmethod.latin.utils.IntentUtils;
|
||||||
|
@ -149,7 +139,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
private View mInputView;
|
private View mInputView;
|
||||||
private InsetsUpdater mInsetsUpdater;
|
private InsetsUpdater mInsetsUpdater;
|
||||||
private SuggestionStripView mSuggestionStripView;
|
private SuggestionStripView mSuggestionStripView;
|
||||||
private TextView mExtractEditText;
|
|
||||||
|
|
||||||
private RichInputMethodManager mRichImm;
|
private RichInputMethodManager mRichImm;
|
||||||
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
||||||
|
@ -776,57 +765,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (hasSuggestionStripView()) {
|
if (hasSuggestionStripView()) {
|
||||||
mSuggestionStripView.setListener(this, view);
|
mSuggestionStripView.setListener(this, view);
|
||||||
}
|
}
|
||||||
mInputLogic.setTextDecoratorUi(new TextDecoratorUi(this, view));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setExtractView(final View view) {
|
|
||||||
final TextView prevExtractEditText = mExtractEditText;
|
|
||||||
super.setExtractView(view);
|
|
||||||
TextView nextExtractEditText = null;
|
|
||||||
if (view != null) {
|
|
||||||
final View extractEditText = view.findViewById(android.R.id.inputExtractEditText);
|
|
||||||
if (extractEditText instanceof TextView) {
|
|
||||||
nextExtractEditText = (TextView)extractEditText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (prevExtractEditText == nextExtractEditText) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (prevExtractEditText != null) {
|
|
||||||
prevExtractEditText.getViewTreeObserver().removeOnPreDrawListener(
|
|
||||||
mExtractTextViewPreDrawListener);
|
|
||||||
}
|
|
||||||
mExtractEditText = nextExtractEditText;
|
|
||||||
if (mExtractEditText != null) {
|
|
||||||
mExtractEditText.getViewTreeObserver().addOnPreDrawListener(
|
|
||||||
mExtractTextViewPreDrawListener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateCursorAnchorInfo() {
|
|
||||||
// CursorAnchorInfo is used on L and later.
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
if (isFullscreenMode() && mExtractEditText != null) {
|
|
||||||
mInputLogic.onUpdateCursorAnchorInfo(
|
|
||||||
CursorAnchorInfoUtils.extractFromTextView(mExtractEditText));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final ViewTreeObserver.OnPreDrawListener mExtractTextViewPreDrawListener =
|
|
||||||
new ViewTreeObserver.OnPreDrawListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onPreDraw() {
|
|
||||||
updateCursorAnchorInfo();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCandidatesView(final View view) {
|
public void setCandidatesView(final View view) {
|
||||||
// To ensure that CandidatesView will never be set.
|
// To ensure that CandidatesView will never be set.
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1095,15 +1038,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
@Override
|
|
||||||
public void onUpdateCursorAnchorInfo(final CursorAnchorInfo info) {
|
|
||||||
if (isFullscreenMode()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mInputLogic.onUpdateCursorAnchorInfo(CursorAnchorInfoCompatWrapper.wrap(info));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is called when the user has clicked on the extracted text view,
|
* This is called when the user has clicked on the extracted text view,
|
||||||
* when running in fullscreen mode. The default implementation hides
|
* when running in fullscreen mode. The default implementation hides
|
||||||
|
@ -1284,7 +1218,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
@Override
|
@Override
|
||||||
public void updateFullscreenMode() {
|
public void updateFullscreenMode() {
|
||||||
super.updateFullscreenMode();
|
super.updateFullscreenMode();
|
||||||
mInputLogic.onUpdateFullscreenMode(isFullscreenMode());
|
|
||||||
updateSoftInputWindowLayoutParameters();
|
updateSoftInputWindowLayoutParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1332,18 +1265,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
return keyboard.getCoordinates(codePoints);
|
return keyboard.getCoordinates(codePoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback for the {@link SuggestionStripView}, to call when the "add to dictionary" hint is
|
|
||||||
// pressed.
|
|
||||||
@Override
|
|
||||||
public void addWordToUserDictionary(final String word) {
|
|
||||||
if (TextUtils.isEmpty(word)) {
|
|
||||||
// Probably never supposed to happen, but just in case.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mDictionaryFacilitator.addWordToUserDictionary(this /* context */, word);
|
|
||||||
mInputLogic.onAddWordToUserDictionary();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callback for the {@link SuggestionStripView}, to call when the important notice strip is
|
// Callback for the {@link SuggestionStripView}, to call when the important notice strip is
|
||||||
// pressed.
|
// pressed.
|
||||||
@Override
|
@Override
|
||||||
|
@ -1538,19 +1459,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
return null != mSuggestionStripView;
|
return null != mSuggestionStripView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isShowingAddToDictionaryHint() {
|
|
||||||
return hasSuggestionStripView() && mSuggestionStripView.isShowingAddToDictionaryHint();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dismissAddToDictionaryHint() {
|
|
||||||
if (!hasSuggestionStripView()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mSuggestionStripView.dismissAddToDictionaryHint();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSuggestedWords(final SuggestedWords suggestedWords) {
|
private void setSuggestedWords(final SuggestedWords suggestedWords) {
|
||||||
final SettingsValues currentSettingsValues = mSettings.getCurrent();
|
final SettingsValues currentSettingsValues = mSettings.getCurrent();
|
||||||
mInputLogic.setSuggestedWords(suggestedWords);
|
mInputLogic.setSuggestedWords(suggestedWords);
|
||||||
|
@ -1639,21 +1547,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
updateStateAfterInputTransaction(completeInputTransaction);
|
updateStateAfterInputTransaction(completeInputTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void suggestAddingToDictionary(final String word, final boolean isFromSuggestionStrip) {
|
|
||||||
if (!hasSuggestionStripView()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final String wordToShow;
|
|
||||||
if (CapsModeUtils.isAutoCapsMode(mInputLogic.mLastComposedWord.mCapitalizedMode)) {
|
|
||||||
wordToShow = word.toLowerCase(mDictionaryFacilitator.getMostProbableLocale());
|
|
||||||
} else {
|
|
||||||
wordToShow = word;
|
|
||||||
}
|
|
||||||
mSuggestionStripView.showAddToDictionaryHint(wordToShow,
|
|
||||||
isFromSuggestionStrip /* shouldShowWordToSave */);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will show either an empty suggestion strip (if prediction is enabled) or
|
// This will show either an empty suggestion strip (if prediction is enabled) or
|
||||||
// punctuation suggestions (if it's disabled).
|
// punctuation suggestions (if it's disabled).
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
import android.content.ContentProviderClient;
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
|
@ -29,7 +28,6 @@ import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.inputmethod.annotations.ExternallyReferenced;
|
import com.android.inputmethod.annotations.ExternallyReferenced;
|
||||||
import com.android.inputmethod.compat.UserDictionaryCompatUtils;
|
|
||||||
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -54,13 +52,13 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
private static final int USER_DICT_SHORTCUT_FREQUENCY = 14;
|
private static final int USER_DICT_SHORTCUT_FREQUENCY = 14;
|
||||||
|
|
||||||
private static final String[] PROJECTION_QUERY_WITH_SHORTCUT = new String[] {
|
private static final String[] PROJECTION_QUERY_WITH_SHORTCUT = new String[] {
|
||||||
Words.WORD,
|
Words.WORD,
|
||||||
Words.SHORTCUT,
|
Words.SHORTCUT,
|
||||||
Words.FREQUENCY,
|
Words.FREQUENCY,
|
||||||
};
|
};
|
||||||
private static final String[] PROJECTION_QUERY_WITHOUT_SHORTCUT = new String[] {
|
private static final String[] PROJECTION_QUERY_WITHOUT_SHORTCUT = new String[] {
|
||||||
Words.WORD,
|
Words.WORD,
|
||||||
Words.FREQUENCY,
|
Words.FREQUENCY,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final String NAME = "userunigram";
|
private static final String NAME = "userunigram";
|
||||||
|
@ -70,7 +68,8 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
final private boolean mAlsoUseMoreRestrictiveLocales;
|
final private boolean mAlsoUseMoreRestrictiveLocales;
|
||||||
|
|
||||||
protected UserBinaryDictionary(final Context context, final Locale locale,
|
protected UserBinaryDictionary(final Context context, final Locale locale,
|
||||||
final boolean alsoUseMoreRestrictiveLocales, final File dictFile, final String name) {
|
final boolean alsoUseMoreRestrictiveLocales,
|
||||||
|
final File dictFile, final String name) {
|
||||||
super(context, getDictName(name, locale, dictFile), locale, Dictionary.TYPE_USER, dictFile);
|
super(context, getDictName(name, locale, dictFile), locale, Dictionary.TYPE_USER, dictFile);
|
||||||
if (null == locale) throw new NullPointerException(); // Catch the error earlier
|
if (null == locale) throw new NullPointerException(); // Catch the error earlier
|
||||||
final String localeStr = locale.toString();
|
final String localeStr = locale.toString();
|
||||||
|
@ -105,9 +104,11 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
|
|
||||||
// Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
|
// Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
|
||||||
@ExternallyReferenced
|
@ExternallyReferenced
|
||||||
public static UserBinaryDictionary getDictionary(final Context context, final Locale locale,
|
public static UserBinaryDictionary getDictionary(
|
||||||
final File dictFile, final String dictNamePrefix, @Nullable final String account) {
|
final Context context, final Locale locale, final File dictFile,
|
||||||
return new UserBinaryDictionary(context, locale, false /* alsoUseMoreRestrictiveLocales */,
|
final String dictNamePrefix, @Nullable final String account) {
|
||||||
|
return new UserBinaryDictionary(
|
||||||
|
context, locale, false /* alsoUseMoreRestrictiveLocales */,
|
||||||
dictFile, dictNamePrefix + NAME);
|
dictFile, dictNamePrefix + NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +188,8 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addWordsFromProjectionLocked(final String[] query, String request,
|
private void addWordsFromProjectionLocked(final String[] query, String request,
|
||||||
final String[] requestArguments) throws IllegalArgumentException {
|
final String[] requestArguments)
|
||||||
|
throws IllegalArgumentException {
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
try {
|
try {
|
||||||
cursor = mContext.getContentResolver().query(
|
cursor = mContext.getContentResolver().query(
|
||||||
|
@ -204,31 +206,6 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isEnabled(final Context context) {
|
|
||||||
final ContentResolver cr = context.getContentResolver();
|
|
||||||
final ContentProviderClient client = cr.acquireContentProviderClient(Words.CONTENT_URI);
|
|
||||||
if (client != null) {
|
|
||||||
client.release();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a word to the user dictionary and makes it persistent.
|
|
||||||
*
|
|
||||||
* @param context the context
|
|
||||||
* @param locale the locale
|
|
||||||
* @param word the word to add. If the word is capitalized, then the dictionary will
|
|
||||||
* recognize it as a capitalized word when searched.
|
|
||||||
*/
|
|
||||||
public static void addWordToUserDictionary(final Context context, final Locale locale,
|
|
||||||
final String word) {
|
|
||||||
// Update the user dictionary provider
|
|
||||||
UserDictionaryCompatUtils.addWord(context, word,
|
|
||||||
HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY, null, locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) {
|
private static int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) {
|
||||||
// The default frequency for the user dictionary is 250 for historical reasons.
|
// The default frequency for the user dictionary is 250 for historical reasons.
|
||||||
// Latin IME considers a good value for the default user dictionary frequency
|
// Latin IME considers a good value for the default user dictionary frequency
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package com.android.inputmethod.latin.inputlogic;
|
package com.android.inputmethod.latin.inputlogic;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.inputmethodservice.InputMethodService;
|
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
@ -28,17 +27,13 @@ import android.util.Log;
|
||||||
import android.view.KeyCharacterMap;
|
import android.view.KeyCharacterMap;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.inputmethod.CorrectionInfo;
|
import android.view.inputmethod.CorrectionInfo;
|
||||||
import android.view.inputmethod.CursorAnchorInfo;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
|
||||||
import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
|
|
||||||
import com.android.inputmethod.compat.SuggestionSpanUtils;
|
import com.android.inputmethod.compat.SuggestionSpanUtils;
|
||||||
import com.android.inputmethod.event.Event;
|
import com.android.inputmethod.event.Event;
|
||||||
import com.android.inputmethod.event.InputTransaction;
|
import com.android.inputmethod.event.InputTransaction;
|
||||||
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
||||||
import com.android.inputmethod.keyboard.ProximityInfo;
|
import com.android.inputmethod.keyboard.ProximityInfo;
|
||||||
import com.android.inputmethod.keyboard.TextDecorator;
|
|
||||||
import com.android.inputmethod.keyboard.TextDecoratorUiOperator;
|
|
||||||
import com.android.inputmethod.latin.Dictionary;
|
import com.android.inputmethod.latin.Dictionary;
|
||||||
import com.android.inputmethod.latin.DictionaryFacilitator;
|
import com.android.inputmethod.latin.DictionaryFacilitator;
|
||||||
import com.android.inputmethod.latin.LastComposedWord;
|
import com.android.inputmethod.latin.LastComposedWord;
|
||||||
|
@ -91,14 +86,6 @@ public final class InputLogic {
|
||||||
public final Suggest mSuggest;
|
public final Suggest mSuggest;
|
||||||
private final DictionaryFacilitator mDictionaryFacilitator;
|
private final DictionaryFacilitator mDictionaryFacilitator;
|
||||||
|
|
||||||
private final TextDecorator mTextDecorator = new TextDecorator(new TextDecorator.Listener() {
|
|
||||||
@Override
|
|
||||||
public void onClickComposingTextToAddToDictionary(final String word) {
|
|
||||||
mLatinIME.addWordToUserDictionary(word);
|
|
||||||
mLatinIME.dismissAddToDictionaryHint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
|
public LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
|
||||||
// This has package visibility so it can be accessed from InputLogicHandler.
|
// This has package visibility so it can be accessed from InputLogicHandler.
|
||||||
/* package */ final WordComposer mWordComposer;
|
/* package */ final WordComposer mWordComposer;
|
||||||
|
@ -174,7 +161,6 @@ public final class InputLogic {
|
||||||
mConnection.requestCursorUpdates(true /* enableMonitor */,
|
mConnection.requestCursorUpdates(true /* enableMonitor */,
|
||||||
true /* requestImmediateCallback */);
|
true /* requestImmediateCallback */);
|
||||||
}
|
}
|
||||||
mTextDecorator.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -268,20 +254,6 @@ public final class InputLogic {
|
||||||
return inputTransaction;
|
return inputTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether "Touch again to save" should be shown or not.
|
|
||||||
* @param suggestionInfo the suggested word chosen by the user.
|
|
||||||
* @return {@code true} if we should show the "Touch again to save" hint.
|
|
||||||
*/
|
|
||||||
private boolean shouldShowAddToDictionaryHint(final SuggestedWordInfo suggestionInfo) {
|
|
||||||
// We should show the "Touch again to save" hint if the user pressed the first entry
|
|
||||||
// AND it's in none of our current dictionaries (main, user or otherwise).
|
|
||||||
return (suggestionInfo.isKindOf(SuggestedWordInfo.KIND_TYPED)
|
|
||||||
|| suggestionInfo.isKindOf(SuggestedWordInfo.KIND_OOV_CORRECTION))
|
|
||||||
&& !mDictionaryFacilitator.isValidWord(suggestionInfo.mWord, true /* ignoreCase */)
|
|
||||||
&& mDictionaryFacilitator.isUserDictionaryEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A suggestion was picked from the suggestion strip.
|
* A suggestion was picked from the suggestion strip.
|
||||||
* @param settingsValues the current values of the settings.
|
* @param settingsValues the current values of the settings.
|
||||||
|
@ -340,7 +312,6 @@ public final class InputLogic {
|
||||||
return inputTransaction;
|
return inputTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean shouldShowAddToDictionaryHint = shouldShowAddToDictionaryHint(suggestionInfo);
|
|
||||||
commitChosenWord(settingsValues, suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK,
|
commitChosenWord(settingsValues, suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK,
|
||||||
LastComposedWord.NOT_A_SEPARATOR);
|
LastComposedWord.NOT_A_SEPARATOR);
|
||||||
mConnection.endBatchEdit();
|
mConnection.endBatchEdit();
|
||||||
|
@ -350,14 +321,9 @@ public final class InputLogic {
|
||||||
mSpaceState = SpaceState.PHANTOM;
|
mSpaceState = SpaceState.PHANTOM;
|
||||||
inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
|
inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
|
||||||
|
|
||||||
if (shouldShowAddToDictionaryHint) {
|
// If we're not showing the "Touch again to save", then update the suggestion strip.
|
||||||
mSuggestionStripViewAccessor.suggestAddingToDictionary(suggestion,
|
// That's going to be predictions (or punctuation suggestions), so INPUT_STYLE_NONE.
|
||||||
true /* isFromSuggestionStrip */);
|
handler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
|
||||||
} else {
|
|
||||||
// If we're not showing the "Touch again to save", then update the suggestion strip.
|
|
||||||
// That's going to be predictions (or punctuation suggestions), so INPUT_STYLE_NONE.
|
|
||||||
handler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
StatsUtils.onPickSuggestionManually(mSuggestedWords, suggestionInfo);
|
StatsUtils.onPickSuggestionManually(mSuggestedWords, suggestionInfo);
|
||||||
StatsUtils.onWordCommitSuggestionPickedManually(
|
StatsUtils.onWordCommitSuggestionPickedManually(
|
||||||
|
@ -431,11 +397,6 @@ public final class InputLogic {
|
||||||
|
|
||||||
// The cursor has been moved : we now accept to perform recapitalization
|
// The cursor has been moved : we now accept to perform recapitalization
|
||||||
mRecapitalizeStatus.enable();
|
mRecapitalizeStatus.enable();
|
||||||
// We moved the cursor and need to invalidate the indicator right now.
|
|
||||||
mTextDecorator.reset();
|
|
||||||
// Remaining background color that was used for the add-to-dictionary indicator should be
|
|
||||||
// removed.
|
|
||||||
mConnection.removeBackgroundColorFromHighlightedTextIfNecessary();
|
|
||||||
// We moved the cursor. If we are touching a word, we need to resume suggestion.
|
// We moved the cursor. If we are touching a word, we need to resume suggestion.
|
||||||
mLatinIME.mHandler.postResumeSuggestions(true /* shouldDelay */);
|
mLatinIME.mHandler.postResumeSuggestions(true /* shouldDelay */);
|
||||||
// Stop the last recapitalization, if started.
|
// Stop the last recapitalization, if started.
|
||||||
|
@ -808,12 +769,6 @@ public final class InputLogic {
|
||||||
final LatinIME.UIHandler handler) {
|
final LatinIME.UIHandler handler) {
|
||||||
if (!mWordComposer.isComposingWord()) {
|
if (!mWordComposer.isComposingWord()) {
|
||||||
mConnection.removeBackgroundColorFromHighlightedTextIfNecessary();
|
mConnection.removeBackgroundColorFromHighlightedTextIfNecessary();
|
||||||
// In case the "add to dictionary" hint was still displayed.
|
|
||||||
// TODO: Do we really need to check if we have composing text here?
|
|
||||||
if (mSuggestionStripViewAccessor.isShowingAddToDictionaryHint()) {
|
|
||||||
mSuggestionStripViewAccessor.dismissAddToDictionaryHint();
|
|
||||||
mTextDecorator.reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final int codePoint = event.mCodePoint;
|
final int codePoint = event.mCodePoint;
|
||||||
|
@ -1639,20 +1594,8 @@ public final class InputLogic {
|
||||||
0 /* start */, lastCharIndex /* end */, 0 /* flags */);
|
0 /* start */, lastCharIndex /* end */, 0 /* flags */);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean shouldShowAddToDictionaryForTypedWord =
|
|
||||||
shouldShowAddToDictionaryForTypedWord(mLastComposedWord, settingsValues);
|
|
||||||
|
|
||||||
if (inputTransaction.mSettingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) {
|
if (inputTransaction.mSettingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) {
|
||||||
// For languages with spaces, we revert to the typed string, but the cursor is still
|
mConnection.commitText(textToCommit, 1);
|
||||||
// after the separator so we don't resume suggestions. If the user wants to correct
|
|
||||||
// the word, they have to press backspace again.
|
|
||||||
if (shouldShowAddToDictionaryForTypedWord) {
|
|
||||||
mConnection.commitTextWithBackgroundColor(textToCommit, 1,
|
|
||||||
settingsValues.mTextHighlightColorForAddToDictionaryIndicator,
|
|
||||||
originallyTypedWordString.length());
|
|
||||||
} else {
|
|
||||||
mConnection.commitText(textToCommit, 1);
|
|
||||||
}
|
|
||||||
if (usePhantomSpace) {
|
if (usePhantomSpace) {
|
||||||
mSpaceState = SpaceState.PHANTOM;
|
mSpaceState = SpaceState.PHANTOM;
|
||||||
}
|
}
|
||||||
|
@ -1662,33 +1605,13 @@ public final class InputLogic {
|
||||||
final int[] codePoints = StringUtils.toCodePointArray(stringToCommit);
|
final int[] codePoints = StringUtils.toCodePointArray(stringToCommit);
|
||||||
mWordComposer.setComposingWord(codePoints,
|
mWordComposer.setComposingWord(codePoints,
|
||||||
mLatinIME.getCoordinatesForCurrentKeyboard(codePoints));
|
mLatinIME.getCoordinatesForCurrentKeyboard(codePoints));
|
||||||
if (shouldShowAddToDictionaryForTypedWord) {
|
setComposingTextInternal(textToCommit, 1);
|
||||||
setComposingTextInternalWithBackgroundColor(textToCommit, 1,
|
|
||||||
settingsValues.mTextHighlightColorForAddToDictionaryIndicator,
|
|
||||||
originallyTypedWordString.length());
|
|
||||||
} else {
|
|
||||||
setComposingTextInternal(textToCommit, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Don't restart suggestion yet. We'll restart if the user deletes the separator.
|
// Don't restart suggestion yet. We'll restart if the user deletes the separator.
|
||||||
mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
|
mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
|
||||||
|
|
||||||
if (shouldShowAddToDictionaryForTypedWord) {
|
// We have a separator between the word and the cursor: we should show predictions.
|
||||||
// Due to the API limitation as of L, we cannot reliably retrieve the reverted text
|
inputTransaction.setRequiresUpdateSuggestions();
|
||||||
// when the separator causes line breaking. Until this API limitation is addressed in
|
|
||||||
// the framework, show the indicator only when the separator doesn't contain
|
|
||||||
// line-breaking characters.
|
|
||||||
if (!StringUtils.hasLineBreakCharacter(separatorString)) {
|
|
||||||
mTextDecorator.showAddToDictionaryIndicator(originallyTypedWordString,
|
|
||||||
mConnection.getExpectedSelectionStart(),
|
|
||||||
mConnection.getExpectedSelectionEnd());
|
|
||||||
}
|
|
||||||
mSuggestionStripViewAccessor.suggestAddingToDictionary(originallyTypedWordString,
|
|
||||||
false /* isFromSuggestionStrip */);
|
|
||||||
} else {
|
|
||||||
// We have a separator between the word and the cursor: we should show predictions.
|
|
||||||
inputTransaction.setRequiresUpdateSuggestions();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2215,7 +2138,7 @@ public final class InputLogic {
|
||||||
*
|
*
|
||||||
* <p>Currently using this method is optional and you can still directly call
|
* <p>Currently using this method is optional and you can still directly call
|
||||||
* {@link RichInputConnection#setComposingText(CharSequence, int)}, but it is recommended to
|
* {@link RichInputConnection#setComposingText(CharSequence, int)}, but it is recommended to
|
||||||
* use this method whenever possible to optimize the behavior of {@link TextDecorator}.<p>
|
* use this method whenever possible.<p>
|
||||||
* <p>TODO: Should we move this mechanism to {@link RichInputConnection}?</p>
|
* <p>TODO: Should we move this mechanism to {@link RichInputConnection}?</p>
|
||||||
*
|
*
|
||||||
* @param newComposingText the composing text to be set
|
* @param newComposingText the composing text to be set
|
||||||
|
@ -2300,71 +2223,4 @@ public final class InputLogic {
|
||||||
public int getComposingLength() {
|
public int getComposingLength() {
|
||||||
return mWordComposer.size();
|
return mWordComposer.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Following methods are tentatively placed in this class for the integration with
|
|
||||||
// TextDecorator.
|
|
||||||
// TODO: Decouple things that are not related to the input logic.
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the UI operator for {@link TextDecorator}.
|
|
||||||
* @param uiOperator the UI operator which should be associated with {@link TextDecorator}.
|
|
||||||
*/
|
|
||||||
public void setTextDecoratorUi(@Nonnull final TextDecoratorUiOperator uiOperator) {
|
|
||||||
mTextDecorator.setUiOperator(uiOperator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Must be called from {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} is
|
|
||||||
* called.
|
|
||||||
* @param info The wrapper object with which we can access cursor/anchor info.
|
|
||||||
*/
|
|
||||||
public void onUpdateCursorAnchorInfo(final CursorAnchorInfoCompatWrapper info) {
|
|
||||||
mTextDecorator.onUpdateCursorAnchorInfo(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Must be called when {@link InputMethodService#updateFullscreenMode} is called.
|
|
||||||
* @param isFullscreen {@code true} if the input method is in full-screen mode.
|
|
||||||
*/
|
|
||||||
public void onUpdateFullscreenMode(final boolean isFullscreen) {
|
|
||||||
mTextDecorator.notifyFullScreenMode(isFullscreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Must be called from {@link LatinIME#addWordToUserDictionary(String)}.
|
|
||||||
*/
|
|
||||||
public void onAddWordToUserDictionary() {
|
|
||||||
mConnection.removeBackgroundColorFromHighlightedTextIfNecessary();
|
|
||||||
mTextDecorator.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the add to dictionary indicator should be shown or not.
|
|
||||||
* @param lastComposedWord the last composed word information.
|
|
||||||
* @param settingsValues the current settings value.
|
|
||||||
* @return {@code true} if the commit indicator should be shown.
|
|
||||||
*/
|
|
||||||
private boolean shouldShowAddToDictionaryForTypedWord(final LastComposedWord lastComposedWord,
|
|
||||||
final SettingsValues settingsValues) {
|
|
||||||
if (!mConnection.isCursorAnchorInfoMonitorEnabled()) {
|
|
||||||
// We cannot help in this case because we are heavily relying on this new API.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!settingsValues.mShouldShowLxxSuggestionUi) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (TextUtils.isEmpty(lastComposedWord.mTypedWord)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (TextUtils.equals(lastComposedWord.mTypedWord, lastComposedWord.mCommittedWord)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!mDictionaryFacilitator.isUserDictionaryEnabled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !mDictionaryFacilitator.isValidWord(lastComposedWord.mTypedWord,
|
|
||||||
true /* ignoreCase */);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,9 +102,6 @@ public class SettingsValues {
|
||||||
private final boolean mSuggestionsEnabledPerUserSettings;
|
private final boolean mSuggestionsEnabledPerUserSettings;
|
||||||
private final AsyncResultHolder<AppWorkaroundsUtils> mAppWorkarounds;
|
private final AsyncResultHolder<AppWorkaroundsUtils> mAppWorkarounds;
|
||||||
|
|
||||||
// TextDecorator
|
|
||||||
public final int mTextHighlightColorForAddToDictionaryIndicator;
|
|
||||||
|
|
||||||
// Debug settings
|
// Debug settings
|
||||||
public final boolean mIsInternal;
|
public final boolean mIsInternal;
|
||||||
public final boolean mHasCustomKeyPreviewAnimationParams;
|
public final boolean mHasCustomKeyPreviewAnimationParams;
|
||||||
|
@ -183,8 +180,6 @@ public class SettingsValues {
|
||||||
mAutoCorrectionEnabledPerUserSettings = mAutoCorrectEnabled
|
mAutoCorrectionEnabledPerUserSettings = mAutoCorrectEnabled
|
||||||
&& !mInputAttributes.mInputTypeNoAutoCorrect;
|
&& !mInputAttributes.mInputTypeNoAutoCorrect;
|
||||||
mSuggestionsEnabledPerUserSettings = readSuggestionsEnabled(prefs);
|
mSuggestionsEnabledPerUserSettings = readSuggestionsEnabled(prefs);
|
||||||
mTextHighlightColorForAddToDictionaryIndicator = res.getColor(
|
|
||||||
R.color.text_decorator_add_to_dictionary_indicator_text_highlight_color);
|
|
||||||
mIsInternal = Settings.isInternal(prefs);
|
mIsInternal = Settings.isInternal(prefs);
|
||||||
mHasCustomKeyPreviewAnimationParams = prefs.getBoolean(
|
mHasCustomKeyPreviewAnimationParams = prefs.getBoolean(
|
||||||
DebugSettings.PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS, false);
|
DebugSettings.PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS, false);
|
||||||
|
@ -431,8 +426,6 @@ public class SettingsValues {
|
||||||
sb.append("\n mAppWorkarounds = ");
|
sb.append("\n mAppWorkarounds = ");
|
||||||
final AppWorkaroundsUtils awu = mAppWorkarounds.get(null, 0);
|
final AppWorkaroundsUtils awu = mAppWorkarounds.get(null, 0);
|
||||||
sb.append("" + (null == awu ? "null" : awu.toString()));
|
sb.append("" + (null == awu ? "null" : awu.toString()));
|
||||||
sb.append("\n mTextHighlightColorForAddToDictionaryIndicator = ");
|
|
||||||
sb.append("" + mTextHighlightColorForAddToDictionaryIndicator);
|
|
||||||
sb.append("\n mIsInternal = ");
|
sb.append("\n mIsInternal = ");
|
||||||
sb.append("" + mIsInternal);
|
sb.append("" + mIsInternal);
|
||||||
sb.append("\n mKeyPreviewShowUpDuration = ");
|
sb.append("\n mKeyPreviewShowUpDuration = ");
|
||||||
|
|
|
@ -28,7 +28,6 @@ import android.graphics.Rect;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.support.v4.view.ViewCompat;
|
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
@ -50,7 +49,6 @@ import com.android.inputmethod.latin.PunctuationSuggestions;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.SuggestedWords;
|
import com.android.inputmethod.latin.SuggestedWords;
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import com.android.inputmethod.latin.common.LocaleUtils;
|
|
||||||
import com.android.inputmethod.latin.settings.Settings;
|
import com.android.inputmethod.latin.settings.Settings;
|
||||||
import com.android.inputmethod.latin.settings.SettingsValues;
|
import com.android.inputmethod.latin.settings.SettingsValues;
|
||||||
import com.android.inputmethod.latin.utils.ResourceUtils;
|
import com.android.inputmethod.latin.utils.ResourceUtils;
|
||||||
|
@ -95,8 +93,6 @@ final class SuggestionStripLayoutHelper {
|
||||||
private final int mTypedWordPositionWhenAutocorrect;
|
private final int mTypedWordPositionWhenAutocorrect;
|
||||||
private final Drawable mMoreSuggestionsHint;
|
private final Drawable mMoreSuggestionsHint;
|
||||||
private static final String MORE_SUGGESTIONS_HINT = "\u2026";
|
private static final String MORE_SUGGESTIONS_HINT = "\u2026";
|
||||||
private static final String LEFTWARDS_ARROW = "\u2190";
|
|
||||||
private static final String RIGHTWARDS_ARROW = "\u2192";
|
|
||||||
|
|
||||||
private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
|
private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
|
||||||
private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
|
private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
|
||||||
|
@ -540,55 +536,6 @@ final class SuggestionStripLayoutHelper {
|
||||||
return countInStrip;
|
return countInStrip;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void layoutAddToDictionaryHint(final String word, final ViewGroup addToDictionaryStrip,
|
|
||||||
final boolean shouldShowWordToSave) {
|
|
||||||
final boolean showsHintWithWord = shouldShowWordToSave
|
|
||||||
|| !Settings.getInstance().getCurrent().mShouldShowLxxSuggestionUi;
|
|
||||||
final int stripWidth = addToDictionaryStrip.getWidth();
|
|
||||||
final int width = stripWidth - (showsHintWithWord ? mDividerWidth + mPadding * 2 : 0);
|
|
||||||
|
|
||||||
final TextView wordView = (TextView)addToDictionaryStrip.findViewById(R.id.word_to_save);
|
|
||||||
wordView.setTextColor(mColorTypedWord);
|
|
||||||
final int wordWidth = (int)(width * mCenterSuggestionWeight);
|
|
||||||
final CharSequence wordToSave = getEllipsizedTextWithSettingScaleX(
|
|
||||||
word, wordWidth, wordView.getPaint());
|
|
||||||
final float wordScaleX = wordView.getTextScaleX();
|
|
||||||
wordView.setText(wordToSave);
|
|
||||||
wordView.setTextScaleX(wordScaleX);
|
|
||||||
setLayoutWeight(wordView, mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
|
|
||||||
final int wordVisibility = showsHintWithWord ? View.VISIBLE : View.GONE;
|
|
||||||
wordView.setVisibility(wordVisibility);
|
|
||||||
addToDictionaryStrip.findViewById(R.id.word_to_save_divider).setVisibility(wordVisibility);
|
|
||||||
|
|
||||||
final Resources res = addToDictionaryStrip.getResources();
|
|
||||||
final CharSequence hintText;
|
|
||||||
final int hintWidth;
|
|
||||||
final float hintWeight;
|
|
||||||
final TextView hintView = (TextView)addToDictionaryStrip.findViewById(
|
|
||||||
R.id.hint_add_to_dictionary);
|
|
||||||
if (showsHintWithWord) {
|
|
||||||
final boolean isRtlLanguage = (ViewCompat.getLayoutDirection(addToDictionaryStrip)
|
|
||||||
== ViewCompat.LAYOUT_DIRECTION_RTL);
|
|
||||||
final String arrow = isRtlLanguage ? RIGHTWARDS_ARROW : LEFTWARDS_ARROW;
|
|
||||||
final boolean isRtlSystem = LocaleUtils.isRtlLanguage(res.getConfiguration().locale);
|
|
||||||
final CharSequence hint = res.getText(R.string.hint_add_to_dictionary);
|
|
||||||
hintText = (isRtlLanguage == isRtlSystem) ? (arrow + hint) : (hint + arrow);
|
|
||||||
hintWidth = width - wordWidth;
|
|
||||||
hintWeight = 1.0f - mCenterSuggestionWeight;
|
|
||||||
hintView.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
|
|
||||||
} else {
|
|
||||||
hintText = res.getText(R.string.hint_add_to_dictionary_without_word);
|
|
||||||
hintWidth = width;
|
|
||||||
hintWeight = 1.0f;
|
|
||||||
hintView.setGravity(Gravity.CENTER);
|
|
||||||
}
|
|
||||||
hintView.setTextColor(mColorAutoCorrect);
|
|
||||||
final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint());
|
|
||||||
hintView.setText(hintText); // TextView.setText() resets text scale x to 1.0.
|
|
||||||
hintView.setTextScaleX(hintScaleX);
|
|
||||||
setLayoutWeight(hintView, hintWeight, ViewGroup.LayoutParams.MATCH_PARENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void layoutImportantNotice(final View importantNoticeStrip,
|
public void layoutImportantNotice(final View importantNoticeStrip,
|
||||||
final String importantNoticeTitle) {
|
final String importantNoticeTitle) {
|
||||||
final TextView titleView = (TextView)importantNoticeStrip.findViewById(
|
final TextView titleView = (TextView)importantNoticeStrip.findViewById(
|
||||||
|
|
|
@ -58,7 +58,6 @@ import java.util.ArrayList;
|
||||||
public final class SuggestionStripView extends RelativeLayout implements OnClickListener,
|
public final class SuggestionStripView extends RelativeLayout implements OnClickListener,
|
||||||
OnLongClickListener {
|
OnLongClickListener {
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
public void addWordToUserDictionary(String word);
|
|
||||||
public void showImportantNoticeContents();
|
public void showImportantNoticeContents();
|
||||||
public void pickSuggestionManually(SuggestedWordInfo word);
|
public void pickSuggestionManually(SuggestedWordInfo word);
|
||||||
public void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat);
|
public void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat);
|
||||||
|
@ -69,7 +68,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
|
|
||||||
private final ViewGroup mSuggestionsStrip;
|
private final ViewGroup mSuggestionsStrip;
|
||||||
private final ImageButton mVoiceKey;
|
private final ImageButton mVoiceKey;
|
||||||
private final ViewGroup mAddToDictionaryStrip;
|
|
||||||
private final View mImportantNoticeStrip;
|
private final View mImportantNoticeStrip;
|
||||||
MainKeyboardView mMainKeyboardView;
|
MainKeyboardView mMainKeyboardView;
|
||||||
|
|
||||||
|
@ -91,15 +89,12 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
private static class StripVisibilityGroup {
|
private static class StripVisibilityGroup {
|
||||||
private final View mSuggestionStripView;
|
private final View mSuggestionStripView;
|
||||||
private final View mSuggestionsStrip;
|
private final View mSuggestionsStrip;
|
||||||
private final View mAddToDictionaryStrip;
|
|
||||||
private final View mImportantNoticeStrip;
|
private final View mImportantNoticeStrip;
|
||||||
|
|
||||||
public StripVisibilityGroup(final View suggestionStripView,
|
public StripVisibilityGroup(final View suggestionStripView,
|
||||||
final ViewGroup suggestionsStrip, final ViewGroup addToDictionaryStrip,
|
final ViewGroup suggestionsStrip, final View importantNoticeStrip) {
|
||||||
final View importantNoticeStrip) {
|
|
||||||
mSuggestionStripView = suggestionStripView;
|
mSuggestionStripView = suggestionStripView;
|
||||||
mSuggestionsStrip = suggestionsStrip;
|
mSuggestionsStrip = suggestionsStrip;
|
||||||
mAddToDictionaryStrip = addToDictionaryStrip;
|
|
||||||
mImportantNoticeStrip = importantNoticeStrip;
|
mImportantNoticeStrip = importantNoticeStrip;
|
||||||
showSuggestionsStrip();
|
showSuggestionsStrip();
|
||||||
}
|
}
|
||||||
|
@ -109,35 +104,22 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
: ViewCompat.LAYOUT_DIRECTION_LTR;
|
: ViewCompat.LAYOUT_DIRECTION_LTR;
|
||||||
ViewCompat.setLayoutDirection(mSuggestionStripView, layoutDirection);
|
ViewCompat.setLayoutDirection(mSuggestionStripView, layoutDirection);
|
||||||
ViewCompat.setLayoutDirection(mSuggestionsStrip, layoutDirection);
|
ViewCompat.setLayoutDirection(mSuggestionsStrip, layoutDirection);
|
||||||
ViewCompat.setLayoutDirection(mAddToDictionaryStrip, layoutDirection);
|
|
||||||
ViewCompat.setLayoutDirection(mImportantNoticeStrip, layoutDirection);
|
ViewCompat.setLayoutDirection(mImportantNoticeStrip, layoutDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showSuggestionsStrip() {
|
public void showSuggestionsStrip() {
|
||||||
mSuggestionsStrip.setVisibility(VISIBLE);
|
mSuggestionsStrip.setVisibility(VISIBLE);
|
||||||
mAddToDictionaryStrip.setVisibility(INVISIBLE);
|
|
||||||
mImportantNoticeStrip.setVisibility(INVISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showAddToDictionaryStrip() {
|
|
||||||
mSuggestionsStrip.setVisibility(INVISIBLE);
|
|
||||||
mAddToDictionaryStrip.setVisibility(VISIBLE);
|
|
||||||
mImportantNoticeStrip.setVisibility(INVISIBLE);
|
mImportantNoticeStrip.setVisibility(INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showImportantNoticeStrip() {
|
public void showImportantNoticeStrip() {
|
||||||
mSuggestionsStrip.setVisibility(INVISIBLE);
|
mSuggestionsStrip.setVisibility(INVISIBLE);
|
||||||
mAddToDictionaryStrip.setVisibility(INVISIBLE);
|
|
||||||
mImportantNoticeStrip.setVisibility(VISIBLE);
|
mImportantNoticeStrip.setVisibility(VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowingImportantNoticeStrip() {
|
public boolean isShowingImportantNoticeStrip() {
|
||||||
return mImportantNoticeStrip.getVisibility() == VISIBLE;
|
return mImportantNoticeStrip.getVisibility() == VISIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowingAddToDictionaryStrip() {
|
|
||||||
return mAddToDictionaryStrip.getVisibility() == VISIBLE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,10 +140,9 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
|
|
||||||
mSuggestionsStrip = (ViewGroup)findViewById(R.id.suggestions_strip);
|
mSuggestionsStrip = (ViewGroup)findViewById(R.id.suggestions_strip);
|
||||||
mVoiceKey = (ImageButton)findViewById(R.id.suggestions_strip_voice_key);
|
mVoiceKey = (ImageButton)findViewById(R.id.suggestions_strip_voice_key);
|
||||||
mAddToDictionaryStrip = (ViewGroup)findViewById(R.id.add_to_dictionary_strip);
|
|
||||||
mImportantNoticeStrip = findViewById(R.id.important_notice_strip);
|
mImportantNoticeStrip = findViewById(R.id.important_notice_strip);
|
||||||
mStripVisibilityGroup = new StripVisibilityGroup(this, mSuggestionsStrip,
|
mStripVisibilityGroup = new StripVisibilityGroup(this, mSuggestionsStrip,
|
||||||
mAddToDictionaryStrip, mImportantNoticeStrip);
|
mImportantNoticeStrip);
|
||||||
|
|
||||||
for (int pos = 0; pos < SuggestedWords.MAX_SUGGESTIONS; pos++) {
|
for (int pos = 0; pos < SuggestedWords.MAX_SUGGESTIONS; pos++) {
|
||||||
final TextView word = new TextView(context, null, R.attr.suggestionWordStyle);
|
final TextView word = new TextView(context, null, R.attr.suggestionWordStyle);
|
||||||
|
@ -227,27 +208,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
mLayoutHelper.setMoreSuggestionsHeight(remainingHeight);
|
mLayoutHelper.setMoreSuggestionsHeight(remainingHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowingAddToDictionaryHint() {
|
|
||||||
return mStripVisibilityGroup.isShowingAddToDictionaryStrip();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showAddToDictionaryHint(final String word, final boolean shouldShowWordToSave) {
|
|
||||||
mLayoutHelper.layoutAddToDictionaryHint(word, mAddToDictionaryStrip, shouldShowWordToSave);
|
|
||||||
// {@link TextView#setTag()} is used to hold the word to be added to dictionary. The word
|
|
||||||
// will be extracted at {@link #onClick(View)}.
|
|
||||||
mAddToDictionaryStrip.setTag(word);
|
|
||||||
mAddToDictionaryStrip.setOnClickListener(this);
|
|
||||||
mStripVisibilityGroup.showAddToDictionaryStrip();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean dismissAddToDictionaryHint() {
|
|
||||||
if (isShowingAddToDictionaryHint()) {
|
|
||||||
clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method checks if we should show the important notice (checks on permanent storage if
|
// This method checks if we should show the important notice (checks on permanent storage if
|
||||||
// it has been shown once already or not, and if in the setup wizard). If applicable, it shows
|
// it has been shown once already or not, and if in the setup wizard). If applicable, it shows
|
||||||
// the notice. In all cases, it returns true if it was shown, false otherwise.
|
// the notice. In all cases, it returns true if it was shown, false otherwise.
|
||||||
|
@ -494,15 +454,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
false /* isKeyRepeat */);
|
false /* isKeyRepeat */);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Object tag = view.getTag();
|
|
||||||
// {@link String} tag is set at {@link #suggestAddingToDictionary(String,CharSequence)}.
|
|
||||||
if (tag instanceof String) {
|
|
||||||
final String wordToSave = (String)tag;
|
|
||||||
mListener.addWordToUserDictionary(wordToSave);
|
|
||||||
clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
final Object tag = view.getTag();
|
||||||
// {@link Integer} tag is set at
|
// {@link Integer} tag is set at
|
||||||
// {@link SuggestionStripLayoutHelper#setupWordViewsTextAndColor(SuggestedWords,int)} and
|
// {@link SuggestionStripLayoutHelper#setupWordViewsTextAndColor(SuggestedWords,int)} and
|
||||||
// {@link SuggestionStripLayoutHelper#layoutPunctuationSuggestions(SuggestedWords,ViewGroup}
|
// {@link SuggestionStripLayoutHelper#layoutPunctuationSuggestions(SuggestedWords,ViewGroup}
|
||||||
|
|
|
@ -22,9 +22,6 @@ import com.android.inputmethod.latin.SuggestedWords;
|
||||||
* An object that gives basic control of a suggestion strip and some info on it.
|
* An object that gives basic control of a suggestion strip and some info on it.
|
||||||
*/
|
*/
|
||||||
public interface SuggestionStripViewAccessor {
|
public interface SuggestionStripViewAccessor {
|
||||||
public void suggestAddingToDictionary(final String word, final boolean isFromSuggestionStrip);
|
|
||||||
public boolean isShowingAddToDictionaryHint();
|
|
||||||
public void dismissAddToDictionaryHint();
|
|
||||||
public void setNeutralSuggestionStrip();
|
public void setNeutralSuggestionStrip();
|
||||||
public void showSuggestionStrip(final SuggestedWords suggestedWords);
|
public void showSuggestionStrip(final SuggestedWords suggestedWords);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,178 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2013 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.userdictionary;
|
|
||||||
|
|
||||||
import com.android.inputmethod.latin.R;
|
|
||||||
import com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordContents.LocaleRenderer;
|
|
||||||
import com.android.inputmethod.latin.userdictionary.UserDictionaryLocalePicker.LocationChangedListener;
|
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.preference.PreferenceActivity;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
// Caveat: This class is basically taken from
|
|
||||||
// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryAddWordFragment.java
|
|
||||||
// in order to deal with some devices that have issues with the user dictionary handling
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fragment to add a word/shortcut to the user dictionary.
|
|
||||||
*
|
|
||||||
* As opposed to the UserDictionaryActivity, this is only invoked within Settings
|
|
||||||
* from the UserDictionarySettings.
|
|
||||||
*/
|
|
||||||
public class UserDictionaryAddWordFragment extends Fragment
|
|
||||||
implements AdapterView.OnItemSelectedListener, LocationChangedListener {
|
|
||||||
|
|
||||||
private static final int OPTIONS_MENU_ADD = Menu.FIRST;
|
|
||||||
private static final int OPTIONS_MENU_DELETE = Menu.FIRST + 1;
|
|
||||||
|
|
||||||
private UserDictionaryAddWordContents mContents;
|
|
||||||
private View mRootView;
|
|
||||||
private boolean mIsDeleting = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActivityCreated(final Bundle savedInstanceState) {
|
|
||||||
super.onActivityCreated(savedInstanceState);
|
|
||||||
setHasOptionsMenu(true);
|
|
||||||
getActivity().getActionBar().setTitle(R.string.edit_personal_dictionary);
|
|
||||||
// Keep the instance so that we remember mContents when configuration changes (eg rotation)
|
|
||||||
setRetainInstance(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
|
|
||||||
final Bundle savedState) {
|
|
||||||
mRootView = inflater.inflate(R.layout.user_dictionary_add_word_fullscreen, null);
|
|
||||||
mIsDeleting = false;
|
|
||||||
// If we have a non-null mContents object, it's the old value before a configuration
|
|
||||||
// change (eg rotation) so we need to use its values. Otherwise, read from the arguments.
|
|
||||||
if (null == mContents) {
|
|
||||||
mContents = new UserDictionaryAddWordContents(mRootView, getArguments());
|
|
||||||
} else {
|
|
||||||
// We create a new mContents object to account for the new situation : a word has
|
|
||||||
// been added to the user dictionary when we started rotating, and we are now editing
|
|
||||||
// it. That means in particular if the word undergoes any change, the old version should
|
|
||||||
// be updated, so the mContents object needs to switch to EDIT mode if it was in
|
|
||||||
// INSERT mode.
|
|
||||||
mContents = new UserDictionaryAddWordContents(mRootView,
|
|
||||||
mContents /* oldInstanceToBeEdited */);
|
|
||||||
}
|
|
||||||
getActivity().getActionBar().setSubtitle(UserDictionarySettingsUtils.getLocaleDisplayName(
|
|
||||||
getActivity(), mContents.getCurrentUserDictionaryLocale()));
|
|
||||||
return mRootView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
|
||||||
final MenuItem actionItemAdd = menu.add(0, OPTIONS_MENU_ADD, 0,
|
|
||||||
R.string.user_dict_settings_add_menu_title).setIcon(R.drawable.ic_menu_add);
|
|
||||||
actionItemAdd.setShowAsAction(
|
|
||||||
MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
|
|
||||||
final MenuItem actionItemDelete = menu.add(0, OPTIONS_MENU_DELETE, 0,
|
|
||||||
R.string.user_dict_settings_delete).setIcon(android.R.drawable.ic_menu_delete);
|
|
||||||
actionItemDelete.setShowAsAction(
|
|
||||||
MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for the framework when a menu option is pressed.
|
|
||||||
*
|
|
||||||
* @param item the item that was pressed
|
|
||||||
* @return false to allow normal menu processing to proceed, true to consume it here
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if (item.getItemId() == OPTIONS_MENU_ADD) {
|
|
||||||
// added the entry in "onPause"
|
|
||||||
getActivity().onBackPressed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (item.getItemId() == OPTIONS_MENU_DELETE) {
|
|
||||||
mContents.delete(getActivity());
|
|
||||||
mIsDeleting = true;
|
|
||||||
getActivity().onBackPressed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
// We are being shown: display the word
|
|
||||||
updateSpinner();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateSpinner() {
|
|
||||||
final ArrayList<LocaleRenderer> localesList = mContents.getLocalesList(getActivity());
|
|
||||||
|
|
||||||
final Spinner localeSpinner =
|
|
||||||
(Spinner)mRootView.findViewById(R.id.user_dictionary_add_locale);
|
|
||||||
final ArrayAdapter<LocaleRenderer> adapter = new ArrayAdapter<>(
|
|
||||||
getActivity(), android.R.layout.simple_spinner_item, localesList);
|
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
localeSpinner.setAdapter(adapter);
|
|
||||||
localeSpinner.setOnItemSelectedListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
// We are being hidden: commit changes to the user dictionary, unless we were deleting it
|
|
||||||
if (!mIsDeleting) {
|
|
||||||
mContents.apply(getActivity(), null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(final AdapterView<?> parent, final View view, final int pos,
|
|
||||||
final long id) {
|
|
||||||
final LocaleRenderer locale = (LocaleRenderer)parent.getItemAtPosition(pos);
|
|
||||||
if (locale.isMoreLanguages()) {
|
|
||||||
PreferenceActivity preferenceActivity = (PreferenceActivity)getActivity();
|
|
||||||
preferenceActivity.startPreferenceFragment(new UserDictionaryLocalePicker(), true);
|
|
||||||
} else {
|
|
||||||
mContents.updateLocale(locale.getLocaleString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(final AdapterView<?> parent) {
|
|
||||||
// I'm not sure we can come here, but if we do, that's the right thing to do.
|
|
||||||
final Bundle args = getArguments();
|
|
||||||
mContents.updateLocale(args.getString(UserDictionaryAddWordContents.EXTRA_LOCALE));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called by the locale picker
|
|
||||||
@Override
|
|
||||||
public void onLocaleSelected(final Locale locale) {
|
|
||||||
mContents.updateLocale(locale.toString());
|
|
||||||
getActivity().onBackPressed();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -240,8 +240,6 @@ public class UserDictionarySettings extends ListFragment {
|
||||||
args.putString(UserDictionaryAddWordContents.EXTRA_LOCALE, mLocale);
|
args.putString(UserDictionaryAddWordContents.EXTRA_LOCALE, mLocale);
|
||||||
android.preference.PreferenceActivity pa =
|
android.preference.PreferenceActivity pa =
|
||||||
(android.preference.PreferenceActivity)getActivity();
|
(android.preference.PreferenceActivity)getActivity();
|
||||||
pa.startPreferencePanel(UserDictionaryAddWordFragment.class.getName(),
|
|
||||||
args, R.string.user_dict_settings_add_dialog_title, null, null, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getWord(final int position) {
|
private String getWord(final int position) {
|
||||||
|
|
|
@ -29,7 +29,6 @@ import com.android.inputmethod.latin.settings.PreferencesSettingsFragment;
|
||||||
import com.android.inputmethod.latin.settings.SettingsFragment;
|
import com.android.inputmethod.latin.settings.SettingsFragment;
|
||||||
import com.android.inputmethod.latin.settings.ThemeSettingsFragment;
|
import com.android.inputmethod.latin.settings.ThemeSettingsFragment;
|
||||||
import com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsFragment;
|
import com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsFragment;
|
||||||
import com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordFragment;
|
|
||||||
import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
|
import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
|
||||||
import com.android.inputmethod.latin.userdictionary.UserDictionaryLocalePicker;
|
import com.android.inputmethod.latin.userdictionary.UserDictionaryLocalePicker;
|
||||||
import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
|
import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
|
||||||
|
@ -52,7 +51,6 @@ public class FragmentUtils {
|
||||||
sLatinImeFragments.add(DebugSettingsFragment.class.getName());
|
sLatinImeFragments.add(DebugSettingsFragment.class.getName());
|
||||||
sLatinImeFragments.add(SettingsFragment.class.getName());
|
sLatinImeFragments.add(SettingsFragment.class.getName());
|
||||||
sLatinImeFragments.add(SpellCheckerSettingsFragment.class.getName());
|
sLatinImeFragments.add(SpellCheckerSettingsFragment.class.getName());
|
||||||
sLatinImeFragments.add(UserDictionaryAddWordFragment.class.getName());
|
|
||||||
sLatinImeFragments.add(UserDictionaryList.class.getName());
|
sLatinImeFragments.add(UserDictionaryList.class.getName());
|
||||||
sLatinImeFragments.add(UserDictionaryLocalePicker.class.getName());
|
sLatinImeFragments.add(UserDictionaryLocalePicker.class.getName());
|
||||||
sLatinImeFragments.add(UserDictionarySettings.class.getName());
|
sLatinImeFragments.add(UserDictionarySettings.class.getName());
|
||||||
|
|
Loading…
Reference in New Issue