[go: nahoru, domu]

blob: afc4f25f6140a4b925a81827aa47859064c81473 [file] [log] [blame]
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.ui.test.util
import androidx.ui.core.PointerEventPass
import androidx.ui.core.PointerId
import androidx.ui.core.PointerInputChange
import androidx.ui.core.PointerInputData
import androidx.ui.core.gesture.util.VelocityTracker
import androidx.ui.core.pointerinput.PointerInputFilter
import androidx.ui.core.pointerinput.PointerInputModifier
import androidx.ui.geometry.Offset
import androidx.ui.unit.Duration
import androidx.ui.unit.IntSize
import androidx.ui.unit.Uptime
import com.google.common.truth.Truth.assertThat
data class DataPoint(val id: PointerId, val data: PointerInputData) {
val timestamp get() = data.uptime!!
val position get() = data.position!!
val x get() = data.position!!.x
val y get() = data.position!!.y
val down get() = data.down
}
class SinglePointerInputRecorder : PointerInputModifier {
private val _events = mutableListOf<DataPoint>()
val events get() = _events as List<DataPoint>
private val velocityTracker = VelocityTracker()
val recordedVelocity get() = velocityTracker.calculateVelocity()
override val pointerInputFilter = RecordingFilter { changes ->
changes.forEach {
_events.add(DataPoint(it.id, it.current))
velocityTracker.addPosition(it.current.uptime!!, it.current.position!!)
}
}
}
class MultiPointerInputRecorder : PointerInputModifier {
data class Event(val pointers: List<DataPoint>) {
val pointerCount: Int get() = pointers.size
fun getPointer(index: Int) = pointers[index]
}
private val _events = mutableListOf<Event>()
val events get() = _events as List<Event>
override val pointerInputFilter = RecordingFilter { changes ->
_events.add(Event(changes.map { DataPoint(it.id, it.current) }))
}
}
class RecordingFilter(
private val record: (List<PointerInputChange>) -> Unit
) : PointerInputFilter() {
override fun onPointerInput(
changes: List<PointerInputChange>,
pass: PointerEventPass,
bounds: IntSize
): List<PointerInputChange> {
if (pass == PointerEventPass.InitialDown) {
record(changes)
}
return changes
}
override fun onCancel() {
// Do nothing
}
}
val SinglePointerInputRecorder.downEvents get() = events.filter { it.down }
val SinglePointerInputRecorder.recordedDuration: Duration
get() {
check(events.isNotEmpty()) { "No events recorded" }
return events.last().timestamp - events.first().timestamp
}
fun SinglePointerInputRecorder.assertTimestampsAreIncreasing() {
check(events.isNotEmpty()) { "No events recorded" }
events.reduce { prev, curr ->
assertThat(curr.timestamp).isAtLeast(prev.timestamp)
curr
}
}
fun MultiPointerInputRecorder.assertTimestampsAreIncreasing() {
check(events.isNotEmpty()) { "No events recorded" }
// Check that each event has the same timestamp
events.forEach { event ->
assertThat(event.pointerCount).isAtLeast(1)
val currTime = event.pointers[0].timestamp
for (i in 1 until event.pointerCount) {
assertThat(event.pointers[i].timestamp).isEqualTo(currTime)
}
}
// Check that the timestamps are ordered
assertThat(events.map { it.pointers[0].timestamp }).isInOrder()
}
fun SinglePointerInputRecorder.assertOnlyLastEventIsUp() {
check(events.isNotEmpty()) { "No events recorded" }
assertThat(events.last().down).isFalse()
assertThat(events.count { !it.down }).isEqualTo(1)
}
fun DataPoint.verify(
expectedTimestamp: Uptime?,
expectedId: PointerId?,
expectedDown: Boolean,
expectedPosition: Offset
) {
if (expectedTimestamp != null) {
assertThat(timestamp).isEqualTo(expectedTimestamp)
}
if (expectedId != null) {
assertThat(id).isEqualTo(expectedId)
}
assertThat(down).isEqualTo(expectedDown)
assertThat(position).isEqualTo(expectedPosition)
}
/**
* Checks that the coordinates are progressing in a monotonous direction
*/
fun List<DataPoint>.isMonotonicBetween(start: Offset, end: Offset) {
map { it.x }.isMonotonicBetween(start.x, end.x, 1e-3f)
map { it.y }.isMonotonicBetween(start.y, end.y, 1e-3f)
}