Bullet & ordered lists
This commit is contained in:
parent
c3b6c1ce39
commit
7f5db84bbe
@ -13,9 +13,15 @@
|
|||||||
<h1>Yo!
|
<h1>Yo!
|
||||||
Omg
|
Omg
|
||||||
|
|
||||||
|
|
||||||
ddffdg
|
ddffdg
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
1. First
|
||||||
|
2. Second
|
||||||
|
3. Third
|
||||||
|
* Interesting
|
||||||
|
4. Forth
|
||||||
|
|
||||||
## Unordered list
|
## Unordered list
|
||||||
|
|
||||||
@ -35,6 +41,41 @@ ddffdg
|
|||||||
* it's also here
|
* it's also here
|
||||||
2. and this
|
2. and this
|
||||||
3. and that
|
3. and that
|
||||||
|
1. Another one nested this time and a lot of text here, well, at least some to check how multiline will be handled
|
||||||
|
1. And it goes on and on
|
||||||
|
2. And it goes on and on
|
||||||
|
3. And it goes on and on
|
||||||
|
4. And it goes on and on
|
||||||
|
5. And it goes on and on
|
||||||
|
6. And it goes on and on
|
||||||
|
7. And it goes on and on
|
||||||
|
8. And it goes on and on
|
||||||
|
9. And it goes on and on
|
||||||
|
10. And it goes on and on
|
||||||
|
11. And it goes on and on
|
||||||
|
12. And it goes on and on
|
||||||
|
13. And it goes on and on
|
||||||
|
14. And it goes on and on
|
||||||
|
15. And it goes on and on
|
||||||
|
16. And it goes on and on
|
||||||
|
17. And it goes on and on
|
||||||
|
18. And it goes on and on
|
||||||
|
19. And it goes on and on
|
||||||
|
20. And it goes on and on
|
||||||
|
21. And it goes on and on
|
||||||
|
22. And it goes on and on
|
||||||
|
23. And it goes on and on
|
||||||
|
24. And it goes on and on
|
||||||
|
25. And it goes on and on
|
||||||
|
26. And it goes on and on
|
||||||
|
27. And it goes on and on
|
||||||
|
28. And it goes on and on
|
||||||
|
29. And it goes on and on
|
||||||
|
30. And it goes on and on
|
||||||
|
31. And it goes on and on
|
||||||
|
32. And it goes on and on
|
||||||
|
33. And it goes on and on
|
||||||
|
|
||||||
|
|
||||||
### Quoted list
|
### Quoted list
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import ru.noties.markwon.spans.BlockQuoteSpan;
|
|||||||
import ru.noties.markwon.spans.BulletListItemSpan;
|
import ru.noties.markwon.spans.BulletListItemSpan;
|
||||||
import ru.noties.markwon.spans.CodeSpan;
|
import ru.noties.markwon.spans.CodeSpan;
|
||||||
import ru.noties.markwon.spans.HeadingSpan;
|
import ru.noties.markwon.spans.HeadingSpan;
|
||||||
|
import ru.noties.markwon.spans.OrderedListItemSpan;
|
||||||
import ru.noties.markwon.spans.ThematicBreakSpan;
|
import ru.noties.markwon.spans.ThematicBreakSpan;
|
||||||
|
|
||||||
public class SpannableConfiguration {
|
public class SpannableConfiguration {
|
||||||
@ -25,6 +26,7 @@ public class SpannableConfiguration {
|
|||||||
private final BulletListItemSpan.Config bulletListConfig;
|
private final BulletListItemSpan.Config bulletListConfig;
|
||||||
private final HeadingSpan.Config headingConfig;
|
private final HeadingSpan.Config headingConfig;
|
||||||
private final ThematicBreakSpan.Config thematicConfig;
|
private final ThematicBreakSpan.Config thematicConfig;
|
||||||
|
private final OrderedListItemSpan.Config orderedListConfig;
|
||||||
|
|
||||||
private SpannableConfiguration(Builder builder) {
|
private SpannableConfiguration(Builder builder) {
|
||||||
this.blockQuoteConfig = builder.blockQuoteConfig;
|
this.blockQuoteConfig = builder.blockQuoteConfig;
|
||||||
@ -32,6 +34,7 @@ public class SpannableConfiguration {
|
|||||||
this.bulletListConfig = builder.bulletListConfig;
|
this.bulletListConfig = builder.bulletListConfig;
|
||||||
this.headingConfig = builder.headingConfig;
|
this.headingConfig = builder.headingConfig;
|
||||||
this.thematicConfig = builder.thematicConfig;
|
this.thematicConfig = builder.thematicConfig;
|
||||||
|
this.orderedListConfig = builder.orderedListConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockQuoteSpan.Config getBlockQuoteConfig() {
|
public BlockQuoteSpan.Config getBlockQuoteConfig() {
|
||||||
@ -54,6 +57,10 @@ public class SpannableConfiguration {
|
|||||||
return thematicConfig;
|
return thematicConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OrderedListItemSpan.Config getOrderedListConfig() {
|
||||||
|
return orderedListConfig;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
@ -62,6 +69,7 @@ public class SpannableConfiguration {
|
|||||||
private BulletListItemSpan.Config bulletListConfig;
|
private BulletListItemSpan.Config bulletListConfig;
|
||||||
private HeadingSpan.Config headingConfig;
|
private HeadingSpan.Config headingConfig;
|
||||||
private ThematicBreakSpan.Config thematicConfig;
|
private ThematicBreakSpan.Config thematicConfig;
|
||||||
|
private OrderedListItemSpan.Config orderedListConfig;
|
||||||
|
|
||||||
public Builder(Context context) {
|
public Builder(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -92,11 +100,17 @@ public class SpannableConfiguration {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setOrderedListConfig(@NonNull OrderedListItemSpan.Config orderedListConfig) {
|
||||||
|
this.orderedListConfig = orderedListConfig;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// todo, change to something more reliable
|
// todo, change to something more reliable
|
||||||
|
// todo, must mention that bullet/ordered/quote must have the same margin (or maybe we can just enforce it?)
|
||||||
public SpannableConfiguration build() {
|
public SpannableConfiguration build() {
|
||||||
if (blockQuoteConfig == null) {
|
if (blockQuoteConfig == null) {
|
||||||
blockQuoteConfig = new BlockQuoteSpan.Config(
|
blockQuoteConfig = new BlockQuoteSpan.Config(
|
||||||
px(16),
|
px(24),
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
@ -107,7 +121,7 @@ public class SpannableConfiguration {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
if (bulletListConfig == null) {
|
if (bulletListConfig == null) {
|
||||||
bulletListConfig = new BulletListItemSpan.Config(0, px(16), px(1));
|
bulletListConfig = new BulletListItemSpan.Config(px(24), 0, px(8), px(1));
|
||||||
}
|
}
|
||||||
if (headingConfig == null) {
|
if (headingConfig == null) {
|
||||||
headingConfig = new HeadingSpan.Config(px(1), 0);
|
headingConfig = new HeadingSpan.Config(px(1), 0);
|
||||||
@ -115,6 +129,9 @@ public class SpannableConfiguration {
|
|||||||
if (thematicConfig == null) {
|
if (thematicConfig == null) {
|
||||||
thematicConfig = new ThematicBreakSpan.Config(0, px(2));
|
thematicConfig = new ThematicBreakSpan.Config(0, px(2));
|
||||||
}
|
}
|
||||||
|
if (orderedListConfig == null) {
|
||||||
|
orderedListConfig = new OrderedListItemSpan.Config(px(24), 0);
|
||||||
|
}
|
||||||
return new SpannableConfiguration(this);
|
return new SpannableConfiguration(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ import org.commonmark.node.FencedCodeBlock;
|
|||||||
import org.commonmark.node.HardLineBreak;
|
import org.commonmark.node.HardLineBreak;
|
||||||
import org.commonmark.node.Heading;
|
import org.commonmark.node.Heading;
|
||||||
import org.commonmark.node.HtmlBlock;
|
import org.commonmark.node.HtmlBlock;
|
||||||
import org.commonmark.node.Image;
|
|
||||||
import org.commonmark.node.ListBlock;
|
import org.commonmark.node.ListBlock;
|
||||||
import org.commonmark.node.ListItem;
|
import org.commonmark.node.ListItem;
|
||||||
import org.commonmark.node.Node;
|
import org.commonmark.node.Node;
|
||||||
@ -33,6 +32,8 @@ import ru.noties.markwon.spans.BulletListItemSpan;
|
|||||||
import ru.noties.markwon.spans.CodeSpan;
|
import ru.noties.markwon.spans.CodeSpan;
|
||||||
import ru.noties.markwon.spans.EmphasisSpan;
|
import ru.noties.markwon.spans.EmphasisSpan;
|
||||||
import ru.noties.markwon.spans.HeadingSpan;
|
import ru.noties.markwon.spans.HeadingSpan;
|
||||||
|
import ru.noties.markwon.spans.OrderedListItemSpan;
|
||||||
|
import ru.noties.markwon.spans.SimpleLeadingMarginSpan;
|
||||||
import ru.noties.markwon.spans.StrongEmphasisSpan;
|
import ru.noties.markwon.spans.StrongEmphasisSpan;
|
||||||
import ru.noties.markwon.spans.ThematicBreakSpan;
|
import ru.noties.markwon.spans.ThematicBreakSpan;
|
||||||
|
|
||||||
@ -54,13 +55,13 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(Text text) {
|
public void visit(Text text) {
|
||||||
Debug.i(text);
|
// Debug.i(text);
|
||||||
builder.append(text.getLiteral());
|
builder.append(text.getLiteral());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(StrongEmphasis strongEmphasis) {
|
public void visit(StrongEmphasis strongEmphasis) {
|
||||||
Debug.i(strongEmphasis);
|
// Debug.i(strongEmphasis);
|
||||||
final int length = builder.length();
|
final int length = builder.length();
|
||||||
visitChildren(strongEmphasis);
|
visitChildren(strongEmphasis);
|
||||||
setSpan(length, new StrongEmphasisSpan());
|
setSpan(length, new StrongEmphasisSpan());
|
||||||
@ -68,7 +69,7 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(Emphasis emphasis) {
|
public void visit(Emphasis emphasis) {
|
||||||
Debug.i(emphasis);
|
// Debug.i(emphasis);
|
||||||
final int length = builder.length();
|
final int length = builder.length();
|
||||||
visitChildren(emphasis);
|
visitChildren(emphasis);
|
||||||
setSpan(length, new EmphasisSpan());
|
setSpan(length, new EmphasisSpan());
|
||||||
@ -77,7 +78,7 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visit(BlockQuote blockQuote) {
|
public void visit(BlockQuote blockQuote) {
|
||||||
|
|
||||||
Debug.i(blockQuote);
|
// Debug.i(blockQuote);
|
||||||
|
|
||||||
newLine();
|
newLine();
|
||||||
if (blockQuoteIndent != 0) {
|
if (blockQuoteIndent != 0) {
|
||||||
@ -106,7 +107,7 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visit(Code code) {
|
public void visit(Code code) {
|
||||||
|
|
||||||
Debug.i(code);
|
// Debug.i(code);
|
||||||
|
|
||||||
final int length = builder.length();
|
final int length = builder.length();
|
||||||
|
|
||||||
@ -125,7 +126,7 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visit(FencedCodeBlock fencedCodeBlock) {
|
public void visit(FencedCodeBlock fencedCodeBlock) {
|
||||||
|
|
||||||
Debug.i(fencedCodeBlock);
|
// Debug.i(fencedCodeBlock);
|
||||||
|
|
||||||
newLine();
|
newLine();
|
||||||
|
|
||||||
@ -141,33 +142,35 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
builder.append('\n');
|
builder.append('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// @Override
|
||||||
public void visit(Image image) {
|
// public void visit(Image image) {
|
||||||
|
//
|
||||||
Debug.i(image);
|
// Debug.i(image);
|
||||||
|
//
|
||||||
final int length = builder.length();
|
//// final int length = builder.length();
|
||||||
|
//
|
||||||
visitChildren(image);
|
// visitChildren(image);
|
||||||
|
//
|
||||||
if (length == builder.length()) {
|
//// if (length == builder.length()) {
|
||||||
// nothing is added, and we need at least one symbol
|
//// // nothing is added, and we need at least one symbol
|
||||||
builder.append(' ');
|
//// builder.append(' ');
|
||||||
}
|
//// }
|
||||||
|
// }
|
||||||
|
|
||||||
//// final int length = builder.length();
|
|
||||||
// final TestDrawable drawable = new TestDrawable();
|
|
||||||
// final DrawableSpan span = new DrawableSpan(drawable);
|
|
||||||
// builder.append(" ");
|
|
||||||
// builder.setSpan(span, length, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BulletList bulletList) {
|
public void visit(BulletList bulletList) {
|
||||||
Debug.i(bulletList);
|
visitList(bulletList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(OrderedList orderedList) {
|
||||||
|
visitList(orderedList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitList(Node node) {
|
||||||
|
Debug.i(node);
|
||||||
newLine();
|
newLine();
|
||||||
visitChildren(bulletList);
|
visitChildren(node);
|
||||||
newLine();
|
newLine();
|
||||||
if (listLevel == 0 && blockQuoteIndent == 0) {
|
if (listLevel == 0 && blockQuoteIndent == 0) {
|
||||||
builder.append('\n');
|
builder.append('\n');
|
||||||
@ -180,16 +183,67 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
Debug.i(listItem);
|
Debug.i(listItem);
|
||||||
|
|
||||||
final int length = builder.length();
|
final int length = builder.length();
|
||||||
|
|
||||||
blockQuoteIndent += 1;
|
blockQuoteIndent += 1;
|
||||||
listLevel += 1;
|
listLevel += 1;
|
||||||
visitChildren(listItem);
|
|
||||||
// todo, can be a bullet list & ordered list (with leading numbers... looks like we need to `draw` numbers...
|
// todo, can be a bullet list & ordered list (with leading numbers... looks like we need to `draw` numbers...
|
||||||
setSpan(length, new BulletListItemSpan(
|
|
||||||
configuration.getBulletListConfig(),
|
final Node parent = listItem.getParent();
|
||||||
blockQuoteIndent,
|
if (parent instanceof OrderedList) {
|
||||||
listLevel - 1,
|
|
||||||
length
|
// // let's build ordered number
|
||||||
));
|
// final StringBuilder lead = new StringBuilder();
|
||||||
|
// Node p = parent;
|
||||||
|
// while (p != null && p instanceof OrderedList) {
|
||||||
|
// lead.insert(0, ((OrderedList) p).getDelimiter());
|
||||||
|
// lead.insert(0, ((OrderedList) p).getStartNumber());
|
||||||
|
// p = p.getParent();
|
||||||
|
// if (p instanceof ListItem) {
|
||||||
|
// p = p.getParent();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// builder.append(lead)
|
||||||
|
// .append('\u00a0');
|
||||||
|
//
|
||||||
|
// blockQuoteIndent -= 1;
|
||||||
|
|
||||||
|
final int start = ((OrderedList) parent).getStartNumber();
|
||||||
|
|
||||||
|
visitChildren(listItem);
|
||||||
|
|
||||||
|
setSpan(length, new OrderedListItemSpan(
|
||||||
|
configuration.getOrderedListConfig(),
|
||||||
|
String.valueOf(start) + "." + '\u00a0',
|
||||||
|
blockQuoteIndent,
|
||||||
|
length
|
||||||
|
));
|
||||||
|
|
||||||
|
// blockQuoteIndent += 1;
|
||||||
|
|
||||||
|
// if (listLevel != 1) {
|
||||||
|
// setSpan(length, new SimpleLeadingMarginSpan(32));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// after we have visited the children increment start number
|
||||||
|
final OrderedList orderedList = (OrderedList) parent;
|
||||||
|
orderedList.setStartNumber(orderedList.getStartNumber() + 1);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
visitChildren(listItem);
|
||||||
|
|
||||||
|
// if we are inside orderedList increase the margin?
|
||||||
|
|
||||||
|
setSpan(length, new BulletListItemSpan(
|
||||||
|
configuration.getBulletListConfig(),
|
||||||
|
blockQuoteIndent,
|
||||||
|
listLevel - 1,
|
||||||
|
length
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
blockQuoteIndent -= 1;
|
blockQuoteIndent -= 1;
|
||||||
listLevel -= 1;
|
listLevel -= 1;
|
||||||
|
|
||||||
@ -199,7 +253,7 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visit(ThematicBreak thematicBreak) {
|
public void visit(ThematicBreak thematicBreak) {
|
||||||
|
|
||||||
Debug.i(thematicBreak);
|
// Debug.i(thematicBreak);
|
||||||
|
|
||||||
newLine();
|
newLine();
|
||||||
|
|
||||||
@ -211,27 +265,10 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
builder.append('\n');
|
builder.append('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(OrderedList orderedList) {
|
|
||||||
|
|
||||||
Debug.i(orderedList);
|
|
||||||
|
|
||||||
newLine();
|
|
||||||
|
|
||||||
// Debug.i(orderedList, orderedList.getDelimiter(), orderedList.getStartNumber());
|
|
||||||
// todo, ordering numbers
|
|
||||||
super.visit(orderedList);
|
|
||||||
|
|
||||||
newLine();
|
|
||||||
if (listLevel == 0 && blockQuoteIndent == 0) {
|
|
||||||
builder.append('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(Heading heading) {
|
public void visit(Heading heading) {
|
||||||
|
|
||||||
Debug.i(heading);
|
// Debug.i(heading);
|
||||||
|
|
||||||
newLine();
|
newLine();
|
||||||
|
|
||||||
@ -264,7 +301,7 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visit(CustomNode customNode) {
|
public void visit(CustomNode customNode) {
|
||||||
|
|
||||||
Debug.i(customNode);
|
// Debug.i(customNode);
|
||||||
|
|
||||||
if (customNode instanceof Strikethrough) {
|
if (customNode instanceof Strikethrough) {
|
||||||
final int length = builder.length();
|
final int length = builder.length();
|
||||||
@ -280,7 +317,7 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
|
|
||||||
final boolean inTightList = isInTightList(paragraph);
|
final boolean inTightList = isInTightList(paragraph);
|
||||||
|
|
||||||
Debug.i(paragraph, inTightList, listLevel);
|
// Debug.i(paragraph, inTightList, listLevel);
|
||||||
|
|
||||||
if (!inTightList) {
|
if (!inTightList) {
|
||||||
newLine();
|
newLine();
|
||||||
@ -326,4 +363,23 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String dump(Node node) {
|
||||||
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
node.accept(new DumpVisitor(builder));
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DumpVisitor extends AbstractVisitor {
|
||||||
|
private final StringBuilder builder;
|
||||||
|
|
||||||
|
DumpVisitor(StringBuilder builder) {
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Text text) {
|
||||||
|
builder.append(text.getLiteral());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,20 @@ public class BulletListItemSpan implements LeadingMarginSpan {
|
|||||||
|
|
||||||
public static class Config {
|
public static class Config {
|
||||||
|
|
||||||
final int bulletColor; // by default uses text color
|
|
||||||
final int marginWidth;
|
final int marginWidth;
|
||||||
|
final int bulletColor; // by default uses text color
|
||||||
|
final int bulletSide;
|
||||||
final int bulletStrokeWidth;
|
final int bulletStrokeWidth;
|
||||||
|
|
||||||
// from 0 but it makes sense to provide something wider
|
// from 0 but it makes sense to provide something wider
|
||||||
public Config(@ColorInt int bulletColor, @IntRange(from = 0) int marginWidth, int bulletStrokeWidth) {
|
public Config(
|
||||||
this.bulletColor = bulletColor;
|
@IntRange(from = 0) int marginWidth,
|
||||||
|
@ColorInt int bulletColor,
|
||||||
|
@IntRange(from = 0) int bulletSide,
|
||||||
|
@IntRange(from = 0) int bulletStrokeWidth) {
|
||||||
this.marginWidth = marginWidth;
|
this.marginWidth = marginWidth;
|
||||||
|
this.bulletColor = bulletColor;
|
||||||
|
this.bulletSide = bulletSide;
|
||||||
this.bulletStrokeWidth = bulletStrokeWidth;
|
this.bulletStrokeWidth = bulletStrokeWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,7 +64,7 @@ public class BulletListItemSpan implements LeadingMarginSpan {
|
|||||||
@Override
|
@Override
|
||||||
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) {
|
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) {
|
||||||
|
|
||||||
// if there was a line break, we don't need to draw it
|
// if there was a line break, we don't need to draw anything
|
||||||
if (this.start != start) {
|
if (this.start != start) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -88,7 +94,14 @@ public class BulletListItemSpan implements LeadingMarginSpan {
|
|||||||
final int width = config.marginWidth;
|
final int width = config.marginWidth;
|
||||||
final int height = bottom - top;
|
final int height = bottom - top;
|
||||||
|
|
||||||
final int side = Math.min(config.marginWidth, height) / 2;
|
final int min = Math.min(config.marginWidth, height) / 2;
|
||||||
|
final int side;
|
||||||
|
if (config.bulletSide == 0
|
||||||
|
|| config.bulletSide > min) {
|
||||||
|
side = min;
|
||||||
|
} else {
|
||||||
|
side = config.bulletSide;
|
||||||
|
}
|
||||||
|
|
||||||
final int marginLeft = (width - side) / 2;
|
final int marginLeft = (width - side) / 2;
|
||||||
final int marginTop = (height - side) / 2;
|
final int marginTop = (height - side) / 2;
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
package ru.noties.markwon.spans;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.support.annotation.ColorInt;
|
||||||
|
import android.support.annotation.IntRange;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.text.Layout;
|
||||||
|
import android.text.style.LeadingMarginSpan;
|
||||||
|
|
||||||
|
public class OrderedListItemSpan implements LeadingMarginSpan {
|
||||||
|
|
||||||
|
public static class Config {
|
||||||
|
|
||||||
|
final int marginWidth; // by default 0
|
||||||
|
final int numberColor; // by default color of the main text
|
||||||
|
|
||||||
|
public Config(@IntRange(from = 0) int marginWidth, @ColorInt int numberColor) {
|
||||||
|
this.marginWidth = marginWidth;
|
||||||
|
this.numberColor = numberColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Config config;
|
||||||
|
private final String number;
|
||||||
|
private final int blockIndent;
|
||||||
|
private final int start;
|
||||||
|
|
||||||
|
public OrderedListItemSpan(
|
||||||
|
@NonNull Config config,
|
||||||
|
@NonNull String number,
|
||||||
|
@IntRange(from = 0) int blockIndent,
|
||||||
|
@IntRange(from = 0) int start
|
||||||
|
) {
|
||||||
|
this.config = config;
|
||||||
|
this.number = number;
|
||||||
|
this.blockIndent = blockIndent;
|
||||||
|
this.start = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLeadingMargin(boolean first) {
|
||||||
|
return config.marginWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) {
|
||||||
|
|
||||||
|
// if there was a line break, we don't need to draw anything
|
||||||
|
if (this.start != start) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.numberColor != 0) {
|
||||||
|
p.setColor(config.numberColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int width = config.marginWidth;
|
||||||
|
final int numberWidth = (int) (p.measureText(number) + .5F);
|
||||||
|
final int numberX = (width * blockIndent) - numberWidth;
|
||||||
|
|
||||||
|
final int numberY = bottom - ((bottom - top) / 2) - (int) ((p.descent() + p.ascent()) / 2);
|
||||||
|
|
||||||
|
c.drawText(number, numberX, numberY, p);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package ru.noties.markwon.spans;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.text.Layout;
|
||||||
|
import android.text.style.LeadingMarginSpan;
|
||||||
|
|
||||||
|
public class SimpleLeadingMarginSpan implements LeadingMarginSpan {
|
||||||
|
|
||||||
|
private final int margin;
|
||||||
|
|
||||||
|
public SimpleLeadingMarginSpan(int margin) {
|
||||||
|
this.margin = margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLeadingMargin(boolean first) {
|
||||||
|
return margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user