blob: 3855cc346b25c905870f918d96e698c51749b2a3 [file] [log] [blame]
Siyamed Sinir8fe71b02022-01-15 15:21:34 -08001/*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package androidx.compose.ui.text.input
18
Siyamed Sinir01e97782022-01-16 07:48:22 -080019import android.graphics.Matrix
Siyamed Sinir8fe71b02022-01-15 15:21:34 -080020import android.view.inputmethod.CursorAnchorInfo
Siyamed Sinir01e97782022-01-16 07:48:22 -080021import androidx.compose.ui.text.TextLayoutResult
22import androidx.compose.ui.text.style.ResolvedTextDirection
Siyamed Sinir8fe71b02022-01-15 15:21:34 -080023
24/**
25 * Helper function to build [CursorAnchorInfo](https://developer.android.com/reference/android/view/inputmethod/CursorAnchorInfo).
26 *
27 * @param textFieldValue required to set text, composition and selection information into the
28 * CursorAnchorInfo.
Siyamed Sinir01e97782022-01-16 07:48:22 -080029 * @param textLayoutResult TextLayoutResult for the [textFieldValue] used to enter cursor and
30 * character information
31 * @param matrix Matrix used to convert local coordinates to global coordinates.
Siyamed Sinir8fe71b02022-01-15 15:21:34 -080032 */
33internal fun CursorAnchorInfo.Builder.build(
Siyamed Sinir01e97782022-01-16 07:48:22 -080034 textFieldValue: TextFieldValue,
35 textLayoutResult: TextLayoutResult,
36 matrix: Matrix
Siyamed Sinir8fe71b02022-01-15 15:21:34 -080037): CursorAnchorInfo {
38 reset()
39
Siyamed Sinir01e97782022-01-16 07:48:22 -080040 setMatrix(matrix)
41
Siyamed Sinir8fe71b02022-01-15 15:21:34 -080042 val selectionStart = textFieldValue.selection.min
43 val selectionEnd = textFieldValue.selection.max
44 setSelectionRange(selectionStart, selectionEnd)
45
Siyamed Sinir01e97782022-01-16 07:48:22 -080046 setInsertionMarker(selectionStart, textLayoutResult)
47
Siyamed Sinir8fe71b02022-01-15 15:21:34 -080048 // set composition
49 val compositionStart = textFieldValue.composition?.min ?: -1
50 val compositionEnd = textFieldValue.composition?.max ?: -1
51
52 if (compositionStart in 0 until compositionEnd) {
53 setComposingText(
54 compositionStart,
55 textFieldValue.text.subSequence(compositionStart, compositionEnd)
56 )
57 }
58
59 return build()
60}
Siyamed Sinir01e97782022-01-16 07:48:22 -080061
62private fun CursorAnchorInfo.Builder.setInsertionMarker(
63 selectionStart: Int,
64 textLayoutResult: TextLayoutResult
65): CursorAnchorInfo.Builder {
66 if (selectionStart < 0) return this
67
68 val cursorRect = textLayoutResult.getCursorRect(selectionStart)
69 val isRtl = textLayoutResult.getBidiRunDirection(selectionStart) == ResolvedTextDirection.Rtl
70
71 var flags = 0
72 if (isRtl) flags = flags or CursorAnchorInfo.FLAG_IS_RTL
73
74 // Sets the location of the text insertion point (zero width cursor) as a rectangle in local
75 // coordinates.
76 setInsertionMarkerLocation(
77 cursorRect.left,
78 cursorRect.top,
79 cursorRect.bottom,
80 cursorRect.bottom,
81 flags
82 )
83
84 return this
85}