From cdabf650c6f96fc83ee0c5f91f9db8ea1eae2639 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Wed, 28 Jun 2023 18:54:23 +0200 Subject: [PATCH] user-adjustable colors --- README.md | 7 +- .../keyboard/KeyboardSwitcher.java | 6 + .../inputmethod/keyboard/KeyboardTheme.java | 42 +++++- .../inputmethod/keyboard/KeyboardView.java | 57 ++++++++ .../clipboard/ClipboardHistoryView.kt | 10 ++ .../keyboard/emoji/EmojiPalettesView.java | 8 ++ .../GestureFloatingTextDrawingPreview.java | 7 +- .../internal/GestureTrailDrawingParams.java | 5 +- .../internal/KeyPreviewChoreographer.java | 10 ++ .../settings/AppearanceSettingsFragment.kt | 29 +++++ .../latin/settings/ColorPickerDialog.java | 123 ++++++++++++++++++ .../inputmethod/latin/settings/Settings.java | 6 + .../latin/settings/SettingsValues.java | 35 +++++ .../SuggestionStripLayoutHelper.java | 6 +- .../suggestions/SuggestionStripView.java | 5 +- app/src/main/res/layout/color_dialog.xml | 54 ++++++++ app/src/main/res/values/attrs.xml | 3 + app/src/main/res/values/strings.xml | 16 +++ .../main/res/xml/prefs_screen_appearance.xml | 5 + 19 files changed, 425 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/ColorPickerDialog.java create mode 100644 app/src/main/res/layout/color_dialog.xml diff --git a/README.md b/README.md index 2e38289e2..909130c6e 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,11 @@ Plan / to do: * ~suggestion fixes, https://github.com/openboard-team/openboard/pull/694, https://github.com/openboard-team/openboard/issues/795, https://github.com/openboard-team/openboard/issues/660~ * ~improve auto-space insertion, https://github.com/openboard-team/openboard/pull/576~ * emoji prediction/search, either https://github.com/openboard-team/openboard/pull/749 (using emoji dictionaries already possible) -* theming, https://github.com/openboard-team/openboard/issues/124 +* ~theming, https://github.com/openboard-team/openboard/issues/124~ + * fix emoji view not themed properly + * fix ABC buttons in emoji and clipboard view have wrong text color + * fix buttons on long-press action key not themed + * allow adjusting colors without requiring manual reload of keyboard * delete suggestions, https://github.com/openboard-team/openboard/issues/106 * ~gesture typing, https://github.com/openboard-team/openboard/issues/3~ * ~license issues, require using an external library~ @@ -43,6 +47,7 @@ Changes: * Allow loading an external library to enable gesture typing, https://github.com/openboard-team/openboard/issues/3 * based on wordmage's work https://github.com/openboard-team/openboard/tree/57d33791d7674e3fe0600eddb72f6b4317b5df00 * tested with Google libraries and [others](https://github.com/openboard-team/openboard/issues/3#issuecomment-1200456262) (when building with the [rename](https://github.com/openboard-team/openboard/tree/57d33791d7674e3fe0600eddb72f6b4317b5df00)) +* Allow adjusting keyboard colors, https://github.com/openboard-team/openboard/issues/124 ----- diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardSwitcher.java b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardSwitcher.java index e46d85d2e..8687807f1 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardSwitcher.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardSwitcher.java @@ -549,6 +549,12 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { mClipboardHistoryView.setHardwareAcceleratedDrawingEnabled( isHardwareAcceleratedDrawingEnabled); mClipboardHistoryView.setKeyboardActionListener(mLatinIME); + + // set background color here, otherwise there is a narrow white line between keyboard and suggestion strip + final SettingsValues settingsValues = Settings.getInstance().getCurrent(); + if (settingsValues.mUserTheme) + mKeyboardViewWrapper.getBackground().setColorFilter(settingsValues.mBackgroundColorFilter); + return mCurrentInputView; } diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardTheme.java b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardTheme.java index b6fd7e3cf..3ccf9f18b 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardTheme.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardTheme.java @@ -38,15 +38,17 @@ public final class KeyboardTheme implements Comparable { public static final String THEME_VARIANT_DARK = "Dark"; public static final String THEME_VARIANT_WHITE = "White"; public static final String THEME_VARIANT_BLUE = "Blue"; + public static final String THEME_VARIANT_USER = "User-defined"; + public static final String THEME_VARIANT_HOLO_USER = "User-defined (Holo)"; public static final String[] THEME_FAMILIES = {THEME_FAMILY_MATERIAL, THEME_FAMILY_HOLO}; public static final Map THEME_VARIANTS = new HashMap<>(); static { THEME_VARIANTS.put(THEME_FAMILY_MATERIAL, - new String[] {THEME_VARIANT_LIGHT, THEME_VARIANT_DARK}); + new String[] {THEME_VARIANT_LIGHT, THEME_VARIANT_DARK, THEME_VARIANT_USER}); THEME_VARIANTS.put(THEME_FAMILY_HOLO, - new String[] {THEME_VARIANT_WHITE, THEME_VARIANT_BLUE}); + new String[] {THEME_VARIANT_WHITE, THEME_VARIANT_BLUE, THEME_VARIANT_HOLO_USER}); } private static final String TAG = KeyboardTheme.class.getSimpleName(); @@ -58,6 +60,7 @@ public final class KeyboardTheme implements Comparable { // attributes' values in attrs.xml. public static final int THEME_ID_ICS = 0; public static final int THEME_ID_KLP = 2; + public static final int THEME_ID_KLP_USER = 13; public static final int THEME_ID_LXX_LIGHT = 3; public static final int THEME_ID_LXX_DARK_AMOLED = 4; public static final int THEME_ID_LXX_AUTO_AMOLED = 10; @@ -66,6 +69,8 @@ public final class KeyboardTheme implements Comparable { public static final int THEME_ID_LXX_DARK = 7; public static final int THEME_ID_LXX_AUTO = 9; public static final int THEME_ID_LXX_AUTO_BORDER = 8; + public static final int THEME_ID_LXX_USER = 11; + public static final int THEME_ID_LXX_USER_BORDER = 12; public static final int DEFAULT_THEME_ID = THEME_ID_LXX_DARK_BORDER; private static KeyboardTheme[] AVAILABLE_KEYBOARD_THEMES; @@ -102,6 +107,15 @@ public final class KeyboardTheme implements Comparable { new KeyboardTheme(THEME_ID_LXX_AUTO_AMOLED, "LXXAutoAmoled", R.style.KeyboardTheme_LXX_Auto_Amoled, // This has never been selected as default theme. VERSION_CODES.LOLLIPOP), + new KeyboardTheme(THEME_ID_LXX_USER, "LXXUser", R.style.KeyboardTheme_LXX_Light, + // This has never been selected as default theme. + VERSION_CODES.LOLLIPOP), + new KeyboardTheme(THEME_ID_LXX_USER_BORDER, "LXXUserBorder", R.style.KeyboardTheme_LXX_Light_Border, + // This has never been selected as default theme. + VERSION_CODES.LOLLIPOP), + new KeyboardTheme(THEME_ID_KLP_USER, "KLPUser", R.style.KeyboardTheme_KLP, + // This has never been selected as default theme. + VERSION_CODES.BASE), }; static { @@ -237,7 +251,7 @@ public final class KeyboardTheme implements Comparable { } public static String getThemeFamily(int themeId) { - if (themeId == THEME_ID_ICS || themeId == THEME_ID_KLP) return THEME_FAMILY_HOLO; + if (themeId == THEME_ID_ICS || themeId == THEME_ID_KLP || themeId == THEME_ID_KLP_USER) return THEME_FAMILY_HOLO; return THEME_FAMILY_MATERIAL; } @@ -254,6 +268,11 @@ public final class KeyboardTheme implements Comparable { return THEME_VARIANT_WHITE; case THEME_ID_ICS: return THEME_VARIANT_BLUE; + case THEME_ID_LXX_USER: + case THEME_ID_LXX_USER_BORDER: + return THEME_VARIANT_USER; + case THEME_ID_KLP_USER: + return THEME_VARIANT_HOLO_USER; default: return null; } @@ -264,6 +283,7 @@ public final class KeyboardTheme implements Comparable { case THEME_ID_LXX_DARK_BORDER: case THEME_ID_LXX_LIGHT_BORDER: case THEME_ID_LXX_AUTO_BORDER: + case THEME_ID_LXX_USER_BORDER: case THEME_ID_ICS: case THEME_ID_KLP: return true; @@ -272,6 +292,17 @@ public final class KeyboardTheme implements Comparable { } } + public static boolean getIsUser(int themeId) { + switch (themeId) { + case THEME_ID_LXX_USER: + case THEME_ID_LXX_USER_BORDER: + case THEME_ID_KLP_USER: + return true; + default: + return false; + } + } + public static boolean getIsDayNight(int themeId) { switch (themeId) { case THEME_ID_LXX_AUTO: @@ -297,6 +328,7 @@ public final class KeyboardTheme implements Comparable { boolean keyBorders, boolean dayNight, boolean amoledMode) { if (THEME_FAMILY_HOLO.equals(family)) { if (THEME_VARIANT_BLUE.equals(variant)) return THEME_ID_ICS; + if (THEME_VARIANT_HOLO_USER.equals(variant)) return THEME_ID_KLP_USER; return THEME_ID_KLP; } if (dayNight) { @@ -309,6 +341,10 @@ public final class KeyboardTheme implements Comparable { if (amoledMode) return THEME_ID_LXX_DARK_AMOLED; return THEME_ID_LXX_DARK; } + if (THEME_VARIANT_USER.equals(variant)) { + if (keyBorders) return THEME_ID_LXX_USER_BORDER; + return THEME_ID_LXX_USER; + } if (keyBorders) return THEME_ID_LXX_LIGHT_BORDER; return THEME_ID_LXX_LIGHT; } diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardView.java b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardView.java index 02bfd1ee2..a6d658cff 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardView.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/KeyboardView.java @@ -21,6 +21,7 @@ import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.PorterDuff; @@ -32,11 +33,15 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; +import androidx.core.graphics.BlendModeColorFilterCompat; +import androidx.core.graphics.BlendModeCompat; + import org.dslul.openboard.inputmethod.keyboard.internal.KeyDrawParams; import org.dslul.openboard.inputmethod.keyboard.internal.KeyVisualAttributes; import org.dslul.openboard.inputmethod.latin.R; import org.dslul.openboard.inputmethod.latin.common.Constants; import org.dslul.openboard.inputmethod.latin.settings.Settings; +import org.dslul.openboard.inputmethod.latin.settings.SettingsValues; import org.dslul.openboard.inputmethod.latin.utils.TypefaceUtils; import java.util.HashSet; @@ -96,6 +101,11 @@ public class KeyboardView extends View { private final float mSpacebarIconWidthRatio; private final Rect mKeyBackgroundPadding = new Rect(); private static final float KET_TEXT_SHADOW_RADIUS_DISABLED = -1.0f; + private final ColorFilter keyHintTextColorFilter; + private final ColorFilter keyTextColorFilter; + private final ColorFilter keyBgFilter; + private final ColorFilter accentColorFilter; + private final boolean mUserTheme; // The maximum key label width in the proportion to the key width. private static final float MAX_LABEL_RATIO = 0.90f; @@ -166,6 +176,22 @@ public class KeyboardView extends View { keyAttr.recycle(); mPaint.setAntiAlias(true); + + final SettingsValues settingsValues = Settings.getInstance().getCurrent(); + mUserTheme = settingsValues.mUserTheme; + if (mUserTheme) { + getBackground().setColorFilter(settingsValues.mBackgroundColorFilter); + + keyBgFilter = settingsValues.mKeyBackgroundColorFilter; + keyHintTextColorFilter = settingsValues.mHintTextColorFilter; + keyTextColorFilter = settingsValues.mKeyTextColorFilter; + accentColorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(settingsValues.mUserThemeColorAccent, BlendModeCompat.SRC_ATOP); + } else { + keyHintTextColorFilter = null; + keyTextColorFilter = null; + keyBgFilter = null; + accentColorFilter = null; + } } @Nullable @@ -370,6 +396,27 @@ public class KeyboardView extends View { bgX = -padding.left; bgY = -padding.top; } +/* if (mUserTheme) { + // color filter is applied to background, which is re-used + // but we don't want it applied to "blue" keys + // so we always need to select the color filter dependent on the current key + if (key.isActionKey() + || (key.getBackgroundType() == Key.BACKGROUND_TYPE_NORMAL && key.getCode() < 0 && key.getCode() != Constants.CODE_SWITCH_ALPHA_SYMBOL)) + background.clearColorFilter(); + else + background.setColorFilter(keyBgFilter); + }*/ + if (mUserTheme) { + // color filter is applied to background, which is re-used + // but we don't want it applied to "blue" keys + // so we always need to select the color filter dependent on the current key + if (key.isActionKey()) + background.setColorFilter(accentColorFilter); + else if (key.getBackgroundType() == Key.BACKGROUND_TYPE_NORMAL && key.getCode() < 0 && key.getCode() != Constants.CODE_SWITCH_ALPHA_SYMBOL) + background.clearColorFilter(); + else + background.setColorFilter(keyBgFilter); + } background.setBounds(0, 0, bgWidth, bgHeight); canvas.translate(bgX, bgY); background.draw(canvas); @@ -422,6 +469,11 @@ public class KeyboardView extends View { if (key.isEnabled()) { paint.setColor(key.selectTextColor(params)); + if (mUserTheme) { + // set key color only if not in emoji keyboard range + if (keyboard != null && (keyboard.mId.mElementId < 10 || keyboard.mId.mElementId > 26)) + paint.setColorFilter(keyTextColorFilter); + } // Set a drop shadow for the text if the shadow radius is positive value. if (mKeyTextShadowRadius > 0.0f) { paint.setShadowLayer(mKeyTextShadowRadius, 0.0f, 0.0f, params.mTextShadowColor); @@ -445,6 +497,8 @@ public class KeyboardView extends View { if (hintLabel != null && mShowsHints) { paint.setTextSize(key.selectHintTextSize(params)); paint.setColor(key.selectHintTextColor(params)); + if (mUserTheme) + paint.setColorFilter(keyHintTextColorFilter); // TODO: Should add a way to specify type face for hint letters paint.setTypeface(Typeface.DEFAULT_BOLD); blendAlpha(paint, params.mAnimAlpha); @@ -497,6 +551,9 @@ public class KeyboardView extends View { iconY = (keyHeight - iconHeight) / 2; // Align vertically center. } final int iconX = (keyWidth - iconWidth) / 2; // Align horizontally center. + if (mUserTheme && key.getBackgroundType() != Key.BACKGROUND_TYPE_NORMAL && !key.isActionKey() && !key.isShift()) + // no color for shift (because of state indicator) and accent color keys (action and popup) + icon.setColorFilter(keyTextColorFilter); drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight); } diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/clipboard/ClipboardHistoryView.kt b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/clipboard/ClipboardHistoryView.kt index 5b46fe3b4..b29f4576e 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/clipboard/ClipboardHistoryView.kt +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/clipboard/ClipboardHistoryView.kt @@ -1,6 +1,7 @@ package org.dslul.openboard.inputmethod.keyboard.clipboard import android.content.Context +import android.graphics.Color import android.util.AttributeSet import android.util.TypedValue import android.view.MotionEvent @@ -9,6 +10,8 @@ import android.widget.FrameLayout import android.widget.ImageButton import android.widget.LinearLayout import android.widget.TextView +import androidx.core.graphics.BlendModeColorFilterCompat +import androidx.core.graphics.BlendModeCompat import androidx.recyclerview.widget.StaggeredGridLayoutManager import org.dslul.openboard.inputmethod.keyboard.KeyboardActionListener import org.dslul.openboard.inputmethod.keyboard.internal.KeyDrawParams @@ -17,6 +20,7 @@ import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardIconsSet import org.dslul.openboard.inputmethod.latin.ClipboardHistoryManager import org.dslul.openboard.inputmethod.latin.R import org.dslul.openboard.inputmethod.latin.common.Constants +import org.dslul.openboard.inputmethod.latin.settings.Settings import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils class ClipboardHistoryView @JvmOverloads constructor( @@ -89,16 +93,22 @@ class ClipboardHistoryView @JvmOverloads constructor( findViewById(R.id.clipboard_action_bar)?.apply { clipboardLayoutParams.setActionBarProperties(this) } + val cf = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.CYAN, BlendModeCompat.MODULATE) + val settingsValues = Settings.getInstance().current alphabetKey = findViewById(R.id.clipboard_keyboard_alphabet).apply { tag = Constants.CODE_ALPHA_FROM_CLIPBOARD setBackgroundResource(functionalKeyBackgroundId) setOnTouchListener(this@ClipboardHistoryView) setOnClickListener(this@ClipboardHistoryView) + background.colorFilter = settingsValues.mKeyBackgroundColorFilter + setTextColor(settingsValues.mKeyTextColor) } clearKey = findViewById(R.id.clipboard_clear).apply { setOnTouchListener(this@ClipboardHistoryView) setOnClickListener(this@ClipboardHistoryView) + colorFilter = settingsValues.mKeyTextColorFilter } + background.colorFilter = settingsValues.mBackgroundColorFilter } private fun setupAlphabetKey(key: TextView?, label: String, params: KeyDrawParams) { diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiPalettesView.java b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiPalettesView.java index 4d904d3a9..37b1a6e89 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiPalettesView.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiPalettesView.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Color; +import android.graphics.ColorFilter; import android.util.AttributeSet; import android.util.TypedValue; import android.view.LayoutInflater; @@ -34,6 +35,8 @@ import android.widget.TabWidget; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.core.graphics.BlendModeColorFilterCompat; +import androidx.core.graphics.BlendModeCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import org.dslul.openboard.inputmethod.compat.TabHostCompat; @@ -262,6 +265,11 @@ public final class EmojiPalettesView extends LinearLayout mSpacebar.setTag(Constants.CODE_SPACE); mSpacebar.setOnTouchListener(this); mSpacebar.setOnClickListener(this); + final ColorFilter cf = Settings.getInstance().getCurrent().mKeyBackgroundColorFilter; + mAlphabetKeyLeft.getBackground().setColorFilter(cf); + mAlphabetKeyLeft.setTextColor(Settings.getInstance().getCurrent().mKeyTextColor); + mSpacebar.getBackground().setColorFilter(cf); + mDeleteKey.getBackground().setColorFilter(cf); mEmojiLayoutParams.setKeyProperties(mSpacebar); mSpacebarIcon = findViewById(R.id.emoji_keyboard_space_icon); } diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java index 8d459f972..787823255 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java @@ -28,6 +28,8 @@ import org.dslul.openboard.inputmethod.keyboard.PointerTracker; import org.dslul.openboard.inputmethod.latin.R; import org.dslul.openboard.inputmethod.latin.SuggestedWords; import org.dslul.openboard.inputmethod.latin.common.CoordinateUtils; +import org.dslul.openboard.inputmethod.latin.settings.Settings; +import org.dslul.openboard.inputmethod.latin.settings.SettingsValues; import javax.annotation.Nonnull; @@ -60,13 +62,14 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview { private static final char[] TEXT_HEIGHT_REFERENCE_CHAR = { 'M' }; public GesturePreviewTextParams(final TypedArray mainKeyboardViewAttr) { + final SettingsValues sv = Settings.getInstance().getCurrent(); mGesturePreviewTextSize = mainKeyboardViewAttr.getDimensionPixelSize( R.styleable.MainKeyboardView_gestureFloatingPreviewTextSize, 0); - mGesturePreviewTextColor = mainKeyboardViewAttr.getColor( + mGesturePreviewTextColor = sv.mUserTheme ? sv.mKeyTextColor : mainKeyboardViewAttr.getColor( R.styleable.MainKeyboardView_gestureFloatingPreviewTextColor, 0); mGesturePreviewTextOffset = mainKeyboardViewAttr.getDimensionPixelOffset( R.styleable.MainKeyboardView_gestureFloatingPreviewTextOffset, 0); - mGesturePreviewColor = mainKeyboardViewAttr.getColor( + mGesturePreviewColor = sv.mUserTheme ? sv.mBackgroundColor : mainKeyboardViewAttr.getColor( R.styleable.MainKeyboardView_gestureFloatingPreviewColor, 0); mGesturePreviewHorizontalPadding = mainKeyboardViewAttr.getDimension( R.styleable.MainKeyboardView_gestureFloatingPreviewHorizontalPadding, 0.0f); diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/GestureTrailDrawingParams.java b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/GestureTrailDrawingParams.java index 16d498a7e..b6a0fb671 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/GestureTrailDrawingParams.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/GestureTrailDrawingParams.java @@ -19,6 +19,8 @@ package org.dslul.openboard.inputmethod.keyboard.internal; import android.content.res.TypedArray; import org.dslul.openboard.inputmethod.latin.R; +import org.dslul.openboard.inputmethod.latin.settings.Settings; +import org.dslul.openboard.inputmethod.latin.settings.SettingsValues; /** * This class holds parameters to control how a gesture trail is drawn and animated on the screen. @@ -50,7 +52,8 @@ final class GestureTrailDrawingParams { public final int mTrailLingerDuration; public GestureTrailDrawingParams(final TypedArray mainKeyboardViewAttr) { - mTrailColor = mainKeyboardViewAttr.getColor( + final SettingsValues sv = Settings.getInstance().getCurrent(); + mTrailColor = sv.mUserTheme ? sv.mUserThemeColorAccent : mainKeyboardViewAttr.getColor( R.styleable.MainKeyboardView_gestureTrailColor, 0); mTrailStartWidth = mainKeyboardViewAttr.getDimension( R.styleable.MainKeyboardView_gestureTrailStartWidth, 0.0f); diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/KeyPreviewChoreographer.java b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/KeyPreviewChoreographer.java index c0061562b..acf576024 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/KeyPreviewChoreographer.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/KeyPreviewChoreographer.java @@ -20,8 +20,13 @@ import android.content.Context; import android.view.View; import android.view.ViewGroup; +import androidx.core.graphics.BlendModeColorFilterCompat; +import androidx.core.graphics.BlendModeCompat; + import org.dslul.openboard.inputmethod.keyboard.Key; import org.dslul.openboard.inputmethod.latin.common.CoordinateUtils; +import org.dslul.openboard.inputmethod.latin.settings.Settings; +import org.dslul.openboard.inputmethod.latin.settings.SettingsValues; import org.dslul.openboard.inputmethod.latin.utils.ViewLayoutUtils; import java.util.ArrayDeque; @@ -117,6 +122,11 @@ public final class KeyPreviewChoreographer { } final boolean hasMoreKeys = (key.getMoreKeys() != null); keyPreviewView.setPreviewBackground(hasMoreKeys, keyPreviewPosition); + final SettingsValues settingsValues = Settings.getInstance().getCurrent(); + if (settingsValues.mUserTheme) { + keyPreviewView.getBackground().setColorFilter(settingsValues.mBackgroundColorFilter); + keyPreviewView.setTextColor(settingsValues.mKeyTextColor); + } // The key preview is placed vertically above the top edge of the parent key with an // arbitrary offset. final int previewY = key.getY() - previewHeight + key.getHeight() - mParams.mPreviewOffset diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/AppearanceSettingsFragment.kt b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/AppearanceSettingsFragment.kt index b6fe7c732..01fcb680e 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/AppearanceSettingsFragment.kt +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/AppearanceSettingsFragment.kt @@ -15,6 +15,7 @@ */ package org.dslul.openboard.inputmethod.latin.settings +import android.app.AlertDialog import android.os.Build import android.os.Bundle import android.preference.ListPreference @@ -38,6 +39,7 @@ class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceC private lateinit var keyBordersPref: TwoStatePreference private lateinit var amoledModePref: TwoStatePreference private var dayNightPref: TwoStatePreference? = null + private lateinit var userColorsPref: Preference override fun onCreate(icicle: Bundle?) { @@ -112,12 +114,16 @@ class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceC amoledModePref.apply { isEnabled = !isLegacyFamily && variant != KeyboardTheme.THEME_VARIANT_LIGHT && !KeyboardTheme.getHasKeyBorders(selectedThemeId) + && !KeyboardTheme.getIsUser(selectedThemeId) isChecked = !isLegacyFamily && KeyboardTheme.getIsAmoledMode(selectedThemeId) } dayNightPref?.apply { isEnabled = !isLegacyFamily isChecked = !isLegacyFamily && KeyboardTheme.getIsDayNight(selectedThemeId) } + userColorsPref.apply { + isEnabled = KeyboardTheme.getIsUser(selectedThemeId) + } } private fun setupTheme() { @@ -159,6 +165,29 @@ class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceC updateThemePreferencesState(skipThemeFamily = true) true } + userColorsPref = preferenceScreen.findPreference(Settings.PREF_THEME_USER) + userColorsPref.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ -> + val items = listOf(R.string.select_color_background, R.string.select_color_key, R.string.select_color_key_hint, R.string.select_color_accent, R.string.select_color_key_background) + .map { activity.getString(it) } + val itemsArray = if (keyBordersPref.isChecked) items.toTypedArray() + else items.subList(0, 4).toTypedArray() + AlertDialog.Builder(activity) + .setPositiveButton(android.R.string.ok, null) + .setTitle(R.string.select_color_to_adjust) + .setItems(itemsArray) { _, i -> + val pref = when (i) { + 0 -> Settings.PREF_THEME_USER_COLOR_BACKGROUND + 1 -> Settings.PREF_THEME_USER_COLOR_TEXT + 2 -> Settings.PREF_THEME_USER_COLOR_HINT_TEXT + 3 -> Settings.PREF_THEME_USER_COLOR_ACCENT + else -> Settings.PREF_THEME_USER_COLOR_KEYS + } + val d = ColorPickerDialog(activity, sharedPreferences, pref) + d.show() + } + .show() + true + } } private fun setupKeyboardHeight(prefKey: String, defaultValue: Float) { diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/ColorPickerDialog.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/ColorPickerDialog.java new file mode 100644 index 000000000..ddfde2223 --- /dev/null +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/ColorPickerDialog.java @@ -0,0 +1,123 @@ +/* + * 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. + */ + +// adapted from https://github.com/rkkr/simple-keyboard/blob/master/app/src/main/java/rkr/simplekeyboard/inputmethod/latin/settings/ColorDialogPreference.java +package org.dslul.openboard.inputmethod.latin.settings; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.view.View; +import android.widget.SeekBar; +import android.widget.TextView; + +import org.dslul.openboard.inputmethod.latin.R; + +public class ColorPickerDialog extends AlertDialog implements SeekBar.OnSeekBarChangeListener { + protected ColorPickerDialog(Context context, SharedPreferences prefs, String colorPref) { + super(context); + setTitle("bla"); + View view = getLayoutInflater().inflate(R.layout.color_dialog, null); + mSeekBarRed = (SeekBar)view.findViewById(R.id.seek_bar_dialog_bar_red); + mSeekBarRed.setMax(255); + mSeekBarRed.setOnSeekBarChangeListener(this); + mSeekBarRed.getProgressDrawable().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN); + mSeekBarRed.getThumb().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN); + mSeekBarGreen = (SeekBar)view.findViewById(R.id.seek_bar_dialog_bar_green); + mSeekBarGreen.setMax(255); + mSeekBarGreen.setOnSeekBarChangeListener(this); + mSeekBarGreen.getThumb().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN); + mSeekBarGreen.getProgressDrawable().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN); + mSeekBarBlue = (SeekBar)view.findViewById(R.id.seek_bar_dialog_bar_blue); + mSeekBarBlue.setMax(255); + mSeekBarBlue.setOnSeekBarChangeListener(this); + mSeekBarBlue.getThumb().setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN); + mSeekBarBlue.getProgressDrawable().setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN); + mValueView = (TextView)view.findViewById(R.id.seek_bar_dialog_value); + setView(view); + + // init with correct values + // using onShowListener? + setOnShowListener(new OnShowListener() { + @Override + public void onShow(DialogInterface dialogInterface) { + int color = prefs.getInt(colorPref, 0); + mSeekBarRed.setProgress(Color.red(color)); + mSeekBarGreen.setProgress(Color.green(color)); + mSeekBarBlue.setProgress(Color.blue(color)); + setHeaderText(color); + } + }); + + // set on ok and on cancel listeners + setButton(BUTTON_NEGATIVE, context.getText(android.R.string.cancel), new OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dismiss(); + } + }); + setButton(BUTTON_POSITIVE, context.getText(android.R.string.ok), new OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + final int value = Color.rgb( + mSeekBarRed.getProgress(), + mSeekBarGreen.getProgress(), + mSeekBarBlue.getProgress()); + prefs.edit().putInt(colorPref, value).apply(); + dismiss(); + } + }); + } + + private TextView mValueView; + private SeekBar mSeekBarRed; + private SeekBar mSeekBarGreen; + private SeekBar mSeekBarBlue; + + @Override + public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) { + int color = Color.rgb( + mSeekBarRed.getProgress(), + mSeekBarGreen.getProgress(), + mSeekBarBlue.getProgress()); + setHeaderText(color); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + + private void setHeaderText(int color) { + mValueView.setText(getValueText(color)); + boolean bright = Color.red(color) + Color.green(color) + Color.blue(color) > 128 * 3; + mValueView.setTextColor(bright ? Color.BLACK : Color.WHITE); + mValueView.setBackgroundColor(color); + } + + private String getValueText(final int value) { + String temp = Integer.toHexString(value); + for (; temp.length() < 8; temp = "0" + temp); + return temp.substring(2).toUpperCase(); + } + +} diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java index 917fac182..ae69eeb1b 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java @@ -63,6 +63,12 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_THEME_KEY_BORDERS = "theme_key_borders"; public static final String PREF_THEME_DAY_NIGHT = "theme_auto_day_night"; public static final String PREF_THEME_AMOLED_MODE = "theme_amoled_mode"; + public static final String PREF_THEME_USER = "theme_select_colors"; + public static final String PREF_THEME_USER_COLOR_TEXT = "theme_color_text"; + public static final String PREF_THEME_USER_COLOR_HINT_TEXT = "theme_color_hint_text"; + public static final String PREF_THEME_USER_COLOR_BACKGROUND = "theme_color_background"; + public static final String PREF_THEME_USER_COLOR_KEYS = "theme_color_keys"; + public static final String PREF_THEME_USER_COLOR_ACCENT = "theme_color_accent"; // PREF_VOICE_MODE_OBSOLETE is obsolete. Use PREF_VOICE_INPUT_KEY instead. public static final String PREF_VOICE_MODE_OBSOLETE = "voice_mode"; public static final String PREF_VOICE_INPUT_KEY = "pref_voice_input_key"; diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java index a07aefba0..e54113e5a 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java @@ -21,10 +21,16 @@ import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.res.Configuration; import android.content.res.Resources; +import android.graphics.Color; +import android.graphics.ColorFilter; import android.util.Log; import android.view.inputmethod.EditorInfo; +import androidx.core.graphics.BlendModeColorFilterCompat; +import androidx.core.graphics.BlendModeCompat; + import org.dslul.openboard.inputmethod.compat.AppWorkaroundsUtils; +import org.dslul.openboard.inputmethod.keyboard.KeyboardTheme; import org.dslul.openboard.inputmethod.latin.InputAttributes; import org.dslul.openboard.inputmethod.latin.R; import org.dslul.openboard.inputmethod.latin.RichInputMethodManager; @@ -118,6 +124,16 @@ public class SettingsValues { public final boolean mIncognitoModeEnabled; private final AsyncResultHolder mAppWorkarounds; + // User-defined colors + public boolean mUserTheme; + public final ColorFilter mKeyBackgroundColorFilter; + public final int mBackgroundColor; + public final ColorFilter mBackgroundColorFilter; + public final ColorFilter mKeyTextColorFilter; + public final ColorFilter mHintTextColorFilter; + public final int mUserThemeColorAccent; + public final int mKeyTextColor; + // Debug settings public final boolean mIsInternal; public final boolean mHasCustomKeyPreviewAnimationParams; @@ -243,6 +259,25 @@ public class SettingsValues { mOneHandedModeEnabled = Settings.readOneHandedModeEnabled(prefs); mOneHandedModeGravity = Settings.readOneHandedModeGravity(prefs); mSecondaryLocale = Settings.getSecondaryLocale(prefs, RichInputMethodManager.getInstance().getCurrentSubtypeLocale().toString()); + mUserTheme = KeyboardTheme.getIsUser(KeyboardTheme.getThemeForParameters( + prefs.getString(Settings.PREF_THEME_FAMILY, ""), + prefs.getString(Settings.PREF_THEME_VARIANT, ""), + prefs.getBoolean(Settings.PREF_THEME_KEY_BORDERS, false), + prefs.getBoolean(Settings.PREF_THEME_DAY_NIGHT, false), + prefs.getBoolean(Settings.PREF_THEME_AMOLED_MODE, false) + )); + mUserThemeColorAccent = prefs.getInt(Settings.PREF_THEME_USER_COLOR_ACCENT, Color.BLUE); + final int keyBgColor; + if (prefs.getBoolean(Settings.PREF_THEME_KEY_BORDERS, false)) + keyBgColor = prefs.getInt(Settings.PREF_THEME_USER_COLOR_KEYS, Color.LTGRAY); + else + keyBgColor = prefs.getInt(Settings.PREF_THEME_USER_COLOR_BACKGROUND, Color.DKGRAY); + mKeyBackgroundColorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(keyBgColor, BlendModeCompat.MODULATE); + mHintTextColorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(prefs.getInt(Settings.PREF_THEME_USER_COLOR_HINT_TEXT, Color.WHITE), BlendModeCompat.SRC_ATOP); + mKeyTextColor = prefs.getInt(Settings.PREF_THEME_USER_COLOR_TEXT, Color.WHITE); + mKeyTextColorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(mKeyTextColor, BlendModeCompat.SRC_ATOP); + mBackgroundColor = prefs.getInt(Settings.PREF_THEME_USER_COLOR_BACKGROUND, Color.DKGRAY); + mBackgroundColorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(mBackgroundColor, BlendModeCompat.MODULATE); } public boolean isMetricsLoggingEnabled() { diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java index 402b70a98..81bb1ecd9 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java @@ -508,7 +508,11 @@ final class SuggestionStripLayoutHelper { // {@link SuggestionStripView#onClick(View)}. wordView.setTag(indexInSuggestedWords); wordView.setText(getStyledSuggestedWord(suggestedWords, indexInSuggestedWords)); - wordView.setTextColor(getSuggestionTextColor(suggestedWords, indexInSuggestedWords)); + final SettingsValues settingsValues = Settings.getInstance().getCurrent(); + if (settingsValues.mUserTheme) + wordView.setTextColor(settingsValues.mKeyTextColor); + else + wordView.setTextColor(getSuggestionTextColor(suggestedWords, indexInSuggestedWords)); if (SuggestionStripView.DBG) { mDebugInfoViews.get(positionInStrip).setText( suggestedWords.getDebugString(indexInSuggestedWords)); diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripView.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripView.java index baf690d75..641d57c67 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripView.java @@ -40,7 +40,6 @@ import android.widget.TextView; import org.dslul.openboard.inputmethod.accessibility.AccessibilityUtils; import org.dslul.openboard.inputmethod.keyboard.Keyboard; -import org.dslul.openboard.inputmethod.keyboard.KeyboardSwitcher; import org.dslul.openboard.inputmethod.keyboard.MainKeyboardView; import org.dslul.openboard.inputmethod.keyboard.MoreKeysPanel; import org.dslul.openboard.inputmethod.latin.AudioAndHapticFeedbackManager; @@ -177,6 +176,10 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mClipboardKey.setOnLongClickListener(this); mOtherKey.setImageDrawable(iconIncognito); + + final SettingsValues settingsValues = Settings.getInstance().getCurrent(); + if (settingsValues.mUserTheme) + mStripVisibilityGroup.mSuggestionStripView.getBackground().setColorFilter(settingsValues.mBackgroundColorFilter); } /** diff --git a/app/src/main/res/layout/color_dialog.xml b/app/src/main/res/layout/color_dialog.xml new file mode 100644 index 000000000..95e458dc4 --- /dev/null +++ b/app/src/main/res/layout/color_dialog.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 1cb096ef0..14cbd1601 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -245,6 +245,9 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3e3a3d771..0b19a7a9e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -638,4 +638,20 @@ disposition rather than other common dispositions for Latin languages. [CHAR LIM Deep black backgrounds Can reduce power usage depending on the device’s screen technology + + Adjust theme colors + + Select colors for text and background + + Select colors to adjust + + Keyboard background + + Key text + + Key hint text + + Key background + + Accent \ No newline at end of file diff --git a/app/src/main/res/xml/prefs_screen_appearance.xml b/app/src/main/res/xml/prefs_screen_appearance.xml index 4ba30a581..15d51c89c 100644 --- a/app/src/main/res/xml/prefs_screen_appearance.xml +++ b/app/src/main/res/xml/prefs_screen_appearance.xml @@ -45,6 +45,11 @@ android:title="@string/amoled_mode" android:summary="@string/amoled_mode_summary"/> + +