From 3ad1d40bb5d2f9b14e66a3760def68e693a2576e Mon Sep 17 00:00:00 2001 From: M66B Date: Sat, 15 Oct 2022 10:41:07 +0200 Subject: [PATCH] Added sub/superscript to composer --- .../java/eu/faircode/email/HtmlHelper.java | 15 +---- .../java/eu/faircode/email/StyleHelper.java | 55 +++++++++++++++++++ .../eu/faircode/email/SubscriptSpanEx.java | 39 +++++++++++++ .../eu/faircode/email/SuperscriptSpanEx.java | 39 +++++++++++++ .../res/drawable/twotone_subscript_24.xml | 10 ++++ .../res/drawable/twotone_superscript_24.xml | 10 ++++ app/src/main/res/menu/popup_style.xml | 24 +++++++- app/src/main/res/values/strings.xml | 2 + 8 files changed, 178 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/eu/faircode/email/SubscriptSpanEx.java create mode 100644 app/src/main/java/eu/faircode/email/SuperscriptSpanEx.java create mode 100644 app/src/main/res/drawable/twotone_subscript_24.xml create mode 100644 app/src/main/res/drawable/twotone_superscript_24.xml diff --git a/app/src/main/java/eu/faircode/email/HtmlHelper.java b/app/src/main/java/eu/faircode/email/HtmlHelper.java index c23d480b2a..e3036536de 100644 --- a/app/src/main/java/eu/faircode/email/HtmlHelper.java +++ b/app/src/main/java/eu/faircode/email/HtmlHelper.java @@ -53,8 +53,6 @@ import android.text.style.QuoteSpan; import android.text.style.RelativeSizeSpan; import android.text.style.StrikethroughSpan; import android.text.style.StyleSpan; -import android.text.style.SubscriptSpan; -import android.text.style.SuperscriptSpan; import android.text.style.TypefaceSpan; import android.text.style.URLSpan; import android.text.style.UnderlineSpan; @@ -1206,13 +1204,6 @@ public class HtmlHelper { // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr document.select("abbr").tagName("u"); - // Subscript/Superscript - // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub - // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup - if (!view) - for (Element subp : document.select("sub,sup")) - subp.tagName("small"); - // Tables // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table for (Element table : document.select("table")) { @@ -3645,12 +3636,10 @@ public class HtmlHelper { // Do nothing break; case "sub": - setSpan(ssb, new SubscriptSpan(), start, ssb.length()); - setSpan(ssb, new RelativeSizeSpan(FONT_SMALL), start, ssb.length()); + setSpan(ssb, new SubscriptSpanEx(), start, ssb.length()); break; case "sup": - setSpan(ssb, new SuperscriptSpan(), start, ssb.length()); - setSpan(ssb, new RelativeSizeSpan(FONT_SMALL), start, ssb.length()); + setSpan(ssb, new SuperscriptSpanEx(), start, ssb.length()); break; case "table": case "thead": diff --git a/app/src/main/java/eu/faircode/email/StyleHelper.java b/app/src/main/java/eu/faircode/email/StyleHelper.java index 6eb758a8d1..758143795a 100644 --- a/app/src/main/java/eu/faircode/email/StyleHelper.java +++ b/app/src/main/java/eu/faircode/email/StyleHelper.java @@ -80,6 +80,7 @@ public class StyleHelper { AlignmentSpan.class, BulletSpanEx.class, NumberSpan.class, QuoteSpan.class, IndentSpan.class, + SubscriptSpanEx.class, SuperscriptSpanEx.class, StrikethroughSpan.class, URLSpan.class, TypefaceSpan.class, CustomTypefaceSpan.class, @@ -246,6 +247,10 @@ public class StyleHelper { return setBlockQuote(etBody, start, end, true); } else if (groupId == R.id.group_style_mark) { return setMark(item); + } else if (groupId == R.id.group_style_subscript) { + return setSubscript(item); + } else if (groupId == R.id.group_style_superscript) { + return setSuperscript(item); } else if (groupId == R.id.group_style_strikethrough) { return setStrikeThrough(item); } else if (groupId == R.id.group_style_code) { @@ -465,6 +470,56 @@ public class StyleHelper { return true; } + private boolean setSubscript(MenuItem item) { + Log.breadcrumb("style", "action", "subscript"); + + boolean has = false; + SubscriptSpanEx[] spans = edit.getSpans(start, end, SubscriptSpanEx.class); + for (SubscriptSpanEx span : spans) { + int s = edit.getSpanStart(span); + int e = edit.getSpanEnd(span); + int f = edit.getSpanFlags(span); + edit.removeSpan(span); + if (splitSpan(edit, start, end, s, e, f, true, + new SubscriptSpanEx(), new SubscriptSpanEx())) + has = true; + } + + if (!has) + edit.setSpan(new SubscriptSpanEx(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + etBody.setText(edit); + etBody.setSelection(start, end); + + return true; + } + + private boolean setSuperscript(MenuItem item) { + Log.breadcrumb("style", "action", "superscript"); + + boolean has = false; + SuperscriptSpanEx[] spans = edit.getSpans(start, end, SuperscriptSpanEx.class); + for (SuperscriptSpanEx span : spans) { + int s = edit.getSpanStart(span); + int e = edit.getSpanEnd(span); + int f = edit.getSpanFlags(span); + edit.removeSpan(span); + if (splitSpan(edit, start, end, s, e, f, true, + new SuperscriptSpanEx(), new SuperscriptSpanEx())) + has = true; + } + + if (!has) { + edit.setSpan(new SuperscriptSpanEx(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + edit.setSpan(new RelativeSizeSpan(HtmlHelper.FONT_SMALL), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + + etBody.setText(edit); + etBody.setSelection(start, end); + + return true; + } + private boolean setStrikeThrough(MenuItem item) { Log.breadcrumb("style", "action", "strike"); diff --git a/app/src/main/java/eu/faircode/email/SubscriptSpanEx.java b/app/src/main/java/eu/faircode/email/SubscriptSpanEx.java new file mode 100644 index 0000000000..725fadf3c7 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/SubscriptSpanEx.java @@ -0,0 +1,39 @@ +package eu.faircode.email; + +/* + This file is part of FairEmail. + + FairEmail is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FairEmail is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FairEmail. If not, see . + + Copyright 2018-2022 by Marcel Bokhorst (M66B) +*/ + +import android.text.TextPaint; +import android.text.style.SubscriptSpan; + +import androidx.annotation.NonNull; + +public class SubscriptSpanEx extends SubscriptSpan { + @Override + public void updateDrawState(@NonNull TextPaint textPaint) { + super.updateDrawState(textPaint); + textPaint.setTextSize(textPaint.getTextSize() * HtmlHelper.FONT_SMALL); + } + + @Override + public void updateMeasureState(@NonNull TextPaint textPaint) { + super.updateMeasureState(textPaint); + textPaint.setTextSize(textPaint.getTextSize() * HtmlHelper.FONT_SMALL); + } +} diff --git a/app/src/main/java/eu/faircode/email/SuperscriptSpanEx.java b/app/src/main/java/eu/faircode/email/SuperscriptSpanEx.java new file mode 100644 index 0000000000..ee5ced2e70 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/SuperscriptSpanEx.java @@ -0,0 +1,39 @@ +package eu.faircode.email; + +/* + This file is part of FairEmail. + + FairEmail is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FairEmail is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FairEmail. If not, see . + + Copyright 2018-2022 by Marcel Bokhorst (M66B) +*/ + +import android.text.TextPaint; +import android.text.style.SuperscriptSpan; + +import androidx.annotation.NonNull; + +public class SuperscriptSpanEx extends SuperscriptSpan { + @Override + public void updateDrawState(@NonNull TextPaint textPaint) { + super.updateDrawState(textPaint); + textPaint.setTextSize(textPaint.getTextSize() * HtmlHelper.FONT_SMALL); + } + + @Override + public void updateMeasureState(@NonNull TextPaint textPaint) { + super.updateMeasureState(textPaint); + textPaint.setTextSize(textPaint.getTextSize() * HtmlHelper.FONT_SMALL); + } +} diff --git a/app/src/main/res/drawable/twotone_subscript_24.xml b/app/src/main/res/drawable/twotone_subscript_24.xml new file mode 100644 index 0000000000..ac0d19e9da --- /dev/null +++ b/app/src/main/res/drawable/twotone_subscript_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/twotone_superscript_24.xml b/app/src/main/res/drawable/twotone_superscript_24.xml new file mode 100644 index 0000000000..e3e4fc9ebb --- /dev/null +++ b/app/src/main/res/drawable/twotone_superscript_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/menu/popup_style.xml b/app/src/main/res/menu/popup_style.xml index 2973a1e79c..9234fdf148 100644 --- a/app/src/main/res/menu/popup_style.xml +++ b/app/src/main/res/menu/popup_style.xml @@ -151,8 +151,26 @@ + + + + + + + + + android:orderInCategory="13"> + android:orderInCategory="14"> Block quote Indentation Highlight + Subscript + Superscript Strikethrough Code Clear formatting