blob: 3855cc346b25c905870f918d96e698c51749b2a3 [file] [log] [blame]
/*
* Copyright 2022 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.compose.ui.text.input
import android.graphics.Matrix
import android.view.inputmethod.CursorAnchorInfo
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.style.ResolvedTextDirection
/**
* Helper function to build [CursorAnchorInfo](https://developer.android.com/reference/android/view/inputmethod/CursorAnchorInfo).
*
* @param textFieldValue required to set text, composition and selection information into the
* CursorAnchorInfo.
* @param textLayoutResult TextLayoutResult for the [textFieldValue] used to enter cursor and
* character information
* @param matrix Matrix used to convert local coordinates to global coordinates.
*/
internal fun CursorAnchorInfo.Builder.build(
textFieldValue: TextFieldValue,
textLayoutResult: TextLayoutResult,
matrix: Matrix
): CursorAnchorInfo {
reset()
setMatrix(matrix)
val selectionStart = textFieldValue.selection.min
val selectionEnd = textFieldValue.selection.max
setSelectionRange(selectionStart, selectionEnd)
setInsertionMarker(selectionStart, textLayoutResult)
// set composition
val compositionStart = textFieldValue.composition?.min ?: -1
val compositionEnd = textFieldValue.composition?.max ?: -1
if (compositionStart in 0 until compositionEnd) {
setComposingText(
compositionStart,
textFieldValue.text.subSequence(compositionStart, compositionEnd)
)
}
return build()
}
private fun CursorAnchorInfo.Builder.setInsertionMarker(
selectionStart: Int,
textLayoutResult: TextLayoutResult
): CursorAnchorInfo.Builder {
if (selectionStart < 0) return this
val cursorRect = textLayoutResult.getCursorRect(selectionStart)
val isRtl = textLayoutResult.getBidiRunDirection(selectionStart) == ResolvedTextDirection.Rtl
var flags = 0
if (isRtl) flags = flags or CursorAnchorInfo.FLAG_IS_RTL
// Sets the location of the text insertion point (zero width cursor) as a rectangle in local
// coordinates.
setInsertionMarkerLocation(
cursorRect.left,
cursorRect.top,
cursorRect.bottom,
cursorRect.bottom,
flags
)
return this
}