Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Mark formatting #1073

Merged
merged 13 commits into from
Mar 21, 2024
1 change: 1 addition & 0 deletions aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
AztecTextFormat.FORMAT_CODE -> inlineFormatter.toggle(textFormat)
AztecTextFormat.FORMAT_BOLD,
AztecTextFormat.FORMAT_STRONG -> inlineFormatter.toggleAny(ToolbarAction.BOLD.textFormats)
AztecTextFormat.FORMAT_MARK -> inlineFormatter.toggle(textFormat)
AztecTextFormat.FORMAT_UNORDERED_LIST -> blockFormatter.toggleUnorderedList()
AztecTextFormat.FORMAT_TASK_LIST -> blockFormatter.toggleTaskList()
AztecTextFormat.FORMAT_ORDERED_LIST -> blockFormatter.toggleOrderedList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import org.wordpress.aztec.watchers.TextChangedEvent
class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle, private val highlightStyle: HighlightStyle) : AztecFormatter(editor) {

var backgroundSpanColor: Int? = null
var markStyleColor: String? = null

data class CodeStyle(val codeBackground: Int, val codeBackgroundAlpha: Float, val codeColor: Int)
data class HighlightStyle(@ColorRes val color: Int)
Expand Down Expand Up @@ -107,12 +108,8 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle, private val h
applyInlineStyle(item, textChangedEvent.inputStart, textChangedEvent.inputEnd)
}
AztecTextFormat.FORMAT_MARK -> {
// For cases of an empty mark tag, either at the beginning of the text or in between
if (textChangedEvent.inputStart == 0 && textChangedEvent.inputEnd == 1) {
applyMarkInlineStyle(textChangedEvent.inputStart, textChangedEvent.inputEnd)
} else {
applyInlineStyle(item, textChangedEvent.inputStart, textChangedEvent.inputEnd)
}
applyInlineStyle(item, textChangedEvent.inputStart, textChangedEvent.inputEnd)
applyAfterMarkInlineStyle(textChangedEvent.inputStart, textChangedEvent.inputEnd)
}
else -> {
// do nothing
Expand All @@ -128,6 +125,16 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle, private val h
val newStart = if (start > end) end else start
// if there is END_OF_BUFFER_MARKER at the end of or range, extend the range to include it

// Clear Mark formatting styles
if (!editor.selectedStyles.contains(AztecTextFormat.FORMAT_MARK) && start >= 1 && end > 1 ) {
val previousMarkSpan = editableText.getSpans(start - 1, start, MarkSpan::class.java)
val markSpan = editableText.getSpans(start, end, MarkSpan::class.java)
if (markSpan.isNotEmpty() || previousMarkSpan.isNotEmpty()) {
removeInlineCssStyle(start, end)
return
}
}

// remove lingering empty spans when removing characters
if (start > end) {
editableText.getSpans(newStart, end, IAztecInlineSpan::class.java)
Expand Down Expand Up @@ -250,10 +257,40 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle, private val h
}
}

private fun applyMarkInlineStyle(start: Int = selectionStart, end: Int = selectionEnd) {
val previousSpans = editableText.getSpans(start, end, MarkSpan::class.java)
previousSpans.forEach {
it.applyInlineStyleAttributes(editableText, start, end)
private fun applyAfterMarkInlineStyle(start: Int = selectionStart, end: Int = selectionEnd) {
// If there's no new mark style color to update, it skips applying the style updates.
if (markStyleColor == null) {
return
}

val spans = editableText.getSpans(start, end, MarkSpan::class.java)
spans.forEach { span ->
if (span != null) {
val color = span.getTextColor()
val currentSpanStart = editableText.getSpanStart(span)
val currentSpanEnd = editableText.getSpanEnd(span)

if (end < currentSpanEnd) {
markStyleColor = null
return
}

if (!color.equals(markStyleColor, ignoreCase = true)) {
editableText.removeSpan(span)
editableText.setSpan(
MarkSpan(AztecAttributes(), color),
currentSpanStart,
start,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
editableText.setSpan(
MarkSpan(AztecAttributes(), markStyleColor),
start,
end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
}
}

Expand Down Expand Up @@ -444,7 +481,7 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle, private val h
AztecTextFormat.FORMAT_HIGHLIGHT -> {
HighlightSpan.create(context = editor.context, defaultStyle = highlightStyle)
}
AztecTextFormat.FORMAT_MARK -> MarkSpan()
AztecTextFormat.FORMAT_MARK -> MarkSpan(AztecAttributes(), markStyleColor)
else -> AztecStyleSpan(Typeface.NORMAL)
}
}
Expand Down
25 changes: 25 additions & 0 deletions aztec/src/main/kotlin/org/wordpress/aztec/plugins/MarkPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.wordpress.aztec.plugins

import android.text.SpannableStringBuilder
import org.wordpress.aztec.plugins.visual2html.ISpanPreprocessor
import org.wordpress.aztec.source.CssStyleFormatter
import org.wordpress.aztec.spans.MarkSpan

class MarkPlugin : ISpanPreprocessor {

override fun beforeSpansProcessed(spannable: SpannableStringBuilder) {
spannable.getSpans(0, spannable.length, MarkSpan::class.java).forEach {
if (!CssStyleFormatter.containsStyleAttribute(it.attributes, CssStyleFormatter.CSS_BACKGROUND_COLOR_ATTRIBUTE)) {
CssStyleFormatter.addStyleAttribute(it.attributes, CssStyleFormatter.CSS_BACKGROUND_COLOR_ATTRIBUTE, "rgba(0, 0, 0, 0)")
}

if (!CssStyleFormatter.containsStyleAttribute(it.attributes, CssStyleFormatter.CSS_COLOR_ATTRIBUTE)) {
CssStyleFormatter.addStyleAttribute(it.attributes, CssStyleFormatter.CSS_COLOR_ATTRIBUTE, it.getTextColor())
}

if (!it.attributes.hasAttribute("class")) {
it.attributes.setValue("class", "has-inline-color")
}
}
}
}
37 changes: 35 additions & 2 deletions aztec/src/main/kotlin/org/wordpress/aztec/spans/MarkSpan.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,45 @@
package org.wordpress.aztec.spans

import android.graphics.Color
import android.text.TextPaint
import android.text.style.CharacterStyle
import org.wordpress.aztec.AztecAttributes
import org.wordpress.aztec.source.CssStyleFormatter

class MarkSpan(override var attributes: AztecAttributes = AztecAttributes()) : CharacterStyle(), IAztecInlineSpan {
class MarkSpan : CharacterStyle, IAztecInlineSpan {
override var TAG = "mark"

override fun updateDrawState(tp: TextPaint?) {
override var attributes: AztecAttributes = AztecAttributes()
private val textColorValue: Int?

constructor(attributes: AztecAttributes = AztecAttributes()) : super() {
this.attributes = attributes

val color = CssStyleFormatter.getStyleAttribute(attributes,
CssStyleFormatter.CSS_COLOR_ATTRIBUTE)
textColorValue = if (color.isNotEmpty()) {
Color.parseColor(color)
} else {
null
}
}

constructor(attributes: AztecAttributes = AztecAttributes(), colorString: String?) : super() {
this.attributes = attributes

textColorValue = if (colorString != null) {
Color.parseColor(colorString)
} else {
null
}
}

override fun updateDrawState(tp: TextPaint) {
textColorValue?.let { tp.color = it }
}

fun getTextColor(): String {
geriux marked this conversation as resolved.
Show resolved Hide resolved
val currentColor = textColorValue ?: 0
return String.format("#%06X", 0xFFFFFF and currentColor)
}
}
Loading