diff --git a/app/src/main/kotlin/org/wordpress/aztec/demo/MainActivity.kt b/app/src/main/kotlin/org/wordpress/aztec/demo/MainActivity.kt
index 5552e7f3b..20d8a1f59 100644
--- a/app/src/main/kotlin/org/wordpress/aztec/demo/MainActivity.kt
+++ b/app/src/main/kotlin/org/wordpress/aztec/demo/MainActivity.kt
@@ -45,6 +45,8 @@ import org.wordpress.aztec.IHistoryListener
import org.wordpress.aztec.ITextFormat
import org.wordpress.aztec.glideloader.GlideImageLoader
import org.wordpress.aztec.glideloader.GlideVideoThumbnailLoader
+import org.wordpress.aztec.plugins.BackgroundColorButton
+import org.wordpress.aztec.plugins.CssBackgroundColorPlugin
import org.wordpress.aztec.plugins.CssUnderlinePlugin
import org.wordpress.aztec.plugins.IMediaToolbarButton
import org.wordpress.aztec.plugins.shortcodes.AudioShortcodePlugin
@@ -89,6 +91,7 @@ open class MainActivity : AppCompatActivity(),
private val BOLD = "Bold
"
private val ITALIC = "Italic
"
private val UNDERLINE = "Underline
"
+ private val BACKGROUND = "BACKGROUND
"
private val STRIKETHROUGH = "Strikethrough
" // or or
private val ORDERED = "- Ordered
- should have color
"
private val ORDERED_WITH_START = "Start in 10 List:
" +
@@ -185,6 +188,7 @@ open class MainActivity : AppCompatActivity(),
BOLD +
ITALIC +
UNDERLINE +
+ BACKGROUND +
STRIKETHROUGH +
ORDERED +
ORDERED_WITH_START +
@@ -459,9 +463,13 @@ open class MainActivity : AppCompatActivity(),
aztec.visualEditor.setCalypsoMode(false)
aztec.sourceEditor?.setCalypsoMode(false)
+ aztec.visualEditor.setBackgroundSpanColor(resources.getColor(R.color.blue_dark))
+
aztec.sourceEditor?.displayStyledAndFormattedHtml(EXAMPLE)
aztec.addPlugin(CssUnderlinePlugin())
+ aztec.addPlugin(CssBackgroundColorPlugin())
+ aztec.addPlugin(BackgroundColorButton(visualEditor))
}
if (savedInstanceState == null) {
diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/AztecTagHandler.kt b/aztec/src/main/kotlin/org/wordpress/aztec/AztecTagHandler.kt
index b491cc1a6..77a7faf0b 100644
--- a/aztec/src/main/kotlin/org/wordpress/aztec/AztecTagHandler.kt
+++ b/aztec/src/main/kotlin/org/wordpress/aztec/AztecTagHandler.kt
@@ -28,7 +28,9 @@ import android.text.Spanned
import androidx.appcompat.content.res.AppCompatResources
import org.wordpress.aztec.plugins.IAztecPlugin
import org.wordpress.aztec.plugins.html2visual.IHtmlTagHandler
+import org.wordpress.aztec.source.CssStyleFormatter
import org.wordpress.aztec.spans.AztecAudioSpan
+import org.wordpress.aztec.spans.AztecBackgroundColorSpan
import org.wordpress.aztec.spans.AztecHorizontalRuleSpan
import org.wordpress.aztec.spans.AztecImageSpan
import org.wordpress.aztec.spans.AztecMediaClickableSpan
@@ -38,6 +40,7 @@ import org.wordpress.aztec.spans.AztecVideoSpan
import org.wordpress.aztec.spans.HiddenHtmlSpan
import org.wordpress.aztec.spans.IAztecAttributedSpan
import org.wordpress.aztec.spans.IAztecNestable
+import org.wordpress.aztec.spans.IAztecSpan
import org.wordpress.aztec.spans.createAztecQuoteSpan
import org.wordpress.aztec.spans.createHeadingSpan
import org.wordpress.aztec.spans.createHiddenHtmlBlockSpan
@@ -47,6 +50,7 @@ import org.wordpress.aztec.spans.createOrderedListSpan
import org.wordpress.aztec.spans.createParagraphSpan
import org.wordpress.aztec.spans.createPreformatSpan
import org.wordpress.aztec.spans.createUnorderedListSpan
+import org.wordpress.aztec.util.ColorConverter
import org.wordpress.aztec.util.getLast
import org.xml.sax.Attributes
import java.util.ArrayList
@@ -83,7 +87,7 @@ class AztecTagHandler(val context: Context, val plugins: List = Ar
return true
}
SPAN -> {
- val span = createHiddenHtmlSpan(tag, AztecAttributes(attributes), nestingLevel, alignmentRendering)
+ val span = handleBackgroundColorSpanTag(attributes, tag, nestingLevel)
handleElement(output, opening, span)
return true
}
@@ -154,6 +158,17 @@ class AztecTagHandler(val context: Context, val plugins: List = Ar
return false
}
+ private fun handleBackgroundColorSpanTag(attributes: Attributes, tag: String, nestingLevel: Int): IAztecSpan {
+ val attrs = AztecAttributes(attributes)
+ return if (CssStyleFormatter.containsStyleAttribute(attrs, CssStyleFormatter.CSS_BACKGROUND_COLOR_ATTRIBUTE) || (tagStack.isNotEmpty() && tagStack.last() is AztecBackgroundColorSpan)) {
+ val att = CssStyleFormatter.getStyleAttribute(attrs, CssStyleFormatter.CSS_BACKGROUND_COLOR_ATTRIBUTE)
+ val color = ColorConverter.getColorInt(att)
+ AztecBackgroundColorSpan(color)
+ } else {
+ createHiddenHtmlSpan(tag, attrs, nestingLevel, alignmentRendering)
+ }
+ }
+
private fun processTagHandlerPlugins(tag: String, opening: Boolean, output: Editable, attributes: Attributes, nestingLevel: Int): Boolean {
plugins.filter { it is IHtmlTagHandler }
.map { it as IHtmlTagHandler }
diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt b/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt
index 2a5734cf7..d590c9995 100644
--- a/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt
+++ b/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt
@@ -366,6 +366,10 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
isInCalypsoMode = isCompatibleWithCalypso
}
+ fun setBackgroundSpanColor(color: Int) {
+ inlineFormatter.backgroundSpanColor = color
+ }
+
fun setGutenbergMode(isCompatibleWithGutenberg: Boolean) {
isInGutenbergMode = isCompatibleWithGutenberg
}
@@ -1143,6 +1147,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
AztecTextFormat.FORMAT_CITE,
AztecTextFormat.FORMAT_UNDERLINE,
AztecTextFormat.FORMAT_STRIKETHROUGH,
+ AztecTextFormat.FORMAT_BACKGROUND,
AztecTextFormat.FORMAT_CODE -> inlineFormatter.toggle(textFormat)
AztecTextFormat.FORMAT_BOLD,
AztecTextFormat.FORMAT_STRONG -> inlineFormatter.toggleAny(ToolbarAction.BOLD.textFormats)
@@ -1178,6 +1183,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
AztecTextFormat.FORMAT_CITE,
AztecTextFormat.FORMAT_UNDERLINE,
AztecTextFormat.FORMAT_STRIKETHROUGH,
+ AztecTextFormat.FORMAT_BACKGROUND,
AztecTextFormat.FORMAT_CODE -> return inlineFormatter.containsInlineStyle(format, selStart, selEnd)
AztecTextFormat.FORMAT_UNORDERED_LIST,
AztecTextFormat.FORMAT_ORDERED_LIST -> return blockFormatter.containsList(format, selStart, selEnd)
@@ -1191,7 +1197,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
}
}
- fun setToolbar(toolbar: IAztecToolbar) {
+ fun setToolbar(toolbar: IAztecToolbar?) {
formatToolbar = toolbar
}
@@ -1633,6 +1639,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
inlineFormatter.removeInlineStyle(AztecTextFormat.FORMAT_STRIKETHROUGH, start, end)
inlineFormatter.removeInlineStyle(AztecTextFormat.FORMAT_UNDERLINE, start, end)
inlineFormatter.removeInlineStyle(AztecTextFormat.FORMAT_CODE, start, end)
+ inlineFormatter.removeInlineStyle(AztecTextFormat.FORMAT_BACKGROUND, start, end)
}
fun removeBlockStylesFromRange(start: Int, end: Int, ignoreLineBounds: Boolean = false) {
diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/AztecTextFormat.kt b/aztec/src/main/kotlin/org/wordpress/aztec/AztecTextFormat.kt
index 2f0bb4bae..a4b94dd5a 100644
--- a/aztec/src/main/kotlin/org/wordpress/aztec/AztecTextFormat.kt
+++ b/aztec/src/main/kotlin/org/wordpress/aztec/AztecTextFormat.kt
@@ -35,4 +35,5 @@ enum class AztecTextFormat : ITextFormat {
FORMAT_FONT,
FORMAT_MONOSPACE,
FORMAT_CODE,
+ FORMAT_BACKGROUND,
}
diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/formatting/InlineFormatter.kt b/aztec/src/main/kotlin/org/wordpress/aztec/formatting/InlineFormatter.kt
index 13b96f1e0..5aca2e2bf 100644
--- a/aztec/src/main/kotlin/org/wordpress/aztec/formatting/InlineFormatter.kt
+++ b/aztec/src/main/kotlin/org/wordpress/aztec/formatting/InlineFormatter.kt
@@ -11,14 +11,16 @@ import org.wordpress.aztec.AztecText
import org.wordpress.aztec.AztecTextFormat
import org.wordpress.aztec.Constants
import org.wordpress.aztec.ITextFormat
+import org.wordpress.aztec.R
+import org.wordpress.aztec.spans.AztecBackgroundColorSpan
import org.wordpress.aztec.spans.AztecCodeSpan
import org.wordpress.aztec.spans.AztecStrikethroughSpan
import org.wordpress.aztec.spans.AztecStyleBoldSpan
import org.wordpress.aztec.spans.AztecStyleCiteSpan
-import org.wordpress.aztec.spans.AztecStyleItalicSpan
import org.wordpress.aztec.spans.AztecStyleEmphasisSpan
-import org.wordpress.aztec.spans.AztecStyleStrongSpan
+import org.wordpress.aztec.spans.AztecStyleItalicSpan
import org.wordpress.aztec.spans.AztecStyleSpan
+import org.wordpress.aztec.spans.AztecStyleStrongSpan
import org.wordpress.aztec.spans.AztecUnderlineSpan
import org.wordpress.aztec.spans.IAztecInlineSpan
import org.wordpress.aztec.watchers.TextChangedEvent
@@ -30,6 +32,8 @@ import java.util.ArrayList
*/
class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle) : AztecFormatter(editor) {
+ var backgroundSpanColor: Int? = null
+
data class CodeStyle(val codeBackground: Int, val codeBackgroundAlpha: Float, val codeColor: Int)
fun toggle(textFormat: ITextFormat) {
@@ -69,6 +73,7 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle) : AztecFormat
AztecTextFormat.FORMAT_EMPHASIS,
AztecTextFormat.FORMAT_CITE,
AztecTextFormat.FORMAT_STRIKETHROUGH,
+ AztecTextFormat.FORMAT_BACKGROUND,
AztecTextFormat.FORMAT_UNDERLINE,
AztecTextFormat.FORMAT_CODE -> {
applyInlineStyle(item, textChangedEvent.inputStart, textChangedEvent.inputEnd)
@@ -111,6 +116,11 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle) : AztecFormat
return
}
+ if (textFormat == AztecTextFormat.FORMAT_BACKGROUND) {
+ //clear previous background before applying a new one to avoid problems when using multiple bg colors
+ removeBackgroundInSelection(selectionStart, selectionEnd)
+ }
+
var precedingSpan: IAztecInlineSpan? = null
var followingSpan: IAztecInlineSpan? = null
@@ -129,10 +139,10 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle) : AztecFormat
if (spanEnd > start) {
// ensure css style is applied
- (precedingSpan as IAztecInlineSpan).applyInlineStyleAttributes(editableText, start, end)
+ spanToApply.applyInlineStyleAttributes(editableText, start, end)
return@applyInlineStyle // we are adding text inside span - no need to do anything special
} else {
- applySpan(precedingSpan as IAztecInlineSpan, spanStart, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
+ applySpan(spanToApply, spanStart, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
}
}
@@ -148,8 +158,7 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle) : AztecFormat
if (followingSpan != null) {
val spanEnd = editableText.getSpanEnd(followingSpan)
- applySpan(followingSpan as IAztecInlineSpan, start, spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
- editableText.setSpan(followingSpan, start, spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
+ applySpan(spanToApply, start, spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
}
@@ -172,10 +181,27 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle) : AztecFormat
applySpan(spanToApply, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
-
joinStyleSpans(start, end)
}
+ private fun removeBackgroundInSelection(selStart: Int, selEnd: Int) {
+ val spans = editableText.getSpans(selStart, selEnd, AztecBackgroundColorSpan::class.java)
+ spans.forEach { span ->
+ if (span != null) {
+ val currentSpanStart = editableText.getSpanStart(span)
+ val currentSpanEnd = editableText.getSpanEnd(span)
+ val color = span.backgroundColor
+ editableText.removeSpan(span)
+ if (selEnd < currentSpanEnd) {
+ editableText.setSpan(AztecBackgroundColorSpan(color), selEnd, currentSpanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
+ }
+ if (selStart > currentSpanStart) {
+ editableText.setSpan(AztecBackgroundColorSpan(color), currentSpanStart, selStart, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
+ }
+ }
+ }
+ }
+
private fun applySpan(span: IAztecInlineSpan, start: Int, end: Int, type: Int) {
if (start > end || start < 0 || end > editableText.length) {
// If an external logger is available log the error there.
@@ -205,6 +231,7 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle) : AztecFormat
AztecStrikethroughSpan::class.java -> return AztecTextFormat.FORMAT_STRIKETHROUGH
AztecUnderlineSpan::class.java -> return AztecTextFormat.FORMAT_UNDERLINE
AztecCodeSpan::class.java -> return AztecTextFormat.FORMAT_CODE
+ AztecBackgroundColorSpan::class.java -> return AztecTextFormat.FORMAT_BACKGROUND
else -> return null
}
}
@@ -221,7 +248,7 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle) : AztecFormat
editableText.removeSpan(it)
}
}
- // remove the CSS style span
+
removeInlineCssStyle()
list.forEach {
@@ -238,7 +265,7 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle) : AztecFormat
joinStyleSpans(start, end)
}
- fun removeInlineCssStyle(start: Int = selectionStart, end: Int = selectionEnd) {
+ private fun removeInlineCssStyle(start: Int = selectionStart, end: Int = selectionEnd) {
val spans = editableText.getSpans(start, end, ForegroundColorSpan::class.java)
spans.forEach {
editableText.removeSpan(it)
@@ -254,12 +281,17 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle) : AztecFormat
if (firstSpan is StyleSpan && secondSpan is StyleSpan) {
return firstSpan.style == secondSpan.style
}
+ // special check for BackgroundSpan
+ if (firstSpan is AztecBackgroundColorSpan && secondSpan is AztecBackgroundColorSpan) {
+ return firstSpan.backgroundColor == secondSpan.backgroundColor
+ }
return firstSpan.javaClass == secondSpan.javaClass
}
// TODO: Check if there is more efficient way to tidy spans
fun joinStyleSpans(start: Int, end: Int) {
+
// joins spans on the left
if (start > 1) {
val spansInSelection = editableText.getSpans(start, end, IAztecInlineSpan::class.java)
@@ -349,6 +381,8 @@ class InlineFormatter(editor: AztecText, val codeStyle: CodeStyle) : AztecFormat
AztecTextFormat.FORMAT_STRIKETHROUGH -> return AztecStrikethroughSpan()
AztecTextFormat.FORMAT_UNDERLINE -> return AztecUnderlineSpan()
AztecTextFormat.FORMAT_CODE -> return AztecCodeSpan(codeStyle)
+ AztecTextFormat.FORMAT_BACKGROUND -> return AztecBackgroundColorSpan(backgroundSpanColor ?: R.color.background)
+
else -> return AztecStyleSpan(Typeface.NORMAL)
}
}
diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/plugins/BackgroundColorButton.kt b/aztec/src/main/kotlin/org/wordpress/aztec/plugins/BackgroundColorButton.kt
new file mode 100644
index 000000000..3a03c17d9
--- /dev/null
+++ b/aztec/src/main/kotlin/org/wordpress/aztec/plugins/BackgroundColorButton.kt
@@ -0,0 +1,29 @@
+package org.wordpress.aztec.plugins
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import org.wordpress.aztec.AztecText
+import org.wordpress.aztec.R
+import org.wordpress.aztec.toolbar.AztecToolbar
+import org.wordpress.aztec.toolbar.IToolbarAction
+import org.wordpress.aztec.toolbar.ToolbarAction
+
+class BackgroundColorButton(private val visualEditor: AztecText) : IToolbarButton {
+
+ override val action: IToolbarAction = ToolbarAction.BACKGROUND
+ override val context = visualEditor.context!!
+
+ override fun toggle() {
+ visualEditor.toggleFormatting(action.textFormats.first())
+ }
+
+ override fun inflateButton(parent: ViewGroup) {
+ LayoutInflater.from(context).inflate(R.layout.background_color_button, parent)
+ }
+
+ override fun toolbarStateAboutToChange(toolbar: AztecToolbar, enable: Boolean) {
+ toolbar.findViewById(action.buttonId).isEnabled = enable
+ }
+
+}
diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/plugins/CssBackgroundColorPlugin.kt b/aztec/src/main/kotlin/org/wordpress/aztec/plugins/CssBackgroundColorPlugin.kt
new file mode 100644
index 000000000..b002063d3
--- /dev/null
+++ b/aztec/src/main/kotlin/org/wordpress/aztec/plugins/CssBackgroundColorPlugin.kt
@@ -0,0 +1,17 @@
+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.AztecBackgroundColorSpan
+
+class CssBackgroundColorPlugin : ISpanPreprocessor {
+
+ override fun beforeSpansProcessed(spannable: SpannableStringBuilder) {
+ spannable.getSpans(0, spannable.length, AztecBackgroundColorSpan::class.java).forEach {
+ if (!CssStyleFormatter.containsStyleAttribute(it.attributes, CssStyleFormatter.CSS_BACKGROUND_COLOR_ATTRIBUTE)) {
+ CssStyleFormatter.addStyleAttribute(it.attributes, CssStyleFormatter.CSS_BACKGROUND_COLOR_ATTRIBUTE, it.getColorHex())
+ }
+ }
+ }
+}
diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/source/CssStyleFormatter.kt b/aztec/src/main/kotlin/org/wordpress/aztec/source/CssStyleFormatter.kt
index d977d920c..563d72579 100644
--- a/aztec/src/main/kotlin/org/wordpress/aztec/source/CssStyleFormatter.kt
+++ b/aztec/src/main/kotlin/org/wordpress/aztec/source/CssStyleFormatter.kt
@@ -1,10 +1,11 @@
package org.wordpress.aztec.source
-import androidx.core.text.TextDirectionHeuristicsCompat
import android.text.Editable
import android.text.Layout
import android.text.Spannable
+import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan
+import androidx.core.text.TextDirectionHeuristicsCompat
import org.wordpress.aztec.AztecAttributes
import org.wordpress.aztec.spans.IAztecAlignmentSpan
import org.wordpress.aztec.spans.IAztecAttributedSpan
@@ -26,10 +27,11 @@ class CssStyleFormatter {
val CSS_TEXT_DECORATION_ATTRIBUTE = "text-decoration"
val CSS_TEXT_ALIGN_ATTRIBUTE = "text-align"
val CSS_COLOR_ATTRIBUTE = "color"
+ val CSS_BACKGROUND_COLOR_ATTRIBUTE = "background-color"
/**
* Check the provided [attributedSpan] for the *style* attribute. If found, parse out the
- * supported CSS style properties and use the results to create a [ForegroundColorSpan],
+ * supported CSS style properties and use the results to create a [ForegroundColorSpan] and/or [BackgroundColorSpan]
* then add it to the provided [text].
*
* Must be called immediately after the base [IAztecAttributedSpan] has been processed.
@@ -41,6 +43,7 @@ class CssStyleFormatter {
fun applyInlineStyleAttributes(text: Editable, attributedSpan: IAztecAttributedSpan, start: Int, end: Int) {
if (attributedSpan.attributes.hasAttribute(STYLE_ATTRIBUTE) && start != end) {
processColor(attributedSpan.attributes, text, start, end)
+ processBackgroundColor(attributedSpan.attributes, text, start, end)
if (attributedSpan is IAztecParagraphStyle) {
processAlignment(attributedSpan, text, start, end)
}
@@ -85,6 +88,16 @@ class CssStyleFormatter {
}
}
+ private fun processBackgroundColor(attributes: AztecAttributes, text: Editable, start: Int, end: Int) {
+ val colorAttrValue = getStyleAttribute(attributes, CSS_BACKGROUND_COLOR_ATTRIBUTE)
+ if (!colorAttrValue.isBlank()) {
+ val colorInt = ColorConverter.getColorInt(colorAttrValue)
+ if (colorInt != ColorConverter.COLOR_NOT_FOUND) {
+ text.setSpan(BackgroundColorSpan(colorInt), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
+ }
+ }
+ }
+
fun containsStyleAttribute(attributes: AztecAttributes, styleAttributeName: String): Boolean {
return attributes.hasAttribute(STYLE_ATTRIBUTE) && getMatcher(attributes, styleAttributeName).find()
}
diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/spans/AztecBackgroundColorSpan.kt b/aztec/src/main/kotlin/org/wordpress/aztec/spans/AztecBackgroundColorSpan.kt
new file mode 100644
index 000000000..650b0a33f
--- /dev/null
+++ b/aztec/src/main/kotlin/org/wordpress/aztec/spans/AztecBackgroundColorSpan.kt
@@ -0,0 +1,25 @@
+package org.wordpress.aztec.spans
+
+import android.graphics.Color
+import android.text.TextPaint
+import android.text.style.BackgroundColorSpan
+import org.wordpress.aztec.AztecAttributes
+
+class AztecBackgroundColorSpan(
+ val color: Int
+) : BackgroundColorSpan(color), IAztecInlineSpan {
+
+ var alpha: Int = 220
+ var tag: String = "span"
+ override var attributes: AztecAttributes = AztecAttributes()
+
+ fun getColorHex(): String {
+ return java.lang.String.format("#%06X", 0xFFFFFF and color)
+ }
+
+ override fun updateDrawState(textPaint: TextPaint) {
+ textPaint.bgColor = Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color))
+ }
+
+ override val TAG = tag
+}
\ No newline at end of file
diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/AztecToolbar.kt b/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/AztecToolbar.kt
index 4bcf86310..a5fb87946 100644
--- a/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/AztecToolbar.kt
+++ b/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/AztecToolbar.kt
@@ -378,7 +378,7 @@ class AztecToolbar : FrameLayout, IAztecToolbar, OnMenuItemClickListener {
return editor != null && editor is AztecText
}
- override fun setEditor(editor: AztecText, sourceEditor: SourceViewEditText?) {
+ override fun setEditor(editor: AztecText?, sourceEditor: SourceViewEditText?) {
this.sourceEditor = sourceEditor
this.editor = editor
@@ -450,7 +450,15 @@ class AztecToolbar : FrameLayout, IAztecToolbar, OnMenuItemClickListener {
toolbarButtonPlugins.add(buttonPlugin)
val button = findViewById(buttonPlugin.action.buttonId)
- button.setOnClickListener { buttonPlugin.toggle() }
+ val isToolbarAction = ToolbarAction.values().contains(buttonPlugin.action)
+ button.setOnClickListener {
+ if (isToolbarAction) {
+ onToolbarAction(buttonPlugin.action)
+ } else {
+ buttonPlugin.toggle()
+ }
+ }
+
button.setBackgroundDrawableRes(buttonPlugin.action.buttonDrawableRes)
setupMediaButtonForAccessibility(buttonPlugin)
@@ -497,7 +505,7 @@ class AztecToolbar : FrameLayout, IAztecToolbar, OnMenuItemClickListener {
if (action != ToolbarAction.ELLIPSIS_COLLAPSE &&
action != ToolbarAction.ELLIPSIS_EXPAND) {
val view = findViewById(action.buttonId)
- if (view.isChecked) actions.add(action)
+ if (view?.isChecked == true) actions.add(action)
}
}
diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/IAztecToolbar.kt b/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/IAztecToolbar.kt
index 589c2aa2a..cceb2320c 100644
--- a/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/IAztecToolbar.kt
+++ b/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/IAztecToolbar.kt
@@ -8,7 +8,7 @@ import org.wordpress.aztec.source.SourceViewEditText
interface IAztecToolbar {
fun onKeyUp(keyCode: Int, keyEvent: KeyEvent): Boolean
fun addButton(buttonPlugin: IToolbarButton)
- fun setEditor(editor: AztecText, sourceEditor: SourceViewEditText?)
+ fun setEditor(editor: AztecText?, sourceEditor: SourceViewEditText?)
fun setToolbarListener(listener: IAztecToolbarClickListener)
fun toggleMediaToolbar()
fun toggleEditorMode()
diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/ToolbarAction.kt b/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/ToolbarAction.kt
index c15b0a685..ada0fd3e3 100644
--- a/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/ToolbarAction.kt
+++ b/aztec/src/main/kotlin/org/wordpress/aztec/toolbar/ToolbarAction.kt
@@ -15,6 +15,12 @@ enum class ToolbarAction constructor(
override val textFormats: Set = setOf())
: IToolbarAction {
+ BACKGROUND(
+ R.id.format_bar_button_background_color,
+ R.drawable.format_bar_button_background_selector,
+ ToolbarActionType.INLINE_STYLE,
+ setOf(AztecTextFormat.FORMAT_BACKGROUND)
+ ),
ADD_MEDIA_COLLAPSE(
R.id.format_bar_button_media_collapsed,
R.drawable.format_bar_button_media_expanded_selector,
diff --git a/aztec/src/main/res/drawable/format_bar_button_background.xml b/aztec/src/main/res/drawable/format_bar_button_background.xml
new file mode 100644
index 000000000..d78ed9095
--- /dev/null
+++ b/aztec/src/main/res/drawable/format_bar_button_background.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/aztec/src/main/res/drawable/format_bar_button_background_disabled.xml b/aztec/src/main/res/drawable/format_bar_button_background_disabled.xml
new file mode 100644
index 000000000..f923b66c7
--- /dev/null
+++ b/aztec/src/main/res/drawable/format_bar_button_background_disabled.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/aztec/src/main/res/drawable/format_bar_button_background_highlighted.xml b/aztec/src/main/res/drawable/format_bar_button_background_highlighted.xml
new file mode 100644
index 000000000..b1779895c
--- /dev/null
+++ b/aztec/src/main/res/drawable/format_bar_button_background_highlighted.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/aztec/src/main/res/drawable/format_bar_button_background_selector.xml b/aztec/src/main/res/drawable/format_bar_button_background_selector.xml
new file mode 100644
index 000000000..c8ab76fce
--- /dev/null
+++ b/aztec/src/main/res/drawable/format_bar_button_background_selector.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/aztec/src/main/res/layout/background_color_button.xml b/aztec/src/main/res/layout/background_color_button.xml
new file mode 100644
index 000000000..908f3d1d3
--- /dev/null
+++ b/aztec/src/main/res/layout/background_color_button.xml
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/aztec/src/main/res/values/strings.xml b/aztec/src/main/res/values/strings.xml
index a555c2f22..1104f8f97 100644
--- a/aztec/src/main/res/values/strings.xml
+++ b/aztec/src/main/res/values/strings.xml
@@ -19,6 +19,7 @@
Heading
Bold
+ Background Color
Italic
Underline
Strikethrough
diff --git a/aztec/src/test/kotlin/org/wordpress/aztec/AztecToolbarTest.kt b/aztec/src/test/kotlin/org/wordpress/aztec/AztecToolbarTest.kt
index ce9934eb4..0fe823bdb 100644
--- a/aztec/src/test/kotlin/org/wordpress/aztec/AztecToolbarTest.kt
+++ b/aztec/src/test/kotlin/org/wordpress/aztec/AztecToolbarTest.kt
@@ -9,6 +9,7 @@ import org.junit.runner.RunWith
import org.robolectric.Robolectric
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
+import org.wordpress.aztec.plugins.BackgroundColorButton
import org.wordpress.aztec.source.SourceViewEditText
import org.wordpress.aztec.toolbar.AztecToolbar
@@ -26,6 +27,7 @@ class AztecToolbarTest {
lateinit var italicButton: ToggleButton
lateinit var strikeThroughButton: ToggleButton
lateinit var underlineButton: ToggleButton
+ lateinit var backgroundColorButton: ToggleButton
lateinit var quoteButton: ToggleButton
lateinit var linkButton: ToggleButton
lateinit var htmlButton: ToggleButton
@@ -58,6 +60,8 @@ class AztecToolbarTest {
alignCenterButton = toolbar.findViewById(R.id.format_bar_button_align_center)
alignRightButton = toolbar.findViewById(R.id.format_bar_button_align_right)
+ toolbar.addButton(BackgroundColorButton(editText))
+ backgroundColorButton = toolbar.findViewById(R.id.format_bar_button_background_color)
}
/**
@@ -245,6 +249,47 @@ class AztecToolbarTest {
Assert.assertEquals("underline", editText.toHtml())
}
+ /**
+ * Toggle backgroundColor button and type.
+ *
+ * @throws Exception
+ */
+ @Test
+ @Throws(Exception::class)
+ fun testBackgroundColorTyping() {
+ Assert.assertFalse(backgroundColorButton.isChecked)
+ backgroundColorButton.performClick()
+ Assert.assertTrue(backgroundColorButton.isChecked)
+
+ editText.append("backgroundColor")
+ Assert.assertEquals("backgroundColor", editText.toHtml())
+
+ backgroundColorButton.performClick()
+ Assert.assertFalse(backgroundColorButton.isChecked)
+ }
+
+ /**
+ * Select text and toggle backgroundColor button.
+ *
+ * @throws Exception
+ */
+ @Test
+ @Throws(Exception::class)
+ fun testBackgroundColorToggle() {
+ Assert.assertFalse(backgroundColorButton.isChecked)
+
+ editText.append("backgroundColor")
+ editText.setSelection(0, editText.length())
+ backgroundColorButton.performClick()
+ Assert.assertTrue(backgroundColorButton.isChecked)
+ Assert.assertEquals("backgroundColor", editText.toHtml())
+
+ backgroundColorButton.performClick()
+ Assert.assertFalse(backgroundColorButton.isChecked)
+
+ Assert.assertEquals("backgroundColor", editText.toHtml())
+ }
+
/**
* Test inline style when applying and removing styles while typing.
*
@@ -549,7 +594,7 @@ class AztecToolbarTest {
Assert.assertFalse(italicButton.isChecked)
italicButton.performClick()
- Assert.assertEquals("bolditalic", editText.toHtml())
+ Assert.assertEquals("bolditalic", editText.toHtml())
}
/**