Create the path for specifying combining rules in the subtype
Also add the skeleton of the combining rules for Myanmar reordering as a pilot. Bug: 13945569 Change-Id: Iabeb6838f45f1efff482143595ce5b48543e0c43main
parent
c41d261b7e
commit
be99616afa
|
@ -503,7 +503,7 @@
|
||||||
android:subtypeId="0xea266ea4"
|
android:subtypeId="0xea266ea4"
|
||||||
android:imeSubtypeLocale="my_MM"
|
android:imeSubtypeLocale="my_MM"
|
||||||
android:imeSubtypeMode="keyboard"
|
android:imeSubtypeMode="keyboard"
|
||||||
android:imeSubtypeExtraValue="KeyboardLayoutSet=myanmar,EmojiCapable"
|
android:imeSubtypeExtraValue="KeyboardLayoutSet=myanmar,EmojiCapable,CombiningRules=MyanmarReordering"
|
||||||
android:isAsciiCapable="false"
|
android:isAsciiCapable="false"
|
||||||
/>
|
/>
|
||||||
<subtype android:icon="@drawable/ic_ime_switcher_dark"
|
<subtype android:icon="@drawable/ic_ime_switcher_dark"
|
||||||
|
|
|
@ -23,6 +23,7 @@ import com.android.inputmethod.latin.Constants;
|
||||||
import com.android.inputmethod.latin.utils.CollectionUtils;
|
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements the logic chain between receiving events and generating code points.
|
* This class implements the logic chain between receiving events and generating code points.
|
||||||
|
@ -43,6 +44,13 @@ public class CombinerChain {
|
||||||
private SpannableStringBuilder mStateFeedback;
|
private SpannableStringBuilder mStateFeedback;
|
||||||
private final ArrayList<Combiner> mCombiners;
|
private final ArrayList<Combiner> mCombiners;
|
||||||
|
|
||||||
|
private static final HashMap<String, Class> IMPLEMENTED_COMBINERS
|
||||||
|
= new HashMap<String, Class>();
|
||||||
|
static {
|
||||||
|
IMPLEMENTED_COMBINERS.put("MyanmarReordering", MyanmarReordering.class);
|
||||||
|
}
|
||||||
|
private static final String COMBINER_SPEC_SEPARATOR = ";";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an combiner chain.
|
* Create an combiner chain.
|
||||||
*
|
*
|
||||||
|
@ -56,6 +64,9 @@ public class CombinerChain {
|
||||||
mCombiners = CollectionUtils.newArrayList();
|
mCombiners = CollectionUtils.newArrayList();
|
||||||
// The dead key combiner is always active, and always first
|
// The dead key combiner is always active, and always first
|
||||||
mCombiners.add(new DeadKeyCombiner());
|
mCombiners.add(new DeadKeyCombiner());
|
||||||
|
for (final Combiner combiner : combinerList) {
|
||||||
|
mCombiners.add(combiner);
|
||||||
|
}
|
||||||
mCombinedText = new StringBuilder();
|
mCombinedText = new StringBuilder();
|
||||||
mStateFeedback = new SpannableStringBuilder();
|
mStateFeedback = new SpannableStringBuilder();
|
||||||
}
|
}
|
||||||
|
@ -114,4 +125,29 @@ public class CombinerChain {
|
||||||
final SpannableStringBuilder s = new SpannableStringBuilder(mCombinedText);
|
final SpannableStringBuilder s = new SpannableStringBuilder(mCombinedText);
|
||||||
return s.append(mStateFeedback);
|
return s.append(mStateFeedback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Combiner[] createCombiners(final String spec) {
|
||||||
|
if (TextUtils.isEmpty(spec)) {
|
||||||
|
return new Combiner[0];
|
||||||
|
}
|
||||||
|
final String[] combinerDescriptors = spec.split(COMBINER_SPEC_SEPARATOR);
|
||||||
|
final Combiner[] combiners = new Combiner[combinerDescriptors.length];
|
||||||
|
int i = 0;
|
||||||
|
for (final String combinerDescriptor : combinerDescriptors) {
|
||||||
|
final Class combinerClass = IMPLEMENTED_COMBINERS.get(combinerDescriptor);
|
||||||
|
if (null == combinerClass) {
|
||||||
|
throw new RuntimeException("Unknown combiner descriptor: " + combinerDescriptor);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
combiners[i++] = (Combiner)combinerClass.newInstance();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new RuntimeException("Unable to instantiate combiner: " + combinerDescriptor,
|
||||||
|
e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException("Unable to instantiate combiner: " + combinerDescriptor,
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return combiners;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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.event;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A combiner that reorders input for Myanmar.
|
||||||
|
*/
|
||||||
|
public class MyanmarReordering implements Combiner {
|
||||||
|
@Override
|
||||||
|
public Event processEvent(ArrayList<Event> previousEvents, Event event) {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getCombiningStateFeedback() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -115,6 +115,11 @@ public final class Constants {
|
||||||
*/
|
*/
|
||||||
public static final String IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype";
|
public static final String IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The subtype extra value used to specify the combining rules.
|
||||||
|
*/
|
||||||
|
public static final String COMBINING_RULES = "CombiningRules";
|
||||||
|
|
||||||
private ExtraValue() {
|
private ExtraValue() {
|
||||||
// This utility class is not publicly instantiable.
|
// This utility class is not publicly instantiable.
|
||||||
}
|
}
|
||||||
|
|
|
@ -733,6 +733,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
// Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
|
// Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
|
||||||
// is not guaranteed. It may even be called at the same time on a different thread.
|
// is not guaranteed. It may even be called at the same time on a different thread.
|
||||||
mSubtypeSwitcher.onSubtypeChanged(subtype);
|
mSubtypeSwitcher.onSubtypeChanged(subtype);
|
||||||
|
mInputLogic.onSubtypeChanged(SubtypeLocaleUtils.getCombiningRulesExtraValue(subtype));
|
||||||
loadKeyboard();
|
loadKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,7 +809,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
|
|
||||||
// The app calling setText() has the effect of clearing the composing
|
// The app calling setText() has the effect of clearing the composing
|
||||||
// span, so we should reset our state unconditionally, even if restarting is true.
|
// span, so we should reset our state unconditionally, even if restarting is true.
|
||||||
mInputLogic.startInput(restarting, editorInfo);
|
// We also tell the input logic about the combining rules for the current subtype, so
|
||||||
|
// it can adjust its combiners if needed.
|
||||||
|
mInputLogic.startInput(restarting, editorInfo,
|
||||||
|
mSubtypeSwitcher.getCombiningRulesExtraValueOfCurrentSubtype());
|
||||||
|
|
||||||
// Note: the following does a round-trip IPC on the main thread: be careful
|
// Note: the following does a round-trip IPC on the main thread: be careful
|
||||||
final Locale currentLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
|
final Locale currentLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
|
||||||
|
|
|
@ -326,4 +326,8 @@ public final class SubtypeSwitcher {
|
||||||
+ DUMMY_EMOJI_SUBTYPE);
|
+ DUMMY_EMOJI_SUBTYPE);
|
||||||
return DUMMY_EMOJI_SUBTYPE;
|
return DUMMY_EMOJI_SUBTYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCombiningRulesExtraValueOfCurrentSubtype() {
|
||||||
|
return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ public final class WordComposer {
|
||||||
public static final int CAPS_MODE_AUTO_SHIFT_LOCKED = 0x7;
|
public static final int CAPS_MODE_AUTO_SHIFT_LOCKED = 0x7;
|
||||||
|
|
||||||
private CombinerChain mCombinerChain;
|
private CombinerChain mCombinerChain;
|
||||||
|
private String mCombiningSpec; // Memory so that we don't uselessly recreate the combiner chain
|
||||||
|
|
||||||
// The list of events that served to compose this string.
|
// The list of events that served to compose this string.
|
||||||
private final ArrayList<Event> mEvents;
|
private final ArrayList<Event> mEvents;
|
||||||
|
@ -90,6 +91,21 @@ public final class WordComposer {
|
||||||
refreshTypedWordCache();
|
refreshTypedWordCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restart input with a new combining spec.
|
||||||
|
* @param combiningSpec The spec string for combining. This is found in the extra value.
|
||||||
|
*/
|
||||||
|
public void restart(final String combiningSpec) {
|
||||||
|
final String nonNullCombiningSpec = null == combiningSpec ? "" : combiningSpec;
|
||||||
|
if (nonNullCombiningSpec.equals(mCombiningSpec)) {
|
||||||
|
mCombinerChain.reset();
|
||||||
|
} else {
|
||||||
|
mCombinerChain = new CombinerChain(CombinerChain.createCombiners(nonNullCombiningSpec));
|
||||||
|
mCombiningSpec = nonNullCombiningSpec;
|
||||||
|
}
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear out the keys registered so far.
|
* Clear out the keys registered so far.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -97,6 +97,11 @@ public final class InputLogic {
|
||||||
private boolean mIsAutoCorrectionIndicatorOn;
|
private boolean mIsAutoCorrectionIndicatorOn;
|
||||||
private long mDoubleSpacePeriodCountdownStart;
|
private long mDoubleSpacePeriodCountdownStart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of the input logic.
|
||||||
|
* @param latinIME the instance of the parent LatinIME. We should remove this when we can.
|
||||||
|
* @param suggestionStripViewAccessor an object to access the suggestion strip view.
|
||||||
|
*/
|
||||||
public InputLogic(final LatinIME latinIME,
|
public InputLogic(final LatinIME latinIME,
|
||||||
final SuggestionStripViewAccessor suggestionStripViewAccessor) {
|
final SuggestionStripViewAccessor suggestionStripViewAccessor) {
|
||||||
mLatinIME = latinIME;
|
mLatinIME = latinIME;
|
||||||
|
@ -117,9 +122,12 @@ public final class InputLogic {
|
||||||
*
|
*
|
||||||
* @param restarting whether input is starting in the same field as before. Unused for now.
|
* @param restarting whether input is starting in the same field as before. Unused for now.
|
||||||
* @param editorInfo the editorInfo associated with the editor.
|
* @param editorInfo the editorInfo associated with the editor.
|
||||||
|
* @param combiningSpec the combining spec string for this subtype
|
||||||
*/
|
*/
|
||||||
public void startInput(final boolean restarting, final EditorInfo editorInfo) {
|
public void startInput(final boolean restarting, final EditorInfo editorInfo,
|
||||||
|
final String combiningSpec) {
|
||||||
mEnteredText = null;
|
mEnteredText = null;
|
||||||
|
mWordComposer.restart(combiningSpec);
|
||||||
resetComposingState(true /* alsoResetLastComposedWord */);
|
resetComposingState(true /* alsoResetLastComposedWord */);
|
||||||
mDeleteCount = 0;
|
mDeleteCount = 0;
|
||||||
mSpaceState = SpaceState.NONE;
|
mSpaceState = SpaceState.NONE;
|
||||||
|
@ -137,6 +145,14 @@ public final class InputLogic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this when the subtype changes.
|
||||||
|
* @param combiningSpec the spec string for the combining rules
|
||||||
|
*/
|
||||||
|
public void onSubtypeChanged(final String combiningSpec) {
|
||||||
|
mWordComposer.restart(combiningSpec);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean up the input logic after input is finished.
|
* Clean up the input logic after input is finished.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -324,4 +324,8 @@ public final class SubtypeLocaleUtils {
|
||||||
public static boolean isRtlLanguage(final InputMethodSubtype subtype) {
|
public static boolean isRtlLanguage(final InputMethodSubtype subtype) {
|
||||||
return isRtlLanguage(getSubtypeLocale(subtype));
|
return isRtlLanguage(getSubtypeLocale(subtype));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getCombiningRulesExtraValue(final InputMethodSubtype subtype) {
|
||||||
|
return subtype.getExtraValueOf(Constants.Subtype.ExtraValue.COMBINING_RULES);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,13 @@ import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compatibility class that stands in for the combiner chain in LatinIME.
|
||||||
|
*
|
||||||
|
* This is not used by dicttool, it's just needed by the dependency chain.
|
||||||
|
*/
|
||||||
|
// TODO: there should not be a dependency to this in dicttool, so there
|
||||||
|
// should be a sensible way to separate them cleanly.
|
||||||
public class CombinerChain {
|
public class CombinerChain {
|
||||||
private StringBuilder mComposingWord = new StringBuilder();
|
private StringBuilder mComposingWord = new StringBuilder();
|
||||||
public CombinerChain(final Combiner... combinerList) {}
|
public CombinerChain(final Combiner... combinerList) {}
|
||||||
|
@ -35,4 +42,9 @@ public class CombinerChain {
|
||||||
public void reset() {
|
public void reset() {
|
||||||
mComposingWord.setLength(0);
|
mComposingWord.setLength(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Combiner[] createCombiners(final String spec) {
|
||||||
|
// Dicttool never uses a combiner at all, so we just return a zero-sized array.
|
||||||
|
return new Combiner[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue