1 /* 2 * Copyright 2021 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 17 package androidx.compose.foundation.text.selection 18 19 import androidx.compose.ui.geometry.Offset 20 import androidx.compose.ui.geometry.Rect 21 import androidx.compose.ui.layout.LayoutCoordinates 22 import androidx.compose.ui.text.AnnotatedString 23 import androidx.compose.ui.text.MultiParagraph 24 import androidx.compose.ui.text.TextLayoutInput 25 import androidx.compose.ui.text.TextLayoutResult 26 import androidx.compose.ui.text.TextRange 27 import androidx.compose.ui.unit.Constraints 28 29 /** 30 * Provides [Selection] information for a composable to SelectionContainer. Composables who can be 31 * selected should subscribe to [SelectionRegistrar] using this interface. 32 */ 33 internal interface Selectable { 34 /** 35 * An ID used by [SelectionRegistrar] to identify this [Selectable]. This value should not be 36 * [SelectionRegistrar.InvalidSelectableId]. When a [Selectable] is created, it can request an 37 * ID from [SelectionRegistrar] by calling [SelectionRegistrar.nextSelectableId]. 38 * 39 * @see SelectionRegistrar.nextSelectableId 40 */ 41 val selectableId: Long 42 43 /** 44 * A function which adds [SelectableInfo] representing this [Selectable] to the 45 * [SelectionLayoutBuilder]. 46 */ appendSelectableInfoToBuildernull47 fun appendSelectableInfoToBuilder(builder: SelectionLayoutBuilder) 48 49 /** 50 * Returns selectAll [Selection] information for a selectable composable. If no selection can be 51 * provided null should be returned. 52 * 53 * @return selectAll [Selection] information for a selectable composable. If no selection can be 54 * provided null should be returned. 55 */ 56 fun getSelectAllSelection(): Selection? 57 58 /** 59 * Return the [Offset] of a [SelectionHandle]. 60 * 61 * @param selection [Selection] contains the [SelectionHandle] 62 * @param isStartHandle true if it's the start handle, false if it's the end handle. 63 * @return [Offset] of this handle, based on which the [SelectionHandle] will be drawn. 64 */ 65 fun getHandlePosition(selection: Selection, isStartHandle: Boolean): Offset 66 67 /** 68 * Return the [LayoutCoordinates] of the [Selectable]. 69 * 70 * @return [LayoutCoordinates] of the [Selectable]. This could be null if called before 71 * composing. 72 */ 73 fun getLayoutCoordinates(): LayoutCoordinates? 74 75 /** 76 * Return the [TextLayoutResult] of the selectable. 77 * 78 * @return [TextLayoutResult] of the [Selectable]. This could be null if called before 79 * composing. 80 */ 81 fun textLayoutResult(): TextLayoutResult? 82 83 /** 84 * Return the [AnnotatedString] of the [Selectable]. 85 * 86 * @return text content as [AnnotatedString] of the [Selectable]. 87 */ 88 fun getText(): AnnotatedString 89 90 /** 91 * Return the bounding box of the character for given character offset. This is currently for 92 * text. In future when we implemented other selectable Composables, we can return the bounding 93 * box of the wanted rectangle. For example, for an image selectable, this should return the 94 * bounding box of the image. 95 * 96 * @param offset a character offset 97 * @return the bounding box for the character in [Rect], or [Rect.Zero] if the selectable is 98 * empty. 99 */ 100 fun getBoundingBox(offset: Int): Rect 101 102 /** 103 * Returns the left x coordinate of the line for the given offset. 104 * 105 * @param offset a character offset 106 * @return the line left x coordinate for the given offset 107 */ 108 fun getLineLeft(offset: Int): Float 109 110 /** 111 * Returns the right x coordinate of the line for the given offset. 112 * 113 * @param offset a character offset 114 * @return the line right x coordinate for the given offset 115 */ 116 fun getLineRight(offset: Int): Float 117 118 /** 119 * Returns the center y coordinate of the line on which the specified text offset appears. 120 * 121 * If you ask for a position before 0, you get the center of the first line; if you ask for a 122 * position beyond the end of the text, you get the center of the last line. 123 * 124 * @param offset a character offset 125 * @return the line center y coordinate of the line containing [offset] 126 */ 127 fun getCenterYForOffset(offset: Int): Float 128 129 /** 130 * Return the offsets of the start and end of the line containing [offset], or [TextRange.Zero] 131 * if the selectable is empty. These offsets are in the same "coordinate space" as 132 * [getBoundingBox], and despite being returned in a [TextRange], may not refer to offsets in 133 * actual text if the selectable contains other types of content. This function returns the last 134 * visible line's boundaries if offset is larger than text length or the character at given 135 * offset would fall on a line which is hidden by maxLines or Constraints. 136 */ 137 fun getRangeOfLineContaining(offset: Int): TextRange 138 139 /** 140 * Returns the last visible character's offset. Some lines can be hidden due to either 141 * [TextLayoutInput.maxLines] or [Constraints.maxHeight] being smaller than 142 * [MultiParagraph.height]. If overflow is set to clip and a line is partially visible, it 143 * counts as the last visible line. 144 */ 145 fun getLastVisibleOffset(): Int 146 147 /** 148 * Returns the text line height for the given offset. 149 * 150 * @param offset a character offset 151 * @return the line height for the given offset 152 */ 153 fun getLineHeight(offset: Int): Float 154 } 155