Skip to content

Commit 3d14e18

Browse files
committed
Move code from MediaFormatter to LineBlockFormatter
1 parent 8649275 commit 3d14e18

File tree

3 files changed

+153
-166
lines changed

3 files changed

+153
-166
lines changed

aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ import org.wordpress.aztec.formatting.BlockFormatter
6868
import org.wordpress.aztec.formatting.InlineFormatter
6969
import org.wordpress.aztec.formatting.LineBlockFormatter
7070
import org.wordpress.aztec.formatting.LinkFormatter
71-
import org.wordpress.aztec.formatting.MediaFormatter
7271
import org.wordpress.aztec.handlers.HeadingHandler
7372
import org.wordpress.aztec.handlers.ListHandler
7473
import org.wordpress.aztec.handlers.ListItemHandler
@@ -280,7 +279,6 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
280279
lateinit var blockFormatter: BlockFormatter
281280
lateinit var lineBlockFormatter: LineBlockFormatter
282281
lateinit var linkFormatter: LinkFormatter
283-
lateinit var mediaFormatter: MediaFormatter
284282

285283
var imageGetter: Html.ImageGetter? = null
286284
var videoThumbnailGetter: Html.VideoThumbnailGetter? = null
@@ -457,7 +455,6 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
457455
styles.getBoolean(R.styleable.AztecText_linkUnderline, true)))
458456

459457
lineBlockFormatter = LineBlockFormatter(this)
460-
mediaFormatter = MediaFormatter(this)
461458

462459
styles.recycle()
463460

@@ -1170,7 +1167,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
11701167
AztecTextFormat.FORMAT_PREFORMAT -> blockFormatter.togglePreformat()
11711168
AztecTextFormat.FORMAT_QUOTE -> blockFormatter.toggleQuote()
11721169
AztecTextFormat.FORMAT_HORIZONTAL_RULE -> {
1173-
mediaFormatter.applyHorizontalRule(shouldAddMediaInline)
1170+
lineBlockFormatter.applyHorizontalRule(shouldAddMediaInline)
11741171
}
11751172
else -> {
11761173
plugins.filter { it is IToolbarButton && it.action.textFormats.contains(textFormat) }
@@ -1960,11 +1957,11 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
19601957
}
19611958

19621959
fun insertImage(drawable: Drawable?, attributes: Attributes) {
1963-
mediaFormatter.insertImage(shouldAddMediaInline, drawable, attributes, onImageTappedListener, onMediaDeletedListener)
1960+
lineBlockFormatter.insertImage(shouldAddMediaInline, drawable, attributes, onImageTappedListener, onMediaDeletedListener)
19641961
}
19651962

19661963
fun insertVideo(drawable: Drawable?, attributes: Attributes) {
1967-
mediaFormatter.insertVideo(shouldAddMediaInline, drawable, attributes, onVideoTappedListener, onMediaDeletedListener)
1964+
lineBlockFormatter.insertVideo(shouldAddMediaInline, drawable, attributes, onVideoTappedListener, onMediaDeletedListener)
19681965
}
19691966

19701967
fun removeMedia(attributePredicate: AttributePredicate) {

aztec/src/main/kotlin/org/wordpress/aztec/formatting/LineBlockFormatter.kt

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
11
package org.wordpress.aztec.formatting
22

3+
import android.graphics.drawable.Drawable
4+
import android.text.SpannableStringBuilder
5+
import android.text.Spanned
36
import android.text.TextUtils
7+
import androidx.appcompat.content.res.AppCompatResources
8+
import org.wordpress.aztec.AztecAttributes
49
import org.wordpress.aztec.AztecText
510
import org.wordpress.aztec.AztecTextFormat
11+
import org.wordpress.aztec.Constants
612
import org.wordpress.aztec.ITextFormat
13+
import org.wordpress.aztec.R
714
import org.wordpress.aztec.spans.AztecHeadingSpan
15+
import org.wordpress.aztec.spans.AztecHorizontalRuleSpan
16+
import org.wordpress.aztec.spans.AztecImageSpan
17+
import org.wordpress.aztec.spans.AztecMediaClickableSpan
18+
import org.wordpress.aztec.spans.AztecMediaSpan
19+
import org.wordpress.aztec.spans.AztecVideoSpan
20+
import org.wordpress.aztec.spans.IAztecBlockSpan
21+
import org.wordpress.aztec.spans.IAztecNestable
22+
import org.wordpress.aztec.watchers.EndOfBufferMarkerAdder
23+
import org.xml.sax.Attributes
824

925
class LineBlockFormatter(editor: AztecText) : AztecFormatter(editor) {
1026

@@ -76,4 +92,138 @@ class LineBlockFormatter(editor: AztecText) : AztecFormatter(editor) {
7692

7793
return false
7894
}
95+
fun applyHorizontalRule(inline: Boolean) {
96+
val nestingLevel = if (inline) {
97+
editor.removeInlineStylesFromRange(selectionStart, selectionEnd)
98+
editor.removeBlockStylesFromRange(selectionStart, selectionEnd, true)
99+
IAztecNestable.getNestingLevelAt(editableText, selectionStart)
100+
} else {
101+
0
102+
}
103+
104+
val span = AztecHorizontalRuleSpan(
105+
editor.context,
106+
AppCompatResources.getDrawable(editor.context, R.drawable.img_hr)!!,
107+
nestingLevel,
108+
AztecAttributes(),
109+
editor
110+
)
111+
112+
val builder = SpannableStringBuilder(Constants.MAGIC_STRING)
113+
builder.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
114+
115+
if (inline) {
116+
editableText.replace(selectionStart, selectionEnd, builder)
117+
val newSelectionPosition = editableText.indexOf(Constants.MAGIC_CHAR, selectionStart) + 1
118+
editor.setSelection(newSelectionPosition)
119+
} else {
120+
builder.append("\n")
121+
insertSpanAfterBlock(builder)
122+
}
123+
}
124+
125+
fun insertVideo(inline: Boolean, drawable: Drawable?, attributes: Attributes, onVideoTappedListener: AztecText.OnVideoTappedListener?,
126+
onMediaDeletedListener: AztecText.OnMediaDeletedListener?) {
127+
val nestingLevel = if (inline) IAztecNestable.getNestingLevelAt(editableText, selectionStart) else 0
128+
val span = AztecVideoSpan(editor.context, drawable, nestingLevel, AztecAttributes(attributes), onVideoTappedListener,
129+
onMediaDeletedListener, editor)
130+
if (inline) {
131+
insertMediaInline(span)
132+
} else {
133+
insertMediaAfterBlock(span)
134+
}
135+
}
136+
137+
fun insertImage(inline: Boolean, drawable: Drawable?, attributes: Attributes, onImageTappedListener: AztecText.OnImageTappedListener?,
138+
onMediaDeletedListener: AztecText.OnMediaDeletedListener?) {
139+
val nestingLevel = if (inline) IAztecNestable.getNestingLevelAt(editableText, selectionStart) else 0
140+
val span = AztecImageSpan(editor.context, drawable, nestingLevel, AztecAttributes(attributes), onImageTappedListener,
141+
onMediaDeletedListener, editor)
142+
if (inline) {
143+
insertMediaInline(span)
144+
} else {
145+
insertMediaAfterBlock(span)
146+
}
147+
}
148+
149+
private fun insertMediaInline(span: AztecMediaSpan) {
150+
editor.removeInlineStylesFromRange(selectionStart, selectionEnd)
151+
152+
val ssb = SpannableStringBuilder(Constants.IMG_STRING)
153+
154+
buildClickableMediaSpan(ssb, span)
155+
156+
// We need to be sure the cursor is placed correctly after media insertion
157+
// Note that media has '\n' around them when needed
158+
val isLastItem = selectionEnd == EndOfBufferMarkerAdder.safeLength(editor)
159+
editableText.replace(selectionStart, selectionEnd, ssb)
160+
161+
setSelection(isLastItem, selectionEnd)
162+
}
163+
164+
private fun insertMediaAfterBlock(span: AztecMediaSpan) {
165+
val ssb = SpannableStringBuilder(Constants.IMG_STRING)
166+
ssb.append("\n")
167+
buildClickableMediaSpan(ssb, span)
168+
insertSpanAfterBlock(ssb)
169+
}
170+
171+
private fun insertSpanAfterBlock(ssb: SpannableStringBuilder) {
172+
val position = getEndOfBlock()
173+
// We need to be sure the cursor is placed correctly after media insertion
174+
// Note that media has '\n' around them when needed
175+
val isLastItem = position == EndOfBufferMarkerAdder.safeLength(editor)
176+
val insertedLength = ssb.length
177+
editableText.insert(position, ssb)
178+
val spans = editableText.getSpans(position, position + insertedLength, IAztecBlockSpan::class.java).filter {
179+
it !is AztecMediaSpan && editableText.getSpanStart(it) == position
180+
}
181+
spans.forEach {
182+
val spanStart = editableText.getSpanStart(it)
183+
val spanEnd = editableText.getSpanEnd(it)
184+
val spanFlags = editableText.getSpanFlags(it)
185+
editableText.removeSpan(it)
186+
if (spanStart + insertedLength < spanEnd) {
187+
editableText.setSpan(it, spanStart + insertedLength, spanEnd, spanFlags)
188+
}
189+
}
190+
setSelection(isLastItem, position)
191+
}
192+
193+
private fun setSelection(isLastItem: Boolean, position: Int) {
194+
val newSelection = if (isLastItem) {
195+
EndOfBufferMarkerAdder.safeLength(editor)
196+
} else {
197+
if (position < EndOfBufferMarkerAdder.safeLength(editor)) position + 1 else position
198+
}
199+
editor.setSelection(newSelection)
200+
editor.isMediaAdded = true
201+
}
202+
203+
private fun buildClickableMediaSpan(ssb: SpannableStringBuilder, span: AztecMediaSpan) {
204+
ssb.setSpan(
205+
span,
206+
0,
207+
1,
208+
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
209+
)
210+
211+
ssb.setSpan(
212+
AztecMediaClickableSpan(span),
213+
0,
214+
1,
215+
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
216+
)
217+
}
218+
219+
private fun getEndOfBlock(): Int {
220+
var position = 0
221+
editableText.getSpans(selectionStart, selectionEnd, IAztecBlockSpan::class.java).forEach {
222+
val spanEnd = editableText.getSpanEnd(it)
223+
if (spanEnd > position) {
224+
position = spanEnd
225+
}
226+
}
227+
return position
228+
}
79229
}

aztec/src/main/kotlin/org/wordpress/aztec/formatting/MediaFormatter.kt

Lines changed: 0 additions & 160 deletions
This file was deleted.

0 commit comments

Comments
 (0)