Latex, introduce theme and render-mode
This commit is contained in:
		
							parent
							
								
									8d483fe49d
								
							
						
					
					
						commit
						c7494a9225
					
				| @ -20,7 +20,7 @@ public class LinkResolverDef implements LinkResolver { | ||||
|         try { | ||||
|             context.startActivity(intent); | ||||
|         } catch (ActivityNotFoundException e) { | ||||
|             Log.w("LinkResolverDef", "Actvity was not found for intent, " + intent.toString()); | ||||
|             Log.w("LinkResolverDef", "Actvity was not found for the link: '" + link + "'"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -120,6 +120,7 @@ public class JLatexMathBlockParser extends AbstractBlockParser { | ||||
|             } | ||||
| 
 | ||||
|             // consume spaces until the end of the line, if any other content is found -> NONE | ||||
|             // TODO: here we can check mode in which we operate (legacy or not) | ||||
|             if (Parsing.skip(SPACE, line, nextNonSpaceIndex + signs, length) != length) { | ||||
|                 return BlockStart.none(); | ||||
|             } | ||||
|  | ||||
| @ -42,8 +42,33 @@ import ru.noties.jlatexmath.JLatexMathDrawable; | ||||
| /** | ||||
|  * @since 3.0.0 | ||||
|  */ | ||||
| public class  JLatexMathPlugin extends AbstractMarkwonPlugin { | ||||
| public class JLatexMathPlugin extends AbstractMarkwonPlugin { | ||||
| 
 | ||||
|     /** | ||||
|      * @since 4.3.0-SNAPSHOT | ||||
|      */ | ||||
|     public enum RenderMode { | ||||
|         /** | ||||
|          * <em>LEGACY</em> mode mimics pre {@code 4.3.0-SNAPSHOT} behavior by rendering LaTeX blocks only. | ||||
|          * In this mode LaTeX is started by `$$` (that must be exactly at the start of a line) and | ||||
|          * ended at whatever line that is ended with `$$` characters exactly. | ||||
|          */ | ||||
|         LEGACY, | ||||
| 
 | ||||
|         /** | ||||
|          * Starting with {@code 4.3.0-SNAPSHOT} it is possible to have LaTeX inlines (which flows inside | ||||
|          * a text paragraph without breaking it). Inline LaTeX starts and ends with `$$` symbols. For example: | ||||
|          * {@code | ||||
|          * **bold $$\\begin{array}\\end{array}$$ bold-end**, and whatever more | ||||
|          * } | ||||
|          * LaTeX block starts on a new line started by 0-3 spaces and 2 (or more) {@code $} signs | ||||
|          * followed by a new-line (with any amount of space characters in-between). And ends on a new-line | ||||
|          * starting with 0-3 spaces followed by number of {@code $} signs that was used to <em>start the block</em>. | ||||
|          */ | ||||
|         BLOCKS_AND_INLINES | ||||
|     } | ||||
| 
 | ||||
|     // TODO: inlines are not moved to a new line when exceed available width.. (api 23, emulator) | ||||
|     public interface BuilderConfigure { | ||||
|         void configureBuilder(@NonNull Builder builder); | ||||
|     } | ||||
| @ -338,6 +363,7 @@ public class  JLatexMathPlugin extends AbstractMarkwonPlugin { | ||||
| 
 | ||||
|                         final JLatexMathDrawable jLatexMathDrawable; | ||||
| 
 | ||||
|                         // TODO: obtain real values from theme (for blocks and inlines) | ||||
|                         final JLatextAsyncDrawable jLatextAsyncDrawable = (JLatextAsyncDrawable) drawable; | ||||
|                         if (jLatextAsyncDrawable.isBlock) { | ||||
|                             // create JLatexMathDrawable | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| package io.noties.markwon.ext.latex; | ||||
| 
 | ||||
| import android.graphics.Rect; | ||||
| import android.graphics.drawable.Drawable; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| @ -16,12 +15,22 @@ public abstract class JLatexMathTheme { | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static JLatexMathTheme create(@Px float textSize) { | ||||
|         return null; | ||||
|         return builder(textSize).build(); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static JLatexMathTheme builer() { | ||||
|         return null; | ||||
|     public static JLatexMathTheme create(@Px float inlineTextSize, @Px float blockTextSize) { | ||||
|         return builder(inlineTextSize, blockTextSize).build(); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static JLatexMathTheme.Builder builder(@Px float textSize) { | ||||
|         return new JLatexMathTheme.Builder(textSize, 0F, 0F); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static JLatexMathTheme.Builder builder(@Px float inlineTextSize, @Px float blockTextSize) { | ||||
|         return new Builder(0F, inlineTextSize, blockTextSize); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -73,7 +82,7 @@ public abstract class JLatexMathTheme { | ||||
| 
 | ||||
|     /** | ||||
|      * @return text size in pixels for <strong>inline LaTeX</strong> | ||||
|      * @see #blockTexxtSize() | ||||
|      * @see #blockTextSize() | ||||
|      */ | ||||
|     @Px | ||||
|     public abstract float inlineTextSize(); | ||||
| @ -83,7 +92,7 @@ public abstract class JLatexMathTheme { | ||||
|      * @see #inlineTextSize() | ||||
|      */ | ||||
|     @Px | ||||
|     public abstract float blockTexxtSize(); | ||||
|     public abstract float blockTextSize(); | ||||
| 
 | ||||
|     @Nullable | ||||
|     public abstract BackgroundProvider inlineBackgroundProvider(); | ||||
| @ -111,9 +120,9 @@ public abstract class JLatexMathTheme { | ||||
| 
 | ||||
| 
 | ||||
|     public static class Builder { | ||||
|         private float textSize; | ||||
|         private float inlineTextSize; | ||||
|         private float blockTextSize; | ||||
|         private final float textSize; | ||||
|         private final float inlineTextSize; | ||||
|         private final float blockTextSize; | ||||
| 
 | ||||
|         private BackgroundProvider backgroundProvider; | ||||
|         private BackgroundProvider inlineBackgroundProvider; | ||||
| @ -121,10 +130,168 @@ public abstract class JLatexMathTheme { | ||||
| 
 | ||||
|         private boolean blockFitCanvas; | ||||
|         // horizontal alignment (when there is additional horizontal space) | ||||
|         private int blockAlign; | ||||
|         private int blockHorizontalAlignment; | ||||
| 
 | ||||
|         private Padding padding; | ||||
|         private Padding inlinePadding; | ||||
|         private Padding blockPadding; | ||||
| 
 | ||||
|         Builder(float textSize, float inlineTextSize, float blockTextSize) { | ||||
|             this.textSize = textSize; | ||||
|             this.inlineTextSize = inlineTextSize; | ||||
|             this.blockTextSize = blockTextSize; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         public Builder backgroundProvider(@Nullable BackgroundProvider backgroundProvider) { | ||||
|             this.backgroundProvider = backgroundProvider; | ||||
|             this.inlineBackgroundProvider = backgroundProvider; | ||||
|             this.blockBackgroundProvider = backgroundProvider; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         public Builder inlineBackgroundProvider(@Nullable BackgroundProvider inlineBackgroundProvider) { | ||||
|             this.inlineBackgroundProvider = inlineBackgroundProvider; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         public Builder blockBackgroundProvider(@Nullable BackgroundProvider blockBackgroundProvider) { | ||||
|             this.blockBackgroundProvider = blockBackgroundProvider; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         public Builder blockFitCanvas(boolean blockFitCanvas) { | ||||
|             this.blockFitCanvas = blockFitCanvas; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         public Builder blockHorizontalAlignment(@JLatexMathDrawable.Align int blockHorizontalAlignment) { | ||||
|             this.blockHorizontalAlignment = blockHorizontalAlignment; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         public Builder padding(@Nullable Padding padding) { | ||||
|             this.padding = padding; | ||||
|             this.inlinePadding = padding; | ||||
|             this.blockPadding = padding; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         public Builder inlinePadding(@Nullable Padding inlinePadding) { | ||||
|             this.inlinePadding = inlinePadding; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         public Builder blockPadding(@Nullable Padding blockPadding) { | ||||
|             this.blockPadding = blockPadding; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         public JLatexMathTheme build() { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     static class Impl extends JLatexMathTheme { | ||||
| 
 | ||||
|         private final float textSize; | ||||
|         private final float inlineTextSize; | ||||
|         private final float blockTextSize; | ||||
| 
 | ||||
|         private final BackgroundProvider backgroundProvider; | ||||
|         private final BackgroundProvider inlineBackgroundProvider; | ||||
|         private final BackgroundProvider blockBackgroundProvider; | ||||
| 
 | ||||
|         private final boolean blockFitCanvas; | ||||
|         // horizontal alignment (when there is additional horizontal space) | ||||
|         private int blockHorizontalAlignment; | ||||
| 
 | ||||
|         private final Padding padding; | ||||
|         private final Padding inlinePadding; | ||||
|         private final Padding blockPadding; | ||||
| 
 | ||||
|         Impl(@NonNull Builder builder) { | ||||
|             this.textSize = builder.textSize; | ||||
|             this.inlineTextSize = builder.inlineTextSize; | ||||
|             this.blockTextSize = builder.blockTextSize; | ||||
|             this.backgroundProvider = builder.backgroundProvider; | ||||
|             this.inlineBackgroundProvider = builder.inlineBackgroundProvider; | ||||
|             this.blockBackgroundProvider = builder.blockBackgroundProvider; | ||||
|             this.blockFitCanvas = builder.blockFitCanvas; | ||||
|             this.blockHorizontalAlignment = builder.blockHorizontalAlignment; | ||||
|             this.padding = builder.padding; | ||||
|             this.inlinePadding = builder.inlinePadding; | ||||
|             this.blockPadding = builder.blockPadding; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public float inlineTextSize() { | ||||
|             if (inlineTextSize > 0F) { | ||||
|                 return inlineTextSize; | ||||
|             } | ||||
|             return textSize; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public float blockTextSize() { | ||||
|             if (blockTextSize > 0F) { | ||||
|                 return blockTextSize; | ||||
|             } | ||||
|             return textSize; | ||||
|         } | ||||
| 
 | ||||
|         @Nullable | ||||
|         @Override | ||||
|         public BackgroundProvider inlineBackgroundProvider() { | ||||
|             if (inlineBackgroundProvider != null) { | ||||
|                 return inlineBackgroundProvider; | ||||
|             } | ||||
|             return backgroundProvider; | ||||
|         } | ||||
| 
 | ||||
|         @Nullable | ||||
|         @Override | ||||
|         public BackgroundProvider blockBackgroundProvider() { | ||||
|             if (blockBackgroundProvider != null) { | ||||
|                 return blockBackgroundProvider; | ||||
|             } | ||||
|             return backgroundProvider; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public boolean blockFitCanvas() { | ||||
|             return blockFitCanvas; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public int blockHorizontalAlignment() { | ||||
|             return blockHorizontalAlignment; | ||||
|         } | ||||
| 
 | ||||
|         @Nullable | ||||
|         @Override | ||||
|         public Padding inlinePadding() { | ||||
|             if (inlinePadding != null) { | ||||
|                 return inlinePadding; | ||||
|             } | ||||
|             return padding; | ||||
|         } | ||||
| 
 | ||||
|         @Nullable | ||||
|         @Override | ||||
|         public Padding blockPadding() { | ||||
|             if (blockPadding != null) { | ||||
|                 return blockPadding; | ||||
|             } | ||||
|             return padding; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,34 @@ | ||||
| package io.noties.markwon.sample; | ||||
| 
 | ||||
| import android.app.Activity; | ||||
| import android.os.Bundle; | ||||
| import android.view.Menu; | ||||
| import android.view.MenuItem; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| 
 | ||||
| public abstract class ActivityWithMenuOptions extends Activity { | ||||
| 
 | ||||
|     @NonNull | ||||
|     public abstract MenuOptions menuOptions(); | ||||
| 
 | ||||
|     private MenuOptions menuOptions; | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onCreate(@Nullable Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
| 
 | ||||
|         menuOptions = menuOptions(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean onCreateOptionsMenu(Menu menu) { | ||||
|         return menuOptions.onCreateOptionsMenu(menu); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean onOptionsItemSelected(MenuItem item) { | ||||
|         return menuOptions.onOptionsItemSelected(item); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,46 @@ | ||||
| package io.noties.markwon.sample; | ||||
| 
 | ||||
| import android.view.Menu; | ||||
| import android.view.MenuItem; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| public class MenuOptions { | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static MenuOptions create() { | ||||
|         return new MenuOptions(); | ||||
|     } | ||||
| 
 | ||||
|     // to preserve order use LinkedHashMap | ||||
|     private final Map<String, Runnable> actions = new LinkedHashMap<>(); | ||||
| 
 | ||||
|     @NonNull | ||||
|     public MenuOptions add(@NonNull String title, @NonNull Runnable action) { | ||||
|         actions.put(title, action); | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     boolean onCreateOptionsMenu(Menu menu) { | ||||
|         if (!actions.isEmpty()) { | ||||
|             for (String key : actions.keySet()) { | ||||
|                 menu.add(key); | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     boolean onOptionsItemSelected(MenuItem item) { | ||||
|         final String title = String.valueOf(item.getTitle()); | ||||
|         final Runnable action = actions.get(title); | ||||
|         if (action != null) { | ||||
|             action.run(); | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,5 @@ | ||||
| package io.noties.markwon.sample.editor; | ||||
| 
 | ||||
| import android.app.Activity; | ||||
| import android.os.Bundle; | ||||
| import android.text.Editable; | ||||
| import android.text.SpannableStringBuilder; | ||||
| @ -42,12 +41,26 @@ import io.noties.markwon.inlineparser.EntityInlineProcessor; | ||||
| import io.noties.markwon.inlineparser.HtmlInlineProcessor; | ||||
| import io.noties.markwon.inlineparser.MarkwonInlineParser; | ||||
| import io.noties.markwon.linkify.LinkifyPlugin; | ||||
| import io.noties.markwon.sample.ActivityWithMenuOptions; | ||||
| import io.noties.markwon.sample.MenuOptions; | ||||
| import io.noties.markwon.sample.R; | ||||
| 
 | ||||
| public class EditorActivity extends Activity { | ||||
| public class EditorActivity extends ActivityWithMenuOptions { | ||||
| 
 | ||||
|     private EditText editText; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public MenuOptions menuOptions() { | ||||
|         return MenuOptions.create() | ||||
|                 .add("simpleProcess", this::simple_process) | ||||
|                 .add("simplePreRender", this::simple_pre_render) | ||||
|                 .add("customPunctuationSpan", this::custom_punctuation_span) | ||||
|                 .add("additionalEditSpan", this::additional_edit_span) | ||||
|                 .add("additionalPlugins", this::additional_plugins) | ||||
|                 .add("multipleEditSpans", this::multiple_edit_spans); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(@Nullable Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
| @ -56,16 +69,6 @@ public class EditorActivity extends Activity { | ||||
|         this.editText = findViewById(R.id.edit_text); | ||||
|         initBottomBar(); | ||||
| 
 | ||||
| //        simple_process(); | ||||
| 
 | ||||
| //        simple_pre_render(); | ||||
| 
 | ||||
| //        custom_punctuation_span(); | ||||
| 
 | ||||
| //        additional_edit_span(); | ||||
| 
 | ||||
| //        additional_plugins(); | ||||
| 
 | ||||
|         multiple_edit_spans(); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -40,24 +40,28 @@ class LinkEditHandler extends AbstractEditHandler<LinkSpan> { | ||||
|         final EditLinkSpan editLinkSpan = persistedSpans.get(EditLinkSpan.class); | ||||
|         editLinkSpan.link = span.getLink(); | ||||
| 
 | ||||
|         final int s; | ||||
|         final int e; | ||||
|         // First first __letter__ to find link content (scheme start in URL, receiver in email address) | ||||
|         // NB! do not use phone number auto-link (via LinkifyPlugin) as we cannot guarantee proper link | ||||
|         //  display. For example, we _could_ also look for a digit, but: | ||||
|         //  * if phone number start with special symbol, we won't have it (`+`, `(`) | ||||
|         //  * it might interfere with an ordered-list | ||||
|         int start = -1; | ||||
| 
 | ||||
|         // markdown link vs. autolink | ||||
|         if ('[' == input.charAt(spanStart)) { | ||||
|             s = spanStart + 1; | ||||
|             e = spanStart + 1 + spanTextLength; | ||||
|         } else { | ||||
|             s = spanStart; | ||||
|             e = spanStart + spanTextLength; | ||||
|         for (int i = spanStart, length = input.length(); i < length; i++) { | ||||
|             if (Character.isLetter(input.charAt(i))) { | ||||
|                 start = i; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         editable.setSpan( | ||||
|                 editLinkSpan, | ||||
|                 s, | ||||
|                 e, | ||||
|                 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | ||||
|         ); | ||||
|         if (start > -1) { | ||||
|             editable.setSpan( | ||||
|                     editLinkSpan, | ||||
|                     start, | ||||
|                     start + spanTextLength, | ||||
|                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|  | ||||
| @ -1,57 +1,100 @@ | ||||
| package io.noties.markwon.sample.latex; | ||||
| 
 | ||||
| import android.app.Activity; | ||||
| import android.graphics.drawable.ColorDrawable; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.os.Bundle; | ||||
| import android.util.Log; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| 
 | ||||
| import org.commonmark.node.Node; | ||||
| 
 | ||||
| import io.noties.markwon.AbstractMarkwonPlugin; | ||||
| import io.noties.markwon.Markwon; | ||||
| import io.noties.markwon.ext.latex.JLatexMathPlugin; | ||||
| import io.noties.markwon.ext.latex.JLatexMathTheme; | ||||
| import io.noties.markwon.sample.ActivityWithMenuOptions; | ||||
| import io.noties.markwon.sample.MenuOptions; | ||||
| import io.noties.markwon.sample.R; | ||||
| import io.noties.markwon.utils.DumpNodes; | ||||
| import ru.noties.jlatexmath.JLatexMathDrawable; | ||||
| 
 | ||||
| public class LatexActivity extends Activity { | ||||
| public class LatexActivity extends ActivityWithMenuOptions { | ||||
| 
 | ||||
|     private TextView textView; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public MenuOptions menuOptions() { | ||||
|         return MenuOptions.create() | ||||
|                 .add("array", this::array) | ||||
|                 .add("longDivision", this::longDivision) | ||||
|                 .add("bangle", this::bangle) | ||||
|                 .add("boxes", this::boxes) | ||||
|                 .add("insideBlockQuote", this::insideBlockQuote); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(@Nullable Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
| 
 | ||||
|         setContentView(R.layout.activity_text_view); | ||||
| 
 | ||||
|         final TextView textView = findViewById(R.id.text_view); | ||||
|         textView = findViewById(R.id.text_view); | ||||
| 
 | ||||
| //        String latex = "\\begin{array}{l}"; | ||||
| //        latex += "\\forall\\varepsilon\\in\\mathbb{R}_+^*\\ \\exists\\eta>0\\ |x-x_0|\\leq\\eta\\Longrightarrow|f(x)-f(x_0)|\\leq\\varepsilon\\\\"; | ||||
| //        latex += "\\det\\begin{bmatrix}a_{11}&a_{12}&\\cdots&a_{1n}\\\\a_{21}&\\ddots&&\\vdots\\\\\\vdots&&\\ddots&\\vdots\\\\a_{n1}&\\cdots&\\cdots&a_{nn}\\end{bmatrix}\\overset{\\mathrm{def}}{=}\\sum_{\\sigma\\in\\mathfrak{S}_n}\\varepsilon(\\sigma)\\prod_{k=1}^n a_{k\\sigma(k)}\\\\"; | ||||
| //        latex += "\\sideset{_\\alpha^\\beta}{_\\gamma^\\delta}{\\begin{pmatrix}a&b\\\\c&d\\end{pmatrix}}\\\\"; | ||||
| //        latex += "\\int_0^\\infty{x^{2n} e^{-a x^2}\\,dx} = \\frac{2n-1}{2a} \\int_0^\\infty{x^{2(n-1)} e^{-a x^2}\\,dx} = \\frac{(2n-1)!!}{2^{n+1}} \\sqrt{\\frac{\\pi}{a^{2n+1}}}\\\\"; | ||||
| //        latex += "\\int_a^b{f(x)\\,dx} = (b - a) \\sum\\limits_{n = 1}^\\infty  {\\sum\\limits_{m = 1}^{2^n  - 1} {\\left( { - 1} \\right)^{m + 1} } } 2^{ - n} f(a + m\\left( {b - a} \\right)2^{-n} )\\\\"; | ||||
| //        latex += "\\int_{-\\pi}^{\\pi} \\sin(\\alpha x) \\sin^n(\\beta x) dx = \\textstyle{\\left \\{ \\begin{array}{cc} (-1)^{(n+1)/2} (-1)^m \\frac{2 \\pi}{2^n} \\binom{n}{m} & n \\mbox{ odd},\\ \\alpha = \\beta (2m-n) \\\\ 0 & \\mbox{otherwise} \\\\ \\end{array} \\right .}\\\\"; | ||||
| //        latex += "L = \\int_a^b \\sqrt{ \\left|\\sum_{i,j=1}^ng_{ij}(\\gamma(t))\\left(\\frac{d}{dt}x^i\\circ\\gamma(t)\\right)\\left(\\frac{d}{dt}x^j\\circ\\gamma(t)\\right)\\right|}\\,dt\\\\"; | ||||
| //        latex += "\\begin{array}{rl} s &= \\int_a^b\\left\\|\\frac{d}{dt}\\vec{r}\\,(u(t),v(t))\\right\\|\\,dt \\\\ &= \\int_a^b \\sqrt{u'(t)^2\\,\\vec{r}_u\\cdot\\vec{r}_u + 2u'(t)v'(t)\\, \\vec{r}_u\\cdot\\vec{r}_v+ v'(t)^2\\,\\vec{r}_v\\cdot\\vec{r}_v}\\,\\,\\, dt. \\end{array}\\\\"; | ||||
| //        latex += "\\end{array}"; | ||||
| //        array(); | ||||
|         longDivision(); | ||||
|     } | ||||
| 
 | ||||
|     private void array() { | ||||
|         String latex = "\\begin{array}{l}"; | ||||
|         latex += "\\forall\\varepsilon\\in\\mathbb{R}_+^*\\ \\exists\\eta>0\\ |x-x_0|\\leq\\eta\\Longrightarrow|f(x)-f(x_0)|\\leq\\varepsilon\\\\"; | ||||
|         latex += "\\det\\begin{bmatrix}a_{11}&a_{12}&\\cdots&a_{1n}\\\\a_{21}&\\ddots&&\\vdots\\\\\\vdots&&\\ddots&\\vdots\\\\a_{n1}&\\cdots&\\cdots&a_{nn}\\end{bmatrix}\\overset{\\mathrm{def}}{=}\\sum_{\\sigma\\in\\mathfrak{S}_n}\\varepsilon(\\sigma)\\prod_{k=1}^n a_{k\\sigma(k)}\\\\"; | ||||
|         latex += "\\sideset{_\\alpha^\\beta}{_\\gamma^\\delta}{\\begin{pmatrix}a&b\\\\c&d\\end{pmatrix}}\\\\"; | ||||
|         latex += "\\int_0^\\infty{x^{2n} e^{-a x^2}\\,dx} = \\frac{2n-1}{2a} \\int_0^\\infty{x^{2(n-1)} e^{-a x^2}\\,dx} = \\frac{(2n-1)!!}{2^{n+1}} \\sqrt{\\frac{\\pi}{a^{2n+1}}}\\\\"; | ||||
|         latex += "\\int_a^b{f(x)\\,dx} = (b - a) \\sum\\limits_{n = 1}^\\infty  {\\sum\\limits_{m = 1}^{2^n  - 1} {\\left( { - 1} \\right)^{m + 1} } } 2^{ - n} f(a + m\\left( {b - a} \\right)2^{-n} )\\\\"; | ||||
|         latex += "\\int_{-\\pi}^{\\pi} \\sin(\\alpha x) \\sin^n(\\beta x) dx = \\textstyle{\\left \\{ \\begin{array}{cc} (-1)^{(n+1)/2} (-1)^m \\frac{2 \\pi}{2^n} \\binom{n}{m} & n \\mbox{ odd},\\ \\alpha = \\beta (2m-n) \\\\ 0 & \\mbox{otherwise} \\\\ \\end{array} \\right .}\\\\"; | ||||
|         latex += "L = \\int_a^b \\sqrt{ \\left|\\sum_{i,j=1}^ng_{ij}(\\gamma(t))\\left(\\frac{d}{dt}x^i\\circ\\gamma(t)\\right)\\left(\\frac{d}{dt}x^j\\circ\\gamma(t)\\right)\\right|}\\,dt\\\\"; | ||||
|         latex += "\\begin{array}{rl} s &= \\int_a^b\\left\\|\\frac{d}{dt}\\vec{r}\\,(u(t),v(t))\\right\\|\\,dt \\\\ &= \\int_a^b \\sqrt{u'(t)^2\\,\\vec{r}_u\\cdot\\vec{r}_u + 2u'(t)v'(t)\\, \\vec{r}_u\\cdot\\vec{r}_v+ v'(t)^2\\,\\vec{r}_v\\cdot\\vec{r}_v}\\,\\,\\, dt. \\end{array}\\\\"; | ||||
|         latex += "\\end{array}"; | ||||
| 
 | ||||
|         render(wrapLatexInSampleMarkdown(latex)); | ||||
|     } | ||||
| 
 | ||||
|     private void longDivision() { | ||||
|         String latex = "\\text{A long division \\longdiv{12345}{13}"; | ||||
| //        String latex = "{a \\bangle b} {c \\brace d} {e \\brack f} {g \\choose h}"; | ||||
|         render(wrapLatexInSampleMarkdown(latex)); | ||||
|     } | ||||
| 
 | ||||
| //        String latex = "\\begin{array}{cc}"; | ||||
| //        latex += "\\fbox{\\text{A framed box with \\textdbend}}&\\shadowbox{\\text{A shadowed box}}\\cr"; | ||||
| //        latex += "\\doublebox{\\text{A double framed box}}&\\ovalbox{\\text{An oval framed box}}\\cr"; | ||||
| //        latex += "\\end{array}"; | ||||
|     private void bangle() { | ||||
|         String latex = "{a \\bangle b} {c \\brace d} {e \\brack f} {g \\choose h}"; | ||||
|         render(wrapLatexInSampleMarkdown(latex)); | ||||
|     } | ||||
| 
 | ||||
|         final String markdown = "# Example of LaTeX\n\nhello there: $$" | ||||
|                 + latex + "$$ so nice, really?\n\n $$  \n" + latex + "\n$$\n\n   $$     \n" + latex + "\n$$"; | ||||
|     private void boxes() { | ||||
|         String latex = "\\begin{array}{cc}"; | ||||
|         latex += "\\fbox{\\text{A framed box with \\textdbend}}&\\shadowbox{\\text{A shadowed box}}\\cr"; | ||||
|         latex += "\\doublebox{\\text{A double framed box}}&\\ovalbox{\\text{An oval framed box}}\\cr"; | ||||
|         latex += "\\end{array}"; | ||||
|         render(wrapLatexInSampleMarkdown(latex)); | ||||
|     } | ||||
| 
 | ||||
|     private void insideBlockQuote() { | ||||
|         String latex = "W=W_1+W_2=F_1X_1-F_2X_2"; | ||||
|         final String md = "" + | ||||
|                 "# LaTeX inside a blockquote\n" + | ||||
|                 "> $$" + latex + "$$\n"; | ||||
|         render(md); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     private static String wrapLatexInSampleMarkdown(@NonNull String latex) { | ||||
|         return "" + | ||||
|                 "# Example of LaTeX\n\n" + | ||||
|                 "(inline): $$" + latex + "$$ so nice, really? Now, (block):\n\n" + | ||||
|                 "$$\n" + | ||||
|                 "" + latex + "\n" + | ||||
|                 "$$\n\n" + | ||||
|                 "the end"; | ||||
|     } | ||||
| 
 | ||||
|     private void render(@NonNull String markdown) { | ||||
|         final Markwon markwon = Markwon.builder(this) | ||||
|                 .usePlugin(JLatexMathPlugin.create(textView.getTextSize(), new JLatexMathPlugin.BuilderConfigure() { | ||||
|                     @Override | ||||
| @ -70,37 +113,7 @@ public class LatexActivity extends Activity { | ||||
|                         ; | ||||
|                     } | ||||
|                 })) | ||||
| //                .usePlugin(JLatexMathPlugin.create(textView.getTextSize())) | ||||
|                 .usePlugin(new AbstractMarkwonPlugin() { | ||||
|                     @Override | ||||
|                     public void beforeRender(@NonNull Node node) { | ||||
|                         Log.e("LTX", DumpNodes.dump(node)); | ||||
|                     } | ||||
|                 }) | ||||
|                 .build(); | ||||
| // | ||||
| //        if (true) { | ||||
| ////            final String l = "$$\n" + | ||||
| ////                    "  P(X=r)=\\frac{\\lambda^r e^{-\\lambda}}{r!}\n" + | ||||
| ////                    "$$\n" + | ||||
| ////                    "\n" + | ||||
| ////                    "$$\n" + | ||||
| ////                    "  P(X<r)=P(X<r-1)\n" + | ||||
| ////                    "$$\n" + | ||||
| ////                    "\n" + | ||||
| ////                    "$$\n" + | ||||
| ////                    "  P(X>r)=1-P(X<r=1)\n" + | ||||
| ////                    "$$\n" + | ||||
| ////                    "\n" + | ||||
| ////                    "$$\n" + | ||||
| ////                    "  \\text{Variance} = \\lambda\n" + | ||||
| ////                    "$$"; | ||||
| //            final String l = "$$ \n" + | ||||
| //                    "    \\sigma_T^2 = \\frac{1-p}{p^2}\n" + | ||||
| //                    "$$"; | ||||
| //            markwon.setMarkdown(textView, l); | ||||
| //            return; | ||||
| //        } | ||||
| 
 | ||||
|         markwon.setMarkdown(textView, markdown); | ||||
|     } | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| package io.noties.markwon.sample.tasklist; | ||||
| 
 | ||||
| import android.app.Activity; | ||||
| import android.graphics.Color; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.os.Bundle; | ||||
| import android.text.Spanned; | ||||
| import android.text.TextPaint; | ||||
| @ -10,6 +11,9 @@ import android.widget.TextView; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.core.content.ContextCompat; | ||||
| 
 | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| import io.noties.debug.Debug; | ||||
| import io.noties.markwon.AbstractMarkwonPlugin; | ||||
| @ -19,12 +23,34 @@ import io.noties.markwon.SpanFactory; | ||||
| import io.noties.markwon.ext.tasklist.TaskListItem; | ||||
| import io.noties.markwon.ext.tasklist.TaskListPlugin; | ||||
| import io.noties.markwon.ext.tasklist.TaskListSpan; | ||||
| import io.noties.markwon.sample.ActivityWithMenuOptions; | ||||
| import io.noties.markwon.sample.MenuOptions; | ||||
| import io.noties.markwon.sample.R; | ||||
| 
 | ||||
| public class TaskListActivity extends Activity { | ||||
| public class TaskListActivity extends ActivityWithMenuOptions { | ||||
| 
 | ||||
|     private static final String MD = "" + | ||||
|             "- [ ] Not done here!\n" + | ||||
|             "- [x] and done\n" + | ||||
|             "- [X] and again!\n" + | ||||
|             "* [ ] **and** syntax _included_ `code`\n" + | ||||
|             "- [ ] [link](#)\n" + | ||||
|             "- [ ] [a check box](https://goog.le)\n" + | ||||
|             "- [x] [test]()\n" + | ||||
|             "- [List](https://goog.le) 3"; | ||||
| 
 | ||||
|     private TextView textView; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public MenuOptions menuOptions() { | ||||
|         return MenuOptions.create() | ||||
|                 .add("regular", this::regular) | ||||
|                 .add("customColors", this::customColors) | ||||
|                 .add("customDrawableResources", this::customDrawableResources) | ||||
|                 .add("mutate", this::mutate); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onCreate(@Nullable Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
| @ -32,7 +58,44 @@ public class TaskListActivity extends Activity { | ||||
| 
 | ||||
|         textView = findViewById(R.id.text_view); | ||||
| 
 | ||||
|         mutate(); | ||||
| //        mutate(); | ||||
|         regular(); | ||||
|     } | ||||
| 
 | ||||
|     private void regular() { | ||||
|         // default theme | ||||
| 
 | ||||
|         final Markwon markwon = Markwon.builder(this) | ||||
|                 .usePlugin(TaskListPlugin.create(this)) | ||||
|                 .build(); | ||||
| 
 | ||||
|         markwon.setMarkdown(textView, MD); | ||||
|     } | ||||
| 
 | ||||
|     private void customColors() { | ||||
| 
 | ||||
|         final int checkedFillColor = Color.RED; | ||||
|         final int normalOutlineColor = Color.GREEN; | ||||
|         final int checkMarkColor = Color.BLUE; | ||||
| 
 | ||||
|         final Markwon markwon = Markwon.builder(this) | ||||
|                 .usePlugin(TaskListPlugin.create(checkedFillColor, normalOutlineColor, checkMarkColor)) | ||||
|                 .build(); | ||||
| 
 | ||||
|         markwon.setMarkdown(textView, MD); | ||||
|     } | ||||
| 
 | ||||
|     private void customDrawableResources() { | ||||
|         // drawable **must** be stateful | ||||
| 
 | ||||
|         final Drawable drawable = Objects.requireNonNull( | ||||
|                 ContextCompat.getDrawable(this, R.drawable.custom_task_list)); | ||||
| 
 | ||||
|         final Markwon markwon = Markwon.builder(this) | ||||
|                 .usePlugin(TaskListPlugin.create(drawable)) | ||||
|                 .build(); | ||||
| 
 | ||||
|         markwon.setMarkdown(textView, MD); | ||||
|     } | ||||
| 
 | ||||
|     private void mutate() { | ||||
| @ -56,6 +119,7 @@ public class TaskListActivity extends Activity { | ||||
|                                 return null; | ||||
|                             } | ||||
| 
 | ||||
|                             // NB, toggle click will intercept possible links inside task-list-item | ||||
|                             return new Object[]{ | ||||
|                                     span, | ||||
|                                     new TaskListToggleSpan(span) | ||||
| @ -65,13 +129,7 @@ public class TaskListActivity extends Activity { | ||||
|                 }) | ||||
|                 .build(); | ||||
| 
 | ||||
|         final String md = "" + | ||||
|                 "- [ ] Not done here!\n" + | ||||
|                 "- [x] and done\n" + | ||||
|                 "- [X] and again!\n" + | ||||
|                 "* [ ] **and** syntax _included_ `code`"; | ||||
| 
 | ||||
|         markwon.setMarkdown(textView, md); | ||||
|         markwon.setMarkdown(textView, MD); | ||||
|     } | ||||
| 
 | ||||
|     private static class TaskListToggleSpan extends ClickableSpan { | ||||
|  | ||||
							
								
								
									
										5
									
								
								sample/src/main/res/drawable/custom_task_list.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								sample/src/main/res/drawable/custom_task_list.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <item android:state_checked="true" android:drawable="@drawable/ic_android_black_24dp" /> | ||||
|     <item android:drawable="@drawable/ic_home_black_36dp" /> | ||||
| </selector> | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dimitry Ivanov
						Dimitry Ivanov