Implemented new theme settings

This commit is contained in:
pdroidandroid@gmail.com 2022-01-29 15:58:04 +01:00
parent 599f9cfdf5
commit 551beb69a3
7 changed files with 328 additions and 233 deletions

View file

@ -27,8 +27,28 @@ import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public final class KeyboardTheme implements Comparable<KeyboardTheme> {
public static final String THEME_FAMILY_MATERIAL = "Material";
public static final String THEME_FAMILY_HOLO = "Holo (Legacy)";
public static final String THEME_VARIANT_LIGHT = "Light";
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_FAMILIES = {THEME_FAMILY_MATERIAL, THEME_FAMILY_HOLO};
public static final Map<String, String[]> THEME_VARIANTS = new HashMap<>();
static {
THEME_VARIANTS.put(THEME_FAMILY_MATERIAL,
new String[] {THEME_VARIANT_LIGHT, THEME_VARIANT_DARK});
THEME_VARIANTS.put(THEME_FAMILY_HOLO,
new String[] {THEME_VARIANT_WHITE, THEME_VARIANT_BLUE});
}
private static final String TAG = KeyboardTheme.class.getSimpleName();
static final String KLP_KEYBOARD_THEME_KEY = "pref_keyboard_layout_20110916";
@ -41,12 +61,12 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
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;
public static final int THEME_ID_LIGHT_BORDER = 5;
public static final int THEME_ID_DARK_BORDER = 6;
public static final int THEME_ID_LXX_LIGHT_BORDER = 5;
public static final int THEME_ID_LXX_DARK_BORDER = 6;
public static final int THEME_ID_LXX_DARK = 7;
public static final int THEME_ID_LXX_AUTO = 9;
public static final int THEME_ID_AUTO_BORDER = 8;
public static final int DEFAULT_THEME_ID = THEME_ID_DARK_BORDER;
public static final int THEME_ID_LXX_AUTO_BORDER = 8;
public static final int DEFAULT_THEME_ID = THEME_ID_LXX_DARK_BORDER;
private static KeyboardTheme[] AVAILABLE_KEYBOARD_THEMES;
@ -67,13 +87,13 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
new KeyboardTheme(THEME_ID_LXX_DARK_AMOLED, "LXXDarkAmoled", R.style.KeyboardTheme_LXX_Dark_Amoled,
// This has never been selected as default theme.
VERSION_CODES.BASE),
new KeyboardTheme(THEME_ID_LIGHT_BORDER, "LXXLightBorder", R.style.KeyboardTheme_LXX_Light_Border,
new KeyboardTheme(THEME_ID_LXX_LIGHT_BORDER, "LXXLightBorder", R.style.KeyboardTheme_LXX_Light_Border,
// This has never been selected as default theme.
Build.VERSION_CODES.BASE),
new KeyboardTheme(THEME_ID_DARK_BORDER, "LXXDarkBorder", R.style.KeyboardTheme_LXX_Dark_Border,
new KeyboardTheme(THEME_ID_LXX_DARK_BORDER, "LXXDarkBorder", R.style.KeyboardTheme_LXX_Dark_Border,
// This has never been selected as default theme.
VERSION_CODES.LOLLIPOP),
new KeyboardTheme(THEME_ID_AUTO_BORDER, "LXXAutoBorder", R.style.KeyboardTheme_LXX_Auto_Border,
new KeyboardTheme(THEME_ID_LXX_AUTO_BORDER, "LXXAutoBorder", R.style.KeyboardTheme_LXX_Auto_Border,
// This has never been selected as default theme.
VERSION_CODES.LOLLIPOP),
new KeyboardTheme(THEME_ID_LXX_AUTO, "LXXAuto", R.style.KeyboardTheme_LXX_Auto,
@ -235,4 +255,81 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
prefs.edit().remove(LXX_KEYBOARD_THEME_KEY).apply();
return getDefaultKeyboardTheme(prefs, sdkVersion, availableThemeArray);
}
public static String getThemeFamily(int themeId) {
if (themeId == THEME_ID_ICS || themeId == THEME_ID_KLP) return THEME_FAMILY_HOLO;
return THEME_FAMILY_MATERIAL;
}
public static String getThemeVariant(int themeId) {
switch (themeId) {
case THEME_ID_LXX_DARK:
case THEME_ID_LXX_DARK_AMOLED:
case THEME_ID_LXX_DARK_BORDER:
return THEME_VARIANT_DARK;
case THEME_ID_LXX_LIGHT:
case THEME_ID_LXX_LIGHT_BORDER:
return THEME_VARIANT_LIGHT;
case THEME_ID_KLP:
return THEME_VARIANT_WHITE;
case THEME_ID_ICS:
return THEME_VARIANT_BLUE;
default:
return null;
}
}
public static boolean getHasKeyBorders(int themeId) {
switch (themeId) {
case THEME_ID_LXX_DARK_BORDER:
case THEME_ID_LXX_LIGHT_BORDER:
case THEME_ID_LXX_AUTO_BORDER:
case THEME_ID_ICS:
case THEME_ID_KLP:
return true;
default:
return false;
}
}
public static boolean getIsDayNight(int themeId) {
switch (themeId) {
case THEME_ID_LXX_AUTO:
case THEME_ID_LXX_AUTO_AMOLED:
case THEME_ID_LXX_AUTO_BORDER:
return true;
default:
return false;
}
}
public static boolean getIsAmoledMode(int themeId) {
switch (themeId) {
case THEME_ID_LXX_DARK_AMOLED:
case THEME_ID_LXX_AUTO_AMOLED:
return true;
default:
return false;
}
}
public static int getThemeForParameters(String family, String variant,
boolean keyBorders, boolean dayNight, boolean amoledMode) {
if (THEME_FAMILY_HOLO.equals(family)) {
if (THEME_VARIANT_BLUE.equals(variant)) return THEME_ID_ICS;
return THEME_ID_KLP;
}
if (dayNight) {
if (keyBorders) return THEME_ID_LXX_AUTO_BORDER;
if (amoledMode) return THEME_ID_LXX_AUTO_AMOLED;
return THEME_ID_LXX_AUTO;
}
if (THEME_VARIANT_DARK.equals(variant)) {
if (keyBorders) return THEME_ID_LXX_DARK_BORDER;
if (amoledMode) return THEME_ID_LXX_DARK_AMOLED;
return THEME_ID_LXX_DARK;
}
if (keyBorders) return THEME_ID_LXX_LIGHT_BORDER;
return THEME_ID_LXX_LIGHT;
}
}

View file

@ -13,85 +13,180 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dslul.openboard.inputmethod.latin.settings
package org.dslul.openboard.inputmethod.latin.settings;
import android.content.SharedPreferences;
import android.os.Bundle;
import org.dslul.openboard.inputmethod.latin.R;
import org.dslul.openboard.inputmethod.latin.common.Constants;
import org.dslul.openboard.inputmethod.latin.define.ProductionFlags;
import java.util.Locale;
import android.os.Build
import android.os.Bundle
import android.preference.ListPreference
import android.preference.Preference
import android.preference.TwoStatePreference
import org.dslul.openboard.inputmethod.keyboard.KeyboardTheme
import org.dslul.openboard.inputmethod.latin.R
import org.dslul.openboard.inputmethod.latin.common.Constants
import org.dslul.openboard.inputmethod.latin.define.ProductionFlags
import java.util.*
/**
* "Appearance" settings sub screen.
*/
public final class AppearanceSettingsFragment extends SubScreenFragment {
@Override
public void onCreate(final Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.prefs_screen_appearance);
class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceChangeListener {
private var selectedThemeId = 0
private lateinit var themeFamilyPref: ListPreference
private lateinit var themeVariantPref: ListPreference
private lateinit var keyBordersPref: TwoStatePreference
private lateinit var amoledModePref: TwoStatePreference
private var dayNightPref: TwoStatePreference? = null
override fun onCreate(icicle: Bundle?) {
super.onCreate(icicle)
addPreferencesFromResource(R.xml.prefs_screen_appearance)
val keyboardTheme = KeyboardTheme.getKeyboardTheme(activity)
selectedThemeId = keyboardTheme.mThemeId
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
removePreference(Settings.PREF_THEME_DAY_NIGHT)
}
setupTheme()
if (!ProductionFlags.IS_SPLIT_KEYBOARD_SUPPORTED ||
Constants.isPhone(Settings.readScreenMetrics(getResources()))) {
removePreference(Settings.PREF_ENABLE_SPLIT_KEYBOARD);
Constants.isPhone(Settings.readScreenMetrics(resources))) {
removePreference(Settings.PREF_ENABLE_SPLIT_KEYBOARD)
}
setupKeyboardHeight(
Settings.PREF_KEYBOARD_HEIGHT_SCALE, SettingsValues.DEFAULT_SIZE_SCALE);
Settings.PREF_KEYBOARD_HEIGHT_SCALE, SettingsValues.DEFAULT_SIZE_SCALE)
}
@Override
public void onResume() {
super.onResume();
override fun onResume() {
super.onResume()
updateThemePreferencesState()
CustomInputStyleSettingsFragment.updateCustomInputStylesSummary(
findPreference(Settings.PREF_CUSTOM_INPUT_STYLES));
ThemeSettingsFragment.updateKeyboardThemeSummary(findPreference(Settings.SCREEN_THEME));
findPreference(Settings.PREF_CUSTOM_INPUT_STYLES))
}
private void setupKeyboardHeight(final String prefKey, final float defaultValue) {
final SharedPreferences prefs = getSharedPreferences();
final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(prefKey);
if (pref == null) {
return;
override fun onPreferenceChange(preference: Preference, value: Any?): Boolean {
(preference as? ListPreference)?.apply {
summary = entries[entryValues.indexOfFirst { it == value }]
}
pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
private static final float PERCENTAGE_FLOAT = 100.0f;
private float getValueFromPercentage(final int percentage) {
return percentage / PERCENTAGE_FLOAT;
}
private int getPercentageFromValue(final float floatValue) {
return (int)(floatValue * PERCENTAGE_FLOAT);
}
@Override
public void writeValue(final int value, final String key) {
prefs.edit().putFloat(key, getValueFromPercentage(value)).apply();
}
@Override
public void writeDefaultValue(final String key) {
prefs.edit().remove(key).apply();
}
@Override
public int readValue(final String key) {
return getPercentageFromValue(Settings.readKeyboardHeight(prefs, defaultValue));
}
@Override
public int readDefaultValue(final String key) {
return getPercentageFromValue(defaultValue);
}
@Override
public String getValueText(final int value) {
return String.format(Locale.ROOT, "%d%%", value);
}
@Override
public void feedbackValue(final int value) {}
});
saveSelectedThemeId()
return true
}
}
private fun saveSelectedThemeId(
family: String = themeFamilyPref.value,
variant: String = themeVariantPref.value,
keyBorders: Boolean = keyBordersPref.isChecked,
dayNight: Boolean = dayNightPref?.isChecked ?: false,
amoledMode: Boolean = amoledModePref.isChecked
) {
selectedThemeId = KeyboardTheme.getThemeForParameters(family, variant, keyBorders, dayNight, amoledMode)
KeyboardTheme.saveKeyboardThemeId(selectedThemeId, sharedPreferences)
}
private fun updateThemePreferencesState(skipThemeFamily: Boolean = false, skipThemeVariant: Boolean = false) {
val themeFamily = KeyboardTheme.getThemeFamily(selectedThemeId)
val isLegacyFamily = KeyboardTheme.THEME_FAMILY_HOLO == themeFamily
if (!skipThemeFamily) {
themeFamilyPref.apply {
value = themeFamily
summary = themeFamily
}
}
val variants = KeyboardTheme.THEME_VARIANTS[themeFamily]!!
val variant = KeyboardTheme.getThemeVariant(selectedThemeId)
if (!skipThemeVariant) {
themeVariantPref.apply {
entries = variants
entryValues = variants
value = variant ?: variants[0]
summary = variant ?: "Auto"
isEnabled = isLegacyFamily || !KeyboardTheme.getIsDayNight(selectedThemeId)
}
}
keyBordersPref.apply {
isEnabled = !isLegacyFamily && !KeyboardTheme.getIsAmoledMode(selectedThemeId)
isChecked = isLegacyFamily || KeyboardTheme.getHasKeyBorders(selectedThemeId)
}
amoledModePref.apply {
isEnabled = !isLegacyFamily && variant != KeyboardTheme.THEME_VARIANT_LIGHT
&& !KeyboardTheme.getHasKeyBorders(selectedThemeId)
isChecked = !isLegacyFamily && KeyboardTheme.getIsAmoledMode(selectedThemeId)
}
dayNightPref?.apply {
isEnabled = !isLegacyFamily
isChecked = !isLegacyFamily && KeyboardTheme.getIsDayNight(selectedThemeId)
}
}
private fun setupTheme() {
themeFamilyPref = preferenceScreen.findPreference(Settings.PREF_THEME_FAMILY) as ListPreference
themeFamilyPref.apply {
entries = KeyboardTheme.THEME_FAMILIES
entryValues = KeyboardTheme.THEME_FAMILIES
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, value ->
summary = entries[entryValues.indexOfFirst { it == value }]
saveSelectedThemeId(family = value as String)
updateThemePreferencesState(skipThemeFamily = true)
true
}
}
themeVariantPref = preferenceScreen.findPreference(Settings.PREF_THEME_VARIANT) as ListPreference
themeVariantPref.apply {
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, value ->
summary = entries[entryValues.indexOfFirst { it == value }]
saveSelectedThemeId(variant = value as String)
updateThemePreferencesState(skipThemeFamily = true, skipThemeVariant = true)
true
}
}
keyBordersPref = preferenceScreen.findPreference(Settings.PREF_THEME_KEY_BORDERS) as TwoStatePreference
keyBordersPref.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, value ->
saveSelectedThemeId(keyBorders = value as Boolean)
updateThemePreferencesState(skipThemeFamily = true)
true
}
amoledModePref = preferenceScreen.findPreference(Settings.PREF_THEME_AMOLED_MODE) as TwoStatePreference
amoledModePref.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, value ->
saveSelectedThemeId(amoledMode = value as Boolean)
updateThemePreferencesState(skipThemeFamily = true)
true
}
dayNightPref = preferenceScreen.findPreference(Settings.PREF_THEME_DAY_NIGHT) as? TwoStatePreference
dayNightPref?.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, value ->
saveSelectedThemeId(dayNight = value as Boolean)
updateThemePreferencesState(skipThemeFamily = true)
true
}
}
private fun setupKeyboardHeight(prefKey: String, defaultValue: Float) {
val prefs = sharedPreferences
val pref = findPreference(prefKey) as? SeekBarDialogPreference
pref?.setInterface(object : SeekBarDialogPreference.ValueProxy {
private fun getValueFromPercentage(percentage: Int) = percentage / PERCENTAGE_FLOAT
private fun getPercentageFromValue(floatValue: Float) = (floatValue * PERCENTAGE_FLOAT).toInt()
override fun writeValue(value: Int, key: String) = prefs.edit()
.putFloat(key, getValueFromPercentage(value)).apply()
override fun writeDefaultValue(key: String) = prefs.edit().remove(key).apply()
override fun readValue(key: String) = getPercentageFromValue(
Settings.readKeyboardHeight(prefs, defaultValue))
override fun readDefaultValue(key: String) = getPercentageFromValue(defaultValue)
override fun getValueText(value: Int) = String.format(Locale.ROOT, "%d%%", value)
override fun feedbackValue(value: Int) = Unit
})
}
companion object {
private const val PERCENTAGE_FLOAT = 100.0f
}
}

View file

@ -53,6 +53,11 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_VIBRATE_ON = "vibrate_on";
public static final String PREF_SOUND_ON = "sound_on";
public static final String PREF_POPUP_ON = "popup_on";
public static final String PREF_THEME_FAMILY = "theme_family";
public static final String PREF_THEME_VARIANT = "theme_variant";
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";
// 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";

View file

@ -1,112 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dslul.openboard.inputmethod.latin.settings;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import org.dslul.openboard.inputmethod.keyboard.KeyboardTheme;
import org.dslul.openboard.inputmethod.latin.R;
import org.dslul.openboard.inputmethod.latin.settings.RadioButtonPreference.OnRadioButtonClickedListener;
/**
* "Keyboard theme" settings sub screen.
*/
public final class ThemeSettingsFragment extends SubScreenFragment
implements OnRadioButtonClickedListener {
private int mSelectedThemeId;
static class KeyboardThemePreference extends RadioButtonPreference {
final int mThemeId;
KeyboardThemePreference(final Context context, final String name, final int id) {
super(context);
setTitle(name);
mThemeId = id;
}
}
static void updateKeyboardThemeSummary(final Preference pref) {
final Context context = pref.getContext();
final Resources res = context.getResources();
final KeyboardTheme keyboardTheme = KeyboardTheme.getKeyboardTheme(context);
final String[] keyboardThemeNames = res.getStringArray(R.array.keyboard_theme_names);
final int[] keyboardThemeIds = res.getIntArray(R.array.keyboard_theme_ids);
for (int index = 0; index < keyboardThemeNames.length; index++) {
if (keyboardTheme.mThemeId == keyboardThemeIds[index]) {
pref.setSummary(keyboardThemeNames[index]);
return;
}
}
}
@Override
public void onCreate(final Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.prefs_screen_theme);
final PreferenceScreen screen = getPreferenceScreen();
final Context context = getActivity();
final Resources res = getResources();
final String[] keyboardThemeNames = res.getStringArray(R.array.keyboard_theme_names);
final int[] keyboardThemeIds = res.getIntArray(R.array.keyboard_theme_ids);
for (int index = 0; index < keyboardThemeNames.length; index++) {
final KeyboardThemePreference pref = new KeyboardThemePreference(
context, keyboardThemeNames[index], keyboardThemeIds[index]);
screen.addPreference(pref);
pref.setOnRadioButtonClickedListener(this);
}
final KeyboardTheme keyboardTheme = KeyboardTheme.getKeyboardTheme(context);
mSelectedThemeId = keyboardTheme.mThemeId;
}
@Override
public void onRadioButtonClicked(final RadioButtonPreference preference) {
if (preference instanceof KeyboardThemePreference) {
final KeyboardThemePreference pref = (KeyboardThemePreference)preference;
mSelectedThemeId = pref.mThemeId;
updateSelected();
}
}
@Override
public void onResume() {
super.onResume();
updateSelected();
}
@Override
public void onPause() {
super.onPause();
KeyboardTheme.saveKeyboardThemeId(mSelectedThemeId, getSharedPreferences());
}
private void updateSelected() {
final PreferenceScreen screen = getPreferenceScreen();
final int count = screen.getPreferenceCount();
for (int index = 0; index < count; index++) {
final Preference preference = screen.getPreference(index);
if (preference instanceof KeyboardThemePreference) {
final KeyboardThemePreference pref = (KeyboardThemePreference)preference;
final boolean selected = (mSelectedThemeId == pref.mThemeId);
pref.setSelected(selected);
}
}
}
}

View file

@ -24,7 +24,6 @@ import org.dslul.openboard.inputmethod.latin.settings.DebugSettingsFragment;
import org.dslul.openboard.inputmethod.latin.settings.GestureSettingsFragment;
import org.dslul.openboard.inputmethod.latin.settings.PreferencesSettingsFragment;
import org.dslul.openboard.inputmethod.latin.settings.SettingsFragment;
import org.dslul.openboard.inputmethod.latin.settings.ThemeSettingsFragment;
import org.dslul.openboard.inputmethod.latin.spellcheck.SpellCheckerSettingsFragment;
import org.dslul.openboard.inputmethod.latin.userdictionary.UserDictionaryAddWordFragment;
import org.dslul.openboard.inputmethod.latin.userdictionary.UserDictionaryList;
@ -38,7 +37,6 @@ public class FragmentUtils {
static {
sLatinImeFragments.add(PreferencesSettingsFragment.class.getName());
sLatinImeFragments.add(AppearanceSettingsFragment.class.getName());
sLatinImeFragments.add(ThemeSettingsFragment.class.getName());
sLatinImeFragments.add(CustomInputStyleSettingsFragment.class.getName());
sLatinImeFragments.add(GestureSettingsFragment.class.getName());
sLatinImeFragments.add(CorrectionSettingsFragment.class.getName());