Skip to content

Commit

Permalink
Add unordered list style type
Browse files Browse the repository at this point in the history
  • Loading branch information
MohamedRejeb committed Feb 16, 2025
1 parent 57d281d commit 2942ffe
Show file tree
Hide file tree
Showing 6 changed files with 295 additions and 12 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#Gradle
org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M"
org.gradle.jvmargs=-Xmx4096M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx4096M"
org.gradle.caching=true
org.gradle.parallel=true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.mohamedrejeb.richeditor.model

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextDecoration
import com.mohamedrejeb.richeditor.paragraph.type.UnorderedListStyleType

public class RichTextConfig internal constructor(
private val updateText: () -> Unit,
Expand Down Expand Up @@ -72,6 +73,24 @@ public class RichTextConfig internal constructor(
unorderedListIndent = value
}

/**
* The prefixes for unordered lists items.
*
* The prefixes are used in order if the list is nested.
*
* For example, if the list is nested twice, the first prefix is used for the first level,
* the second prefix is used for the second level, and so on.
*
* If the list is nested more than the number of prefixes, the last prefix is used.
*
* The default prefixes are `•`, `◦`, and `▪`.
*/
public var unorderedListStyleType: UnorderedListStyleType = DefaultUnorderedListStyleType
set(value) {
field = value
updateText()
}

/**
* Whether to preserve the style when the line is empty.
* The line can be empty when the user deletes all the characters
Expand All @@ -82,4 +101,6 @@ public class RichTextConfig internal constructor(
public var preserveStyleOnEmptyLine: Boolean = true
}

internal const val DefaultListIndent = 38
internal const val DefaultListIndent = 38

internal val DefaultUnorderedListStyleType = UnorderedListStyleType.from("", "", "")
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,7 @@ public class RichTextState internal constructor(
1

val newType = UnorderedList(
initialIndent = config.unorderedListIndent,
config = config,
initialNestedLevel = nestedLevel,
)

Expand Down Expand Up @@ -2072,7 +2072,7 @@ public class RichTextState internal constructor(

if (richSpan.text == "- " || richSpan.text == "* ") {
richSpan.paragraph.type = UnorderedList(
initialIndent = config.unorderedListIndent,
config = config,
)
richSpan.text = ""
} else if (richSpan.text.matches(Regex("^\\d+\\. "))) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,89 @@
package com.mohamedrejeb.richeditor.paragraph.type

import androidx.compose.ui.text.ParagraphStyle
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.style.TextIndent
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.sp
import com.mohamedrejeb.richeditor.annotation.ExperimentalRichTextApi
import com.mohamedrejeb.richeditor.model.DefaultListIndent
import com.mohamedrejeb.richeditor.model.DefaultUnorderedListStyleType
import com.mohamedrejeb.richeditor.model.RichSpan
import com.mohamedrejeb.richeditor.model.RichTextConfig
import com.mohamedrejeb.richeditor.paragraph.RichParagraph

internal class UnorderedList(
internal class UnorderedList private constructor(
initialIndent: Int = DefaultListIndent,
startTextSpanStyle: SpanStyle = SpanStyle(),
startTextWidth: TextUnit = 0.sp,
initialNestedLevel: Int = 1,
initialStyleType: UnorderedListStyleType = DefaultUnorderedListStyleType,
): ParagraphType, ConfigurableStartTextWidth, ConfigurableNestedLevel {

constructor(
initialNestedLevel: Int = 1,
): this(
initialIndent = DefaultListIndent,
initialNestedLevel = initialNestedLevel,
)

constructor(
config: RichTextConfig,
initialNestedLevel: Int = 1,
): this(
initialIndent = config.unorderedListIndent,
initialNestedLevel = initialNestedLevel,
initialStyleType = config.unorderedListStyleType,
)

var startTextSpanStyle = startTextSpanStyle
set(value) {
field = value
style = getNewParagraphStyle()
}

override var startTextWidth: TextUnit = startTextWidth
set(value) {
field = value
style = getParagraphStyle()
style = getNewParagraphStyle()
}

private var indent = initialIndent
set(value) {
field = value
style = getNewParagraphStyle()
}

override var nestedLevel = initialNestedLevel
set(value) {
field = value
style = getParagraphStyle()
style = getNewParagraphStyle()
startRichSpan = getNewStartRichSpan()
}

private var styleType = initialStyleType
set(value) {
field = value
startRichSpan = getNewStartRichSpan()
}

private var style: ParagraphStyle =
getParagraphStyle()
getNewParagraphStyle()

override fun getStyle(config: RichTextConfig): ParagraphStyle {
if (config.unorderedListIndent != indent) {
indent = config.unorderedListIndent
style = getParagraphStyle()
}

if (config.unorderedListStyleType != styleType) {
styleType = config.unorderedListStyleType
}

return style
}

private fun getParagraphStyle() =
private fun getNewParagraphStyle() =
ParagraphStyle(
textIndent = TextIndent(
firstLine = (indent * nestedLevel).sp,
Expand All @@ -52,16 +93,36 @@ internal class UnorderedList(

@OptIn(ExperimentalRichTextApi::class)
override var startRichSpan: RichSpan =
RichSpan(
getNewStartRichSpan()

@OptIn(ExperimentalRichTextApi::class)
private fun getNewStartRichSpan(textRange: TextRange = TextRange(0)): RichSpan {
val prefixIndex =
(nestedLevel - 1).coerceIn(styleType.prefixes.indices)

val prefix = styleType.prefixes
.getOrNull(prefixIndex)
?: ""

val text = "$prefix "

return RichSpan(
paragraph = RichParagraph(type = this),
text = "",
text = text,
spanStyle = startTextSpanStyle,
textRange = TextRange(
textRange.min,
textRange.min + text.length
)
)
}

override fun getNextParagraphType(): ParagraphType =
UnorderedList(
initialIndent = indent,
startTextWidth = startTextWidth,
initialNestedLevel = nestedLevel,
initialStyleType = styleType,
)

override fun copy(): ParagraphType =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.mohamedrejeb.richeditor.paragraph.type

@ConsistentCopyVisibility
public data class UnorderedListStyleType private constructor(
internal val prefixes: List<String>,
) {
public companion object {
public fun from(vararg prefix: String): UnorderedListStyleType {
return UnorderedListStyleType(prefix.toList())
}

public fun from(prefixes: List<String>): UnorderedListStyleType {
return UnorderedListStyleType(prefixes)
}

public val Disc: UnorderedListStyleType = UnorderedListStyleType(
prefixes = listOf("")
)

public val Circle: UnorderedListStyleType = UnorderedListStyleType(
prefixes = listOf("")
)

public val Square: UnorderedListStyleType = UnorderedListStyleType(
prefixes = listOf("")
)
}
}
Loading

0 comments on commit 2942ffe

Please sign in to comment.