mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-16 04:12:02 +00:00
parse number and alpha/symbol layouts using the same function
This commit is contained in:
parent
9bb64d561f
commit
38228f8b70
10 changed files with 129 additions and 189 deletions
|
@ -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": "," }
|
||||
] } }
|
||||
|
|
|
@ -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" }
|
||||
]
|
||||
]
|
||||
|
|
|
@ -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" }
|
||||
]
|
||||
]
|
||||
|
|
|
@ -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" }
|
||||
]
|
||||
]
|
||||
|
|
|
@ -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" }
|
||||
]
|
||||
]
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<List<KeyData>>
|
||||
|
||||
|
@ -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<List<KeyData>> = 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<List<KeyData>>): ArrayList<ArrayList<KeyParams>> {
|
||||
private fun createRows(baseKeys: MutableList<List<KeyData>>): ArrayList<ArrayList<KeyParams>> {
|
||||
// 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<Pair<List<KeyParams>, List<KeyParams>>>()
|
||||
val baseKeyParams = baseKeys.mapIndexed { i, it ->
|
||||
val row: List<KeyData> = if (i == baseKeys.lastIndex - 1 && Settings.getInstance().isTablet) {
|
||||
val row: List<KeyData> = 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<List<KeyData>>) {
|
||||
|
@ -363,87 +370,6 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
}
|
||||
}
|
||||
|
||||
private fun createNumericRows(baseKeys: MutableList<List<KeyData>>): ArrayList<ArrayList<KeyParams>> {
|
||||
val keysInRows = ArrayList<ArrayList<KeyParams>>()
|
||||
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<KeyParams>()
|
||||
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"
|
||||
|
|
|
@ -43,6 +43,7 @@ enum class KeyType {
|
|||
"space" -> NAVIGATION
|
||||
"action" -> ENTER_EDITING
|
||||
"shift" -> LOCK
|
||||
"normal" -> CHARACTER
|
||||
else -> valueOf(string.uppercase())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
10
layouts.md
10
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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue