Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Use AlignmentApproach with list spans
  • Loading branch information
mchowning committed Apr 24, 2020
commit 7701b32be61de33717775e32ba34b8710f15cff9
14 changes: 7 additions & 7 deletions aztec/src/main/kotlin/org/wordpress/aztec/AztecTagHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,21 @@ import org.wordpress.aztec.plugins.html2visual.IHtmlTagHandler
import org.wordpress.aztec.spans.AztecAudioSpan
import org.wordpress.aztec.spans.AztecHorizontalRuleSpan
import org.wordpress.aztec.spans.AztecImageSpan
import org.wordpress.aztec.spans.AztecListItemSpan
import org.wordpress.aztec.spans.AztecMediaClickableSpan
import org.wordpress.aztec.spans.AztecMediaSpan
import org.wordpress.aztec.spans.AztecOrderedListSpan
import org.wordpress.aztec.spans.AztecQuoteSpan
import org.wordpress.aztec.spans.AztecStrikethroughSpan
import org.wordpress.aztec.spans.AztecUnorderedListSpan
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.createAztecQuoteSpan
import org.wordpress.aztec.spans.createHeadingSpan
import org.wordpress.aztec.spans.createHiddenHtmlBlockSpan
import org.wordpress.aztec.spans.createListItemSpan
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.getLast
import org.xml.sax.Attributes
import java.util.ArrayList
Expand Down Expand Up @@ -74,7 +73,8 @@ class AztecTagHandler(val context: Context, val plugins: List<IAztecPlugin> = Ar

when (tag.toLowerCase()) {
LIST_LI -> {
handleElement(output, opening, AztecListItemSpan(nestingLevel, AztecAttributes(attributes)))
val span = createListItemSpan(nestingLevel, alignmentApproach, AztecAttributes(attributes))
handleElement(output, opening, span)
return true
}
STRIKETHROUGH_S, STRIKETHROUGH_STRIKE, STRIKETHROUGH_DEL -> {
Expand All @@ -91,11 +91,11 @@ class AztecTagHandler(val context: Context, val plugins: List<IAztecPlugin> = Ar
return true
}
LIST_UL -> {
handleElement(output, opening, AztecUnorderedListSpan(nestingLevel, AztecAttributes(attributes)))
handleElement(output, opening, createUnorderedListSpan(nestingLevel, alignmentApproach, AztecAttributes(attributes)))
return true
}
LIST_OL -> {
handleElement(output, opening, AztecOrderedListSpan(nestingLevel, AztecAttributes(attributes)))
handleElement(output, opening, createOrderedListSpan(nestingLevel, alignmentApproach, AztecAttributes(attributes)))
return true
}
BLOCKQUOTE -> {
Expand Down
2 changes: 1 addition & 1 deletion aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
BlockElementWatcher(this)
.add(HeadingHandler(alignmentApproach))
.add(ListHandler())
.add(ListItemHandler())
.add(ListItemHandler(alignmentApproach))
.add(QuoteHandler())
.add(PreformatHandler())
.install(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ import org.wordpress.aztec.spans.IAztecNestable
import org.wordpress.aztec.spans.ParagraphSpan
import org.wordpress.aztec.spans.createAztecQuoteSpan
import org.wordpress.aztec.spans.createHeadingSpan
import org.wordpress.aztec.spans.createListItemSpan
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.SpanWrapper
import java.util.Arrays
import kotlin.reflect.KClass
Expand Down Expand Up @@ -251,7 +254,7 @@ class BlockFormatter(editor: AztecText,
// when removing style from multiple selected lines, if the last selected line is empty
// or at the end of editor the selection wont include the trailing newline/EOB marker
// that will leave us with orphan <li> tag, so we need to shift index to the right
val hasLingeringEmptyListItem = spanType.isAssignableFrom(AztecListItemSpan::class.java)
val hasLingeringEmptyListItem = AztecListItemSpan::class.java.isAssignableFrom(spanType)
Copy link
Contributor Author

@mchowning mchowning Apr 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change to the logic, but I think it was incorrect before because a spanType of, for example Object would have returned true before since an AztecListItemSpan can be assigned to an Object. With my change, we are instead checking that it is either an AztecListItemSpan or a subclass.

&& editableText.length > end
&& (editableText[end] == '\n' || editableText[end] == Constants.END_OF_BUFFER_MARKER)

Expand Down Expand Up @@ -294,8 +297,8 @@ class BlockFormatter(editor: AztecText,
// TODO: Come up with a better way to init spans and get their classes (all the "make" methods)
fun makeBlock(textFormat: ITextFormat, nestingLevel: Int, attrs: AztecAttributes = AztecAttributes()): List<IAztecBlockSpan> {
when (textFormat) {
AztecTextFormat.FORMAT_ORDERED_LIST -> return Arrays.asList(AztecOrderedListSpan(nestingLevel, attrs, listStyle), AztecListItemSpan(nestingLevel + 1))
AztecTextFormat.FORMAT_UNORDERED_LIST -> return Arrays.asList(AztecUnorderedListSpan(nestingLevel, attrs, listStyle), AztecListItemSpan(nestingLevel + 1))
AztecTextFormat.FORMAT_ORDERED_LIST -> return Arrays.asList(createOrderedListSpan(nestingLevel, alignmentApproach, attrs, listStyle), createListItemSpan(nestingLevel + 1, alignmentApproach))
AztecTextFormat.FORMAT_UNORDERED_LIST -> return Arrays.asList(createUnorderedListSpan(nestingLevel, alignmentApproach, attrs, listStyle), createListItemSpan(nestingLevel + 1, alignmentApproach))
AztecTextFormat.FORMAT_QUOTE -> return Arrays.asList(createAztecQuoteSpan(nestingLevel, attrs, alignmentApproach, quoteStyle))
AztecTextFormat.FORMAT_HEADING_1,
AztecTextFormat.FORMAT_HEADING_2,
Expand Down Expand Up @@ -339,9 +342,9 @@ class BlockFormatter(editor: AztecText,
private fun <T : KClass<out IAztecBlockSpan>> makeBlockSpan(type: T, textFormat: ITextFormat, nestingLevel: Int, attrs: AztecAttributes = AztecAttributes()): IAztecBlockSpan {
val typeIsAssignableTo = { clazz: KClass<out Any> -> clazz.java.isAssignableFrom(type.java) }
return when {
typeIsAssignableTo(AztecOrderedListSpan::class) -> AztecOrderedListSpan(nestingLevel, attrs, listStyle)
typeIsAssignableTo(AztecUnorderedListSpan::class) -> AztecUnorderedListSpan(nestingLevel, attrs, listStyle)
typeIsAssignableTo(AztecListItemSpan::class) -> AztecListItemSpan(nestingLevel, attrs)
typeIsAssignableTo(AztecOrderedListSpan::class) -> createOrderedListSpan(nestingLevel, alignmentApproach, attrs, listStyle)
typeIsAssignableTo(AztecUnorderedListSpan::class) -> createUnorderedListSpan(nestingLevel, alignmentApproach, attrs, listStyle)
typeIsAssignableTo(AztecListItemSpan::class) -> createListItemSpan(nestingLevel, alignmentApproach, attrs)
typeIsAssignableTo(AztecQuoteSpan::class) -> createAztecQuoteSpan(nestingLevel, attrs, alignmentApproach, quoteStyle)
typeIsAssignableTo(AztecHeadingSpan::class) -> createHeadingSpan(nestingLevel, textFormat, attrs, alignmentApproach, headerStyle)
typeIsAssignableTo(AztecPreformatSpan::class) -> createPreformatSpan(nestingLevel, alignmentApproach, attrs, preformatStyle)
Expand Down Expand Up @@ -651,7 +654,7 @@ class BlockFormatter(editor: AztecText,
BlockHandler.set(editableText, listSpan, start, end)
// special case for styling single empty lines
if (end - start == 1 && (editableText[end - 1] == '\n' || editableText[end - 1] == Constants.END_OF_BUFFER_MARKER)) {
ListItemHandler.newListItem(editableText, start, end, listSpan.nestingLevel + 1)
ListItemHandler.newListItem(editableText, start, end, listSpan.nestingLevel + 1, alignmentApproach)
} else {
val listEnd = if (end == editableText.length) end else end - 1
val listContent = editableText.substring(start, listEnd)
Expand All @@ -666,7 +669,12 @@ class BlockFormatter(editor: AztecText,
if ((start + it) != editableText.length) it + 1 else it // include the newline or not
}

ListItemHandler.newListItem(editableText, start + lineStart, start + lineEnd, listSpan.nestingLevel + 1)
ListItemHandler.newListItem(
editableText,
start + lineStart,
start + lineEnd,
listSpan.nestingLevel + 1,
alignmentApproach)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package org.wordpress.aztec.handlers

import android.text.Spannable
import org.wordpress.aztec.AlignmentApproach
import org.wordpress.aztec.spans.AztecListItemSpan
import org.wordpress.aztec.spans.IAztecNestable
import org.wordpress.aztec.spans.createListItemSpan
import org.wordpress.aztec.watchers.TextDeleter

class ListItemHandler : BlockHandler<AztecListItemSpan>(AztecListItemSpan::class.java) {
class ListItemHandler(
val alignmentApproach: AlignmentApproach
) : BlockHandler<AztecListItemSpan>(AztecListItemSpan::class.java) {

override fun handleNewlineAtStartOfBlock() {
// newline added at start of bullet so, add a new bullet
newListItem(text, newlineIndex, newlineIndex + 1, block.span.nestingLevel)
newListItem(text, newlineIndex, newlineIndex + 1, block.span.nestingLevel, alignmentApproach)

// push current bullet forward
block.start = newlineIndex + 1
Expand Down Expand Up @@ -51,7 +55,7 @@ class ListItemHandler : BlockHandler<AztecListItemSpan>(AztecListItemSpan::class
newListItemStart = newlineIndex
}

newListItem(text, newListItemStart, block.end, block.span.nestingLevel)
newListItem(text, newListItemStart, block.end, block.span.nestingLevel, alignmentApproach)
block.end = newListItemStart
}

Expand All @@ -62,16 +66,22 @@ class ListItemHandler : BlockHandler<AztecListItemSpan>(AztecListItemSpan::class
}

// attach a new bullet around the end-of-text marker
newListItem(text, markerIndex, markerIndex + 1, block.span.nestingLevel)
newListItem(text, markerIndex, markerIndex + 1, block.span.nestingLevel, alignmentApproach)

// the current list item has bled over to the marker so, let's adjust its range to just before the marker.
// There's a newline there hopefully :)
block.end = markerIndex
}

companion object {
fun newListItem(text: Spannable, start: Int, end: Int, nestingLevel: Int) {
set(text, AztecListItemSpan(nestingLevel), start, end)
fun newListItem(
text: Spannable,
start: Int,
end: Int,
nestingLevel: Int,
alignmentApproach: AlignmentApproach
) {
set(text, createListItemSpan(nestingLevel, alignmentApproach), start, end)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,36 @@
package org.wordpress.aztec.spans

import android.text.Layout
import org.wordpress.aztec.AlignmentApproach
import org.wordpress.aztec.AztecAttributes

class AztecListItemSpan(override var nestingLevel: Int,
override var attributes: AztecAttributes = AztecAttributes(),
override var align: Layout.Alignment? = null
) : IAztecAlignmentSpan, IAztecCompositeBlockSpan {
fun createListItemSpan(nestingLevel: Int,
alignmentApproach: AlignmentApproach,
attributes: AztecAttributes = AztecAttributes()) : IAztecBlockSpan =
when (alignmentApproach) {
AlignmentApproach.SPAN_LEVEL -> AztecListItemSpanAligned(nestingLevel, attributes, null)
AlignmentApproach.VIEW_LEVEL -> AztecListItemSpan(nestingLevel, attributes)
}

/**
* We need to have two classes for handling alignment at either the Span-level (ListItemSpanAligned)
* or the View-level (ListItemSpan). IAztecAlignment implements AlignmentSpan, which has a
* getAlignment method that returns a non-null Layout.Alignment. The Android system checks for
* AlignmentSpans and, if present, overrides the view's gravity with their value. Having a class
* that does not implement AlignmentSpan allows the view's gravity to control. These classes should
* be created using the createListItemSpan(...) methods.
*/
open class AztecListItemSpan(
override var nestingLevel: Int,
override var attributes: AztecAttributes) : IAztecCompositeBlockSpan {
override val TAG = "li"

override var endBeforeBleed: Int = -1
override var startBeforeCollapse: Int = -1
}

class AztecListItemSpanAligned(
nestingLevel: Int,
attributes: AztecAttributes,
override var align: Layout.Alignment?
) : AztecListItemSpan(nestingLevel, attributes), IAztecAlignmentSpan
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package org.wordpress.aztec.spans

import android.graphics.Paint
import android.text.Layout
import android.text.Spanned
import android.text.style.LeadingMarginSpan
import android.text.style.LineHeightSpan
import android.text.style.UpdateLayout
import org.wordpress.aztec.Constants

abstract class AztecListSpan(override var nestingLevel: Int,
var verticalPadding: Int = 0,
override var align: Layout.Alignment? = null
) : LeadingMarginSpan.Standard(0),
var verticalPadding: Int = 0
) : LeadingMarginSpan.Standard(0),
LineHeightSpan,
UpdateLayout,
IAztecAlignmentSpan,
IAztecBlockSpan {
override var endBeforeBleed: Int = -1
override var startBeforeCollapse: Int = -1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,36 @@ import android.graphics.Canvas
import android.graphics.Paint
import android.text.Layout
import android.text.Spanned
import org.wordpress.aztec.AlignmentApproach
import org.wordpress.aztec.AztecAttributes
import org.wordpress.aztec.formatting.BlockFormatter

class AztecOrderedListSpan(
fun createOrderedListSpan(
nestingLevel: Int,
alignmentApproach: AlignmentApproach,
attributes: AztecAttributes = AztecAttributes(),
listStyle: BlockFormatter.ListStyle = BlockFormatter.ListStyle(0, 0, 0, 0, 0)
) = when (alignmentApproach) {
AlignmentApproach.SPAN_LEVEL -> AztecOrderedListSpanAligned(nestingLevel, attributes, listStyle, null)
AlignmentApproach.VIEW_LEVEL -> AztecOrderedListSpan(nestingLevel, attributes, listStyle)
}

/**
* We need to have two classes for handling alignment at either the Span-level (AztecOrderedListSpanAligned)
* or the View-level (AztecOrderedListSpan). IAztecAlignment implements AlignmentSpan, which has a
* getAlignment method that returns a non-null Layout.Alignment. The Android system checks for
* AlignmentSpans and, if present, overrides the view's gravity with their value. Having a class
* that does not implement AlignmentSpan allows the view's gravity to control. These classes should
* be created using the createOrderedListSpan(...) methods.
*/
class AztecOrderedListSpanAligned(
nestingLevel: Int,
attributes: AztecAttributes = AztecAttributes(),
listStyle: BlockFormatter.ListStyle = BlockFormatter.ListStyle(0, 0, 0, 0, 0),
override var align: Layout.Alignment?
) : AztecOrderedListSpan(nestingLevel, attributes, listStyle), IAztecAlignmentSpan

open class AztecOrderedListSpan(
override var nestingLevel: Int,
override var attributes: AztecAttributes = AztecAttributes(),
var listStyle: BlockFormatter.ListStyle = BlockFormatter.ListStyle(0, 0, 0, 0, 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,36 @@ import android.graphics.Canvas
import android.graphics.Paint
import android.text.Layout
import android.text.Spanned
import org.wordpress.aztec.AlignmentApproach
import org.wordpress.aztec.AztecAttributes
import org.wordpress.aztec.formatting.BlockFormatter

class AztecUnorderedListSpan(
fun createUnorderedListSpan(
nestingLevel: Int,
alignmentApproach: AlignmentApproach,
attributes: AztecAttributes = AztecAttributes(),
listStyle: BlockFormatter.ListStyle = BlockFormatter.ListStyle(0, 0, 0, 0, 0)
) = when (alignmentApproach) {
AlignmentApproach.SPAN_LEVEL -> AztecUnorderedListSpanAligned(nestingLevel, attributes, listStyle, null)
AlignmentApproach.VIEW_LEVEL -> AztecUnorderedListSpan(nestingLevel, attributes, listStyle)
}

/**
* We need to have two classes for handling alignment at either the Span-level (AztecUnorderedListSpanAligned)
* or the View-level (AztecUnorderedListSpan). IAztecAlignment implements AlignmentSpan, which has a
* getAlignment method that returns a non-null Layout.Alignment. The Android system checks for
* AlignmentSpans and, if present, overrides the view's gravity with their value. Having a class
* that does not implement AlignmentSpan allows the view's gravity to control. These classes should
* be created using the createUnorderedListSpan(...) methods.
*/
class AztecUnorderedListSpanAligned(
nestingLevel: Int,
attributes: AztecAttributes = AztecAttributes(),
listStyle: BlockFormatter.ListStyle = BlockFormatter.ListStyle(0, 0, 0, 0, 0),
override var align: Layout.Alignment?
) : AztecUnorderedListSpan(nestingLevel, attributes, listStyle), IAztecAlignmentSpan

open class AztecUnorderedListSpan(
override var nestingLevel: Int,
override var attributes: AztecAttributes = AztecAttributes(),
var listStyle: BlockFormatter.ListStyle = BlockFormatter.ListStyle(0, 0, 0, 0, 0)
Expand Down