From 38228f8b706953a77ce845c021e13262f0151db9 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sat, 11 May 2024 23:25:47 +0200 Subject: [PATCH] parse number and alpha/symbol layouts using the same function --- app/src/main/assets/layouts/number.json | 20 +-- app/src/main/assets/layouts/numpad.json | 20 +-- .../main/assets/layouts/numpad_landscape.json | 64 +++---- app/src/main/assets/layouts/phone.json | 8 +- .../main/assets/layouts/phone_symbols.json | 12 +- .../keyboard/internal/KeyboardParams.java | 7 +- .../keyboard_parser/KeyboardParser.kt | 160 +++++------------- .../keyboard_parser/floris/KeyType.kt | 1 + .../keyboard_parser/floris/TextKeyData.kt | 16 +- layouts.md | 10 +- 10 files changed, 129 insertions(+), 189 deletions(-) diff --git a/app/src/main/assets/layouts/number.json b/app/src/main/assets/layouts/number.json index ca36417a..bc6bae10 100644 --- a/app/src/main/assets/layouts/number.json +++ b/app/src/main/assets/layouts/number.json @@ -3,13 +3,13 @@ { "label": "1", "type": "numeric" }, { "label": "2", "type": "numeric" }, { "label": "3", "type": "numeric" }, - { "label": "-", "popup": { "main": { "label": "+" } }, "labelFlags": 1073742336 } + { "label": "-", "type": "function", "popup": { "main": { "label": "+" } }, "labelFlags": 64 } ], [ { "label": "4", "type": "numeric" }, { "label": "5", "type": "numeric" }, { "label": "6", "type": "numeric" }, - { "label": "space" } + { "label": "space", "type": "function" } ], [ { "label": "7", "type": "numeric" }, @@ -19,15 +19,15 @@ ], [ { "$": "variation_selector", - "default": { "label": "," }, - "date": { "label": "." }, - "time": { "label": ".", "popup": { "relevant": [ + "default": { "label": ",", "type": "numeric" }, + "date": { "label": ".", "type": "numeric" }, + "time": { "label": ".", "type": "numeric", "popup": { "relevant": [ { "label": "!fixedColumnOrder!2" }, { "label": "!hasLabels!" }, { "label": "AM" }, { "label": "PM" } ] } }, - "datetime": { "label": ".", "popup": { "relevant": [ + "datetime": { "label": ".", "type": "numeric", "popup": { "relevant": [ { "label": "!fixedColumnOrder!2" }, { "label": "!hasLabels!" }, { "label": "AM" }, @@ -36,10 +36,10 @@ }, { "label": "0", "type": "numeric" }, { "$": "variation_selector", - "default": { "label": "." }, - "date": { "label": "/" }, - "time": { "label": ":" }, - "datetime": { "label": "/ :|/", "popup": { "relevant": [ + "default": { "label": ".", "type": "numeric" }, + "date": { "label": "/", "type": "numeric" }, + "time": { "label": ":", "type": "numeric" }, + "datetime": { "label": "/ :|/", "type": "numeric", "popup": { "relevant": [ { "label": "!noPanelAutoPopupKey!" }, { "label": "," } ] } } diff --git a/app/src/main/assets/layouts/numpad.json b/app/src/main/assets/layouts/numpad.json index 1ef9038e..4edfca2f 100644 --- a/app/src/main/assets/layouts/numpad.json +++ b/app/src/main/assets/layouts/numpad.json @@ -1,6 +1,6 @@ [ [ - { "label": "+", "popup": { + { "label": "+", "type": "function", "popup": { "relevant": [ { "label": "(" }, { "label": "<" }, @@ -10,10 +10,10 @@ { "label": "1", "type": "numeric" }, { "label": "2", "type": "numeric" }, { "label": "3", "type": "numeric" }, - { "label": "%", "popup": { "main": { "label": "$$$"} }, "labelFlags": 512 } + { "label": "%", "type": "function", "popup": { "main": { "label": "$$$"} }, "labelFlags": 512 } ], [ - { "label": "-", "popup": { + { "label": "-", "type": "function", "popup": { "relevant": [ { "label": ")" }, { "label": ">" }, @@ -23,10 +23,10 @@ { "label": "4", "type": "numeric" }, { "label": "5", "type": "numeric" }, { "label": "6", "type": "numeric" }, - { "label": "space" } + { "label": "space", "type": "function" } ], [ - { "label": "*", "popup": { + { "label": "*", "type": "function", "popup": { "relevant": [ { "label": "/" }, { "label": "×" }, @@ -40,11 +40,11 @@ ], [ { "label": "alpha" }, - { "label": "comma" }, - { "label": "symbol" }, + { "label": "comma", "width": 0.1 }, + { "label": "symbol", "type": "character", "width": 0.12 }, { "label": "0", "type": "numeric" }, - { "label": "=", "popup": { "relevant": [ { "label": "≠"}, { "label": "≈"} ] } }, - { "label": "period" }, - { "label": "enter" } + { "label": "=", "width": 0.12, "popup": { "relevant": [ { "label": "≠"}, { "label": "≈"} ] } }, + { "label": "period", "width": 0.1 }, + { "label": "action" } ] ] diff --git a/app/src/main/assets/layouts/numpad_landscape.json b/app/src/main/assets/layouts/numpad_landscape.json index 66237624..19f3cff0 100644 --- a/app/src/main/assets/layouts/numpad_landscape.json +++ b/app/src/main/assets/layouts/numpad_landscape.json @@ -1,46 +1,46 @@ [ [ - { "label": "(", "popup": { "relevant": [ { "label": "[" }, { "label": "{" } ] } }, - { "label": ")", "popup": { "relevant": [ { "label": "]" }, { "label": "}" } ] } }, - { "label": ":" }, - { "label": "1", "type": "numeric" }, - { "label": "2", "type": "numeric" }, - { "label": "3", "type": "numeric" }, - { "label": "+", "popup": { "main": { "label": "±" } } }, - { "label": "-", "popup": { "main": { "label": "~" } } }, - { "label": "space" } + { "label": "(", "type": "function", "popup": { "relevant": [ { "label": "[" }, { "label": "{" } ] } }, + { "label": ")", "type": "function", "popup": { "relevant": [ { "label": "]" }, { "label": "}" } ] } }, + { "label": ":", "type": "function" }, + { "label": "1", "type": "numeric", "width": 0.3 }, + { "label": "2", "type": "numeric", "width": 0.3 }, + { "label": "3", "type": "numeric", "width": 0.3 }, + { "label": "+", "type": "function", "popup": { "main": { "label": "±" } } }, + { "label": "-", "type": "function", "popup": { "main": { "label": "~" } } }, + { "label": "space", "type": "function" } ], [ - { "label": "!" }, - { "label": "?" }, - { "label": ";" }, - { "label": "4", "type": "numeric" }, - { "label": "5", "type": "numeric" }, - { "label": "6", "type": "numeric" }, - { "label": "*", "popup": { "main": { "label": "×" } } }, - { "label": "/", "popup": { "main": { "label": "÷" } } }, + { "label": "!", "type": "function" }, + { "label": "?", "type": "function" }, + { "label": ";", "type": "function" }, + { "label": "4", "type": "numeric", "width": 0.3 }, + { "label": "5", "type": "numeric", "width": 0.3 }, + { "label": "6", "type": "numeric", "width": 0.3 }, + { "label": "*", "type": "function", "popup": { "main": { "label": "×" } } }, + { "label": "/", "type": "function", "popup": { "main": { "label": "÷" } } }, { "label": "delete" } ], [ - { "label": "|" }, - { "label": "$$$" }, - { "label": "&" }, - { "label": "7", "type": "numeric" }, - { "label": "8", "type": "numeric" }, - { "label": "9", "type": "numeric" }, - { "label": "#" }, - { "label": "%", "popup": { "main": { "label": "‰" } } }, + { "label": "|", "type": "function" }, + { "label": "$$$", "type": "function" }, + { "label": "&", "type": "function" }, + { "label": "7", "type": "numeric", "width": 0.3 }, + { "label": "8", "type": "numeric", "width": 0.3 }, + { "label": "9", "type": "numeric", "width": 0.3 }, + { "label": "#", "type": "function" }, + { "label": "%", "type": "function", "popup": { "main": { "label": "‰" } } }, { "label": "action" } ], [ { "label": "alpha" }, - { "label": "<", "popup": { "main": { "label": "≤" } } }, - { "label": ">", "popup": { "main": { "label": "≥" } } }, - { "label": "comma" }, - { "label": "0", "type": "numeric" }, - { "label": "period" }, - { "label": "=", "popup": { "relevant": [ { "label": "≠"}, { "label": "≈"} ] } }, - { "label": "=", "popup": { "relevant": [ { "label": "≠"}, { "label": "≈"} ] } }, + { "label": "<", "type": "function", "popup": { "main": { "label": "≤" } } }, + { "label": ">", "type": "function", "popup": { "main": { "label": "≥" } } }, + { "label": "comma", "type": "numeric", "width": 0.3 }, + { "label": "0", "type": "numeric", "width": 0.3 }, + { "label": "period", "type": "numeric", "width": 0.3 }, + { "label": "=", "type": "function", "popup": { "relevant": [ { "label": "≠"}, { "label": "≈"} ] } }, + { "label": "=", "type": "function", "popup": { "relevant": [ { "label": "≠"}, { "label": "≈"} ] } }, { "label": "symbol" } ] ] diff --git a/app/src/main/assets/layouts/phone.json b/app/src/main/assets/layouts/phone.json index a6cccc99..c3ffd667 100644 --- a/app/src/main/assets/layouts/phone.json +++ b/app/src/main/assets/layouts/phone.json @@ -3,13 +3,13 @@ { "label": "1", "type": "numeric" }, { "label": "2", "type": "numeric", "popup": { "main": { "label": "ABC" } } }, { "label": "3", "type": "numeric", "popup": { "main": { "label": "DEF" } } }, - { "label": "-", "popup": { "main": { "label": "+" } }, "labelFlags": 1073742336 } + { "label": "-", "type": "function", "labelFlags": 1073742400, "popup": { "main": { "label": "+" } } } ], [ { "label": "4", "type": "numeric", "popup": { "main": { "label": "GHI" } } }, { "label": "5", "type": "numeric", "popup": { "main": { "label": "JKL" } } }, { "label": "6", "type": "numeric", "popup": { "main": { "label": "MNO" } } }, - { "label": "space" } + { "label": "space", "type": "function" } ], [ { "label": "7", "type": "numeric", "popup": { "main": { "label": "PQRS" } } }, @@ -18,9 +18,9 @@ { "label": "delete" } ], [ - { "label": "*#|!code/key_switch_alpha_symbol", "labelFlags": 524432 }, + { "label": "*#|!code/key_switch_alpha_symbol", "type": "numeric", "labelFlags": 524432 }, { "label": "0 +|0", "type": "numeric", "popup": { "relevant": [ { "label": "!noPanelAutoPopupKey!" }, { "label": "+" } ] } }, - { "label": "." }, + { "label": ".", "type": "numeric", "labelFlags": 64 }, { "label": "action" } ] ] diff --git a/app/src/main/assets/layouts/phone_symbols.json b/app/src/main/assets/layouts/phone_symbols.json index 140bd474..d1dd29d1 100644 --- a/app/src/main/assets/layouts/phone_symbols.json +++ b/app/src/main/assets/layouts/phone_symbols.json @@ -3,24 +3,24 @@ { "label": "(", "type": "numeric" }, { "label": "/", "type": "numeric" }, { "label": ")", "type": "numeric" }, - { "label": "-", "popup": { "main": { "label": "+" } } } + { "label": "-", "type": "function", "labelFlags": 1073742400, "popup": { "main": { "label": "+" } } } ], [ { "label": "N", "type": "numeric" }, - { "label": "!string/label_pause_key|,", "type": "numeric" }, + { "label": "!string/label_pause_key", "code": 44, "type": "numeric" }, { "label": ",", "type": "numeric" }, - { "label": "space" } + { "label": "space", "type": "function" } ], [ { "label": "*|*", "type": "numeric" }, - { "label": "!string/label_wait_key|;", "type": "numeric" }, + { "label": "!string/label_wait_key", "code": 59, "type": "numeric" }, { "label": "\\#", "type": "numeric" }, { "label": "delete" } ], [ - { "label": "123|!code/key_switch_alpha_symbol", "labelFlags": 524432 }, + { "label": "123|!code/key_switch_alpha_symbol", "type": "numeric", "labelFlags": 524432 }, { "label": "+", "type": "numeric" }, - { "label": "." }, + { "label": ".", "type": "numeric" }, { "label": "action" } ] ] diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardParams.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardParams.java index b63d1544..0b9f6e9a 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardParams.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardParams.java @@ -224,9 +224,10 @@ public class KeyboardParams { R.styleable.Keyboard_keyboardRightPadding, width, width, 0); mBaseWidth = mOccupiedWidth - mLeftPadding - mRightPadding; - final float defaultKeyWidthFactor = context.getResources().getInteger(R.integer.config_screen_metrics) > 2 - ? 0.9f : 1f; - mDefaultKeyWidth = keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth, + final float defaultKeyWidthFactor = context.getResources().getInteger(R.integer.config_screen_metrics) > 2 ? 0.9f : 1f; + mDefaultKeyWidth = mId.isNumberLayout() + ? 0.17f + : keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth, 1, 1, defaultKeyWidthFactor / DEFAULT_KEYBOARD_COLUMNS); mDefaultAbsoluteKeyWidth = (int) (mDefaultKeyWidth * mBaseWidth); diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt index 591a1013..75dda2fd 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt @@ -48,11 +48,13 @@ import java.io.File */ abstract class KeyboardParser(private val params: KeyboardParams, private val context: Context) { private val infos = layoutInfos(params) - private val defaultLabelFlags = if (params.mId.isAlphabetKeyboard) { - params.mLocaleKeyboardInfos.labelFlags - } else if (params.mId.mElementId == KeyboardId.ELEMENT_SYMBOLS || params.mId.mElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED) { - Key.LABEL_FLAGS_DISABLE_HINT_LABEL // reproduce the no-hints in symbol layouts, todo: add setting - } else 0 + private val defaultLabelFlags = when { + params.mId.isAlphabetKeyboard -> params.mLocaleKeyboardInfos.labelFlags + // reproduce the no-hints in symbol layouts + // todo: add setting? or put it in TextKeyData to happen only if no label flags specified explicitly? + params.mId.isAlphaOrSymbolKeyboard -> Key.LABEL_FLAGS_DISABLE_HINT_LABEL + else -> 0 + } abstract fun parseCoreLayout(layoutContent: String): MutableList> @@ -66,16 +68,10 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co else params.mTouchPositionCorrection.load(context.resources.getStringArray(infos.touchPositionCorrectionData)) - val baseKeys: MutableList> = parseCoreLayout(layoutContent) - val keysInRows = if (params.mId.isAlphaOrSymbolKeyboard) { - createAlphaSymbolRows(baseKeys) - } else if (params.mId.isNumberLayout) { - createNumericRows(baseKeys) - } else { - throw(UnsupportedOperationException("creating KeyboardId ${params.mId.mElementId} not supported")) - } - // rescale height if we have more than 4 rows - val heightRescale = if (keysInRows.size > 4) 4f / keysInRows.size else 1f + val baseKeys = parseCoreLayout(layoutContent) + val keysInRows = createRows(baseKeys) + // rescale height if we have anything but the usual 4 rows + val heightRescale = if (keysInRows.size != 4) 4f / keysInRows.size else 1f if (heightRescale != 1f) { keysInRows.forEach { row -> row.forEach { it.mHeight *= heightRescale } } } @@ -86,7 +82,7 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co // this should be ready for customizable functional layouts, but needs cleanup // todo (later): remove this as part of adding a cache for parsed layouts private fun getFunctionalKeyLayoutText(): String { - if (!params.mId.isAlphaOrSymbolKeyboard) throw IllegalStateException("functional key layout only for aloha and symbol layouts") + if (params.mId.isNumberLayout) return "[]" // empty list val layouts = Settings.getLayoutsDir(context).list() ?: emptyArray() if (params.mId.mElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED) { if ("functional_keys_symbols_shifted.json" in layouts) @@ -102,15 +98,21 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co return context.readAssetsLayoutFile(fileName) } - private fun createAlphaSymbolRows(baseKeys: MutableList>): ArrayList> { + private fun createRows(baseKeys: MutableList>): ArrayList> { + // add padding for number layouts in landscape mode (maybe do it some other way later) + if (params.mId.isNumberLayout && params.mId.mElementId != KeyboardId.ELEMENT_NUMPAD + && context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { + params.mLeftPadding = (params.mOccupiedWidth * 0.1f).toInt() + params.mRightPadding = (params.mOccupiedWidth * 0.1f).toInt() + params.mBaseWidth = params.mOccupiedWidth - params.mLeftPadding - params.mRightPadding + } + addNumberRowOrPopupKeys(baseKeys) if (params.mId.isAlphabetKeyboard) addSymbolPopupKeys(baseKeys) - if (params.mId.mNumberRowEnabled) - baseKeys.add( - 0, - params.mLocaleKeyboardInfos.getNumberRow() - .map { it.copy(newLabelFlags = Key.LABEL_FLAGS_DISABLE_HINT_LABEL or defaultLabelFlags) }) + if (params.mId.isAlphaOrSymbolKeyboard && params.mId.mNumberRowEnabled) + baseKeys.add(0, params.mLocaleKeyboardInfos.getNumberRow() + .map { it.copy(newLabelFlags = Key.LABEL_FLAGS_DISABLE_HINT_LABEL or defaultLabelFlags) }) val allFunctionalKeys = JsonKeyboardParser(params, context).parseCoreLayout(getFunctionalKeyLayoutText()) adjustBottomFunctionalRowAndBaseKeys(allFunctionalKeys, baseKeys) @@ -126,7 +128,7 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co val functionalKeys = mutableListOf, List>>() val baseKeyParams = baseKeys.mapIndexed { i, it -> - val row: List = if (i == baseKeys.lastIndex - 1 && Settings.getInstance().isTablet) { + val row: List = if (params.mId.isAlphaOrSymbolKeyboard && i == baseKeys.lastIndex - 1 && Settings.getInstance().isTablet) { // add bottom row extra keys // todo (later): this can make very customized layouts look awkward // decide when to (not) add it @@ -142,13 +144,14 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co val functionalKeysFromBottom = functionalKeysBottom.getOrNull(i - bottomIndexOffset) ?: emptyList() functionalKeys.add(getFunctionalKeysBySide(functionalKeysFromTop, functionalKeysFromBottom)) - row.map { key -> + row.mapNotNull { key -> val extraFlags = if (key.label.length > 2 && key.label.codePointCount(0, key.label.length) > 2 && !isEmoji(key.label)) Key.LABEL_FLAGS_AUTO_X_SCALE else 0 + val keyData = key.processFunctionalKeys() ?: return@mapNotNull null // all keys could actually be functional keys... if (DebugFlags.DEBUG_ENABLED) - Log.d(TAG, "adding key ${key.label}, ${key.code}") - key.toKeyParams(params, defaultLabelFlags or extraFlags) + Log.d(TAG, "adding key ${keyData.label}, ${keyData.code}") + keyData.toKeyParams(params, defaultLabelFlags or extraFlags) } } return setReasonableWidths(baseKeyParams, functionalKeys) @@ -247,7 +250,6 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co } // replace comma / period if 2 keys in normal bottom row if (baseKeys.last().size == 2) { - Log.i("test", "$functionalKeysBottom") functionalKeysBottom.replaceFirst( { it.label == KeyLabel.COMMA || it.groupId == KeyData.GROUP_COMMA}, { baseKeys.last()[0].copy(newGroupId = 1, newType = baseKeys.last()[0].type ?: it.type) } @@ -256,7 +258,6 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co { it.label == KeyLabel.PERIOD || it.groupId == KeyData.GROUP_PERIOD}, { baseKeys.last()[1].copy(newGroupId = 2, newType = baseKeys.last()[1].type ?: it.type) } ) - Log.i("test", "$functionalKeysBottom") baseKeys.removeLast() } // add those extra keys depending on layout (remove later) @@ -304,14 +305,11 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co // this is not nice in here, but otherwise we'd need context, and defaultLabelFlags and infos for toKeyParams // improve it later, but currently this messy way is still ok - private fun KeyData.processFunctionalKeys(): KeyData? { - if (label == KeyLabel.PERIOD) { - // todo: why defaultLabelFlags exactly here? is this for armenian or bengali period labels? try removing also check in holo theme - return copy(newLabelFlags = labelFlags or defaultLabelFlags) - } - if (label == KeyLabel.SHIFT && !infos.hasShiftKey) return null - if (label != KeyLabel.ACTION) return this - return copy( + private fun KeyData.processFunctionalKeys(): KeyData? = when (label) { + // todo: why defaultLabelFlags exactly here? is this for armenian or bengali period labels? try removing also check in holo theme + KeyLabel.PERIOD -> copy(newLabelFlags = labelFlags or defaultLabelFlags) + KeyLabel.SHIFT -> if (infos.hasShiftKey) this else null + KeyLabel.ACTION -> copy( // todo: evaluating the label should actually only happen in toKeyParams // this label change already makes it necessary to provide the background in here too, because toKeyParams can't use action as label newLabel = "${getActionKeyLabel()}|${getActionKeyCode()}", @@ -319,6 +317,15 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co // the label change is messing with toKeyParams, so we need to supply the appropriate BG type here newType = type ?: KeyType.ENTER_EDITING ) + else -> { + // this is ugly... + if (label.length > 8 && label.startsWith("!string/")) { + val id = context.resources.getIdentifier(label.substringAfter("!string/"), "string", context.packageName) + Log.i("test", "id of $label: $id") + if (id != 0) copy(newLabel = getInLocale(id)) + else this + } else this + } } private fun addNumberRowOrPopupKeys(baseKeys: MutableList>) { @@ -363,87 +370,6 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co } } - private fun createNumericRows(baseKeys: MutableList>): ArrayList> { - val keysInRows = ArrayList>() - if (context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && params.mId.mElementId != KeyboardId.ELEMENT_NUMPAD) { - // add padding here instead of using xml (actually this is not good... todo (later)) - params.mLeftPadding = (params.mOccupiedWidth * 0.1f).toInt() - params.mRightPadding = (params.mOccupiedWidth * 0.1f).toInt() - params.mBaseWidth = params.mOccupiedWidth - params.mLeftPadding - params.mRightPadding - } - baseKeys.forEachIndexed { i, row -> - val paramsRow = ArrayList() - row.forEach { key -> - var keyParams: KeyParams? = null - // try parsing a functional key - val functionalKeyName = when (key.label) { - // todo (later): maybe add special popupKeys for phone and number layouts? - "." -> if (params.mId.mElementId == KeyboardId.ELEMENT_NUMPAD) KeyLabel.PERIOD else "." - "," -> if (params.mId.mElementId == KeyboardId.ELEMENT_NUMPAD) KeyLabel.COMMA else "," - else -> key.label - } - if (functionalKeyName.length > 1 && key.type != KeyType.NUMERIC) { - try { - keyParams = key.copy(newLabel = functionalKeyName).processFunctionalKeys()!!.toKeyParams(params) - } catch (_: Throwable) {} // just use normal label - } - if (keyParams == null) { - keyParams = if (key.type == KeyType.NUMERIC) { - val labelFlags = when (params.mId.mElementId) { - KeyboardId.ELEMENT_PHONE -> Key.LABEL_FLAGS_ALIGN_LABEL_OFF_CENTER or Key.LABEL_FLAGS_HAS_HINT_LABEL or Key.LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO - KeyboardId.ELEMENT_PHONE_SYMBOLS -> 0 - else -> Key.LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO - } - key.toKeyParams(params, labelFlags or defaultLabelFlags) - } else if (key.label.length == 1 && (params.mId.mElementId == KeyboardId.ELEMENT_PHONE || params.mId.mElementId == KeyboardId.ELEMENT_NUMBER)) - key.toKeyParams(params, additionalLabelFlags = Key.LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO or defaultLabelFlags) - else - key.toKeyParams(params, additionalLabelFlags = defaultLabelFlags) - } - if (key.type != KeyType.NUMERIC && keyParams.mBackgroundType != Key.BACKGROUND_TYPE_ACTION) - keyParams.mBackgroundType = Key.BACKGROUND_TYPE_FUNCTIONAL - - if (params.mId.mElementId == KeyboardId.ELEMENT_PHONE && key.popup.main?.getPopupLabel(params)?.length?.let { it > 1 } == true) { - keyParams.mPopupKeys = null // the ABC and stuff labels should not create popupKeys - } - if (keyParams.mLabel?.length?.let { it > 1 } == true && keyParams.mLabel?.startsWith("!string/") == true) { - // resolve string label - val id = context.resources.getIdentifier(keyParams.mLabel?.substringAfter("!string/"), "string", context.packageName) - if (id != 0) - keyParams.mLabel = getInLocale(id) - } - paramsRow.add(keyParams) - if (DebugFlags.DEBUG_ENABLED) - Log.d(TAG, "adding key ${keyParams.mLabel}, ${keyParams.mCode}") - } - if (i == baseKeys.lastIndex) { // bottom row needs some adjustments - val n = row.indexOfFirst { it.type == KeyType.NUMERIC } - if (n != -1) { - // make sure the keys next to 0 have normal background - paramsRow.getOrNull(n - 1)?.mBackgroundType = Key.BACKGROUND_TYPE_NORMAL - paramsRow.getOrNull(n + 1)?.mBackgroundType = Key.BACKGROUND_TYPE_NORMAL - - // make those keys same width as numeric keys except in numpad layout - // but determine from row size instead of from elementId, in case user wants to adjust numpad layout - if (row.size == baseKeys[0].size) { - paramsRow.getOrNull(n - 1)?.mWidth = paramsRow[n].mWidth - paramsRow.getOrNull(n + 1)?.mWidth = paramsRow[n].mWidth - } else if (row.size == baseKeys[0].size + 2) { - // numpad last row -> make sure the keys next to 0 fit nicely - paramsRow.getOrNull(n - 1)?.mWidth = paramsRow[n].mWidth * 0.55f - paramsRow.getOrNull(n - 2)?.mWidth = paramsRow[n].mWidth * 0.45f - paramsRow.getOrNull(n + 1)?.mWidth = paramsRow[n].mWidth * 0.55f - paramsRow.getOrNull(n + 2)?.mWidth = paramsRow[n].mWidth * 0.45f - } - } - } - val widthSum = paramsRow.sumOf { it.mWidth } - paramsRow.forEach { it.mWidth /= widthSum } - keysInRows.add(paramsRow) - } - return keysInRows - } - private fun getActionKeyLabel(): String { if (params.mId.isMultiLine && (params.mId.mElementId == KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED || params.mId.mElementId == KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED)) return "!icon/enter_key" diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyType.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyType.kt index 41444db9..5ce00a4d 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyType.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyType.kt @@ -43,6 +43,7 @@ enum class KeyType { "space" -> NAVIGATION "action" -> ENTER_EDITING "shift" -> LOCK + "normal" -> CHARACTER else -> valueOf(string.uppercase()) } } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt index 1cd18a16..d1d7c2ca 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt @@ -144,11 +144,21 @@ sealed interface KeyData : AbstractKeyData { override fun compute(params: KeyboardParams): KeyData { require(groupId <= GROUP_ENTER) { "only groups up to GROUP_ENTER are supported" } require(label.isNotEmpty() || type == KeyType.PLACEHOLDER || code != KeyCode.UNSPECIFIED) { "non-placeholder key has no code and no label" } + require(width >= 0f || width == -1f) { "illegal width $width" } val newLabel = label.convertFlorisLabel() val newCode = code.checkAndConvertCode() + val newLabelFlags = if (labelFlags == 0 && params.mId.isNumberLayout) { + if (type == KeyType.NUMERIC) { + when (params.mId.mElementId) { + KeyboardId.ELEMENT_PHONE -> Key.LABEL_FLAGS_ALIGN_LABEL_OFF_CENTER or Key.LABEL_FLAGS_HAS_HINT_LABEL or Key.LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO + KeyboardId.ELEMENT_PHONE_SYMBOLS -> 0 + else -> Key.LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO + } + } else 0 + } else labelFlags - if (newCode != code || newLabel != label) - return copy(newCode = newCode, newLabel = newLabel) + if (newCode != code || newLabel != label || labelFlags != newLabelFlags) + return copy(newCode = newCode, newLabel = newLabel, newLabelFlags = newLabelFlags) return this } @@ -258,7 +268,7 @@ sealed interface KeyData : AbstractKeyData { private fun getDefaultWidth(params: KeyboardParams): Float { return if (label == KeyLabel.SPACE && params.mId.isAlphaOrSymbolKeyboard) -1f - else if (type == KeyType.NUMERIC && params.mId.isNumberLayout) 0.17f // todo (later) consider making this -1? + else if (type == KeyType.NUMERIC && params.mId.isNumberLayout) -1f else params.mDefaultKeyWidth } diff --git a/layouts.md b/layouts.md index 104ed041..d3d59727 100644 --- a/layouts.md +++ b/layouts.md @@ -38,12 +38,13 @@ If the layout has exactly 2 keys in the bottom row, these keys will replace comm ### Properties * A (non-selector) key can have the following properties: * `type`: only specific values, HeliBoard mostly uses this to determine background color and type, determined automatically by default - * `character`: normal key color + * `normal`: normal key color * `function`: functional key color * `space`: space bar color * `action`: action key color * `unspecified`: no background color * `placeholder`: no background color, no label, and pressing the key does nothing + * `numeric`: normal key color, only in number layouts: sets default width to `-1` and sets default label flags if none specified * There are some more values, but they do nothing * `code`: code point that is entered when the key is pressed, determined from the label by default, not available for `multi_text_key` * There are special negative values available, e.g. the ones used by functional keys, see [KeyCode.kt](/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt). There are several not yet supported key codes in there, you can see in the function `checkAndConvertCode` which ones are working. @@ -57,9 +58,10 @@ If the layout has exactly 2 keys in the bottom row, these keys will replace comm * `width`: width of the key in units of screen width, e.g. a key with `"width": 0.1` has a width of 10% of the screen, defaults to `0` * A special value is `-1`, which means the key expands to the available space not already used by other keys (e.g. the space bar) * `0` is interpreted as follows - * `-1` on the `space` key in alphabet or symbols layouts - * `0.17` for keys with `"type": numeric` in number layouts - * Otherwise the default width is used, which is `0.1` for phones and `0.09` for tablets + * `-1` on the `space` key in alphabet or symbols layouts, and for keys with `"type": numeric` in number layouts + * `0.17` for number layouts + * `0.1` for phones + * `0.09` for tablets * If the sum of widths in a row is greater than 1, keys are rescaled to fit on the screen * `labelFlags`: allows specific effects, see [here](app/src/main/res/values/attrs.xml) in the section _keyLabelFlags_ for names and numeric values