mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-19 13:49:13 +00:00
use new parser for symbols layouts
This commit is contained in:
parent
4d0b7915c8
commit
57bf742da0
45 changed files with 574 additions and 136 deletions
10
app/src/main/assets/language_key_texts/ar.txt
Normal file
10
app/src/main/assets/language_key_texts/ar.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
[morekeys]
|
||||
punctuation !fixedColumnOrder!7 ٕ|ٕ ٔ|ٔ ْ|ْ ٍ|ٍ ٌ|ٌ ً|ً ّ|ّ ٖ|ٖ ٰ|ٰ ٓ|ٓ ِ|ِ ُ|ُ َ|َ ـــ|ـ
|
||||
|
||||
[labels]
|
||||
alphabet: أبج
|
||||
symbol: ٣٢١؟
|
||||
comma: ،
|
||||
|
||||
[number_row]
|
||||
١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩ ٠
|
8
app/src/main/assets/language_key_texts/be.txt
Normal file
8
app/src/main/assets/language_key_texts/be.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
[morekeys]
|
||||
е ё
|
||||
ь ъ
|
||||
' ’ ‚ ‘
|
||||
" ” „ “
|
||||
|
||||
[labels]
|
||||
alphabet: АБВ
|
5
app/src/main/assets/language_key_texts/bg.txt
Normal file
5
app/src/main/assets/language_key_texts/bg.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
[morekeys]
|
||||
" ” „ “
|
||||
|
||||
[labels]
|
||||
alphabet: АБВ
|
10
app/src/main/assets/language_key_texts/bn_bd.txt
Normal file
10
app/src/main/assets/language_key_texts/bn_bd.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
[morekeys]
|
||||
punctuation !autoColumnOrder!8 \, ॥ ? ! !icon/zwnj_key|\u200C !icon/zwj_key|\u200D # @ ( ) / ; : - + \%
|
||||
|
||||
[labels]
|
||||
alphabet: কখগ
|
||||
symbol: ?১২৩
|
||||
period: ।
|
||||
|
||||
[number_row]
|
||||
১ ২ ৩ ৪ ৫ ৬ ৭ ৮ ৯ ০
|
2
app/src/main/assets/language_key_texts/bn_in.txt
Normal file
2
app/src/main/assets/language_key_texts/bn_in.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: কখগ
|
2
app/src/main/assets/language_key_texts/el.txt
Normal file
2
app/src/main/assets/language_key_texts/el.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: ΑΒΓ
|
10
app/src/main/assets/language_key_texts/fa.txt
Normal file
10
app/src/main/assets/language_key_texts/fa.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
[morekeys]
|
||||
punctuation !fixedColumnOrder!7 ٕ|ٕ ْ|ْ ّ|ّ ٌ|ٌ ٍ|ٍ ً|ً ٔ|ٔ ٖ|ٖ ٰ|ٰ ٓ|ٓ ُ|ُ ِ|ِ َ|َ ـــ|ـ
|
||||
|
||||
[labels]
|
||||
alphabet: ابپ
|
||||
symbol: ۳۲۱؟
|
||||
comma: ،
|
||||
|
||||
[number_row]
|
||||
۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۰
|
10
app/src/main/assets/language_key_texts/hi.txt
Normal file
10
app/src/main/assets/language_key_texts/hi.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
[morekeys]
|
||||
punctuation !autoColumnOrder!9 \, . ? ! # ) ( / ; ' @ : - " + \% &
|
||||
|
||||
[labels]
|
||||
alphabet: कखग
|
||||
symbol: ?१२३
|
||||
period: ।
|
||||
|
||||
[number_row]
|
||||
१ २ ३ ४ ५ ६ ७ ८ ९ ०
|
8
app/src/main/assets/language_key_texts/hy.txt
Normal file
8
app/src/main/assets/language_key_texts/hy.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
[morekeys]
|
||||
punctuation !autoColumnOrder!8 \, ՞ ՜ ․ … ' = / ՝ ՛ ֊ » « ― ) (
|
||||
? ՞ ¿
|
||||
! ՜ ¡
|
||||
|
||||
[labels]
|
||||
alphabet: ԱԲԳ
|
||||
period: ։
|
7
app/src/main/assets/language_key_texts/iw.txt
Normal file
7
app/src/main/assets/language_key_texts/iw.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
[morekeys]
|
||||
' ‘ ’ ‚
|
||||
" “ ” „
|
||||
+ ﬩
|
||||
|
||||
[labels]
|
||||
alphabet: אבג
|
6
app/src/main/assets/language_key_texts/ka.txt
Normal file
6
app/src/main/assets/language_key_texts/ka.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
[morekeys]
|
||||
' ’ ‚ ‘
|
||||
" ” „ “
|
||||
|
||||
[labels]
|
||||
alphabet: აბგ
|
12
app/src/main/assets/language_key_texts/kk.txt
Normal file
12
app/src/main/assets/language_key_texts/kk.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
[morekeys]
|
||||
у ү ұ
|
||||
к қ
|
||||
е ё
|
||||
н ң
|
||||
г ғ
|
||||
а ә
|
||||
о ө
|
||||
ь ъ
|
||||
|
||||
[labels]
|
||||
alphabet: АБВ
|
2
app/src/main/assets/language_key_texts/km.txt
Normal file
2
app/src/main/assets/language_key_texts/km.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: កខគ
|
2
app/src/main/assets/language_key_texts/kn.txt
Normal file
2
app/src/main/assets/language_key_texts/kn.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: ಅಆಇ
|
2
app/src/main/assets/language_key_texts/ko.txt
Normal file
2
app/src/main/assets/language_key_texts/ko.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: ㄱㄴㄷ
|
9
app/src/main/assets/language_key_texts/ky.txt
Normal file
9
app/src/main/assets/language_key_texts/ky.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
[morekeys]
|
||||
у ү
|
||||
е ё
|
||||
н ң
|
||||
о ө
|
||||
ь ъ
|
||||
|
||||
[labels]
|
||||
alphabet: АБВ
|
2
app/src/main/assets/language_key_texts/lo.txt
Normal file
2
app/src/main/assets/language_key_texts/lo.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: ກຂຄ
|
8
app/src/main/assets/language_key_texts/mk.txt
Normal file
8
app/src/main/assets/language_key_texts/mk.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
[morekeys]
|
||||
е ѐ
|
||||
и ѝ
|
||||
' ’ ‚ ‘
|
||||
" ” „ “
|
||||
|
||||
[labels]
|
||||
alphabet: АБВ
|
2
app/src/main/assets/language_key_texts/ml.txt
Normal file
2
app/src/main/assets/language_key_texts/ml.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: അ
|
2
app/src/main/assets/language_key_texts/mn.txt
Normal file
2
app/src/main/assets/language_key_texts/mn.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: АБВ
|
6
app/src/main/assets/language_key_texts/mr.txt
Normal file
6
app/src/main/assets/language_key_texts/mr.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
[labels]
|
||||
alphabet: कखग
|
||||
symbol: ?१२३
|
||||
|
||||
[number_row]
|
||||
१ २ ३ ४ ५ ६ ७ ८ ९ ०
|
6
app/src/main/assets/language_key_texts/my.txt
Normal file
6
app/src/main/assets/language_key_texts/my.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
[morekeys]
|
||||
punctuation !autoColumnOrder!9 ၊ . ? ! # ) ( / ; ... ' @ : - " + \% &
|
||||
|
||||
[labels]
|
||||
alphabet: ကခဂ
|
||||
period: ။
|
10
app/src/main/assets/language_key_texts/ne.txt
Normal file
10
app/src/main/assets/language_key_texts/ne.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
[morekeys]
|
||||
punctuation !autoColumnOrder!9 . \, ? ! # ) ( / ; ' @ : - " + \% &
|
||||
|
||||
[labels]
|
||||
alphabet: कखग
|
||||
symbol: ?१२३
|
||||
period: ।
|
||||
|
||||
[number_row]
|
||||
१ २ ३ ४ ५ ६ ७ ८ ९ ०
|
8
app/src/main/assets/language_key_texts/ru.txt
Normal file
8
app/src/main/assets/language_key_texts/ru.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
[morekeys]
|
||||
е ё
|
||||
ь ъ
|
||||
' ’ ‚ ‘
|
||||
" ” „ “
|
||||
|
||||
[labels]
|
||||
alphabet: АБВ
|
2
app/src/main/assets/language_key_texts/si.txt
Normal file
2
app/src/main/assets/language_key_texts/si.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: අ ආ
|
8
app/src/main/assets/language_key_texts/sr.txt
Normal file
8
app/src/main/assets/language_key_texts/sr.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
[morekeys]
|
||||
е ѐ
|
||||
и ѝ
|
||||
' ’ ‚ ‘ › ‹
|
||||
" ” „ “ » «
|
||||
|
||||
[labels]
|
||||
alphabet: АБВ
|
2
app/src/main/assets/language_key_texts/ta_in.txt
Normal file
2
app/src/main/assets/language_key_texts/ta_in.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: தமிழ்
|
2
app/src/main/assets/language_key_texts/ta_lk.txt
Normal file
2
app/src/main/assets/language_key_texts/ta_lk.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: தமிழ்
|
2
app/src/main/assets/language_key_texts/ta_sg.txt
Normal file
2
app/src/main/assets/language_key_texts/ta_sg.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: தமிழ்
|
2
app/src/main/assets/language_key_texts/te.txt
Normal file
2
app/src/main/assets/language_key_texts/te.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: అఆఇ
|
2
app/src/main/assets/language_key_texts/th.txt
Normal file
2
app/src/main/assets/language_key_texts/th.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
[labels]
|
||||
alphabet: กขค
|
8
app/src/main/assets/language_key_texts/uk.txt
Normal file
8
app/src/main/assets/language_key_texts/uk.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
[morekeys]
|
||||
г ґ
|
||||
ь ъ
|
||||
' ’ ‚ ‘
|
||||
" ” „ “
|
||||
|
||||
[labels]
|
||||
alphabet: АБВ
|
11
app/src/main/assets/language_key_texts/ur.txt
Normal file
11
app/src/main/assets/language_key_texts/ur.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
[morekeys]
|
||||
punctuation ؟ ، ! . -
|
||||
|
||||
[labels]
|
||||
alphabet: ابپ
|
||||
comma: ،
|
||||
symbol: ۳۲۱؟
|
||||
period: ۔
|
||||
|
||||
[number_row]
|
||||
۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۰
|
28
app/src/main/assets/layouts/symbols.txt
Normal file
28
app/src/main/assets/layouts/symbols.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
~
|
||||
`
|
||||
|
|
||||
• ♪ ♥ ♠ ♦ ♣
|
||||
√
|
||||
π Π
|
||||
÷
|
||||
×
|
||||
¶ §
|
||||
∆
|
||||
|
||||
@
|
||||
#
|
||||
$$$
|
||||
% ‰
|
||||
&
|
||||
- _ – — ·
|
||||
+ ±
|
||||
( < { [
|
||||
) > } ]
|
||||
|
||||
* † ‡ ★
|
||||
"
|
||||
'
|
||||
:
|
||||
;
|
||||
!
|
||||
?
|
28
app/src/main/assets/layouts/symbols_arabic.txt
Normal file
28
app/src/main/assets/layouts/symbols_arabic.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
~
|
||||
`
|
||||
|
|
||||
• ♪ ♥ ♠ ♦ ♣
|
||||
√
|
||||
π Π
|
||||
÷
|
||||
×
|
||||
¶ §
|
||||
∆
|
||||
|
||||
٬ @
|
||||
٫ #
|
||||
$$$
|
||||
٪ % ‰
|
||||
&
|
||||
- _ – — ·
|
||||
+ ±
|
||||
( ﴾ < { [
|
||||
) ﴿ > } ]
|
||||
|
||||
* ٭ ★ † ‡
|
||||
« „ “ ”
|
||||
» ‚ ‘ ’ ‹ ›
|
||||
:
|
||||
؛ ;
|
||||
!
|
||||
؟ ? ¿
|
28
app/src/main/assets/layouts/symbols_shifted.txt
Normal file
28
app/src/main/assets/layouts/symbols_shifted.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
~
|
||||
`
|
||||
|
|
||||
• ♪ ♥ ♠ ♦ ♣
|
||||
√
|
||||
π Π
|
||||
÷
|
||||
×
|
||||
¶ §
|
||||
∆
|
||||
|
||||
$$$1
|
||||
$$$2
|
||||
$$$3
|
||||
$$$4
|
||||
^ ↑ ↓ ← →
|
||||
° ′ ″
|
||||
= ≠ ≈ ∞
|
||||
{
|
||||
}
|
||||
|
||||
\
|
||||
©
|
||||
®
|
||||
™
|
||||
℅
|
||||
[
|
||||
]
|
|
@ -52,12 +52,10 @@ open class KeyboardBuilder<KP : KeyboardParams>(protected val mContext: Context,
|
|||
mParams.mId = id
|
||||
addLocaleKeyTextsToParams(mContext, mParams, Settings.getInstance().current.mShowMoreKeys)
|
||||
try {
|
||||
val parser = KeyboardParser.createParserForLayout(mParams, mContext) ?: return null
|
||||
Log.d(TAG, "parsing $id using ${parser::class.simpleName}")
|
||||
keysInRows = parser.parseLayoutFromAssets(id.mSubtype.keyboardLayoutSetName)
|
||||
keysInRows = KeyboardParser.parseFromAssets(mParams, mContext) ?: return null
|
||||
} catch (e: Throwable) {
|
||||
if (DebugFlags.DEBUG_ENABLED || BuildConfig.DEBUG)
|
||||
Toast.makeText(mContext, "error loading keyboard: ${e.message}", Toast.LENGTH_LONG).show()
|
||||
Toast.makeText(mContext, "error parsing keyboard: ${e.message}", Toast.LENGTH_LONG).show()
|
||||
Log.e(TAG, "loading $id from assets failed", e)
|
||||
return null
|
||||
}
|
||||
|
@ -65,8 +63,14 @@ open class KeyboardBuilder<KP : KeyboardParams>(protected val mContext: Context,
|
|||
return this
|
||||
|
||||
// todo: further plan
|
||||
// migrate symbol layouts to this style
|
||||
// simplified if possible, but json should be fine too
|
||||
// add option for number row (latin first vs locale numbers first
|
||||
// show only if number row enabled
|
||||
// release next version before continuing
|
||||
// migrate other languages to this style
|
||||
// may be tricky in some cases, like additional row, or no shift key, or pc qwerty layout
|
||||
// also the integrated number row might cause issues, and should be removed / ignored
|
||||
// at least some of these layouts will need more complicated definition
|
||||
// test the zwnj key
|
||||
// migrate keypad layouts to this style
|
||||
// will need more configurable layout definition -> another parser, or do it with compatible jsons
|
||||
// allow users to define their own layouts (maybe migrate other layouts first?)
|
||||
|
@ -105,12 +109,11 @@ open class KeyboardBuilder<KP : KeyboardParams>(protected val mContext: Context,
|
|||
// write another parser, it should already consider split
|
||||
// migrate moreKeys and moreSuggestions to this style?
|
||||
// at least they should not make use of the KeyTextsSet/Table (and of the XmlKeyboardParser?)
|
||||
// migrate other languages to this style
|
||||
// may be difficult in some cases, like additional row, or no shift key, or pc qwerty layout
|
||||
// also the (integrated) number row might cause issues
|
||||
// at least some of these layouts will need more complicated definition, not just a simple text file
|
||||
// some languages also change symbol view, e.g. fa changes symbols row 3
|
||||
// add more layouts before doing this? or just keep the layout conversion script
|
||||
// remove the old parser
|
||||
// then finally the spanish/german/swiss/nordic layouts can be removed and replaced by some hasExtraKeys parameter
|
||||
// also the eo check could then be removed
|
||||
// and maybe the language -> layout thing could be moved to assets? and maybe even here the extra keys could be defined...
|
||||
// should be either both in method.xml, or both in assets (actually method might be more suitable)
|
||||
|
||||
// labelFlags should be set correctly
|
||||
// alignHintLabelToBottom: on lxx and rounded themes, but did not find what it actually does...
|
||||
|
@ -145,7 +148,6 @@ open class KeyboardBuilder<KP : KeyboardParams>(protected val mContext: Context,
|
|||
|
||||
fun loadFromXml(xmlId: Int, id: KeyboardId): KeyboardBuilder<KP> {
|
||||
if (Settings.getInstance().current.mUseNewKeyboardParsing
|
||||
&& id.isAlphabetKeyboard
|
||||
&& this::class == KeyboardBuilder::class // otherwise this will apply to moreKeys and moreSuggestions, and then some parameters are off
|
||||
) {
|
||||
if (loadFromAssets(id) != null)
|
||||
|
|
|
@ -2,7 +2,9 @@ package org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser
|
|||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.util.Log
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.Toast
|
||||
import org.dslul.openboard.inputmethod.keyboard.Key
|
||||
import org.dslul.openboard.inputmethod.keyboard.Key.KeyParams
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardId
|
||||
|
@ -12,9 +14,12 @@ import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardParams
|
|||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.floris.KeyData
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.floris.toTextKey
|
||||
import org.dslul.openboard.inputmethod.latin.R
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants
|
||||
import org.dslul.openboard.inputmethod.latin.common.splitOnWhitespace
|
||||
import org.dslul.openboard.inputmethod.latin.define.DebugFlags
|
||||
import org.dslul.openboard.inputmethod.latin.utils.InputTypeUtils
|
||||
import org.dslul.openboard.inputmethod.latin.utils.RunInLocale
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ScriptUtils
|
||||
import org.dslul.openboard.inputmethod.latin.utils.sumOf
|
||||
|
||||
/**
|
||||
|
@ -29,6 +34,9 @@ import org.dslul.openboard.inputmethod.latin.utils.sumOf
|
|||
* Currently the number, phone and numpad layouts are not compatible with this parser.
|
||||
*/
|
||||
abstract class KeyboardParser(private val params: KeyboardParams, private val context: Context) {
|
||||
private val defaultLabelFlags = if (!params.mId.isAlphabetKeyboard)
|
||||
Key.LABEL_FLAGS_DISABLE_HINT_LABEL // reproduce the no-hints in symbol layouts, todo: add setting
|
||||
else 0
|
||||
|
||||
protected abstract fun getLayoutFromAssets(layoutName: String): String
|
||||
|
||||
|
@ -42,9 +50,13 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
val keysInRows = ArrayList<ArrayList<KeyParams>>()
|
||||
|
||||
val baseKeys: MutableList<List<KeyData>> = parseCoreLayout(layoutContent)
|
||||
if (!params.mId.mNumberRowEnabled) {
|
||||
// todo (non-latin): not all layouts have numbers on first row, so maybe have some layout flag to switch it off (or an option)
|
||||
((1..9) + 0).forEachIndexed { i, n -> baseKeys.first().getOrNull(i)?.popup?.number = n }
|
||||
if (!params.mId.mNumberRowEnabled && params.mId.mElementId == KeyboardId.ELEMENT_SYMBOLS) {
|
||||
// replace first symbols row with number row
|
||||
baseKeys[0] = params.mLocaleKeyTexts.getNumberRow()
|
||||
} else if (!params.mId.mNumberRowEnabled && params.mId.isAlphabetKeyboard) {
|
||||
// add number to the first 10 keys in first row
|
||||
// setting the correct moreKeys is handled in PopupSet
|
||||
baseKeys.first().take(10).forEachIndexed { index, keyData -> keyData.popup.numberIndex = index }
|
||||
}
|
||||
val functionalKeysReversed = parseFunctionalKeys().reversed()
|
||||
|
||||
|
@ -98,7 +110,7 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
for (key in row) {
|
||||
// todo: maybe autoScale / autoXScale if label has more than 2 characters (exception for emojis?)
|
||||
// but that could also be determined in toKeyParams
|
||||
val keyParams = key.compute(params)?.toKeyParams(params, keyWidth) ?: continue
|
||||
val keyParams = key.compute(params)?.toKeyParams(params, keyWidth, defaultLabelFlags) ?: continue
|
||||
paramsRow.add(keyParams)
|
||||
}
|
||||
if (spacerWidth != 0f) {
|
||||
|
@ -185,25 +197,25 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
adjustedKeys?.get(1)?.label ?: "/",
|
||||
params,
|
||||
params.mDefaultRelativeKeyWidth,
|
||||
0,
|
||||
defaultLabelFlags,
|
||||
Key.BACKGROUND_TYPE_FUNCTIONAL,
|
||||
adjustedKeys?.get(1)?.popup?.toMoreKeys(params)
|
||||
))
|
||||
} else if (params.mId.mElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED) {
|
||||
bottomRow.add(KeyParams(
|
||||
adjustedKeys?.get(1)?.label ?: "<",
|
||||
(adjustedKeys?.get(1)?.label ?: "<").rtlLabel(params),
|
||||
params,
|
||||
params.mDefaultRelativeKeyWidth,
|
||||
0,
|
||||
defaultLabelFlags,
|
||||
Key.BACKGROUND_TYPE_FUNCTIONAL,
|
||||
adjustedKeys?.get(1)?.popup?.toMoreKeys(params)
|
||||
))
|
||||
bottomRow.add(keyParams)
|
||||
bottomRow.add(KeyParams(
|
||||
adjustedKeys?.get(2)?.label ?: ">",
|
||||
(adjustedKeys?.get(2)?.label ?: ">").rtlLabel(params),
|
||||
params,
|
||||
params.mDefaultRelativeKeyWidth,
|
||||
0,
|
||||
defaultLabelFlags,
|
||||
Key.BACKGROUND_TYPE_FUNCTIONAL,
|
||||
adjustedKeys?.get(2)?.popup?.toMoreKeys(params)
|
||||
))
|
||||
|
@ -214,7 +226,7 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
bottomRow.add(getFunctionalKeyParams(FunctionalKey.EMOJI))
|
||||
bottomRow.add(keyParams)
|
||||
if (params.mId.locale.language in languagesThatNeedZwnjKey)
|
||||
bottomRow.add(getFunctionalKeyParams(FunctionalKey.ZWNJ)) // todo (non-latin): test it
|
||||
bottomRow.add(getFunctionalKeyParams(FunctionalKey.ZWNJ))
|
||||
}
|
||||
} else {
|
||||
bottomRow.add(keyParams)
|
||||
|
@ -226,19 +238,9 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
return bottomRow
|
||||
}
|
||||
|
||||
private fun getNumberRow(): ArrayList<KeyParams> {
|
||||
val row = ArrayList<KeyParams>()
|
||||
((1..9) + 0).forEachIndexed { i, n ->
|
||||
row.add(KeyParams(
|
||||
n.toString(), // todo (non-latin): use language more keys to adjust, possibly in combination with some setting
|
||||
params,
|
||||
params.mDefaultRelativeKeyWidth,
|
||||
Key.LABEL_FLAGS_DISABLE_HINT_LABEL, // todo (later): maybe optional or enable (but then all numbers should have moreKeys)
|
||||
Key.BACKGROUND_TYPE_NORMAL,
|
||||
numbersMoreKeys[i] // todo (non-latin): alternative numbers should be in language more keys, which to put where needs to be decided
|
||||
))
|
||||
}
|
||||
return row
|
||||
private fun getNumberRow(): ArrayList<KeyParams> =
|
||||
params.mLocaleKeyTexts.getNumberRow().mapTo(ArrayList()) {
|
||||
it.toKeyParams(params, labelFlags = Key.LABEL_FLAGS_DISABLE_HINT_LABEL or defaultLabelFlags)
|
||||
}
|
||||
|
||||
private fun getFunctionalKeyParams(def: String, label: String? = null, moreKeys: Array<String>? = null): KeyParams {
|
||||
|
@ -254,7 +256,17 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
val width = relativeWidth ?: params.mDefaultRelativeKeyWidth
|
||||
return when (key) {
|
||||
FunctionalKey.SYMBOL -> KeyParams(
|
||||
"${getSymbolLabel()}|!code/key_switch_alpha_symbol", // todo (later): in numpad the code is key_symbolNumpad
|
||||
getToSymbolLabel(),
|
||||
getToSymbolCode(),
|
||||
params,
|
||||
width,
|
||||
Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR,
|
||||
Key.BACKGROUND_TYPE_FUNCTIONAL,
|
||||
null
|
||||
)
|
||||
FunctionalKey.ALPHA -> KeyParams(
|
||||
params.mLocaleKeyTexts.labelAlphabet,
|
||||
getToAlphaCode(),
|
||||
params,
|
||||
width,
|
||||
Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR,
|
||||
|
@ -262,15 +274,23 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
null
|
||||
)
|
||||
FunctionalKey.COMMA -> KeyParams(
|
||||
label ?: getDefaultCommaLabel(),
|
||||
label ?: getCommaLabel(),
|
||||
params,
|
||||
width,
|
||||
Key.LABEL_FLAGS_HAS_POPUP_HINT, // previously only if normal comma, but always is more correct
|
||||
if (label?.first()
|
||||
?.isLetter() == true
|
||||
) Key.BACKGROUND_TYPE_NORMAL else Key.BACKGROUND_TYPE_FUNCTIONAL,
|
||||
if (label?.first()?.isLetter() == true) Key.BACKGROUND_TYPE_NORMAL // mimic behavior of old dvorak and halmak layouts
|
||||
else Key.BACKGROUND_TYPE_FUNCTIONAL,
|
||||
moreKeys?.let { getCommaMoreKeys() + it } ?: getCommaMoreKeys()
|
||||
)
|
||||
FunctionalKey.PERIOD -> KeyParams(
|
||||
label ?: params.mLocaleKeyTexts.labelPeriod,
|
||||
params,
|
||||
width,
|
||||
Key.LABEL_FLAGS_HAS_POPUP_HINT or Key.LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT or defaultLabelFlags, // todo (later): check what LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT does, maybe remove the flag here
|
||||
if (label?.first()?.isLetter() == true) Key.BACKGROUND_TYPE_NORMAL
|
||||
else Key.BACKGROUND_TYPE_FUNCTIONAL,
|
||||
moreKeys?.let { getPunctuationMoreKeys() + it } ?: getPunctuationMoreKeys()
|
||||
)
|
||||
FunctionalKey.SPACE -> KeyParams(
|
||||
"!icon/space_key|!code/key_space", // !icon/space_key_for_number_layout in number layout, but not on tablet
|
||||
params,
|
||||
|
@ -279,16 +299,6 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
Key.BACKGROUND_TYPE_SPACEBAR,
|
||||
null
|
||||
)
|
||||
FunctionalKey.PERIOD -> KeyParams(
|
||||
label ?: ".",
|
||||
params,
|
||||
width,
|
||||
Key.LABEL_FLAGS_HAS_POPUP_HINT or Key.LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT, // todo (later): check what LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT does, maybe remove the flag here
|
||||
if (label?.first()
|
||||
?.isLetter() == true
|
||||
) Key.BACKGROUND_TYPE_NORMAL else Key.BACKGROUND_TYPE_FUNCTIONAL,
|
||||
moreKeys?.let { getPunctuationMoreKeys() + it } ?: getPunctuationMoreKeys()
|
||||
)
|
||||
FunctionalKey.ACTION -> KeyParams(
|
||||
"${getActionKeyLabel()}|${getActionKeyCode()}",
|
||||
params,
|
||||
|
@ -348,14 +358,6 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
Key.BACKGROUND_TYPE_FUNCTIONAL,
|
||||
null
|
||||
)
|
||||
FunctionalKey.ALPHA -> KeyParams(
|
||||
"${getAlphabetLabel()}|!code/key_switch_alpha_symbol", // todo (later): in numpad the code is key_alphaNumpad
|
||||
params,
|
||||
width,
|
||||
Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR,
|
||||
Key.BACKGROUND_TYPE_FUNCTIONAL,
|
||||
null
|
||||
)
|
||||
FunctionalKey.NUMPAD -> KeyParams(
|
||||
"!icon/numpad_key|!code/key_numpad",
|
||||
params,
|
||||
|
@ -460,34 +462,51 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
private fun String.replaceIconWithLabelIfNoDrawable(): String {
|
||||
if (params.mIconsSet.getIconDrawable(KeyboardIconsSet.getIconId(this)) != null) return this
|
||||
val id = context.resources.getIdentifier("label_$this", "string", context.packageName)
|
||||
if (id == 0) {
|
||||
Log.w(this::class.simpleName, "no resource for label $this")
|
||||
if (DebugFlags.DEBUG_ENABLED)
|
||||
Toast.makeText(context, "no resource for label $this", Toast.LENGTH_LONG).show()
|
||||
return this
|
||||
}
|
||||
val ril = object : RunInLocale<String>() { // todo (later): simpler way of doing this in a single line?
|
||||
override fun job(res: Resources) = res.getString(id)
|
||||
}
|
||||
return ril.runInLocale(context.resources, params.mId.locale)
|
||||
}
|
||||
|
||||
private fun getAlphabetLabel() = params.mLocaleKeyTexts.labelAlphabet
|
||||
private fun getToSymbolLabel() =
|
||||
if (params.mId.mElementId == KeyboardId.ELEMENT_SYMBOLS || params.mId.mElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED)
|
||||
params.mLocaleKeyTexts.labelAlphabet
|
||||
else params.mLocaleKeyTexts.labelSymbol
|
||||
|
||||
private fun getSymbolLabel() = params.mLocaleKeyTexts.labelSymbols
|
||||
private fun getToSymbolCode() =
|
||||
if (params.mId.mElementId == KeyboardId.ELEMENT_NUMPAD)
|
||||
Constants.CODE_SYMBOL_FROM_NUMPAD
|
||||
else Constants.CODE_SWITCH_ALPHA_SYMBOL
|
||||
|
||||
private fun getToAlphaCode() =
|
||||
if (params.mId.mElementId == KeyboardId.ELEMENT_NUMPAD)
|
||||
Constants.CODE_ALPHA_FROM_NUMPAD
|
||||
else Constants.CODE_SWITCH_ALPHA_SYMBOL
|
||||
|
||||
private fun getShiftLabel(): String {
|
||||
val elementId = params.mId.mElementId
|
||||
if (elementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED)
|
||||
return params.mLocaleKeyTexts.labelShiftSymbols
|
||||
return params.mLocaleKeyTexts.labelSymbol
|
||||
if (elementId == KeyboardId.ELEMENT_SYMBOLS)
|
||||
return getSymbolLabel()
|
||||
return params.mLocaleKeyTexts.labelShiftSymbol
|
||||
if (elementId == KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED || elementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED
|
||||
|| elementId == KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED || elementId == KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED)
|
||||
return "!icon/shift_key_shifted"
|
||||
return "!icon/shift_key"
|
||||
}
|
||||
|
||||
private fun getDefaultCommaLabel(): String {
|
||||
private fun getCommaLabel(): String {
|
||||
if (params.mId.mMode == KeyboardId.MODE_URL)
|
||||
return "/"
|
||||
if (params.mId.mMode == KeyboardId.MODE_EMAIL)
|
||||
return "\\@"
|
||||
return ","
|
||||
return params.mLocaleKeyTexts.labelComma
|
||||
}
|
||||
|
||||
private fun getCommaMoreKeys(): Array<String> {
|
||||
|
@ -509,7 +528,6 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
if (params.mId.mElementId == KeyboardId.ELEMENT_SYMBOLS || params.mId.mElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED)
|
||||
return arrayOf("…")
|
||||
val moreKeys = params.mLocaleKeyTexts.getMoreKeys("punctuation") ?:
|
||||
// todo: some (non-latin) languages have different parenthesis keys (maybe rtl has inverted?)
|
||||
arrayOf("${Key.MORE_KEYS_AUTO_COLUMN_ORDER}8", "\\,", "?", "!", "#", ")", "(", "/", ";", "'", "@", ":", "-", "\"", "+", "\\%", "&")
|
||||
if (context.resources.getInteger(R.integer.config_screen_metrics) >= 3 && moreKeys.contains("!") && moreKeys.contains("?")) {
|
||||
// we have a tablet, remove ! and ? keys and reduce number in autoColumnOrder
|
||||
|
@ -524,19 +542,26 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
}
|
||||
|
||||
companion object {
|
||||
fun createParserForLayout(params: KeyboardParams, context: Context): KeyboardParser? {
|
||||
fun parseFromAssets(params: KeyboardParams, context: Context): ArrayList<ArrayList<KeyParams>>? {
|
||||
val id = params.mId
|
||||
val layoutName = params.mId.mSubtype.keyboardLayoutSetName
|
||||
val layoutFileNames = context.assets.list("layouts") ?: return null
|
||||
if (layoutFileNames.contains("$layoutName.json"))
|
||||
return JsonKeyboardParser(params, context)
|
||||
val simpleLayoutName = getSimpleLayoutName(layoutName)
|
||||
if (layoutFileNames.contains("$simpleLayoutName.txt"))
|
||||
return SimpleKeyboardParser(params, context)
|
||||
return null
|
||||
return when {
|
||||
id.mElementId == KeyboardId.ELEMENT_SYMBOLS && ScriptUtils.getScriptFromSpellCheckerLocale(params.mId.locale) == ScriptUtils.SCRIPT_ARABIC
|
||||
-> SimpleKeyboardParser(params, context).parseLayoutFromAssets("symbols_arabic")
|
||||
id.mElementId == KeyboardId.ELEMENT_SYMBOLS -> SimpleKeyboardParser(params, context).parseLayoutFromAssets("symbols")
|
||||
id.mElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED
|
||||
-> SimpleKeyboardParser(params, context).parseLayoutFromAssets("symbols_shifted")
|
||||
!id.isAlphabetKeyboard -> null
|
||||
layoutFileNames.contains("$layoutName.json") -> JsonKeyboardParser(params, context).parseLayoutFromAssets(layoutName)
|
||||
layoutFileNames.contains("${getSimpleLayoutName(layoutName)}.txt")
|
||||
-> SimpleKeyboardParser(params, context).parseLayoutFromAssets(layoutName)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic // unsupported without JvmStatic
|
||||
protected fun getSimpleLayoutName(layoutName: String)= when (layoutName) {
|
||||
protected fun getSimpleLayoutName(layoutName: String) = when (layoutName) {
|
||||
"swiss", "german", "serbian_qwertz" -> "qwertz"
|
||||
"nordic", "spanish" -> "qwerty"
|
||||
else -> layoutName
|
||||
|
@ -548,20 +573,29 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
}
|
||||
|
||||
}
|
||||
// moreKeys for numbers, order is 1-9 and then 0
|
||||
// todo (later): like numbers, for non-latin layouts this depends on language and therefore should not be in the parser
|
||||
private val numbersMoreKeys = arrayOf(
|
||||
arrayOf("¹", "½", "⅓","¼", "⅛"),
|
||||
arrayOf("²", "⅔"),
|
||||
arrayOf("³", "¾", "⅜"),
|
||||
arrayOf("⁴"),
|
||||
arrayOf("⅝"),
|
||||
null,
|
||||
arrayOf("⅞"),
|
||||
null,
|
||||
null,
|
||||
arrayOf("ⁿ", "∅"),
|
||||
)
|
||||
|
||||
fun String.rtlLabel(params: KeyboardParams): String {
|
||||
if (!params.mId.mSubtype.isRtlSubtype) return this
|
||||
return when (this) {
|
||||
"{" -> "{|}"
|
||||
"}" -> "}|{"
|
||||
"(" -> "(|)"
|
||||
")" -> ")|("
|
||||
"[" -> "{|]"
|
||||
"]" -> "]|["
|
||||
"<" -> "<|>"
|
||||
">" -> ">|<"
|
||||
"≤" -> "≤|≥"
|
||||
"≥" -> "≥|≤"
|
||||
"«" -> "«|»"
|
||||
"»" -> "»|«"
|
||||
"‹" -> "‹|›"
|
||||
"›" -> "›|‹"
|
||||
"﴾" -> "﴾|﴿"
|
||||
"﴿" -> "﴿|﴾"
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
// could make arrays right away, but they need to be copied anyway as moreKeys arrays are modified when creating KeyParams
|
||||
private const val MORE_KEYS_NAVIGATE_PREVIOUS = "!icon/previous_key|!code/key_action_previous,!icon/clipboard_action_key|!code/key_clipboard"
|
||||
|
|
|
@ -11,12 +11,34 @@ import java.io.InputStream
|
|||
import java.util.Locale
|
||||
import kotlin.math.round
|
||||
|
||||
class LocaleKeyTexts(dataStream: InputStream?) {
|
||||
class LocaleKeyTexts(dataStream: InputStream?, locale: Locale) {
|
||||
private val moreKeys = hashMapOf<String, Array<String>>()
|
||||
private val extraKeys = Array<MutableList<KeyData>?>(5) { null }
|
||||
var labelSymbols = "\\?123"
|
||||
var labelSymbol = "\\?123"
|
||||
private set
|
||||
var labelAlphabet = "ABC"
|
||||
var labelShiftSymbols = "=\\<"
|
||||
private set
|
||||
var labelShiftSymbol = "= \\\\ <"
|
||||
private set
|
||||
var labelComma = ","
|
||||
private set
|
||||
var labelPeriod = "."
|
||||
private set
|
||||
val currencyKey = getCurrencyKey(locale)
|
||||
private var numberKeys = ((1..9) + 0).map { it.toString() }
|
||||
private val numbersMoreKeys = arrayOf(
|
||||
mutableListOf("¹", "½", "⅓","¼", "⅛"),
|
||||
mutableListOf("²", "⅔"),
|
||||
mutableListOf("³", "¾", "⅜"),
|
||||
mutableListOf("⁴"),
|
||||
mutableListOf("⅝"),
|
||||
mutableListOf(),
|
||||
mutableListOf("⅞"),
|
||||
mutableListOf(),
|
||||
mutableListOf(),
|
||||
mutableListOf("ⁿ", "∅"),
|
||||
)
|
||||
|
||||
init {
|
||||
readStream(dataStream, false)
|
||||
// set default quote moreKeys if necessary
|
||||
|
@ -42,11 +64,13 @@ class LocaleKeyTexts(dataStream: InputStream?) {
|
|||
"[morekeys]" -> { mode = READER_MODE_MORE_KEYS; return@forEachLine }
|
||||
"[extra_keys]" -> { mode = READER_MODE_EXTRA_KEYS; return@forEachLine }
|
||||
"[labels]" -> { mode = READER_MODE_LABELS; return@forEachLine }
|
||||
"[number_row]" -> { mode = READER_MODE_NUMBER_ROW; return@forEachLine }
|
||||
}
|
||||
when (mode) {
|
||||
READER_MODE_MORE_KEYS -> addMoreKeys(line.splitOnWhitespace())
|
||||
READER_MODE_EXTRA_KEYS -> if (!onlyMoreKeys) addExtraKey(line.split(colonSpaceRegex, 2))
|
||||
READER_MODE_LABELS -> if (!onlyMoreKeys) addLabel(line.split(colonSpaceRegex, 2))
|
||||
READER_MODE_NUMBER_ROW -> if (!onlyMoreKeys) setNumberRow(line.splitOnWhitespace())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +79,7 @@ class LocaleKeyTexts(dataStream: InputStream?) {
|
|||
// need tp provide a copy because some functions like MoreKeySpec.insertAdditionalMoreKeys may modify the array
|
||||
fun getMoreKeys(label: String): Array<String>? = moreKeys[label]?.copyOf()
|
||||
|
||||
// used by simple parser only, but could be possible for json as well (if necessary)
|
||||
fun getExtraKeys(row: Int): List<KeyData>? =
|
||||
if (row > extraKeys.size) null
|
||||
else extraKeys[row]
|
||||
|
@ -84,11 +109,33 @@ class LocaleKeyTexts(dataStream: InputStream?) {
|
|||
private fun addLabel(split: List<String>) {
|
||||
if (split.size < 2) return
|
||||
when (split.first()) {
|
||||
"symbols" -> labelSymbols = split.last()
|
||||
"symbol" -> labelSymbol = split.last()
|
||||
"alphabet" -> labelAlphabet = split.last()
|
||||
"shift_symbols" -> labelShiftSymbols = split.last()
|
||||
"shift_symbol" -> labelShiftSymbol = split.last() // never used, but could be...
|
||||
"comma" -> labelComma = split.last()
|
||||
"period" -> labelPeriod = split.last()
|
||||
}
|
||||
}
|
||||
|
||||
// set number row only, does not affect moreKeys
|
||||
// setting more than 10 number keys will cause crashes, but could actually be implemented at some point
|
||||
private fun setNumberRow(split: List<String>) {
|
||||
if (numberKeys == split) return
|
||||
numberKeys.forEachIndexed { i, n -> numbersMoreKeys[i].add(0, n) }
|
||||
numberKeys = split
|
||||
}
|
||||
|
||||
// get number row including moreKeys
|
||||
fun getNumberRow(): List<KeyData> =
|
||||
numberKeys.mapIndexed { i, label ->
|
||||
label.toTextKey(numbersMoreKeys[i])
|
||||
}
|
||||
|
||||
// get moreKeys with the number itself (as used on alphabet keyboards)
|
||||
fun getNumberMoreKeys(numberIndex: Int?): List<String> {
|
||||
if (numberIndex == null) return emptyList()
|
||||
return listOf(numberKeys[numberIndex]) + numbersMoreKeys[numberIndex]
|
||||
}
|
||||
}
|
||||
|
||||
private fun mergeMoreKeys(original: Array<String>, added: List<String>): Array<String> {
|
||||
|
@ -141,7 +188,7 @@ fun addLocaleKeyTextsToParams(context: Context, params: KeyboardParams, moreKeys
|
|||
}
|
||||
|
||||
private fun createLocaleKeyTexts(context: Context, params: KeyboardParams, moreKeysSetting: Int): LocaleKeyTexts {
|
||||
val lkt = LocaleKeyTexts(getStreamForLocale(params.mId.locale, context))
|
||||
val lkt = LocaleKeyTexts(getStreamForLocale(params.mId.locale, context), params.mId.locale)
|
||||
if (moreKeysSetting == MORE_KEYS_MORE)
|
||||
lkt.addFile(context.assets.open("$LANGUAGE_TEXTS_FOLDER/all_more_keys.txt"))
|
||||
else if (moreKeysSetting == MORE_KEYS_ALL)
|
||||
|
@ -174,16 +221,17 @@ private const val READER_MODE_NONE = 0
|
|||
private const val READER_MODE_MORE_KEYS = 1
|
||||
private const val READER_MODE_EXTRA_KEYS = 2
|
||||
private const val READER_MODE_LABELS = 3
|
||||
private const val READER_MODE_NUMBER_ROW = 4
|
||||
|
||||
// probably could be improved and extended, currently this is what's done in key_styles_currency.xml
|
||||
fun getCurrencyKey(locale: Locale): Pair<String, Array<String>> {
|
||||
private fun getCurrencyKey(locale: Locale): Pair<String, Array<String>> {
|
||||
if (locale.country.matches(euroCountries))
|
||||
return euro
|
||||
if (locale.toString().matches(euroLocales))
|
||||
return euro
|
||||
if (locale.language.matches("ca|eu|lb|mt".toRegex()))
|
||||
return euro
|
||||
if (locale.language.matches("fa|iw|ko|lo|mn|ne|th|uk|vi".toRegex()))
|
||||
if (locale.language.matches("fa|iw|ko|lo|mn|ne|si|th|uk|vi|km".toRegex()))
|
||||
return genericCurrencyKey(getCurrency(locale))
|
||||
if (locale.language == "hy")
|
||||
return dram
|
||||
|
@ -193,6 +241,8 @@ fun getCurrencyKey(locale: Locale): Pair<String, Array<String>> {
|
|||
return ruble
|
||||
if (locale.country == "LK" || locale.country == "BD")
|
||||
return genericCurrencyKey(getCurrency(locale))
|
||||
if (locale.country == "IN" && locale.language == "ta")
|
||||
return genericCurrencyKey("௹")
|
||||
if (locale.country == "IN" || locale.language.matches("hi|kn|ml|mr|ta|te".toRegex()))
|
||||
return rupee
|
||||
if (locale.country == "GB")
|
||||
|
@ -217,6 +267,7 @@ private fun getCurrency(locale: Locale): String {
|
|||
"th" -> "฿"
|
||||
"uk" -> "₴"
|
||||
"vi" -> "₫"
|
||||
"km" -> "៛"
|
||||
else -> "$"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.dslul.openboard.inputmethod.latin.common.splitOnWhitespace
|
|||
*/
|
||||
class SimpleKeyboardParser(private val params: KeyboardParams, private val context: Context) : KeyboardParser(params, context) {
|
||||
private val addExtraKeys =
|
||||
params.mId.locale.language != "eo"
|
||||
params.mId.isAlphabetKeyboard && params.mId.locale.language != "eo"
|
||||
&& params.mId.mSubtype.keyboardLayoutSetName in listOf("nordic", "spanish", "german", "swiss", "serbian_qwertz")
|
||||
|
||||
override fun getLayoutFromAssets(layoutName: String) =
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.dslul.openboard.inputmethod.keyboard.Key
|
|||
import org.dslul.openboard.inputmethod.keyboard.Key.KeyParams
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardId
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardParams
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.rtlLabel
|
||||
import org.dslul.openboard.inputmethod.latin.common.StringUtils
|
||||
|
||||
// taken from FlorisBoard, small modifications
|
||||
|
@ -113,7 +114,7 @@ interface KeyData : AbstractKeyData {
|
|||
// code will be determined from label if possible (i.e. label is single code point)
|
||||
// but also longer labels should work without issues, also for MultiTextKeyData
|
||||
KeyParams(
|
||||
label, // todo (when supported): convert special labels to keySpec
|
||||
label.rtlLabel(params), // todo (when supported): convert special labels to keySpec
|
||||
params,
|
||||
width,
|
||||
labelFlags, // todo (non-latin): label flags... maybe relevant for some languages
|
||||
|
@ -123,7 +124,7 @@ interface KeyData : AbstractKeyData {
|
|||
} else {
|
||||
KeyParams(
|
||||
label.ifEmpty { StringUtils.newSingleCodePointString(code) },
|
||||
code, // todo (when supported): convert codes < 0
|
||||
code, // todo (when supported): convert codes < 0, because florisboard layouts should still be usable
|
||||
params,
|
||||
width,
|
||||
labelFlags,
|
||||
|
|
|
@ -6,12 +6,12 @@ package org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.floris
|
|||
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardParams
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.getCurrencyKey
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.rtlLabel
|
||||
|
||||
// taken from FlorisBoard, small modifications
|
||||
// mutable set removed (currently the moreKeys assembly is happening in KeyParams)
|
||||
// toMoreKeys and size added
|
||||
// popupKeys not used, but might switch to this later
|
||||
// .toMoreKeys added
|
||||
// PopupKeys not used, but might switch to this later
|
||||
// currently hint would be taken from other, and languageMoreKeys are prioritized
|
||||
/**
|
||||
* A popup set for a single key. This set describes, if the key has a [main] character and other [relevant] popups.
|
||||
|
@ -29,23 +29,27 @@ open class PopupSet<T : AbstractKeyData>(
|
|||
// could make use of PopupKeys, and also provide a hint depending on user choice
|
||||
// then language key joining should be done in here too
|
||||
// also what about getting the moreKeys and key hint from chosen symbol layout?
|
||||
fun toMoreKeys(params: KeyboardParams) = if (isEmpty) null // need null instead of empty array for KeyParams
|
||||
else (listOfNotNull(number?.toString(), main?.getLabel(params)) + relevant
|
||||
// todo: this is not nice and creates unnecessary intermediate lists
|
||||
// best treat the currency key properly, like florisboard does
|
||||
.map { it.getLabel(params) }).map {
|
||||
if (it == "$$$") {
|
||||
fun toMoreKeys(params: KeyboardParams): Array<String>? {
|
||||
val moreKeys = mutableListOf<String>()
|
||||
// number + main + relevant in this order (label is later taken from first element in resulting array)
|
||||
moreKeys.addAll(params.mLocaleKeyTexts.getNumberMoreKeys(numberIndex))
|
||||
main?.getLabel(params)?.let { moreKeys.add(it) }
|
||||
moreKeys.addAll(relevant.map {
|
||||
val label = it.getLabel(params)
|
||||
if (label == "$$$") { // currency key
|
||||
if (params.mId.passwordInput()) "$"
|
||||
else getCurrencyKey(params.mId.locale).first
|
||||
else params.mLocaleKeyTexts.currencyKey.first
|
||||
} else if (params.mId.mSubtype.isRtlSubtype) {
|
||||
label.rtlLabel(params)
|
||||
} else label
|
||||
})
|
||||
return moreKeys.takeIf { it.isNotEmpty() }?.toTypedArray()
|
||||
}
|
||||
else it
|
||||
}.toTypedArray()
|
||||
|
||||
private val popupKeys: PopupKeys<T> by lazy {
|
||||
PopupKeys(null, listOfNotNull(main), relevant)
|
||||
}
|
||||
var number: Int? = null
|
||||
val isEmpty get() = main == null && relevant.isEmpty() && number == null
|
||||
var numberIndex: Int? = null
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,13 +8,12 @@ package org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.floris
|
|||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import org.dslul.openboard.inputmethod.keyboard.Key
|
||||
import org.dslul.openboard.inputmethod.keyboard.Key.KeyParams
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardParams
|
||||
|
||||
// taken from FlorisBoard, small modifications (see also KeyData)
|
||||
// internal keys removed (currently no plan to support them)
|
||||
// added String.toTextKey
|
||||
// currency key handling (see todo below...)
|
||||
/**
|
||||
* Data class which describes a single key and its attributes.
|
||||
*
|
||||
|
@ -41,6 +40,12 @@ class TextKeyData(
|
|||
// TextKeyData(type, data.code, data.label, groupId, popup).compute(params)
|
||||
// }
|
||||
// }
|
||||
if (label.startsWith("$$$")) { // currency key
|
||||
if (label == "$$$") return params.mLocaleKeyTexts.currencyKey.let { it.first.toTextKey(it.second.toList()) }
|
||||
val n = label.substringAfter("$$$").toIntOrNull()
|
||||
if (n != null && n <= 4)
|
||||
return params.mLocaleKeyTexts.currencyKey.second[n - 1].toTextKey()
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,8 @@ public class ScriptUtils {
|
|||
mLanguageCodeToScriptCode = new TreeMap<>();
|
||||
mLanguageCodeToScriptCode.put("", SCRIPT_LATIN); // default
|
||||
mLanguageCodeToScriptCode.put("ar", SCRIPT_ARABIC);
|
||||
mLanguageCodeToScriptCode.put("ur", SCRIPT_ARABIC);
|
||||
mLanguageCodeToScriptCode.put("fa", SCRIPT_ARABIC);
|
||||
mLanguageCodeToScriptCode.put("hy", SCRIPT_ARMENIAN);
|
||||
mLanguageCodeToScriptCode.put("bg", SCRIPT_BULGARIAN);
|
||||
mLanguageCodeToScriptCode.put("bn", SCRIPT_BENGALI);
|
||||
|
|
|
@ -29,6 +29,8 @@ def read_keys(file):
|
|||
root = ET.parse(file).getroot()
|
||||
morekeys = dict()
|
||||
extra_keys = dict()
|
||||
labels = dict()
|
||||
number_row = dict()
|
||||
for key in root.iter("resources"):
|
||||
for string in key.iter("string"):
|
||||
for tag, value in string.items():
|
||||
|
@ -41,23 +43,51 @@ def read_keys(file):
|
|||
text = resolve_text(string.text, file)
|
||||
if "!text/" in text:
|
||||
raise ValueError(f"can't have !text/ in {text} (from {string.text})")
|
||||
if " " in text:
|
||||
if " " in text and "fixedColumnOrder" not in text: # issues with arabic punctuation (more) keys
|
||||
raise ValueError(f"can't have consecutive spaces in {text} (from {string.text})")
|
||||
if value.startswith("keyspec_") and "_row" in value:
|
||||
# put additional key labels (for nordic, spanish, swiss)
|
||||
if value.startswith("keyspec_") and "_row" in value and "slavic" not in value:
|
||||
# put additional key labels (for nordic, spanish, swiss, german, but not for slavic, because here the keys are not extra)
|
||||
key = value.split("_row")[1]
|
||||
d = extra_keys.get(key, dict())
|
||||
d["label"] = text
|
||||
extra_keys[key] = d
|
||||
elif value.startswith("morekeys_") and "_row" in value:
|
||||
# put additional key morekeys (for nordic, spanish, swiss)
|
||||
elif value.startswith("morekeys_") and "_row" in value and "slavic" not in value:
|
||||
# put additional key morekeys (for nordic, spanish, swiss, german, but not for slavic, because here the keys are not extra)
|
||||
key = value.split("_row")[1]
|
||||
d = extra_keys.get(key, dict())
|
||||
d["morekeys"] = text
|
||||
extra_keys[key] = d
|
||||
elif value.startswith("morekeys_"):
|
||||
key_label = value.split("morekeys_")[1]
|
||||
if key_label == "period":
|
||||
key_label = "punctuation" # used in the same place
|
||||
if len(key_label) > 1 and key_label != "punctuation":
|
||||
if key_label.startswith("cyrillic_"):
|
||||
label = key_label.split("cyrillic_")[1]
|
||||
if label == "u":
|
||||
key_label = "у"
|
||||
elif label == "ka":
|
||||
key_label = "к"
|
||||
elif label == "ie":
|
||||
key_label = "е"
|
||||
elif label == "en":
|
||||
key_label = "н"
|
||||
elif label == "ghe":
|
||||
key_label = "г"
|
||||
elif label == "o":
|
||||
key_label = "о"
|
||||
elif label == "soft_sign":
|
||||
key_label = "ь"
|
||||
elif label == "a":
|
||||
key_label = "а"
|
||||
elif label == "i":
|
||||
key_label = "и"
|
||||
else:
|
||||
print(f"ignoring cyrillic long more key: {key_label}: {text}")
|
||||
continue
|
||||
else:
|
||||
if key_label not in ["bullet", "star", "left_parenthesis", "right_parenthesis", "less_than", "greater_than", "symbols_semicolon", "symbols_percent"]:
|
||||
# only print for keys that are not already handled
|
||||
print(f"ignoring long more key: {key_label}: {text}")
|
||||
continue
|
||||
morekeys[key_label] = text
|
||||
|
@ -69,19 +99,35 @@ def read_keys(file):
|
|||
prepend_to_morekeys(morekeys, text, '\"')
|
||||
elif value == "double_angle_quotes":
|
||||
append_to_morekeys(morekeys, text, '\"')
|
||||
# todo: labels should be in [labels] and use sth like symbols: ?123
|
||||
elif value == "keylabel_to_alpha":
|
||||
labels["alphabet"] = text
|
||||
elif value == "keylabel_to_symbol":
|
||||
labels["symbol"] = text
|
||||
elif value == "keyspec_comma":
|
||||
labels["comma"] = text
|
||||
elif value == "keyspec_period":
|
||||
labels["period"] = text
|
||||
elif value.startswith("keyspec_symbols_") and len(value.split("keyspec_symbols_")[1]) == 1: # checking whether it's an int would be better, but bah
|
||||
number_row[value.split("keyspec_symbols_")[1]] = text
|
||||
elif "values-ur" in file and value.startswith("additional_morekeys_symbols_"):
|
||||
number_row[value.split("additional_morekeys_symbols_")[1]] = text
|
||||
# for some reason ur has the arabic numbers in moreKeys
|
||||
elif value in ["keyspec_currency", "symbols_semicolon", "symbols_percent"] or value.startswith("additional_morekeys_symbols_") or "_left_" in value or "_right_" in value or "_greater" in value or "_less_" in value:
|
||||
pass # ignore keys handled somewhere else (currency key not yet fully replaced)
|
||||
else:
|
||||
print(f"ignored tag: {tag}={value}, {text}")
|
||||
keys = dict()
|
||||
keys["morekeys"] = morekeys
|
||||
keys["extra_keys"] = extra_keys
|
||||
keys["labels"] = labels
|
||||
keys["number_row"] = number_row
|
||||
return keys
|
||||
|
||||
|
||||
def resolve_text(text, file):
|
||||
if text.startswith("\"") and text.endswith("\"") and len(text) > 1:
|
||||
text = text[1:-1]
|
||||
sp = re.split("(?<!\\\\),", text)
|
||||
sp = re.split("(?<!\\\\),", text) # split on comma, but not on escaped comma "\,"
|
||||
|
||||
if len(sp) > 1: # resolve each entry separately
|
||||
result = []
|
||||
|
@ -121,13 +167,16 @@ def read_locale_from_folder(folder):
|
|||
def write_keys(outfile, keys, locc=""):
|
||||
with open(outfile, "w") as f:
|
||||
# write section [more_keys], then [extra_keys], skip if empty
|
||||
has_extra_keys = len(keys["extra_keys"]) > 0
|
||||
has_labels = len(keys["labels"]) > 0
|
||||
has_number_row = len(keys["number_row"]) > 0
|
||||
if len(keys["morekeys"]) > 0:
|
||||
f.write("[morekeys]\n")
|
||||
for k, v in keys["morekeys"].items():
|
||||
f.write(f"{k} {v}\n")
|
||||
if len(keys["extra_keys"]) > 0:
|
||||
if has_labels or has_number_row or has_extra_keys:
|
||||
f.write("\n")
|
||||
if len(keys["extra_keys"]) > 0 and locc != "eo": # eo has the extra key moved into the layout
|
||||
if has_extra_keys and locc != "eo": # eo has the extra key moved into the layout
|
||||
f.write("[extra_keys]\n")
|
||||
# clarify somewhere that extra keys only apply to default layout (where to get?)
|
||||
for k, v in sorted(keys["extra_keys"].items()):
|
||||
|
@ -138,6 +187,24 @@ def write_keys(outfile, keys, locc=""):
|
|||
f.write(f"{row}: {label}\n")
|
||||
else:
|
||||
f.write(f"{row}: {label} {morekeys}\n")
|
||||
if has_labels or has_number_row:
|
||||
f.write("\n")
|
||||
if has_labels:
|
||||
f.write("[labels]\n")
|
||||
for k, v in keys["labels"].items():
|
||||
f.write(f"{k}: {v}\n")
|
||||
if has_number_row:
|
||||
f.write("\n")
|
||||
if has_number_row:
|
||||
if len(keys["number_row"]) != 10:
|
||||
raise ValueError("number row must have 10 keys")
|
||||
f.write("[number_row]\n")
|
||||
zero = keys["number_row"]["0"]
|
||||
for k, v in sorted(keys["number_row"].items()):
|
||||
if k == "0":
|
||||
continue
|
||||
f.write(f"{v} ")
|
||||
f.write(f"{zero}\n")
|
||||
|
||||
|
||||
def get_morekeys_texts(write=False):
|
||||
|
@ -156,7 +223,7 @@ def get_morekeys_texts(write=False):
|
|||
script = "Latn"
|
||||
if script is None:
|
||||
raise ValueError("undefined script")
|
||||
if script != "Latn":
|
||||
if script == "Latn":
|
||||
continue # skip non-latin scripts for now
|
||||
print(file)
|
||||
keys = read_keys(f"{file}/donottranslate-more-keys.xml")
|
||||
|
@ -164,12 +231,14 @@ def get_morekeys_texts(write=False):
|
|||
if not write:
|
||||
continue
|
||||
outfile_name = locc.replace("-r", "_").lower() + ".txt"
|
||||
outfile = pathlib.Path(out_folder + outfile_name)
|
||||
# outfile = pathlib.Path(out_folder + outfile_name)
|
||||
outfile = out_folder / outfile_name
|
||||
outfile.parent.mkdir(exist_ok=True, parents=True)
|
||||
write_keys(outfile, keys, locc)
|
||||
return val
|
||||
|
||||
|
||||
# write lists of all moreKeys from different languages
|
||||
def write_combined_lists(keys):
|
||||
infos_by_letters = dict()
|
||||
for key in keys:
|
||||
|
@ -198,10 +267,8 @@ def write_combined_lists(keys):
|
|||
def main():
|
||||
# k = read_keys(default_file)
|
||||
# write_keys(pathlib.Path(__file__).parent / f"defaultkeys.txt", k)
|
||||
keys = get_morekeys_texts()
|
||||
write_combined_lists(keys)
|
||||
|
||||
|
||||
keys = get_morekeys_texts(True)
|
||||
# write_combined_lists(keys)
|
||||
|
||||
|
||||
# need to check strings:
|
||||
|
|
Loading…
Add table
Reference in a new issue