From 937ece0b342b4b5a1bcbb84e08c7941881f49d20 Mon Sep 17 00:00:00 2001 From: Aleksandras Kostarevas Date: Mon, 6 May 2024 16:16:04 -0500 Subject: [PATCH] Add options for keyboard height and bottom offset --- .../inputmethod/keyboard/KeyboardView.java | 11 +- .../keyboard/internal/KeyboardBuilder.java | 12 +- .../org/futo/inputmethod/latin/LatinIME.kt | 6 +- .../latin/uix/BasicThemeProvider.kt | 44 ++++++- .../latin/uix/DynamicThemeProvider.kt | 3 + .../futo/inputmethod/latin/uix/Settings.kt | 4 + .../latin/uix/settings/Components.kt | 122 +++++++++--------- .../latin/uix/settings/pages/DevSettings.kt | 2 +- .../latin/uix/theme/selector/ThemePicker.kt | 50 +++++-- 9 files changed, 160 insertions(+), 94 deletions(-) diff --git a/java/src/org/futo/inputmethod/keyboard/KeyboardView.java b/java/src/org/futo/inputmethod/keyboard/KeyboardView.java index 7169e200c..cc06bd396 100644 --- a/java/src/org/futo/inputmethod/keyboard/KeyboardView.java +++ b/java/src/org/futo/inputmethod/keyboard/KeyboardView.java @@ -213,8 +213,10 @@ public class KeyboardView extends View { public void setKeyboard(@Nonnull final Keyboard keyboard) { mKeyboard = keyboard; final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; - mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes); - mKeyDrawParams.updateParams(keyHeight, keyboard.mKeyVisualAttributes); + final int keyWidth = keyboard.mMostCommonKeyWidth; + + mKeyDrawParams.updateParams(Math.min(keyWidth, keyHeight), mKeyVisualAttributes); + mKeyDrawParams.updateParams(Math.min(keyWidth, keyHeight), keyboard.mKeyVisualAttributes); invalidateAllKeys(); requestLayout(); } @@ -239,7 +241,8 @@ public class KeyboardView extends View { } protected void updateKeyDrawParams(final int keyHeight) { - mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes); + final int keyWidth = mKeyboard.mMostCommonKeyWidth; + mKeyDrawParams.updateParams(Math.min(keyWidth, keyHeight), mKeyVisualAttributes); } @Override @@ -354,7 +357,7 @@ public class KeyboardView extends View { canvas.translate(keyDrawX, keyDrawY); final KeyVisualAttributes attr = key.getVisualAttributes(); - final KeyDrawParams params = mKeyDrawParams.mayCloneAndUpdateParams(key.getHeight(), attr); + final KeyDrawParams params = mKeyDrawParams.mayCloneAndUpdateParams(Math.min(key.getHeight(), key.getWidth()), attr); params.mAnimAlpha = Constants.Color.ALPHA_OPAQUE; if (!key.isSpacer()) { diff --git a/java/src/org/futo/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/org/futo/inputmethod/keyboard/internal/KeyboardBuilder.java index d8ab4a139..c9f56df78 100644 --- a/java/src/org/futo/inputmethod/keyboard/internal/KeyboardBuilder.java +++ b/java/src/org/futo/inputmethod/keyboard/internal/KeyboardBuilder.java @@ -255,14 +255,18 @@ public class KeyboardBuilder { final TypedArray keyAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard_Key); try { final KeyboardParams params = mParams; - final int height = params.mId.mHeight; + + final int offset = (int)mProvider.getKeyboardBottomOffset(); + final int height = (int) (params.mId.mHeight * mProvider.getKeyboardHeightMultiplier() + offset); final int width = params.mId.mWidth; params.mOccupiedHeight = height; params.mOccupiedWidth = width; params.mTopPadding = (int)keyboardAttr.getFraction( R.styleable.Keyboard_keyboardTopPadding, height, height, 0); - params.mBottomPadding = (int)keyboardAttr.getFraction( - R.styleable.Keyboard_keyboardBottomPadding, height, height, 0); + params.mBottomPadding = (int)(keyboardAttr.getFraction( + R.styleable.Keyboard_keyboardBottomPadding, height, height, 0) + + mProvider.getKeyboardBottomOffset() + ); params.mLeftPadding = (int)keyboardAttr.getFraction( R.styleable.Keyboard_keyboardLeftPadding, width, width, 0); params.mRightPadding = (int)keyboardAttr.getFraction( @@ -279,7 +283,7 @@ public class KeyboardBuilder { // rows are determined based on the entire keyboard height including top and bottom // paddings. params.mVerticalGap = (int)keyboardAttr.getFraction( - R.styleable.Keyboard_verticalGap, height, height, 0); + R.styleable.Keyboard_verticalGap, height - offset, height - offset, 0); final int baseHeight = params.mOccupiedHeight - params.mTopPadding - params.mBottomPadding + params.mVerticalGap; params.mBaseHeight = baseHeight; diff --git a/java/src/org/futo/inputmethod/latin/LatinIME.kt b/java/src/org/futo/inputmethod/latin/LatinIME.kt index b3166ca93..90f6877f3 100644 --- a/java/src/org/futo/inputmethod/latin/LatinIME.kt +++ b/java/src/org/futo/inputmethod/latin/LatinIME.kt @@ -257,11 +257,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save dataStore.data.collect { drawableProvider?.let { provider -> if(provider is BasicThemeProvider) { - if ((it[HiddenKeysSetting] ?: provider.expertMode) != provider.expertMode - || (it[KeyBordersSetting] ?: provider.keyBorders) != provider.keyBorders - || (it[KeyHintsSetting] ?: provider.showKeyHints) != provider.showKeyHints - ) { - Log.w("LatinIME", "One of HiddenKeysSetting, KeyBordersSetting or KeyHintsSetting has changed") + if (provider.hasUpdated(it)) { activeThemeOption?.obtainColors?.let { f -> updateDrawableProvider(f(this@LatinIME)) if (!uixManager.isMainKeyboardHidden) { diff --git a/java/src/org/futo/inputmethod/latin/uix/BasicThemeProvider.kt b/java/src/org/futo/inputmethod/latin/uix/BasicThemeProvider.kt index 5a2317d38..1e97026e1 100644 --- a/java/src/org/futo/inputmethod/latin/uix/BasicThemeProvider.kt +++ b/java/src/org/futo/inputmethod/latin/uix/BasicThemeProvider.kt @@ -18,15 +18,20 @@ import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.core.graphics.ColorUtils +import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.floatPreferencesKey import com.google.android.material.color.DynamicColors import org.futo.inputmethod.latin.R import org.futo.inputmethod.latin.uix.theme.DarkColorScheme import kotlin.math.roundToInt -val KeyBordersSetting = booleanPreferencesKey("keyBorders") -val HiddenKeysSetting = booleanPreferencesKey("hiddenKeys") -val KeyHintsSetting = booleanPreferencesKey("keyHints") +val KeyBordersSetting = SettingsKey(booleanPreferencesKey("keyBorders"), true) +val HiddenKeysSetting = SettingsKey(booleanPreferencesKey("hiddenKeys"), false) +val KeyHintsSetting = SettingsKey(booleanPreferencesKey("keyHints"), false) + +val KeyboardHeightMultiplierSetting = SettingsKey(floatPreferencesKey("keyboardHeightMultiplier"), 1.0f) +val KeyboardBottomOffsetSetting = SettingsKey(floatPreferencesKey("keyboardOffset"), 0.0f) fun adjustColorBrightnessForContrast(bgColor: Int, fgColor: Int, desiredContrast: Float, adjustSaturation: Boolean = false): Int { // Convert RGB colors to HSL @@ -76,6 +81,14 @@ class BasicThemeProvider(val context: Context, val overrideColorScheme: ColorSch return drawables[i] } + override fun getKeyboardHeightMultiplier(): Float { + return keyboardHeight + } + + override fun getKeyboardBottomOffset(): Float { + return dp(keyboardBottomOffsetValue.dp) + } + private fun dp(dp: Dp): Float { return TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, @@ -122,6 +135,22 @@ class BasicThemeProvider(val context: Context, val overrideColorScheme: ColorSch val keyBorders: Boolean val showKeyHints: Boolean + val keyboardHeight: Float + val keyboardBottomOffsetValue: Float + + fun hasUpdated(newPreferences: Preferences): Boolean { + return when { + newPreferences[HiddenKeysSetting.key] != expertMode -> true + newPreferences[KeyBordersSetting.key] != keyBorders -> true + newPreferences[KeyHintsSetting.key] != showKeyHints -> true + + newPreferences[KeyboardHeightMultiplierSetting.key] != keyboardHeight -> true + newPreferences[KeyboardBottomOffsetSetting.key] != keyboardBottomOffsetValue -> true + + else -> false + } + } + init { val colorScheme = if(overrideColorScheme != null) { overrideColorScheme @@ -133,9 +162,12 @@ class BasicThemeProvider(val context: Context, val overrideColorScheme: ColorSch dynamicLightColorScheme(dCtx) } - expertMode = context.getSettingBlocking(HiddenKeysSetting, false) - keyBorders = context.getSettingBlocking(KeyBordersSetting, false) - showKeyHints = context.getSettingBlocking(KeyHintsSetting, false) + expertMode = context.getSettingBlocking(HiddenKeysSetting) + keyBorders = context.getSettingBlocking(KeyBordersSetting) + showKeyHints = context.getSettingBlocking(KeyHintsSetting) + + keyboardHeight = context.getSettingBlocking(KeyboardHeightMultiplierSetting.key, KeyboardHeightMultiplierSetting.default) + keyboardBottomOffsetValue = context.getSettingBlocking(KeyboardBottomOffsetSetting.key, KeyboardBottomOffsetSetting.default) val primary = colorScheme.primary.toArgb() val secondary = colorScheme.secondary.toArgb() diff --git a/java/src/org/futo/inputmethod/latin/uix/DynamicThemeProvider.kt b/java/src/org/futo/inputmethod/latin/uix/DynamicThemeProvider.kt index 8ab4a5b2c..e683f006a 100644 --- a/java/src/org/futo/inputmethod/latin/uix/DynamicThemeProvider.kt +++ b/java/src/org/futo/inputmethod/latin/uix/DynamicThemeProvider.kt @@ -22,6 +22,9 @@ interface DynamicThemeProvider { fun getDrawable(i: Int): Drawable? + fun getKeyboardHeightMultiplier(): Float + fun getKeyboardBottomOffset(): Float + companion object { @ColorInt fun getColorOrDefault(i: Int, @ColorInt default: Int, keyAttr: TypedArray, provider: DynamicThemeProvider?): Int { diff --git a/java/src/org/futo/inputmethod/latin/uix/Settings.kt b/java/src/org/futo/inputmethod/latin/uix/Settings.kt index 111bf1c28..85c1cff12 100644 --- a/java/src/org/futo/inputmethod/latin/uix/Settings.kt +++ b/java/src/org/futo/inputmethod/latin/uix/Settings.kt @@ -49,6 +49,10 @@ fun Context.getSettingBlocking(key: Preferences.Key, default: T): T { } } +fun Context.getSettingBlocking(key: SettingsKey): T { + return getSettingBlocking(key.key, key.default) +} + fun Context.setSettingBlocking(key: Preferences.Key, value: T) { val context = this runBlocking { diff --git a/java/src/org/futo/inputmethod/latin/uix/settings/Components.kt b/java/src/org/futo/inputmethod/latin/uix/settings/Components.kt index 36e06e0be..796666018 100644 --- a/java/src/org/futo/inputmethod/latin/uix/settings/Components.kt +++ b/java/src/org/futo/inputmethod/latin/uix/settings/Components.kt @@ -304,71 +304,73 @@ fun SettingSlider( if(isTextFieldVisible) focusRequester.requestFocus() } - ScreenTitle(title, showBack = false) - if(subtitle != null) { - Text(subtitle, style = Typography.bodyMedium, modifier = Modifier.padding(12.dp, 0.dp)) - } - Row(modifier = Modifier.padding(16.dp, 0.dp)) { - if (isTextFieldVisible) { - val apply = { - if(isTextFieldVisible) { - val number = textFieldValue.text.trim().toFloatOrNull() - val newValue = if (number != null) { - transform(number.coerceIn(hardRange)) - } else { - setting.default + Column { + ScreenTitle(title, showBack = false) + if(subtitle != null) { + Text(subtitle, style = Typography.bodyMedium, modifier = Modifier.padding(12.dp, 0.dp)) + } + Row(modifier = Modifier.padding(16.dp, 0.dp)) { + if (isTextFieldVisible) { + val apply = { + if(isTextFieldVisible) { + val number = textFieldValue.text.trim().toFloatOrNull() + val newValue = if (number != null) { + transform(number.coerceIn(hardRange)) + } else { + setting.default + } + + setValue(newValue) + virtualValue = newValue.toFloat().pow(1.0f / power) + + isTextFieldVisible = false + textFieldValue = TextFieldValue() } - - setValue(newValue) - virtualValue = newValue.toFloat().pow(1.0f / power) - - isTextFieldVisible = false - textFieldValue = TextFieldValue() } - } - BasicTextField( - value = textFieldValue, - onValueChange = { textFieldValue = it }, - modifier = Modifier - .weight(0.33f) - .align(Alignment.CenterVertically) - .focusRequester(focusRequester) - .onFocusChanged { - if(it.isFocused) hasTextFieldFocusedYet = true - else if(!it.isFocused && hasTextFieldFocusedYet) apply() - }, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), - keyboardActions = KeyboardActions( - onDone = { - apply() - } - ), - singleLine = true, - textStyle = Typography.labelMedium - ) + BasicTextField( + value = textFieldValue, + onValueChange = { textFieldValue = it }, + modifier = Modifier + .weight(0.33f) + .align(Alignment.CenterVertically) + .focusRequester(focusRequester) + .onFocusChanged { + if (it.isFocused) hasTextFieldFocusedYet = true + else if (!it.isFocused && hasTextFieldFocusedYet) apply() + }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + keyboardActions = KeyboardActions( + onDone = { + apply() + } + ), + singleLine = true, + textStyle = Typography.labelMedium + ) - } else { - Text( - text = indicator(value), - modifier = Modifier - .weight(0.33f) - .align(Alignment.CenterVertically) - .clickable { - hasTextFieldFocusedYet = false - isTextFieldVisible = true - }, - style = Typography.labelMedium + } else { + Text( + text = indicator(value), + modifier = Modifier + .weight(0.33f) + .align(Alignment.CenterVertically) + .clickable { + hasTextFieldFocusedYet = false + isTextFieldVisible = true + }, + style = Typography.labelMedium + ) + } + Slider( + value = virtualValue, + onValueChange = { + virtualValue = it + setValue(transform(it.pow(power))) }, + valueRange = range.start.pow(1.0f / power) .. range.endInclusive.pow(1.0f / power), + enabled = !isTextFieldVisible, + modifier = Modifier.weight(1.0f) ) } - Slider( - value = virtualValue, - onValueChange = { - virtualValue = it - setValue(transform(it.pow(power))) }, - valueRange = range.start.pow(1.0f / power) .. range.endInclusive.pow(1.0f / power), - enabled = !isTextFieldVisible, - modifier = Modifier.weight(1.0f) - ) } } diff --git a/java/src/org/futo/inputmethod/latin/uix/settings/pages/DevSettings.kt b/java/src/org/futo/inputmethod/latin/uix/settings/pages/DevSettings.kt index c772afee4..49cafbc63 100644 --- a/java/src/org/futo/inputmethod/latin/uix/settings/pages/DevSettings.kt +++ b/java/src/org/futo/inputmethod/latin/uix/settings/pages/DevSettings.kt @@ -49,7 +49,7 @@ fun DeveloperScreen(navController: NavHostController = rememberNavController()) SettingToggleDataStore( title = "Touch typing mode", subtitle = "Hides all keys. Touch typists only! Recommended to disable emoji key and enable key borders", - setting = SettingsKey(HiddenKeysSetting, false) + setting = HiddenKeysSetting ) NavigationItem( diff --git a/java/src/org/futo/inputmethod/latin/uix/theme/selector/ThemePicker.kt b/java/src/org/futo/inputmethod/latin/uix/theme/selector/ThemePicker.kt index 2efb959cc..a84746f84 100644 --- a/java/src/org/futo/inputmethod/latin/uix/theme/selector/ThemePicker.kt +++ b/java/src/org/futo/inputmethod/latin/uix/theme/selector/ThemePicker.kt @@ -33,11 +33,12 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import org.futo.inputmethod.latin.uix.HiddenKeysSetting import org.futo.inputmethod.latin.uix.KeyBordersSetting import org.futo.inputmethod.latin.uix.KeyHintsSetting -import org.futo.inputmethod.latin.uix.SettingsKey +import org.futo.inputmethod.latin.uix.KeyboardBottomOffsetSetting +import org.futo.inputmethod.latin.uix.KeyboardHeightMultiplierSetting import org.futo.inputmethod.latin.uix.THEME_KEY +import org.futo.inputmethod.latin.uix.settings.SettingSlider import org.futo.inputmethod.latin.uix.settings.SettingToggleDataStore import org.futo.inputmethod.latin.uix.settings.useDataStore import org.futo.inputmethod.latin.uix.theme.ThemeOption @@ -48,6 +49,7 @@ import org.futo.inputmethod.latin.uix.theme.UixThemeWrapper import org.futo.inputmethod.latin.uix.theme.presets.AMOLEDDarkPurple import org.futo.inputmethod.latin.uix.theme.presets.ClassicMaterialDark import org.futo.inputmethod.latin.uix.theme.presets.VoiceInputTheme +import kotlin.math.roundToInt // TODO: For Dynamic System we need to show the user that it switches between light/dark @Composable @@ -185,18 +187,6 @@ fun ThemePicker(onSelected: (ThemeOption) -> Unit) { modifier = Modifier.fillMaxWidth(), columns = GridCells.Adaptive(minSize = 172.dp) ) { - item(span = { GridItemSpan(maxCurrentLineSpan) }) { - SettingToggleDataStore( - title = "Key borders", - setting = SettingsKey(KeyBordersSetting, false) - ) - } - item(span = { GridItemSpan(maxCurrentLineSpan) }) { - SettingToggleDataStore( - title = "Show symbol hints", - setting = SettingsKey(KeyHintsSetting, false) - ) - } items(availableThemeOptions.count()) { val themeOption = availableThemeOptions[it].second @@ -216,6 +206,38 @@ fun ThemePicker(onSelected: (ThemeOption) -> Unit) { toast.show() } } + + item(span = { GridItemSpan(maxCurrentLineSpan) }) { } + + item(span = { GridItemSpan(maxCurrentLineSpan) }) { + SettingToggleDataStore( + title = "Key borders", + setting = KeyBordersSetting + ) + } + item(span = { GridItemSpan(maxCurrentLineSpan) }) { + SettingToggleDataStore( + title = "Show symbol hints", + setting = KeyHintsSetting + ) + } + + item(span = { GridItemSpan(maxCurrentLineSpan) }) { + SettingSlider( + title = "Keyboard Height", + setting = KeyboardHeightMultiplierSetting, + range = 0.1f .. 2.0f, transform = { it }, + indicator = { "${(it * 100.0f).roundToInt()}%" } + ) + } + item(span = { GridItemSpan(maxCurrentLineSpan) }) { + SettingSlider( + title = "Keyboard Offset", + setting = KeyboardBottomOffsetSetting, + range = 0.0f .. 128.0f, transform = { it }, + indicator = { "${String.format("%.1f", it)} dp" } + ) + } } } }