2023-10-17 13:44:01 +02:00
// SPDX-License-Identifier: GPL-3.0-only
2024-01-31 18:32:43 +01:00
package helium314.keyboard.latin.utils
2023-08-25 17:33:29 +02:00
2025-03-16 14:33:53 +01:00
import android.app.AlertDialog
2023-08-25 17:33:29 +02:00
import android.os.IBinder
import android.text.Spannable
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.style.RelativeSizeSpan
import android.view.WindowManager
import android.view.inputmethod.InputMethodInfo
import android.view.inputmethod.InputMethodSubtype
2024-01-31 18:32:43 +01:00
import helium314.keyboard.latin.LatinIME
import helium314.keyboard.latin.R
import helium314.keyboard.latin.RichInputMethodManager
2025-05-24 09:29:11 +02:00
import helium314.keyboard.latin.utils.SubtypeLocaleUtils.displayName
2023-08-25 17:33:29 +02:00
// similar to what showSubtypePicker does in https://github.com/rkkr/simple-keyboard/blob/master/app/src/main/java/rkr/simplekeyboard/inputmethod/latin/RichInputMethodManager.java
2023-09-10 19:45:03 +02:00
fun createInputMethodPickerDialog ( latinIme : LatinIME , richImm : RichInputMethodManager , windowToken : IBinder ) : AlertDialog {
2023-08-25 17:33:29 +02:00
val pm = latinIme . packageManager
val thisImi = richImm . inputMethodInfoOfThisIme
val currentSubtype = richImm . currentSubtype . rawSubtype
val enabledImis = richImm . inputMethodManager . enabledInputMethodList
. sortedBy { it . hashCode ( ) } . sortedBy { it . loadLabel ( pm ) . toString ( ) } // first label, then hashCode
val enabledSubtypes = mutableListOf < Pair < InputMethodInfo , InputMethodSubtype ? > > ( )
var currentSubtypeIndex = 0
enabledImis . forEach { imi ->
2024-05-18 15:01:30 +02:00
val subtypes = if ( imi != thisImi ) richImm . getEnabledInputMethodSubtypeList ( imi , true )
2025-05-24 11:35:58 +02:00
else richImm . getEnabledInputMethodSubtypeList ( imi , true ) . sortedBy { it . displayName ( ) }
2023-08-25 17:33:29 +02:00
if ( subtypes . isEmpty ( ) ) {
enabledSubtypes . add ( imi to null )
} else {
subtypes . forEach {
if ( ! it . isAuxiliary ) {
enabledSubtypes . add ( imi to it )
if ( imi == thisImi && it == currentSubtype )
currentSubtypeIndex = enabledSubtypes . lastIndex
}
}
}
}
val items = mutableListOf < SpannableStringBuilder > ( )
for ( imiAndSubtype in enabledSubtypes ) {
val ( imi , subtype ) = imiAndSubtype
2025-05-24 11:35:58 +02:00
val subtypeName = if ( imi == thisImi ) subtype ?. displayName ( )
2024-04-11 19:44:37 +02:00
else subtype ?. getDisplayName ( latinIme , imi . packageName , imi . serviceInfo . applicationInfo )
val title = SpannableString ( subtypeName ?. ifBlank { imi . loadLabel ( pm ) } ?: imi . loadLabel ( pm ) )
2023-08-25 17:33:29 +02:00
val subtitle = SpannableString ( if ( subtype == null ) " " else " \n ${imi.loadLabel(pm)} " )
title . setSpan (
RelativeSizeSpan ( 0.9f ) , 0 , title . length ,
Spannable . SPAN _INCLUSIVE _INCLUSIVE
)
subtitle . setSpan (
RelativeSizeSpan ( 0.85f ) , 0 , subtitle . length ,
Spannable . SPAN _EXCLUSIVE _INCLUSIVE
)
items . add ( SpannableStringBuilder ( ) . append ( title ) . append ( subtitle ) )
}
2024-01-01 19:20:28 +01:00
val dialog = AlertDialog . Builder ( getPlatformDialogThemeContext ( latinIme ) )
2023-08-25 17:33:29 +02:00
. setTitle ( R . string . select _input _method )
. setSingleChoiceItems ( items . toTypedArray ( ) , currentSubtypeIndex ) { di , i ->
di . dismiss ( )
val ( imi , subtype ) = enabledSubtypes [ i ]
if ( imi == thisImi )
latinIme . switchToSubtype ( subtype )
else if ( subtype != null )
latinIme . switchInputMethodAndSubtype ( imi , subtype )
else
latinIme . switchInputMethod ( imi . id )
}
. create ( )
val window = dialog . window
val layoutParams = window ?. attributes
layoutParams ?. token = windowToken
layoutParams ?. type = WindowManager . LayoutParams . TYPE _APPLICATION _ATTACHED _DIALOG
window ?. attributes = layoutParams
window ?. addFlags ( WindowManager . LayoutParams . FLAG _ALT _FOCUSABLE _IM )
2023-09-10 19:45:03 +02:00
return dialog
2023-08-25 17:33:29 +02:00
}