Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,9 @@ public class RichTextString internal constructor(
public class Builder(capacity: Int = 16) {
private val builder = AnnotatedString.Builder(capacity)
private val formatObjects = mutableMapOf<String, Any>()
// Tracks formats pushed via pushFormat along with the underlying builder index,
// so we can compute the current SpanStyle without materializing an AnnotatedString.
private val activeFormatStack = mutableListOf<Pair<Int, Format>>()

public fun addFormat(
format: Format,
Expand All @@ -373,12 +376,27 @@ public class RichTextString internal constructor(

public fun pushFormat(format: Format): Int {
val tag = format.registerTag(formatObjects)
return builder.pushStringAnnotation(FormatAnnotationScope, tag)
val idx = builder.pushStringAnnotation(FormatAnnotationScope, tag)
activeFormatStack.add(idx to format)
return idx
}

public fun pop(): Unit = builder.pop()
public fun pop(): Unit {
builder.pop()
if (activeFormatStack.isNotEmpty()) activeFormatStack.removeAt(activeFormatStack.lastIndex)
}

public fun pop(index: Int): Unit {
builder.pop(index)

public fun pop(index: Int): Unit = builder.pop(index)
if (activeFormatStack.isNotEmpty()) {
var i = activeFormatStack.lastIndex
while (i >= 0 && activeFormatStack[i].first >= index) {
activeFormatStack.removeAt(i)
i--
}
}
}

public fun append(text: String): Unit = builder.append(text)

Expand Down Expand Up @@ -407,6 +425,28 @@ public class RichTextString internal constructor(
builder.toAnnotatedString(),
formatObjects.toMap()
)

/**
* Returns the [SpanStyle] that would currently apply to newly appended text, based on
* the formats that are pushed (but not yet popped) on this builder.
*
* Only formats added via [pushFormat] are considered; any direct operations performed
* via [withAnnotatedString] or [addFormat] are not reflected in the result by design.
*/
public fun getCurrentSpanStyle(
style: RichTextStringStyle,
contentColor: Color
): SpanStyle {
val resolvedStyle = style.resolveDefaults()
var current = SpanStyle()
// Only consider formats that are currently pushed (and not yet popped).
// Ignore formats added via addFormat, by design.
for ((_, format) in activeFormatStack) {
val annotation = format.getAnnotation(resolvedStyle, contentColor)
if (annotation is SpanStyle) current = current.merge(annotation)
}
return current
}
}
}

Expand Down