Home | History | Annotate | Download | only in text
      1 package android.text;
      2 
      3 import static android.text.Spanned.SPAN_INCLUSIVE_INCLUSIVE;
      4 
      5 import android.text.style.BulletSpan;
      6 
      7 import java.util.Random;
      8 
      9 /**
     10  *
     11  */
     12 public class NonEditableTextGenerator {
     13 
     14     enum TextType {
     15         STRING,
     16         SPANNED,
     17         SPANNABLE_BUILDER
     18     }
     19 
     20     private boolean mCreateBoring;
     21     private TextType mTextType;
     22     private int mSequenceLength;
     23     private final Random mRandom;
     24 
     25     public NonEditableTextGenerator(Random random) {
     26         mRandom = random;
     27     }
     28 
     29     public NonEditableTextGenerator setCreateBoring(boolean createBoring) {
     30         mCreateBoring = createBoring;
     31         return this;
     32     }
     33 
     34     public NonEditableTextGenerator setTextType(TextType textType) {
     35         mTextType = textType;
     36         return this;
     37     }
     38 
     39     public NonEditableTextGenerator setSequenceLength(int sequenceLength) {
     40         mSequenceLength = sequenceLength;
     41         return this;
     42     }
     43 
     44     /**
     45      * Sample charSequence generated:
     46      * NRjPzjvUadHmH ExoEoTqfx pCLw qtndsqfpk AqajVCbgjGZ igIeC dfnXRgA
     47      */
     48     public CharSequence build() {
     49         final RandomCharSequenceGenerator sequenceGenerator = new RandomCharSequenceGenerator(
     50                 mRandom);
     51         if (mSequenceLength > 0) {
     52             sequenceGenerator.setSequenceLength(mSequenceLength);
     53         }
     54 
     55         final CharSequence charSequence = sequenceGenerator.buildLatinSequence();
     56 
     57         switch (mTextType) {
     58             case SPANNED:
     59             case SPANNABLE_BUILDER:
     60                 return createSpannable(charSequence);
     61             case STRING:
     62             default:
     63                 return createString(charSequence);
     64         }
     65     }
     66 
     67     private Spannable createSpannable(CharSequence charSequence) {
     68         final Spannable spannable = (mTextType == TextType.SPANNABLE_BUILDER) ?
     69                 new SpannableStringBuilder(charSequence) : new SpannableString(charSequence);
     70 
     71         if (!mCreateBoring) {
     72             // add a paragraph style to make it non boring
     73             spannable.setSpan(new BulletSpan(), 0, spannable.length(), SPAN_INCLUSIVE_INCLUSIVE);
     74         }
     75 
     76         spannable.setSpan(new Object(), 0, spannable.length(), SPAN_INCLUSIVE_INCLUSIVE);
     77         spannable.setSpan(new Object(), 0, 1, SPAN_INCLUSIVE_INCLUSIVE);
     78 
     79         return spannable;
     80     }
     81 
     82     private String createString(CharSequence charSequence) {
     83         if (mCreateBoring) {
     84             return charSequence.toString();
     85         } else {
     86             // BoringLayout checks to see if there is a surrogate pair and if so tells that
     87             // the charSequence is not suitable for boring. Add an emoji to make it non boring.
     88             // Emoji is added instead of RTL, since emoji stays in the same run and is a more
     89             // common case.
     90             return charSequence.toString() + "\uD83D\uDC68\uD83C\uDFFF";
     91         }
     92     }
     93 
     94     public static class RandomCharSequenceGenerator {
     95 
     96         private static final int DEFAULT_MIN_WORD_LENGTH = 3;
     97         private static final int DEFAULT_MAX_WORD_LENGTH = 15;
     98         private static final int DEFAULT_SEQUENCE_LENGTH = 256;
     99 
    100         private int mMinWordLength = DEFAULT_MIN_WORD_LENGTH;
    101         private int mMaxWordLength = DEFAULT_MAX_WORD_LENGTH;
    102         private int mSequenceLength = DEFAULT_SEQUENCE_LENGTH;
    103         private final Random mRandom;
    104 
    105         public RandomCharSequenceGenerator(Random random) {
    106             mRandom = random;
    107         }
    108 
    109         public RandomCharSequenceGenerator setSequenceLength(int sequenceLength) {
    110             mSequenceLength = sequenceLength;
    111             return this;
    112         }
    113 
    114         public CharSequence buildLatinSequence() {
    115             final StringBuilder result = new StringBuilder();
    116             while (result.length() < mSequenceLength) {
    117                 // add random word
    118                 result.append(buildLatinWord());
    119                 result.append(' ');
    120             }
    121             return result.substring(0, mSequenceLength);
    122         }
    123 
    124         public CharSequence buildLatinWord() {
    125             final StringBuilder result = new StringBuilder();
    126             // create a random length that is (mMinWordLength + random amount of chars) where
    127             // total size is less than mMaxWordLength
    128             final int length = mRandom.nextInt(mMaxWordLength - mMinWordLength) + mMinWordLength;
    129             while (result.length() < length) {
    130                 // add random letter
    131                 int base = mRandom.nextInt(2) == 0 ? 'A' : 'a';
    132                 result.append(Character.toChars(mRandom.nextInt(26) + base));
    133             }
    134             return result.toString();
    135         }
    136     }
    137 
    138 }
    139