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
|
2022-02-20 16:14:12 +01:00
|
|
|
|
|
|
|
import android.annotation.SuppressLint
|
|
|
|
import android.content.Context
|
2023-12-18 17:30:53 +01:00
|
|
|
import android.content.res.Configuration
|
2022-02-20 16:14:12 +01:00
|
|
|
import android.util.AttributeSet
|
|
|
|
import android.view.Gravity
|
2023-12-18 17:30:53 +01:00
|
|
|
import android.view.MotionEvent
|
2022-02-20 16:14:12 +01:00
|
|
|
import android.view.View
|
|
|
|
import android.widget.FrameLayout
|
|
|
|
import android.widget.ImageButton
|
2024-01-31 18:32:43 +01:00
|
|
|
import helium314.keyboard.keyboard.KeyboardActionListener
|
|
|
|
import helium314.keyboard.keyboard.KeyboardSwitcher
|
|
|
|
import helium314.keyboard.latin.common.ColorType
|
|
|
|
import helium314.keyboard.latin.common.Constants
|
|
|
|
import helium314.keyboard.latin.settings.Settings
|
|
|
|
import helium314.keyboard.latin.utils.DeviceProtectedUtils
|
2023-12-18 17:30:53 +01:00
|
|
|
import kotlin.math.abs
|
2022-02-20 16:14:12 +01:00
|
|
|
|
|
|
|
class KeyboardWrapperView @JvmOverloads constructor(
|
|
|
|
context: Context,
|
|
|
|
attrs: AttributeSet? = null,
|
|
|
|
defStyle: Int = 0
|
|
|
|
) : FrameLayout(context, attrs, defStyle), View.OnClickListener {
|
|
|
|
|
|
|
|
var keyboardActionListener: KeyboardActionListener? = null
|
|
|
|
|
|
|
|
private lateinit var stopOneHandedModeBtn: ImageButton
|
|
|
|
private lateinit var switchOneHandedModeBtn: ImageButton
|
2023-12-18 17:30:53 +01:00
|
|
|
private lateinit var resizeOneHandedModeBtn: ImageButton
|
2022-02-20 16:14:12 +01:00
|
|
|
private val iconStopOneHandedModeId: Int
|
|
|
|
private val iconSwitchOneHandedModeId: Int
|
2023-12-18 17:30:53 +01:00
|
|
|
private val iconResizeOneHandedModeId: Int
|
2022-02-20 16:14:12 +01:00
|
|
|
|
|
|
|
var oneHandedModeEnabled = false
|
|
|
|
set(enabled) {
|
|
|
|
field = enabled
|
|
|
|
updateViewsVisibility()
|
|
|
|
requestLayout()
|
|
|
|
}
|
|
|
|
|
|
|
|
var oneHandedGravity = Gravity.NO_GRAVITY
|
|
|
|
set(value) {
|
|
|
|
field = value
|
|
|
|
updateSwitchButtonSide()
|
|
|
|
requestLayout()
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-12-18 17:30:53 +01:00
|
|
|
@SuppressLint("ClickableViewAccessibility")
|
2022-02-20 16:14:12 +01:00
|
|
|
override fun onFinishInflate() {
|
|
|
|
super.onFinishInflate()
|
|
|
|
stopOneHandedModeBtn = findViewById(R.id.btn_stop_one_handed_mode)
|
|
|
|
stopOneHandedModeBtn.setImageResource(iconStopOneHandedModeId)
|
|
|
|
stopOneHandedModeBtn.visibility = GONE
|
|
|
|
switchOneHandedModeBtn = findViewById(R.id.btn_switch_one_handed_mode)
|
|
|
|
switchOneHandedModeBtn.setImageResource(iconSwitchOneHandedModeId)
|
|
|
|
switchOneHandedModeBtn.visibility = GONE
|
2023-12-18 17:30:53 +01:00
|
|
|
resizeOneHandedModeBtn = findViewById(R.id.btn_resize_one_handed_mode)
|
|
|
|
resizeOneHandedModeBtn.setImageResource(iconResizeOneHandedModeId)
|
|
|
|
resizeOneHandedModeBtn.visibility = GONE
|
2022-02-20 16:14:12 +01:00
|
|
|
|
|
|
|
stopOneHandedModeBtn.setOnClickListener(this)
|
|
|
|
switchOneHandedModeBtn.setOnClickListener(this)
|
2023-08-11 09:23:39 +02:00
|
|
|
|
2023-12-18 17:30:53 +01:00
|
|
|
var x = 0f
|
|
|
|
resizeOneHandedModeBtn.setOnTouchListener { _, motionEvent ->
|
|
|
|
when (motionEvent.action) {
|
|
|
|
MotionEvent.ACTION_DOWN -> x = motionEvent.rawX
|
|
|
|
MotionEvent.ACTION_MOVE -> {
|
|
|
|
// performance is not great because settings are reloaded and keyboard is redrawn
|
|
|
|
// on every move, but it's good enough
|
|
|
|
val sign = -switchOneHandedModeBtn.scaleX
|
|
|
|
// factor 2 to make it more sensitive (maybe could be tuned a little)
|
|
|
|
val changePercent = 2 * sign * (x - motionEvent.rawX) / context.resources.displayMetrics.density
|
|
|
|
if (abs(changePercent) < 1) return@setOnTouchListener true
|
|
|
|
x = motionEvent.rawX
|
|
|
|
val prefs = DeviceProtectedUtils.getSharedPreferences(context)
|
|
|
|
val oldScale = Settings.readOneHandedModeScale(prefs, Settings.getInstance().current.mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT)
|
|
|
|
val newScale = (oldScale + changePercent / 100f).coerceAtMost(2.5f).coerceAtLeast(0.5f)
|
|
|
|
if (newScale == oldScale) return@setOnTouchListener true
|
|
|
|
Settings.getInstance().writeOneHandedModeScale(newScale)
|
|
|
|
oneHandedModeEnabled = false // intentionally putting wrong value, so KeyboardSwitcher.setOneHandedModeEnabled does actually reload
|
|
|
|
keyboardActionListener?.onCodeInput(Constants.CODE_START_ONE_HANDED_MODE,
|
|
|
|
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false)
|
|
|
|
}
|
|
|
|
else -> x = 0f
|
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
2023-08-11 09:23:39 +02:00
|
|
|
val colors = Settings.getInstance().current.mColors
|
2023-12-19 07:48:10 +01:00
|
|
|
colors.setColor(stopOneHandedModeBtn, ColorType.ONE_HANDED_MODE_BUTTON)
|
|
|
|
colors.setColor(switchOneHandedModeBtn, ColorType.ONE_HANDED_MODE_BUTTON)
|
2023-12-19 09:40:01 +01:00
|
|
|
colors.setColor(resizeOneHandedModeBtn, ColorType.ONE_HANDED_MODE_BUTTON)
|
2024-01-26 09:01:39 +01:00
|
|
|
colors.setBackground(stopOneHandedModeBtn, ColorType.ONE_HANDED_MODE_BUTTON)
|
|
|
|
colors.setBackground(switchOneHandedModeBtn, ColorType.ONE_HANDED_MODE_BUTTON)
|
|
|
|
colors.setBackground(resizeOneHandedModeBtn, ColorType.ONE_HANDED_MODE_BUTTON)
|
2022-02-20 16:14:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressLint("RtlHardcoded")
|
|
|
|
fun switchOneHandedModeSide() {
|
|
|
|
oneHandedGravity = if (oneHandedGravity == Gravity.LEFT) Gravity.RIGHT else Gravity.LEFT
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun updateViewsVisibility() {
|
|
|
|
stopOneHandedModeBtn.visibility = if (oneHandedModeEnabled) VISIBLE else GONE
|
|
|
|
switchOneHandedModeBtn.visibility = if (oneHandedModeEnabled) VISIBLE else GONE
|
2023-12-18 17:30:53 +01:00
|
|
|
resizeOneHandedModeBtn.visibility = if (oneHandedModeEnabled) VISIBLE else GONE
|
2022-02-20 16:14:12 +01:00
|
|
|
}
|
|
|
|
|
2022-03-01 12:34:03 +01:00
|
|
|
@SuppressLint("RtlHardcoded")
|
2022-02-20 16:14:12 +01:00
|
|
|
private fun updateSwitchButtonSide() {
|
2022-03-01 12:34:03 +01:00
|
|
|
switchOneHandedModeBtn.scaleX = if (oneHandedGravity == Gravity.LEFT) -1f else 1f
|
2022-02-20 16:14:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onClick(view: View) {
|
|
|
|
if (view === stopOneHandedModeBtn) {
|
|
|
|
keyboardActionListener?.onCodeInput(Constants.CODE_STOP_ONE_HANDED_MODE,
|
|
|
|
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
|
|
|
|
false /* isKeyRepeat */)
|
|
|
|
} else if (view === switchOneHandedModeBtn) {
|
|
|
|
keyboardActionListener?.onCodeInput(Constants.CODE_SWITCH_ONE_HANDED_MODE,
|
|
|
|
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
|
|
|
|
false /* isKeyRepeat */)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressLint("RtlHardcoded")
|
|
|
|
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
|
|
|
if (!oneHandedModeEnabled) {
|
|
|
|
super.onLayout(changed, left, top, right, bottom)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
val isLeftGravity = oneHandedGravity == Gravity.LEFT
|
|
|
|
val width = right - left
|
2023-12-20 19:46:18 +01:00
|
|
|
val keyboardView = KeyboardSwitcher.getInstance().visibleKeyboardView
|
2022-02-20 16:14:12 +01:00
|
|
|
val spareWidth = width - keyboardView.measuredWidth
|
|
|
|
|
|
|
|
val keyboardLeft = if (isLeftGravity) 0 else spareWidth
|
|
|
|
keyboardView.layout(
|
|
|
|
keyboardLeft,
|
|
|
|
0,
|
|
|
|
keyboardLeft + keyboardView.measuredWidth,
|
|
|
|
keyboardView.measuredHeight
|
|
|
|
)
|
|
|
|
|
2023-09-15 12:35:59 +02:00
|
|
|
val scale = Settings.getInstance().current.mKeyboardHeightScale
|
|
|
|
// scale one-handed mode button height if keyboard height scale is < 80%
|
2023-09-16 20:18:37 +02:00
|
|
|
val heightScale = if (scale < 0.8f) scale + 0.2f else 1f
|
2022-02-20 16:14:12 +01:00
|
|
|
val buttonsLeft = if (isLeftGravity) keyboardView.measuredWidth else 0
|
2023-12-18 17:30:53 +01:00
|
|
|
val buttonXLeft = buttonsLeft + (spareWidth - stopOneHandedModeBtn.measuredWidth) / 2
|
|
|
|
val buttonXRight = buttonsLeft + (spareWidth + stopOneHandedModeBtn.measuredWidth) / 2
|
|
|
|
val buttonHeight = (heightScale * stopOneHandedModeBtn.measuredHeight).toInt()
|
|
|
|
fun View.setLayout(yPosition: Int) {
|
|
|
|
layout(buttonXLeft, yPosition - buttonHeight / 2, buttonXRight, yPosition + buttonHeight / 2)
|
|
|
|
}
|
|
|
|
stopOneHandedModeBtn.setLayout((keyboardView.measuredHeight * 0.2f).toInt())
|
|
|
|
switchOneHandedModeBtn.setLayout((keyboardView.measuredHeight * 0.5f).toInt())
|
|
|
|
resizeOneHandedModeBtn.setLayout((keyboardView.measuredHeight * 0.8f).toInt())
|
2022-02-20 16:14:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
init {
|
2023-09-06 13:23:26 +02:00
|
|
|
@SuppressLint("CustomViewStyleable")
|
|
|
|
val keyboardAttr = context.obtainStyledAttributes(attrs, R.styleable.Keyboard, defStyle, R.style.Keyboard)
|
2022-02-20 16:14:12 +01:00
|
|
|
iconStopOneHandedModeId = keyboardAttr.getResourceId(R.styleable.Keyboard_iconStopOneHandedMode, 0)
|
|
|
|
iconSwitchOneHandedModeId = keyboardAttr.getResourceId(R.styleable.Keyboard_iconSwitchOneHandedMode, 0)
|
2023-12-18 17:30:53 +01:00
|
|
|
iconResizeOneHandedModeId = keyboardAttr.getResourceId(R.styleable.Keyboard_iconResizeOneHandedMode, 0)
|
2022-02-20 16:14:12 +01:00
|
|
|
keyboardAttr.recycle()
|
|
|
|
}
|
2023-09-06 12:15:22 +02:00
|
|
|
}
|