Coverage Summary for Class: TransformGestureDetectorWithEndCallbacksKt (com.vsevolodganin.clicktrack.utils.compose)
Class |
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
TransformGestureDetectorWithEndCallbacksKt |
0%
(0/1)
|
|
0%
(0/4)
|
0%
(0/25)
|
TransformGestureDetectorWithEndCallbacksKt$detectTransformGesturesWithEndCallbacks$4 |
0%
(0/1)
|
0%
(0/32)
|
0%
(0/42)
|
0%
(0/246)
|
Total |
0%
(0/2)
|
0%
(0/32)
|
0%
(0/46)
|
0%
(0/271)
|
package com.vsevolodganin.clicktrack.utils.compose
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.calculateCentroid
import androidx.compose.foundation.gestures.calculateCentroidSize
import androidx.compose.foundation.gestures.calculatePan
import androidx.compose.foundation.gestures.calculateRotation
import androidx.compose.foundation.gestures.calculateZoom
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.PointerInputChange
import androidx.compose.ui.input.pointer.PointerInputScope
import androidx.compose.ui.input.pointer.positionChanged
import androidx.compose.ui.util.fastAny
import androidx.compose.ui.util.fastForEach
import kotlin.math.PI
import kotlin.math.abs
suspend fun PointerInputScope.detectTransformGesturesWithEndCallbacks(
panZoomLock: Boolean = false,
onGesture: (centroid: Offset, pan: Offset, zoom: Float, rotation: Float) -> Unit,
onGestureEnd: () -> Unit = {},
onGestureCancel: () -> Unit = {},
) {
awaitEachGesture {
var rotation = 0f
var zoom = 1f
var pan = Offset.Zero
var pastTouchSlop = false
val touchSlop = viewConfiguration.touchSlop
var lockedToPanZoom = false
var canceled: Boolean
awaitFirstDown(requireUnconsumed = false)
do {
val event = awaitPointerEvent()
canceled = event.changes.fastAny(PointerInputChange::isConsumed)
if (!canceled) {
val zoomChange = event.calculateZoom()
val rotationChange = event.calculateRotation()
val panChange = event.calculatePan()
if (!pastTouchSlop) {
zoom *= zoomChange
rotation += rotationChange
pan += panChange
val centroidSize = event.calculateCentroidSize(useCurrent = false)
val zoomMotion = abs(1 - zoom) * centroidSize
val rotationMotion = abs(rotation * PI.toFloat() * centroidSize / 180f)
val panMotion = pan.getDistance()
if (zoomMotion > touchSlop ||
rotationMotion > touchSlop ||
panMotion > touchSlop
) {
pastTouchSlop = true
lockedToPanZoom = panZoomLock && rotationMotion < touchSlop
}
}
if (pastTouchSlop) {
val centroid = event.calculateCentroid(useCurrent = false)
val effectiveRotation = if (lockedToPanZoom) 0f else rotationChange
if (effectiveRotation != 0f ||
zoomChange != 1f ||
panChange != Offset.Zero
) {
onGesture(centroid, panChange, zoomChange, effectiveRotation)
}
event.changes.fastForEach {
if (it.positionChanged()) {
it.consume()
}
}
}
}
} while (!canceled && event.changes.fastAny { it.pressed })
if (canceled) {
onGestureCancel()
} else {
onGestureEnd()
}
}
}