@@ -92,6 +92,8 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
9292 private var isViewInitialized = false
9393 private var previousCursorPosition = 0
9494
95+ var isInCalypsoMode = true
96+
9597 private var unknownBlockSpanStart = - 1
9698
9799 private var formatToolbar: AztecToolbar ? = null
@@ -116,6 +118,8 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
116118
117119 var widthMeasureSpec: Int = 0
118120
121+ var verticalParagraphMargin: Int = 0
122+
119123 interface OnSelectionChangedListener {
120124 fun onSelectionChanged (selStart : Int , selEnd : Int )
121125 }
@@ -140,6 +144,10 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
140144 init (attrs)
141145 }
142146
147+ fun setCalypsoMode (isCompatibleWithCalypso : Boolean ) {
148+ isInCalypsoMode = isCompatibleWithCalypso
149+ }
150+
143151 private fun init (attrs : AttributeSet ? ) {
144152 disableTextChangedListener()
145153
@@ -164,6 +172,8 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
164172 historyEnable = styles.getBoolean(R .styleable.AztecText_historyEnable , historyEnable)
165173 historySize = styles.getInt(R .styleable.AztecText_historySize , historySize)
166174
175+ verticalParagraphMargin = styles.getDimensionPixelSize(R .styleable.AztecText_blockVerticalPadding , 0 )
176+
167177 inlineFormatter = InlineFormatter (this ,
168178 InlineFormatter .CodeStyle (
169179 styles.getColor(R .styleable.AztecText_codeBackground , 0 ),
@@ -176,18 +186,18 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
176186 styles.getDimensionPixelSize(R .styleable.AztecText_bulletMargin , 0 ),
177187 styles.getDimensionPixelSize(R .styleable.AztecText_bulletPadding , 0 ),
178188 styles.getDimensionPixelSize(R .styleable.AztecText_bulletWidth , 0 ),
179- styles.getDimensionPixelSize( R .styleable. AztecText_blockVerticalPadding , 0 ) ),
189+ verticalParagraphMargin ),
180190 BlockFormatter .QuoteStyle (
181191 styles.getColor(R .styleable.AztecText_quoteBackground , 0 ),
182192 styles.getColor(R .styleable.AztecText_quoteColor , 0 ),
183193 styles.getFraction(R .styleable.AztecText_quoteBackgroundAlpha , 1 , 1 , 0f ),
184194 styles.getDimensionPixelSize(R .styleable.AztecText_quoteMargin , 0 ),
185195 styles.getDimensionPixelSize(R .styleable.AztecText_quotePadding , 0 ),
186196 styles.getDimensionPixelSize(R .styleable.AztecText_quoteWidth , 0 ),
187- styles.getDimensionPixelSize( R .styleable. AztecText_blockVerticalPadding , 0 ) ),
197+ verticalParagraphMargin ),
188198 BlockFormatter .HeaderStyle (
189- styles.getDimensionPixelSize( R .styleable. AztecText_blockVerticalPadding , 0 ) )
190- )
199+ verticalParagraphMargin )
200+ )
191201
192202 linkFormatter = LinkFormatter (this , LinkFormatter .LinkStyle (styles.getColor(
193203 R .styleable.AztecText_linkColor , 0 ),
@@ -236,6 +246,8 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
236246 ParagraphCollapseAdjuster .install(this )
237247 ParagraphCollapseRemover .install(this )
238248
249+ EndOfParagraphMarkerAdder .install(this , verticalParagraphMargin)
250+
239251 InlineTextWatcher .install(inlineFormatter, this )
240252
241253 // NB: text change handler should not alter text before "afterTextChanged" is called otherwise not all watchers
@@ -625,7 +637,11 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
625637 fun fromHtml (source : String ) {
626638 val builder = SpannableStringBuilder ()
627639 val parser = AztecParser ()
628- builder.append(parser.fromHtml(Format .clearFormatting(source), onMediaTappedListener, this , context))
640+ builder.append(parser.fromHtml(
641+ Format .removeSourceEditorFormatting(
642+ Format .addSourceEditorFormatting(source, isInCalypsoMode), isInCalypsoMode), onMediaTappedListener, this , context))
643+
644+ Format .preProcessSpannedText(builder, isInCalypsoMode)
629645
630646 switchToAztecStyle(builder, 0 , builder.length)
631647 disableTextChangedListener()
@@ -679,7 +695,21 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
679695 }
680696 }
681697
698+ // returns regular or "calypso" html depending on the mode
682699 fun toHtml (withCursorTag : Boolean = false): String {
700+ val html = toPlainHtml(withCursorTag)
701+
702+ if (isInCalypsoMode) {
703+ // calypso format is a mix of newline characters and html
704+ // paragraphs and line breaks are added on server, from newline characters
705+ return Format .addSourceEditorFormatting(html, true )
706+ } else {
707+ return html
708+ }
709+ }
710+
711+ // platform agnostic HTML
712+ fun toPlainHtml (withCursorTag : Boolean = false): String {
683713 val parser = AztecParser ()
684714 val output = SpannableStringBuilder (text)
685715
@@ -688,21 +718,24 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
688718 for (span in output.getSpans(0 , output.length, AztecCursorSpan ::class .java)) {
689719 output.removeSpan(span)
690720 }
691- if (withCursorTag) {
721+ if (withCursorTag && ! isInCalypsoMode ) {
692722 output.setSpan(AztecCursorSpan (), selectionEnd, selectionEnd, Spanned .SPAN_MARK_MARK )
693723 }
694724
695725 parser.syncVisualNewlinesOfBlockElements(output)
696726
697- return Format .clearFormatting(EndOfBufferMarkerAdder .removeEndOfTextMarker(parser.toHtml(output, withCursorTag)))
727+ Format .postProcessSpanedText(output, isInCalypsoMode)
728+
729+ return EndOfBufferMarkerAdder .removeEndOfTextMarker(parser.toHtml(output, withCursorTag))
698730 }
699731
700732 fun toFormattedHtml (): String {
701- return Format .addFormatting (toHtml())
733+ return Format .addSourceEditorFormatting (toHtml(), isInCalypsoMode )
702734 }
703735
704736 private fun switchToAztecStyle (editable : Editable , start : Int , end : Int ) {
705737 editable.getSpans(start, end, AztecBlockSpan ::class .java).forEach { blockFormatter.setBlockStyle(it) }
738+ editable.getSpans(start, end, EndOfParagraphMarker ::class .java).forEach { it.verticalPadding = verticalParagraphMargin }
706739
707740 val urlSpans = editable.getSpans(start, end, AztecURLSpan ::class .java)
708741 for (span in urlSpans) {
@@ -791,7 +824,7 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
791824 output.getSpans(0 , output.length, ParagraphStyle ::class .java).forEach { output.removeSpan(it) }
792825 clearMetaSpans(output)
793826 parser.syncVisualNewlinesOfBlockElements(output)
794- val html = Format .clearFormatting (parser.toHtml(output))
827+ val html = Format .removeSourceEditorFormatting (parser.toHtml(output))
795828
796829 val clipboard = context.getSystemService(Context .CLIPBOARD_SERVICE ) as android.content.ClipboardManager
797830 clipboard.primaryClip = ClipData .newPlainText(null , html)
@@ -808,7 +841,7 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
808841 val textToPaste = clip.getItemAt(i).coerceToText(context)
809842
810843 val builder = SpannableStringBuilder ()
811- builder.append(parser.fromHtml(Format .clearFormatting (textToPaste.toString()), onMediaTappedListener,
844+ builder.append(parser.fromHtml(Format .removeSourceEditorFormatting (textToPaste.toString()), onMediaTappedListener,
812845 this , context).trim())
813846 Selection .setSelection(editable, max)
814847
@@ -977,20 +1010,20 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
9771010
9781011 fun removeMedia (attributePredicate : AttributePredicate ) {
9791012 text.getSpans(0 , text.length, AztecMediaSpan ::class .java)
980- .filter {
981- attributePredicate.matches(it.attributes)
982- }
983- .forEach {
984- val start = text.getSpanStart(it)
985- val end = text.getSpanEnd(it)
1013+ .filter {
1014+ attributePredicate.matches(it.attributes)
1015+ }
1016+ .forEach {
1017+ val start = text.getSpanStart(it)
1018+ val end = text.getSpanEnd(it)
9861019
987- val clickableSpan = text.getSpans(start, end, AztecMediaClickableSpan ::class .java).firstOrNull()
1020+ val clickableSpan = text.getSpans(start, end, AztecMediaClickableSpan ::class .java).firstOrNull()
9881021
989- text.removeSpan(clickableSpan)
990- text.removeSpan(it)
1022+ text.removeSpan(clickableSpan)
1023+ text.removeSpan(it)
9911024
992- text.delete(start, end)
993- }
1025+ text.delete(start, end)
1026+ }
9941027 }
9951028
9961029 interface AttributePredicate {
@@ -1002,45 +1035,45 @@ class AztecText : EditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlClickListe
10021035
10031036 fun updateElementAttributes (attributePredicate : AttributePredicate , attrs : AztecAttributes ) {
10041037 text.getSpans(0 , text.length, AztecAttributedSpan ::class .java)
1005- .filter {
1006- attributePredicate.matches(it.attributes)
1007- }
1008- .firstOrNull()?.attributes = attrs
1038+ .filter {
1039+ attributePredicate.matches(it.attributes)
1040+ }
1041+ .firstOrNull()?.attributes = attrs
10091042 }
10101043
10111044 fun setOverlayLevel (attributePredicate : AttributePredicate , index : Int , level : Int ) {
10121045 text.getSpans(0 , text.length, AztecMediaSpan ::class .java)
1013- .filter {
1014- attributePredicate.matches(it.attributes)
1015- }
1016- .forEach {
1017- it.setOverayLevel(index, level)
1018- }
1046+ .filter {
1047+ attributePredicate.matches(it.attributes)
1048+ }
1049+ .forEach {
1050+ it.setOverayLevel(index, level)
1051+ }
10191052 }
10201053
10211054 fun setOverlay (attributePredicate : AttributePredicate , index : Int , overlay : Drawable ? , gravity : Int ) {
10221055 text.getSpans(0 , text.length, AztecMediaSpan ::class .java)
1023- .filter {
1024- attributePredicate.matches(it.attributes)
1025- }
1026- .forEach {
1027- // set the new overlay drawable
1028- it.setOverlay(index, overlay, gravity)
1056+ .filter {
1057+ attributePredicate.matches(it.attributes)
1058+ }
1059+ .forEach {
1060+ // set the new overlay drawable
1061+ it.setOverlay(index, overlay, gravity)
10291062
1030- invalidate()
1031- }
1063+ invalidate()
1064+ }
10321065 }
10331066
10341067 fun clearOverlays (attributePredicate : AttributePredicate ) {
10351068 text.getSpans(0 , text.length, AztecMediaSpan ::class .java)
1036- .filter {
1037- attributePredicate.matches(it.attributes)
1038- }
1039- .forEach {
1040- it.clearOverlays()
1069+ .filter {
1070+ attributePredicate.matches(it.attributes)
1071+ }
1072+ .forEach {
1073+ it.clearOverlays()
10411074
1042- invalidate()
1043- }
1075+ invalidate()
1076+ }
10441077 }
10451078
10461079 fun getElementAttributes (attributePredicate : AttributePredicate ): AztecAttributes {
0 commit comments