@@ -52,9 +52,30 @@ public class HtmlTagHandler implements Html.TagHandler {
52
52
/**
53
53
* List indentation in pixels. Nested lists use multiple of this.
54
54
*/
55
+ /**
56
+ * Running HTML table string based off of the root table tag. Root table tag being the tag which
57
+ * isn't embedded within any other table tag. Example:
58
+ * <!-- This is the root level opening table tag. This is where we keep track of tables. -->
59
+ * <table>
60
+ * ...
61
+ * <table> <!-- Non-root table tags -->
62
+ * ...
63
+ * </table>
64
+ * ...
65
+ * </table>
66
+ * <!-- This is the root level closing table tag and the end of the string we track. -->
67
+ */
68
+ StringBuilder tableHtmlBuilder = new StringBuilder ();
69
+ /**
70
+ * Tells us which level of table tag we're on; ultimately used to find the root table tag.
71
+ */
72
+ int tableTagLevel = 0 ;
73
+
55
74
private static final int indent = 10 ;
56
75
private static final int listItemIndent = indent * 2 ;
57
76
private static final BulletSpan bullet = new BulletSpan (indent );
77
+ private ClickableTableSpan mClickableTableSpan ;
78
+ private DrawTableLinkSpan mDrawTableLinkSpan ;
58
79
59
80
private static class Ul {
60
81
}
@@ -71,6 +92,18 @@ private static class Center {
71
92
private static class Strike {
72
93
}
73
94
95
+ private static class Table {
96
+ }
97
+
98
+ private static class Tr {
99
+ }
100
+
101
+ private static class Th {
102
+ }
103
+
104
+ private static class Td {
105
+ }
106
+
74
107
@ Override
75
108
public void handleTag (final boolean opening , final String tag , Editable output , final XMLReader xmlReader ) {
76
109
if (opening ) {
@@ -102,6 +135,23 @@ public void handleTag(final boolean opening, final String tag, Editable output,
102
135
start (output , new Center ());
103
136
} else if (tag .equalsIgnoreCase ("s" ) || tag .equalsIgnoreCase ("strike" )) {
104
137
start (output , new Strike ());
138
+ } else if (tag .equalsIgnoreCase ("table" )) {
139
+ start (output , new Table ());
140
+ if (tableTagLevel == 0 ) {
141
+ tableHtmlBuilder = new StringBuilder ();
142
+ // We need some text for the table to be replaced by the span because
143
+ // the other tags will remove their text when their text is extracted
144
+ output .append ("table placeholder" );
145
+ }
146
+
147
+ tableTagLevel ++;
148
+ }
149
+ else if (tag .equalsIgnoreCase ("tr" )) {
150
+ start (output , new Tr ());
151
+ } else if (tag .equalsIgnoreCase ("th" )) {
152
+ start (output , new Th ());
153
+ } else if (tag .equalsIgnoreCase ("td" )) {
154
+ start (output , new Td ());
105
155
}
106
156
} else {
107
157
// closing tag
@@ -150,8 +200,55 @@ public void handleTag(final boolean opening, final String tag, Editable output,
150
200
end (output , Center .class , true , new AlignmentSpan .Standard (Layout .Alignment .ALIGN_CENTER ));
151
201
} else if (tag .equalsIgnoreCase ("s" ) || tag .equalsIgnoreCase ("strike" )) {
152
202
end (output , Strike .class , false , new StrikethroughSpan ());
203
+ } else if (tag .equalsIgnoreCase ("table" )) {
204
+ tableTagLevel --;
205
+
206
+ // When we're back at the root-level table
207
+ if (tableTagLevel == 0 ) {
208
+ final String tableHtml = tableHtmlBuilder .toString ();
209
+
210
+ ClickableTableSpan clickableTableSpan = null ;
211
+ if (mClickableTableSpan != null ) {
212
+ clickableTableSpan = mClickableTableSpan .newInstance ();
213
+ clickableTableSpan .setTableHtml (tableHtml );
214
+ }
215
+
216
+ DrawTableLinkSpan drawTableLinkSpan = null ;
217
+ if (mDrawTableLinkSpan != null ) {
218
+ drawTableLinkSpan = mDrawTableLinkSpan .newInstance ();
219
+ }
220
+
221
+ end (output , Table .class , false , drawTableLinkSpan , clickableTableSpan );
222
+ } else {
223
+ end (output , Table .class , false );
224
+ }
225
+ }
226
+ else if (tag .equalsIgnoreCase ("tr" )) {
227
+ end (output , Tr .class , false );
228
+ } else if (tag .equalsIgnoreCase ("th" )) {
229
+ end (output , Th .class , false );
230
+ } else if (tag .equalsIgnoreCase ("td" )) {
231
+ end (output , Td .class , false );
153
232
}
154
233
}
234
+
235
+ storeTableTags (opening , tag );
236
+ }
237
+
238
+ /**
239
+ * If we're arriving at a table tag or are already within a table tag, then we should store it
240
+ * the raw HTML for our ClickableTableSpan
241
+ */
242
+ private void storeTableTags (boolean opening , String tag ) {
243
+ if (tableTagLevel > 0 || tag .equalsIgnoreCase ("table" )) {
244
+ tableHtmlBuilder .append ("<" );
245
+ if (!opening ) {
246
+ tableHtmlBuilder .append ("/" );
247
+ }
248
+ tableHtmlBuilder
249
+ .append (tag .toLowerCase ())
250
+ .append (">" );
251
+ }
155
252
}
156
253
157
254
/**
@@ -176,6 +273,12 @@ private void end(Editable output, Class kind, boolean paragraphStyle, Object...
176
273
// end of the tag
177
274
int len = output .length ();
178
275
276
+ // If we're in a table, then we need to store the raw HTML for later
277
+ if (tableTagLevel > 0 ) {
278
+ final CharSequence extractedSpanText = extractSpanText (output , kind );
279
+ tableHtmlBuilder .append (extractedSpanText );
280
+ }
281
+
179
282
output .removeSpan (obj );
180
283
181
284
if (where != len ) {
@@ -196,6 +299,21 @@ private void end(Editable output, Class kind, boolean paragraphStyle, Object...
196
299
}
197
300
}
198
301
302
+ /**
303
+ * Returns the text contained within a span and deletes it from the output string
304
+ */
305
+ private CharSequence extractSpanText (Editable output , Class kind ) {
306
+ final Object obj = getLast (output , kind );
307
+ // start of the tag
308
+ final int where = output .getSpanStart (obj );
309
+ // end of the tag
310
+ final int len = output .length ();
311
+
312
+ final CharSequence extractedSpanText = output .subSequence (where , len );
313
+ output .delete (where , len );
314
+ return extractedSpanText ;
315
+ }
316
+
199
317
/**
200
318
* Get last marked position of a specific tag kind (private class)
201
319
*/
@@ -213,4 +331,11 @@ private static Object getLast(Editable text, Class kind) {
213
331
}
214
332
}
215
333
334
+ public void setClickableTableSpan (ClickableTableSpan clickableTableSpan ) {
335
+ this .mClickableTableSpan = clickableTableSpan ;
336
+ }
337
+
338
+ public void setDrawTableLinkSpan (DrawTableLinkSpan drawTableLinkSpan ) {
339
+ this .mDrawTableLinkSpan = drawTableLinkSpan ;
340
+ }
216
341
}
0 commit comments