Update key icon IDs to use Strings

This commit is contained in:
Aleksandras Kostarevas 2024-06-21 19:16:59 +03:00
parent aa025b92e8
commit 0b48de4ac9
18 changed files with 130 additions and 172 deletions

View File

@ -365,8 +365,6 @@
<!-- If true, disable additionalMoreKeys. --> <!-- If true, disable additionalMoreKeys. -->
<flag name="disableAdditionalMoreKeys" value="0x80000000" /> <flag name="disableAdditionalMoreKeys" value="0x80000000" />
</attr> </attr>
<!-- The icon for disabled key -->
<attr name="keyIconDisabled" format="string" />
<!-- The key style to specify a set of key attributes defined by <key_style/> --> <!-- The key style to specify a set of key attributes defined by <key_style/> -->
<attr name="keyStyle" format="string" /> <attr name="keyStyle" format="string" />
<!-- Visual insets, in the proportion of keyboard width. --> <!-- Visual insets, in the proportion of keyboard width. -->

View File

@ -111,24 +111,12 @@
latin:moreKeys="!icon/zwj_key|&#x200D;" latin:moreKeys="!icon/zwj_key|&#x200D;"
latin:keyLabelFlags="hasPopupHint" latin:keyLabelFlags="hasPopupHint"
latin:keyActionFlags="noKeyPreview" /> latin:keyActionFlags="noKeyPreview" />
<key-style
latin:styleName="shortcutKeyStyle"
latin:keySpec="!icon/shortcut_key|!code/key_shortcut"
latin:keyIconDisabled="!icon/shortcut_key_disabled"
latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
latin:altCode="!code/key_space"
latin:parentStyle="settingsMoreKeysStyle" />
<key-style <key-style
latin:styleName="settingsKeyStyle" latin:styleName="settingsKeyStyle"
latin:keySpec="!icon/settings_key|!code/key_settings" latin:keySpec="!icon/settings_key|!code/key_settings"
latin:keyActionFlags="noKeyPreview|altCodeWhileTyping" latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
latin:altCode="!code/key_space" latin:altCode="!code/key_space"
latin:backgroundType="functional" /> latin:backgroundType="functional" />
<key-style
latin:styleName="bottomEmojiKeyStyle"
latin:keySpec="!icon/emoji_normal_key|!code/key_emoji"
latin:backgroundType="functional"
latin:keyActionFlags="noKeyPreview" />
<key-style <key-style
latin:styleName="tabKeyStyle" latin:styleName="tabKeyStyle"
latin:keySpec="!icon/tab_key|!code/key_tab" latin:keySpec="!icon/tab_key|!code/key_tab"

View File

@ -42,6 +42,7 @@ import org.futo.inputmethod.latin.common.StringUtils;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -95,7 +96,7 @@ public class Key implements Comparable<Key> {
private static final int LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS = 0x80000000; private static final int LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS = 0x80000000;
/** Icon to display instead of a label. Icon takes precedence over a label */ /** Icon to display instead of a label. Icon takes precedence over a label */
private final int mIconId; private final String mIconId;
/** Width of the key, excluding the gap */ /** Width of the key, excluding the gap */
private final int mWidth; private final int mWidth;
@ -172,30 +173,24 @@ public class Key implements Comparable<Key> {
/** Text to output when pressed. This can be multiple characters, like ".com" */ /** Text to output when pressed. This can be multiple characters, like ".com" */
public final String mOutputText; public final String mOutputText;
public final int mAltCode; public final int mAltCode;
/** Icon for disabled state */
public final int mDisabledIconId;
/** The visual insets */ /** The visual insets */
public final int mVisualInsetsLeft; public final int mVisualInsetsLeft;
public final int mVisualInsetsRight; public final int mVisualInsetsRight;
private OptionalAttributes(final String outputText, final int altCode, private OptionalAttributes(final String outputText, final int altCode, final int visualInsetsLeft, final int visualInsetsRight) {
final int disabledIconId, final int visualInsetsLeft, final int visualInsetsRight) {
mOutputText = outputText; mOutputText = outputText;
mAltCode = altCode; mAltCode = altCode;
mDisabledIconId = disabledIconId;
mVisualInsetsLeft = 0;//visualInsetsLeft; mVisualInsetsLeft = 0;//visualInsetsLeft;
mVisualInsetsRight = 0;//visualInsetsRight; mVisualInsetsRight = 0;//visualInsetsRight;
} }
@Nullable @Nullable
public static OptionalAttributes newInstance(final String outputText, final int altCode, public static OptionalAttributes newInstance(final String outputText, final int altCode, final int visualInsetsLeft, final int visualInsetsRight) {
final int disabledIconId, final int visualInsetsLeft, final int visualInsetsRight) { if (outputText == null && altCode == CODE_UNSPECIFIED && visualInsetsLeft == 0
if (outputText == null && altCode == CODE_UNSPECIFIED
&& disabledIconId == ICON_UNDEFINED && visualInsetsLeft == 0
&& visualInsetsRight == 0) { && visualInsetsRight == 0) {
return null; return null;
} }
return new OptionalAttributes(outputText, altCode, disabledIconId, visualInsetsLeft, return new OptionalAttributes(outputText, altCode, visualInsetsLeft,
visualInsetsRight); visualInsetsRight);
} }
} }
@ -211,7 +206,7 @@ public class Key implements Comparable<Key> {
* Constructor for a key on <code>MoreKeyKeyboard</code>, on <code>MoreSuggestions</code>, * Constructor for a key on <code>MoreKeyKeyboard</code>, on <code>MoreSuggestions</code>,
* and in a <GridRows/>. * and in a <GridRows/>.
*/ */
public Key(@Nullable final String label, final int iconId, final int code, public Key(@Nullable final String label, final String iconId, final int code,
@Nullable final String outputText, @Nullable final String hintLabel, @Nullable final String outputText, @Nullable final String hintLabel,
final int labelFlags, final int backgroundType, final int x, final int y, final int labelFlags, final int backgroundType, final int x, final int y,
final int width, final int height, final int horizontalGap, final int verticalGap) { final int width, final int height, final int horizontalGap, final int verticalGap) {
@ -227,8 +222,7 @@ public class Key implements Comparable<Key> {
mMoreKeys = null; mMoreKeys = null;
mMoreKeysColumnAndFlags = 0; mMoreKeysColumnAndFlags = 0;
mLabel = label; mLabel = label;
mOptionalAttributes = OptionalAttributes.newInstance(outputText, CODE_UNSPECIFIED, mOptionalAttributes = OptionalAttributes.newInstance(outputText, CODE_UNSPECIFIED, 0 /* visualInsetsLeft */, 0 /* visualInsetsRight */);
ICON_UNDEFINED, 0 /* visualInsetsLeft */, 0 /* visualInsetsRight */);
mCode = code; mCode = code;
mEnabled = (code != CODE_UNSPECIFIED); mEnabled = (code != CODE_UNSPECIFIED);
mIconId = iconId; mIconId = iconId;
@ -348,8 +342,6 @@ public class Key implements Comparable<Key> {
mActionFlags = actionFlags; mActionFlags = actionFlags;
mIconId = KeySpecParser.getIconId(keySpec); mIconId = KeySpecParser.getIconId(keySpec);
final int disabledIconId = KeySpecParser.getIconId(style.getString(keyAttr,
R.styleable.Keyboard_Key_keyIconDisabled));
final int code = KeySpecParser.getCode(keySpec); final int code = KeySpecParser.getCode(keySpec);
if ((mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0) { if ((mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0) {
@ -424,8 +416,7 @@ public class Key implements Comparable<Key> {
final int altCode = needsToUpcase final int altCode = needsToUpcase
? StringUtils.toTitleCaseOfKeyCode(altCodeInAttr, localeForUpcasing) ? StringUtils.toTitleCaseOfKeyCode(altCodeInAttr, localeForUpcasing)
: altCodeInAttr; : altCodeInAttr;
mOptionalAttributes = OptionalAttributes.newInstance(outputText, altCode, mOptionalAttributes = OptionalAttributes.newInstance(outputText, altCode, visualInsetsLeft, visualInsetsRight);
disabledIconId, visualInsetsLeft, visualInsetsRight);
mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr, null); mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr, null);
mHashCode = computeHashCode(this); mHashCode = computeHashCode(this);
} }
@ -562,9 +553,9 @@ public class Key implements Comparable<Key> {
} }
public String toLongString() { public String toLongString() {
final int iconId = getIconId(); final String iconId = getIconId();
final String topVisual = (iconId == KeyboardIconsSet.ICON_UNDEFINED) final String topVisual = (Objects.equals(iconId, ICON_UNDEFINED))
? KeyboardIconsSet.PREFIX_ICON + KeyboardIconsSet.getIconName(iconId) : getLabel(); ? KeyboardIconsSet.PREFIX_ICON + iconId : getLabel();
final String hintLabel = getHintLabel(); final String hintLabel = getHintLabel();
final String visual = (hintLabel == null) ? topVisual : topVisual + "^" + hintLabel; final String visual = (hintLabel == null) ? topVisual : topVisual + "^" + hintLabel;
return toString() + " " + visual + "/" + backgroundName(mBackgroundType); return toString() + " " + visual + "/" + backgroundName(mBackgroundType);
@ -830,15 +821,14 @@ public class Key implements Comparable<Key> {
return (attrs != null) ? attrs.mAltCode : CODE_UNSPECIFIED; return (attrs != null) ? attrs.mAltCode : CODE_UNSPECIFIED;
} }
public int getIconId() { public String getIconId() {
return mIconId; return mIconId;
} }
@Nullable @Nullable
public Drawable getIcon(final KeyboardIconsSet iconSet, final int alpha) { public Drawable getIcon(final KeyboardIconsSet iconSet, final int alpha) {
final OptionalAttributes attrs = mOptionalAttributes; final OptionalAttributes attrs = mOptionalAttributes;
final int disabledIconId = (attrs != null) ? attrs.mDisabledIconId : ICON_UNDEFINED; final String iconId = getIconId();
final int iconId = mEnabled ? getIconId() : disabledIconId;
final Drawable icon = iconSet.getIconDrawable(iconId); final Drawable icon = iconSet.getIconDrawable(iconId);
if (icon != null) { if (icon != null) {
icon.setAlpha(alpha); icon.setAlpha(alpha);

View File

@ -30,6 +30,7 @@ import org.futo.inputmethod.keyboard.Key;
import org.futo.inputmethod.latin.R; import org.futo.inputmethod.latin.R;
import java.util.HashSet; import java.util.HashSet;
import java.util.Objects;
/** /**
* The pop up key preview view. * The pop up key preview view.
@ -54,8 +55,8 @@ public class KeyPreviewView extends androidx.appcompat.widget.AppCompatTextView
public void setPreviewVisual(final Key key, final KeyboardIconsSet iconsSet, public void setPreviewVisual(final Key key, final KeyboardIconsSet iconsSet,
final KeyDrawParams drawParams) { final KeyDrawParams drawParams) {
// What we show as preview should match what we show on a key top in onDraw(). // What we show as preview should match what we show on a key top in onDraw().
final int iconId = key.getIconId(); final String iconId = key.getIconId();
if (iconId != KeyboardIconsSet.ICON_UNDEFINED) { if (!Objects.equals(iconId, KeyboardIconsSet.ICON_UNDEFINED)) {
setCompoundDrawables(null, null, null, key.getPreviewIcon(iconsSet)); setCompoundDrawables(null, null, null, key.getPreviewIcon(iconsSet));
setText(null); setText(null);
return; return;

View File

@ -235,7 +235,7 @@ public final class KeySpecParser {
return defaultCode; return defaultCode;
} }
public static int getIconId(@Nullable final String keySpec) { public static String getIconId(@Nullable final String keySpec) {
if (keySpec == null) { if (keySpec == null) {
// TODO: Throw {@link KeySpecParserError} once Key.keyLabel attribute becomes mandatory. // TODO: Throw {@link KeySpecParserError} once Key.keyLabel attribute becomes mandatory.
return KeyboardIconsSet.ICON_UNDEFINED; return KeyboardIconsSet.ICON_UNDEFINED;
@ -246,7 +246,7 @@ public final class KeySpecParser {
final int labelEnd = indexOfLabelEnd(keySpec); final int labelEnd = indexOfLabelEnd(keySpec);
final String iconName = getBeforeLabelEnd(keySpec, labelEnd) final String iconName = getBeforeLabelEnd(keySpec, labelEnd)
.substring(KeyboardIconsSet.PREFIX_ICON.length()); .substring(KeyboardIconsSet.PREFIX_ICON.length());
return KeyboardIconsSet.getIconId(iconName); return iconName;
} }
@SuppressWarnings("serial") @SuppressWarnings("serial")

View File

@ -152,7 +152,6 @@ public final class KeyStylesSet {
readStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys); readStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
readStringArray(keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys); readStringArray(keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys);
readFlags(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags); readFlags(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags);
readString(keyAttr, R.styleable.Keyboard_Key_keyIconDisabled);
readInt(keyAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn); readInt(keyAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn);
readInt(keyAttr, R.styleable.Keyboard_Key_backgroundType); readInt(keyAttr, R.styleable.Keyboard_Key_backgroundType);
readFlags(keyAttr, R.styleable.Keyboard_Key_keyActionFlags); readFlags(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
@ -227,4 +226,13 @@ public final class KeyStylesSet {
} }
return style; return style;
} }
public void addDynamicKeyStyle(final String styleName, final String keySpec, final int backgroundType, final int keyActionFlags) {
final DeclaredKeyStyle style = new DeclaredKeyStyle(EMPTY_STYLE_NAME, mTextsSet, mStyles);
style.mStyleAttributes.put(R.styleable.Keyboard_Key_keySpec, mTextsSet.resolveTextReference(keySpec));
style.mStyleAttributes.put(R.styleable.Keyboard_Key_backgroundType, (backgroundType));
style.mStyleAttributes.put(R.styleable.Keyboard_Key_keyActionFlags, (keyActionFlags));
mStyles.put(styleName, style);
}
} }

View File

@ -171,6 +171,11 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
mParams = params; mParams = params;
mParams.mKeyStyles.addDynamicKeyStyle("bottomEmojiKeyStyle",
"!icon/emoji_normal_key|!code/key_emoji",
2,
2);
params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width); params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height); params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
} }
@ -815,8 +820,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
return true; return true;
} }
final String iconName = a.getString(index); final String iconName = a.getString(index);
final int iconId = KeyboardIconsSet.getIconId(iconName); return iconsSet.getIconDrawable(iconName) != null;
return iconsSet.getIconDrawable(iconId) != null;
} }
private boolean parseDefault(final XmlPullParser parser, final KeyboardRow row, private boolean parseDefault(final XmlPullParser parser, final KeyboardRow row,

View File

@ -34,8 +34,7 @@ public final class KeyboardIconsSet {
private static final String TAG = KeyboardIconsSet.class.getSimpleName(); private static final String TAG = KeyboardIconsSet.class.getSimpleName();
public static final String PREFIX_ICON = "!icon/"; public static final String PREFIX_ICON = "!icon/";
public static final int ICON_UNDEFINED = 0; public static final String ICON_UNDEFINED = "";
private static final int ATTR_UNDEFINED = 0;
private static final String NAME_UNDEFINED = "undefined"; private static final String NAME_UNDEFINED = "undefined";
public static final String NAME_SHIFT_KEY = "shift_key"; public static final String NAME_SHIFT_KEY = "shift_key";
@ -60,55 +59,10 @@ public final class KeyboardIconsSet {
public static final String NAME_EMOJI_ACTION_KEY = "emoji_action_key"; public static final String NAME_EMOJI_ACTION_KEY = "emoji_action_key";
public static final String NAME_EMOJI_NORMAL_KEY = "emoji_normal_key"; public static final String NAME_EMOJI_NORMAL_KEY = "emoji_normal_key";
private static final SparseIntArray ATTR_ID_TO_ICON_ID = new SparseIntArray(); private DynamicThemeProvider provider;
// Icon name to icon id map.
private static final HashMap<String, Integer> sNameToIdsMap = new HashMap<>();
private static final Object[] NAMES_AND_ATTR_IDS = {
NAME_UNDEFINED, ATTR_UNDEFINED,
NAME_SHIFT_KEY, R.styleable.Keyboard_iconShiftKey,
NAME_DELETE_KEY, R.styleable.Keyboard_iconDeleteKey,
NAME_SETTINGS_KEY, R.styleable.Keyboard_iconSettingsKey,
NAME_SPACE_KEY, R.styleable.Keyboard_iconSpaceKey,
NAME_ENTER_KEY, R.styleable.Keyboard_iconEnterKey,
NAME_GO_KEY, R.styleable.Keyboard_iconGoKey,
NAME_SEARCH_KEY, R.styleable.Keyboard_iconSearchKey,
NAME_SEND_KEY, R.styleable.Keyboard_iconSendKey,
NAME_NEXT_KEY, R.styleable.Keyboard_iconNextKey,
NAME_DONE_KEY, R.styleable.Keyboard_iconDoneKey,
NAME_PREVIOUS_KEY, R.styleable.Keyboard_iconPreviousKey,
NAME_TAB_KEY, R.styleable.Keyboard_iconTabKey,
NAME_SHORTCUT_KEY, R.styleable.Keyboard_iconShortcutKey,
NAME_SPACE_KEY_FOR_NUMBER_LAYOUT, R.styleable.Keyboard_iconSpaceKeyForNumberLayout,
NAME_SHIFT_KEY_SHIFTED, R.styleable.Keyboard_iconShiftKeyShifted,
NAME_SHORTCUT_KEY_DISABLED, R.styleable.Keyboard_iconShortcutKeyDisabled,
NAME_LANGUAGE_SWITCH_KEY, R.styleable.Keyboard_iconLanguageSwitchKey,
NAME_ZWNJ_KEY, R.styleable.Keyboard_iconZwnjKey,
NAME_ZWJ_KEY, R.styleable.Keyboard_iconZwjKey,
NAME_EMOJI_ACTION_KEY, R.styleable.Keyboard_iconEmojiActionKey,
NAME_EMOJI_NORMAL_KEY, R.styleable.Keyboard_iconEmojiNormalKey,
};
private static int NUM_ICONS = NAMES_AND_ATTR_IDS.length / 2;
private static final String[] ICON_NAMES = new String[NUM_ICONS];
private final Drawable[] mIcons = new Drawable[NUM_ICONS];
static {
int iconId = ICON_UNDEFINED;
for (int i = 0; i < NAMES_AND_ATTR_IDS.length; i += 2) {
final String name = (String)NAMES_AND_ATTR_IDS[i];
final Integer attrId = (Integer)NAMES_AND_ATTR_IDS[i + 1];
if (attrId != ATTR_UNDEFINED) {
ATTR_ID_TO_ICON_ID.put(attrId, iconId);
}
sNameToIdsMap.put(name, iconId);
ICON_NAMES[iconId] = name;
iconId++;
}
}
public void loadIcons(final TypedArray keyboardAttrs, @Nullable DynamicThemeProvider provider) { public void loadIcons(final TypedArray keyboardAttrs, @Nullable DynamicThemeProvider provider) {
this.provider = provider;
/*
final int size = ATTR_ID_TO_ICON_ID.size(); final int size = ATTR_ID_TO_ICON_ID.size();
for (int index = 0; index < size; index++) { for (int index = 0; index < size; index++) {
final int attrId = ATTR_ID_TO_ICON_ID.keyAt(index); final int attrId = ATTR_ID_TO_ICON_ID.keyAt(index);
@ -123,31 +77,12 @@ public final class KeyboardIconsSet {
+ " not found"); + " not found");
} }
} }
} */
private static boolean isValidIconId(final int iconId) {
return iconId >= 0 && iconId < ICON_NAMES.length;
}
@Nonnull
public static String getIconName(final int iconId) {
return isValidIconId(iconId) ? ICON_NAMES[iconId] : "unknown<" + iconId + ">";
}
public static int getIconId(final String name) {
Integer iconId = sNameToIdsMap.get(name);
if (iconId != null) {
return iconId;
}
throw new RuntimeException("unknown icon name: " + name);
} }
@Nullable @Nullable
public Drawable getIconDrawable(final int iconId) { public Drawable getIconDrawable(final String iconId) {
if (isValidIconId(iconId)) { return provider.getIcon(iconId);
return mIcons[iconId];
}
throw new RuntimeException("unknown icon id: " + getIconName(iconId));
} }
private static void setDefaultBounds(final Drawable icon) { private static void setDefaultBounds(final Drawable icon) {

View File

@ -50,7 +50,7 @@ public final class MoreKeySpec {
public final String mLabel; public final String mLabel;
@Nullable @Nullable
public final String mOutputText; public final String mOutputText;
public final int mIconId; public final String mIconId;
public MoreKeySpec(@Nonnull final String moreKeySpec, boolean needsToUpperCase, public MoreKeySpec(@Nonnull final String moreKeySpec, boolean needsToUpperCase,
@Nonnull final Locale locale) { @Nonnull final Locale locale) {
@ -88,7 +88,7 @@ public final class MoreKeySpec {
public int hashCode() { public int hashCode() {
int hashCode = 1; int hashCode = 1;
hashCode = 31 + mCode; hashCode = 31 + mCode;
hashCode = hashCode * 31 + mIconId; hashCode = hashCode * 31 + (mIconId == null ? 0 : mIconId.hashCode());
final String label = mLabel; final String label = mLabel;
hashCode = hashCode * 31 + (label == null ? 0 : label.hashCode()); hashCode = hashCode * 31 + (label == null ? 0 : label.hashCode());
final String outputText = mOutputText; final String outputText = mOutputText;
@ -114,7 +114,7 @@ public final class MoreKeySpec {
@Override @Override
public String toString() { public String toString() {
final String label = (mIconId == KeyboardIconsSet.ICON_UNDEFINED ? mLabel final String label = (mIconId == KeyboardIconsSet.ICON_UNDEFINED ? mLabel
: KeyboardIconsSet.PREFIX_ICON + KeyboardIconsSet.getIconName(mIconId)); : KeyboardIconsSet.PREFIX_ICON + (mIconId));
final String output = (mCode == Constants.CODE_OUTPUT_TEXT ? mOutputText final String output = (mCode == Constants.CODE_OUTPUT_TEXT ? mOutputText
: Constants.printableCode(mCode)); : Constants.printableCode(mCode));
if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) { if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) {

View File

@ -1,13 +1,13 @@
package org.futo.inputmethod.latin.uix package org.futo.inputmethod.latin.uix
import android.content.Context import android.content.Context
import android.graphics.Rect
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.graphics.drawable.ShapeDrawable import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.StateListDrawable import android.graphics.drawable.StateListDrawable
import android.graphics.drawable.shapes.RoundRectShape import android.graphics.drawable.shapes.RoundRectShape
import android.util.Log
import android.util.TypedValue import android.util.TypedValue
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
@ -22,6 +22,7 @@ import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.floatPreferencesKey import androidx.datastore.preferences.core.floatPreferencesKey
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
import org.futo.inputmethod.keyboard.internal.KeyboardIconsSet
import org.futo.inputmethod.latin.R import org.futo.inputmethod.latin.R
import org.futo.inputmethod.latin.uix.theme.DarkColorScheme import org.futo.inputmethod.latin.uix.theme.DarkColorScheme
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -85,6 +86,17 @@ class BasicThemeProvider(val context: Context, val overrideColorScheme: ColorSch
return drawables[i] return drawables[i]
} }
val icons: HashMap<String, Drawable?> = hashMapOf()
override fun getIcon(iconName: String): Drawable? {
if(iconName == KeyboardIconsSet.ICON_UNDEFINED) return null
if(!icons.containsKey(iconName)) {
Log.e("BasicThemeProvider", "Unknown icon $iconName")
}
return icons[iconName]
}
override fun getKeyboardHeightMultiplier(): Float { override fun getKeyboardHeightMultiplier(): Float {
return keyboardHeight return keyboardHeight
} }
@ -144,6 +156,20 @@ class BasicThemeProvider(val context: Context, val overrideColorScheme: ColorSch
|| np.get(KeyboardHeightMultiplierSetting) != keyboardHeight || np.get(KeyboardHeightMultiplierSetting) != keyboardHeight
} }
private fun addIcon(iconName: String, drawableIntResId: Int, tint: Int) {
addIcon(iconName, AppCompatResources.getDrawable(
context,
drawableIntResId
), tint)
}
private fun addIcon(iconName: String, drawable: Drawable?, tint: Int) {
icons[iconName] = drawable?.apply {
setTint(tint)
}
}
init { init {
val colorScheme = if(overrideColorScheme != null) { val colorScheme = if(overrideColorScheme != null) {
overrideColorScheme overrideColorScheme
@ -228,6 +254,26 @@ class BasicThemeProvider(val context: Context, val overrideColorScheme: ColorSch
} }
} }
addIcon(KeyboardIconsSet.NAME_SHIFT_KEY, R.drawable.shift, onBackground)
addIcon(KeyboardIconsSet.NAME_SHIFT_KEY_SHIFTED, R.drawable.shiftshifted, onBackground)
addIcon(KeyboardIconsSet.NAME_DELETE_KEY, R.drawable.delete, onBackground)
addIcon(KeyboardIconsSet.NAME_SETTINGS_KEY, R.drawable.settings, onBackground)
addIcon(KeyboardIconsSet.NAME_SPACE_KEY, null, onBackground)
addIcon(KeyboardIconsSet.NAME_ENTER_KEY, R.drawable.sym_keyboard_return_lxx_light, enterKeyForeground)
addIcon(KeyboardIconsSet.NAME_GO_KEY, R.drawable.sym_keyboard_go_lxx_light, enterKeyForeground)
addIcon(KeyboardIconsSet.NAME_SEARCH_KEY, R.drawable.sym_keyboard_search_lxx_light, enterKeyForeground)
addIcon(KeyboardIconsSet.NAME_SEND_KEY, R.drawable.sym_keyboard_send_lxx_light, enterKeyForeground)
addIcon(KeyboardIconsSet.NAME_NEXT_KEY, R.drawable.sym_keyboard_next_lxx_light, enterKeyForeground)
addIcon(KeyboardIconsSet.NAME_DONE_KEY, R.drawable.sym_keyboard_done_lxx_light, enterKeyForeground)
addIcon(KeyboardIconsSet.NAME_PREVIOUS_KEY, R.drawable.sym_keyboard_previous_lxx_light, enterKeyForeground)
addIcon(KeyboardIconsSet.NAME_TAB_KEY, R.drawable.sym_keyboard_tab_holo_dark, onBackground) // TODO: Correct tint
addIcon(KeyboardIconsSet.NAME_ZWNJ_KEY, R.drawable.sym_keyboard_zwnj_lxx_dark, onBackground)
addIcon(KeyboardIconsSet.NAME_ZWJ_KEY, R.drawable.sym_keyboard_zwj_lxx_dark, onPrimary)
addIcon(KeyboardIconsSet.NAME_EMOJI_ACTION_KEY, R.drawable.smile, onPrimary)
addIcon(KeyboardIconsSet.NAME_EMOJI_NORMAL_KEY, R.drawable.smile, onBackground)
// No good replacements for these icons yet, but we set them anyway for setTint // No good replacements for these icons yet, but we set them anyway for setTint
overrideDrawable(R.styleable.Keyboard_iconEnterKey, R.drawable.sym_keyboard_return_lxx_light, enterKeyForeground) overrideDrawable(R.styleable.Keyboard_iconEnterKey, R.drawable.sym_keyboard_return_lxx_light, enterKeyForeground)
overrideDrawable(R.styleable.Keyboard_iconGoKey, R.drawable.sym_keyboard_go_lxx_light, enterKeyForeground) overrideDrawable(R.styleable.Keyboard_iconGoKey, R.drawable.sym_keyboard_go_lxx_light, enterKeyForeground)

View File

@ -22,6 +22,8 @@ interface DynamicThemeProvider {
fun getDrawable(i: Int): Drawable? fun getDrawable(i: Int): Drawable?
fun getIcon(iconName: String): Drawable?
fun getKeyboardHeightMultiplier(): Float fun getKeyboardHeightMultiplier(): Float
companion object { companion object {

View File

@ -63,11 +63,11 @@ abstract class KeyboardLayoutSetNavigateMoreKeysBase extends KeyboardLayoutSetTe
public static final ExpectedMoreKey[] EMPTY_MORE_KEYS = new ExpectedMoreKey[0]; public static final ExpectedMoreKey[] EMPTY_MORE_KEYS = new ExpectedMoreKey[0];
public final int mLabelResId; public final int mLabelResId;
public final int mIconId; public final String mIconId;
public ExpectedMoreKey(final String iconName) { public ExpectedMoreKey(final String iconName) {
mLabelResId = NO_LABEL; mLabelResId = NO_LABEL;
mIconId = KeyboardIconsSet.getIconId(iconName); mIconId = iconName;
} }
public ExpectedMoreKey(final int labelResId) { public ExpectedMoreKey(final int labelResId) {
@ -112,7 +112,7 @@ abstract class KeyboardLayoutSetNavigateMoreKeysBase extends KeyboardLayoutSetTe
final CharSequence expectedLabel = getContext().getText(expectedLabelResId); final CharSequence expectedLabel = getContext().getText(expectedLabelResId);
assertEquals(tag + " label " + index, expectedLabel, actualMoreKeys[index].mLabel); assertEquals(tag + " label " + index, expectedLabel, actualMoreKeys[index].mLabel);
} }
final int expectedIconId = expectedMoreKeys[index].mIconId; final String expectedIconId = expectedMoreKeys[index].mIconId;
assertEquals(tag + " icon " + index, expectedIconId, actualMoreKeys[index].mIconId); assertEquals(tag + " icon " + index, expectedIconId, actualMoreKeys[index].mIconId);
} }
} }

View File

@ -39,8 +39,7 @@ import java.util.Locale;
abstract class ActionTestsBase extends KeyboardLayoutSetTestsBase { abstract class ActionTestsBase extends KeyboardLayoutSetTestsBase {
static class ExpectedActionKey { static class ExpectedActionKey {
static ExpectedActionKey newIconKey(final String iconName) { static ExpectedActionKey newIconKey(final String iconName) {
final int iconId = KeyboardIconsSet.getIconId(iconName); return new ExpectedActionKey(ExpectedKeyVisual.newIconInstance(iconName));
return new ExpectedActionKey(ExpectedKeyVisual.newInstance(iconId));
} }
static ExpectedActionKey newLabelKey(final String label) { static ExpectedActionKey newLabelKey(final String label) {
@ -64,7 +63,7 @@ abstract class ActionTestsBase extends KeyboardLayoutSetTestsBase {
mVisual = visual; mVisual = visual;
} }
public int getIconId() { return mVisual.getIconId(); } public String getIconId() { return mVisual.getIconId(); }
public String getLabel() { return mVisual.getLabel(); } public String getLabel() { return mVisual.getLabel(); }
} }

View File

@ -27,18 +27,18 @@ import org.futo.inputmethod.latin.common.Constants;
public final class KeySpecParserTests extends KeySpecParserTestsBase { public final class KeySpecParserTests extends KeySpecParserTestsBase {
@Override @Override
protected void assertParser(final String message, final String keySpec, protected void assertParser(final String message, final String keySpec,
final String expectedLabel, final String expectedOutputText, final int expectedIcon, final String expectedLabel, final String expectedOutputText, final String expectedIcon,
final int expectedCode) { final int expectedCode) {
final String keySpecResolved = mTextsSet.resolveTextReference(keySpec); final String keySpecResolved = mTextsSet.resolveTextReference(keySpec);
final String actualLabel = KeySpecParser.getLabel(keySpecResolved); final String actualLabel = KeySpecParser.getLabel(keySpecResolved);
final String actualOutputText = KeySpecParser.getOutputText(keySpecResolved); final String actualOutputText = KeySpecParser.getOutputText(keySpecResolved);
final int actualIcon = KeySpecParser.getIconId(keySpecResolved); final String actualIcon = KeySpecParser.getIconId(keySpecResolved);
final int actualCode = KeySpecParser.getCode(keySpecResolved); final int actualCode = KeySpecParser.getCode(keySpecResolved);
assertEquals(message + " [label]", expectedLabel, actualLabel); assertEquals(message + " [label]", expectedLabel, actualLabel);
assertEquals(message + " [ouptputText]", expectedOutputText, actualOutputText); assertEquals(message + " [ouptputText]", expectedOutputText, actualOutputText);
assertEquals(message + " [icon]", assertEquals(message + " [icon]",
KeyboardIconsSet.getIconName(expectedIcon), expectedIcon,
KeyboardIconsSet.getIconName(actualIcon)); actualIcon);
assertEquals(message + " [code]", assertEquals(message + " [code]",
Constants.printableCode(expectedCode), Constants.printableCode(expectedCode),
Constants.printableCode(actualCode)); Constants.printableCode(actualCode));

View File

@ -41,7 +41,7 @@ abstract class KeySpecParserTestsBase extends AndroidTestCase {
private int mCodeSettings; private int mCodeSettings;
private int mCodeActionNext; private int mCodeActionNext;
private int mSettingsIconId; private String mSettingsIconId;
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
@ -50,15 +50,15 @@ abstract class KeySpecParserTestsBase extends AndroidTestCase {
mTextsSet.setLocale(TEST_LOCALE, getContext()); mTextsSet.setLocale(TEST_LOCALE, getContext());
mCodeSettings = KeyboardCodesSet.getCode(CODE_SETTINGS_NAME); mCodeSettings = KeyboardCodesSet.getCode(CODE_SETTINGS_NAME);
mCodeActionNext = KeyboardCodesSet.getCode("key_action_next"); mCodeActionNext = KeyboardCodesSet.getCode("key_action_next");
mSettingsIconId = KeyboardIconsSet.getIconId(ICON_SETTINGS_NAME); mSettingsIconId = ICON_SETTINGS_NAME;
} }
abstract protected void assertParser(final String message, final String keySpec, abstract protected void assertParser(final String message, final String keySpec,
final String expectedLabel, final String expectedOutputText, final int expectedIcon, final String expectedLabel, final String expectedOutputText, final String expectedIcon,
final int expectedCode); final int expectedCode);
protected void assertParserError(final String message, final String keySpec, protected void assertParserError(final String message, final String keySpec,
final String expectedLabel, final String expectedOutputText, final int expectedIconId, final String expectedLabel, final String expectedOutputText, final String expectedIconId,
final int expectedCode) { final int expectedCode) {
try { try {
assertParser(message, keySpec, expectedLabel, expectedOutputText, expectedIconId, assertParser(message, keySpec, expectedLabel, expectedOutputText, expectedIconId,

View File

@ -30,7 +30,7 @@ import java.util.Locale;
public final class MoreKeySpecTests extends KeySpecParserTestsBase { public final class MoreKeySpecTests extends KeySpecParserTestsBase {
@Override @Override
protected void assertParser(final String message, final String moreKeySpec, protected void assertParser(final String message, final String moreKeySpec,
final String expectedLabel, final String expectedOutputText, final int expectedIconId, final String expectedLabel, final String expectedOutputText, final String expectedIconId,
final int expectedCode) { final int expectedCode) {
final String labelResolved = mTextsSet.resolveTextReference(moreKeySpec); final String labelResolved = mTextsSet.resolveTextReference(moreKeySpec);
final MoreKeySpec spec = new MoreKeySpec( final MoreKeySpec spec = new MoreKeySpec(
@ -38,8 +38,8 @@ public final class MoreKeySpecTests extends KeySpecParserTestsBase {
assertEquals(message + " [label]", expectedLabel, spec.mLabel); assertEquals(message + " [label]", expectedLabel, spec.mLabel);
assertEquals(message + " [ouptputText]", expectedOutputText, spec.mOutputText); assertEquals(message + " [ouptputText]", expectedOutputText, spec.mOutputText);
assertEquals(message + " [icon]", assertEquals(message + " [icon]",
KeyboardIconsSet.getIconName(expectedIconId), expectedIconId,
KeyboardIconsSet.getIconName(spec.mIconId)); spec.mIconId);
assertEquals(message + " [code]", assertEquals(message + " [code]",
Constants.printableCode(expectedCode), Constants.printableCode(expectedCode),
Constants.printableCode(spec.mCode)); Constants.printableCode(spec.mCode));

View File

@ -106,32 +106,19 @@ public abstract class AbstractLayoutBase {
} }
// Icon ids. // Icon ids.
private static final int ICON_DELETE = KeyboardIconsSet.getIconId( private static final String ICON_DELETE = KeyboardIconsSet.NAME_DELETE_KEY;
KeyboardIconsSet.NAME_DELETE_KEY); private static final String ICON_SPACE = KeyboardIconsSet.NAME_SPACE_KEY;
private static final int ICON_SPACE = KeyboardIconsSet.getIconId( private static final String ICON_TAB = KeyboardIconsSet.NAME_TAB_KEY;
KeyboardIconsSet.NAME_SPACE_KEY); private static final String ICON_SHORTCUT = KeyboardIconsSet.NAME_SHORTCUT_KEY;
private static final int ICON_TAB = KeyboardIconsSet.getIconId( private static final String ICON_SETTINGS = KeyboardIconsSet.NAME_SETTINGS_KEY;
KeyboardIconsSet.NAME_TAB_KEY); private static final String ICON_LANGUAGE_SWITCH = KeyboardIconsSet.NAME_LANGUAGE_SWITCH_KEY;
private static final int ICON_SHORTCUT = KeyboardIconsSet.getIconId( private static final String ICON_ENTER = KeyboardIconsSet.NAME_ENTER_KEY;
KeyboardIconsSet.NAME_SHORTCUT_KEY); private static final String ICON_EMOJI_ACTION = KeyboardIconsSet.NAME_EMOJI_ACTION_KEY;
private static final int ICON_SETTINGS = KeyboardIconsSet.getIconId( private static final String ICON_EMOJI_NORMAL = KeyboardIconsSet.NAME_EMOJI_NORMAL_KEY;
KeyboardIconsSet.NAME_SETTINGS_KEY); private static final String ICON_SHIFT = KeyboardIconsSet.NAME_SHIFT_KEY;
private static final int ICON_LANGUAGE_SWITCH = KeyboardIconsSet.getIconId( private static final String ICON_SHIFTED_SHIFT = KeyboardIconsSet.NAME_SHIFT_KEY_SHIFTED;
KeyboardIconsSet.NAME_LANGUAGE_SWITCH_KEY); private static final String ICON_ZWNJ = KeyboardIconsSet.NAME_ZWNJ_KEY;
private static final int ICON_ENTER = KeyboardIconsSet.getIconId( private static final String ICON_ZWJ = KeyboardIconsSet.NAME_ZWJ_KEY;
KeyboardIconsSet.NAME_ENTER_KEY);
private static final int ICON_EMOJI_ACTION = KeyboardIconsSet.getIconId(
KeyboardIconsSet.NAME_EMOJI_ACTION_KEY);
private static final int ICON_EMOJI_NORMAL = KeyboardIconsSet.getIconId(
KeyboardIconsSet.NAME_EMOJI_NORMAL_KEY);
private static final int ICON_SHIFT = KeyboardIconsSet.getIconId(
KeyboardIconsSet.NAME_SHIFT_KEY);
private static final int ICON_SHIFTED_SHIFT = KeyboardIconsSet.getIconId(
KeyboardIconsSet.NAME_SHIFT_KEY_SHIFTED);
private static final int ICON_ZWNJ = KeyboardIconsSet.getIconId(
KeyboardIconsSet.NAME_ZWNJ_KEY);
private static final int ICON_ZWJ = KeyboardIconsSet.getIconId(
KeyboardIconsSet.NAME_ZWJ_KEY);
// Functional keys. // Functional keys.
protected static final ExpectedKey DELETE_KEY = key(ICON_DELETE, Constants.CODE_DELETE); protected static final ExpectedKey DELETE_KEY = key(ICON_DELETE, Constants.CODE_DELETE);

View File

@ -33,11 +33,11 @@ public abstract class ExpectedKeyVisual {
return new Label(label); return new Label(label);
} }
public static ExpectedKeyVisual newInstance(final int iconId) { public static ExpectedKeyVisual newIconInstance(final String iconId) {
return new Icon(iconId); return new Icon(iconId);
} }
public abstract int getIconId(); public abstract String getIconId();
public abstract String getLabel(); public abstract String getLabel();
abstract ExpectedKeyVisual toUpperCase(final Locale locale); abstract ExpectedKeyVisual toUpperCase(final Locale locale);
abstract ExpectedKeyVisual preserveCase(); abstract ExpectedKeyVisual preserveCase();
@ -51,20 +51,20 @@ public abstract class ExpectedKeyVisual {
* This class represents an integer icon id. * This class represents an integer icon id.
*/ */
private static class Icon extends ExpectedKeyVisual { private static class Icon extends ExpectedKeyVisual {
private final int mIconId; private final String mIconId;
Icon(final int iconId) { Icon(final String iconId) {
mIconId = iconId; mIconId = iconId;
} }
@Override @Override
public int getIconId() { public String getIconId() {
return mIconId; return mIconId;
} }
@Override @Override
public String getLabel() { public String getLabel() {
return null; return mIconId;
} }
@Override @Override
@ -109,7 +109,7 @@ public abstract class ExpectedKeyVisual {
@Override @Override
public String toString() { public String toString() {
return KeyboardIconsSet.getIconName(mIconId); return mIconId;
} }
} }
@ -124,7 +124,7 @@ public abstract class ExpectedKeyVisual {
} }
@Override @Override
public int getIconId() { public String getIconId() {
return KeyboardIconsSet.ICON_UNDEFINED; return KeyboardIconsSet.ICON_UNDEFINED;
} }