[go: nahoru, domu]

blob: 71d781aac9f2bd866e2dbb3b51f246c536a1289d [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.core.selection
import androidx.ui.core.LayoutCoordinates
import androidx.compose.ui.geometry.Offset
internal class SelectionRegistrarImpl : SelectionRegistrar {
/**
* A flag to check if the [Selectable]s have already been sorted.
*/
internal var sorted: Boolean = false
/**
* This is essentially the list of registered components that want
* to handle text selection that are below the SelectionContainer.
*/
private val _selectables = mutableListOf<Selectable>()
/**
* Getter for handlers that returns an List.
*/
internal val selectables: List<Selectable>
get() = _selectables
/**
* The callback to be invoked when the position change was triggered.
*/
internal var onPositionChangeCallback: (() -> Unit)? = null
override fun subscribe(selectable: Selectable): Selectable {
_selectables.add(selectable)
sorted = false
return selectable
}
override fun unsubscribe(selectable: Selectable) {
_selectables.remove(selectable)
}
/**
* Sort the list of registered [Selectable]s in [SelectionRegistrar]. Currently the order of
* selectables is geometric-based.
*/
fun sort(containerLayoutCoordinates: LayoutCoordinates): List<Selectable> {
if (!sorted) {
// Sort selectables by y-coordinate first, and then x-coordinate, to match English
// hand-writing habit.
_selectables.sortWith(Comparator { a: Selectable, b: Selectable ->
val layoutCoordinatesA = a.getLayoutCoordinates()
val layoutCoordinatesB = b.getLayoutCoordinates()
val positionA =
if (layoutCoordinatesA != null) containerLayoutCoordinates.childToLocal(
layoutCoordinatesA,
Offset.Zero
)
else Offset.Zero
val positionB =
if (layoutCoordinatesB != null) containerLayoutCoordinates.childToLocal(
layoutCoordinatesB,
Offset.Zero
)
else Offset.Zero
if (positionA.y == positionB.y) compareValues(positionA.x, positionB.x)
else compareValues(positionA.y, positionB.y)
})
sorted = true
}
return selectables
}
override fun onPositionChange() {
// Set the variable sorted to be false, when the global position of a registered
// selectable changes.
sorted = false
onPositionChangeCallback?.invoke()
}
}