net.peanuuutz.fork.ui.foundation.text.TextSelectionHelper.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fork-ui Show documentation
Show all versions of fork-ui Show documentation
Comprehensive API designed for Minecraft modders
The newest version!
package net.peanuuutz.fork.ui.foundation.text
import androidx.compose.runtime.Stable
import net.peanuuutz.fork.ui.foundation.text.MeasuredParagraph.Companion.NullIndex
import net.peanuuutz.fork.ui.foundation.text.field.CursorAnchor
import net.peanuuutz.fork.ui.foundation.text.field.getCursorAnchorFromOffsetApproximately
import net.peanuuutz.fork.ui.ui.unit.FloatOffset
import net.peanuuutz.fork.util.common.fastIndexOfFirst
@Stable
fun MeasuredParagraph.getLineIndexFromSelectionIndex(selectionIndex: Int): Int {
if (isEmpty()) {
return NullIndex
}
if (selectionIndex == displayPlainText.length) {
return lines.lastIndex
}
return lines.fastIndexOfFirst { line ->
selectionIndex in line.range.start..line.range.endExclusive
}
}
@Stable
fun MeasuredParagraph.getSectionPositionFromSelectionIndex(selectionIndex: Int): SectionPosition {
if (isEmpty()) {
return SectionPosition.Null
}
if (selectionIndex == displayPlainText.length) {
return lastPosition
}
val lineIndex = getLineIndexFromSelectionIndex(selectionIndex)
if (lineIndex == NullIndex) {
return SectionPosition.Null
}
val line = this[lineIndex]
val sectionIndex = line.sections.fastIndexOfFirst { section ->
selectionIndex in section.range
}
return if (sectionIndex != -1) {
SectionPosition(lineIndex, sectionIndex)
} else {
SectionPosition(lineIndex, line.sections.lastIndex)
}
}
@Stable
fun MeasuredParagraph.getSelectionIndexFromOffset(offset: FloatOffset): Int {
if (isEmpty()) {
return NullIndex
}
val cursorAnchor = getCursorAnchorFromOffsetApproximately(offset)
return convertCursorAnchorToSelectionIndex(cursorAnchor)
}
@Stable
fun MeasuredParagraph.convertCursorAnchorToSelectionIndex(cursorAnchor: CursorAnchor): Int {
if (isEmpty()) {
return NullIndex
}
val section = this[cursorAnchor.lineIndex][cursorAnchor.sectionIndex]
return section.range.start + cursorAnchor.localOffset
}
@Stable
fun MeasuredParagraph.convertSelectionIndexToCursorAnchor(selectionIndex: Int): CursorAnchor {
if (isEmpty()) {
return CursorAnchor.Null
}
val sectionPosition = getSectionPositionFromSelectionIndex(selectionIndex)
if (sectionPosition.isNull()) {
return CursorAnchor.Null
}
val localOffset = selectionIndex - this[sectionPosition].range.start
return CursorAnchor(sectionPosition.lineIndex, sectionPosition.sectionIndex, localOffset)
}