• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.mms.util;
18 
19 import android.content.Context;
20 import android.text.Spannable;
21 import android.text.SpannableStringBuilder;
22 import android.text.style.ImageSpan;
23 
24 import com.android.mms.R;
25 
26 import java.util.HashMap;
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
29 
30 /**
31  * A class for annotating a CharSequence with spans to convert textual emoticons
32  * to graphical ones.
33  */
34 public class SmileyParser {
35     // Singleton stuff
36     private static SmileyParser sInstance;
getInstance()37     public static SmileyParser getInstance() { return sInstance; }
init(Context context)38     public static void init(Context context) {
39         sInstance = new SmileyParser(context);
40     }
41 
42     private final Context mContext;
43     private final String[] mSmileyTexts;
44     private final Pattern mPattern;
45     private final HashMap<String, Integer> mSmileyToRes;
46 
SmileyParser(Context context)47     private SmileyParser(Context context) {
48         mContext = context;
49         mSmileyTexts = mContext.getResources().getStringArray(DEFAULT_SMILEY_TEXTS);
50         mSmileyToRes = buildSmileyToRes();
51         mPattern = buildPattern();
52     }
53 
54     static class Smileys {
55         private static final int[] sIconIds = {
56             R.drawable.emo_im_happy,
57             R.drawable.emo_im_sad,
58             R.drawable.emo_im_winking,
59             R.drawable.emo_im_tongue_sticking_out,
60             R.drawable.emo_im_surprised,
61             R.drawable.emo_im_kissing,
62             R.drawable.emo_im_yelling,
63             R.drawable.emo_im_cool,
64             R.drawable.emo_im_money_mouth,
65             R.drawable.emo_im_foot_in_mouth,
66             R.drawable.emo_im_embarrassed,
67             R.drawable.emo_im_angel,
68             R.drawable.emo_im_undecided,
69             R.drawable.emo_im_crying,
70             R.drawable.emo_im_lips_are_sealed,
71             R.drawable.emo_im_laughing,
72             R.drawable.emo_im_wtf,
73             R.drawable.emo_im_heart,
74             R.drawable.emo_im_mad,
75             R.drawable.emo_im_smirk,
76             R.drawable.emo_im_pokerface
77         };
78 
79         public static int HAPPY = 0;
80         public static int SAD = 1;
81         public static int WINKING = 2;
82         public static int TONGUE_STICKING_OUT = 3;
83         public static int SURPRISED = 4;
84         public static int KISSING = 5;
85         public static int YELLING = 6;
86         public static int COOL = 7;
87         public static int MONEY_MOUTH = 8;
88         public static int FOOT_IN_MOUTH = 9;
89         public static int EMBARRASSED = 10;
90         public static int ANGEL = 11;
91         public static int UNDECIDED = 12;
92         public static int CRYING = 13;
93         public static int LIPS_ARE_SEALED = 14;
94         public static int LAUGHING = 15;
95         public static int WTF = 16;
96         public static int MAD = 17;
97         public static int HEART = 18;
98         public static int SMIRK = 19;
99         public static int POKERFACE = 20;
100 
getSmileyResource(int which)101         public static int getSmileyResource(int which) {
102             return sIconIds[which];
103         }
104     }
105 
106     // NOTE: if you change anything about this array, you must make the corresponding change
107     // to the string arrays: default_smiley_texts and default_smiley_names in res/values/arrays.xml
108     public static final int[] DEFAULT_SMILEY_RES_IDS = {
109         Smileys.getSmileyResource(Smileys.HAPPY),                //  0
110         Smileys.getSmileyResource(Smileys.SAD),                  //  1
111         Smileys.getSmileyResource(Smileys.WINKING),              //  2
112         Smileys.getSmileyResource(Smileys.TONGUE_STICKING_OUT),  //  3
113         Smileys.getSmileyResource(Smileys.SURPRISED),            //  4
114         Smileys.getSmileyResource(Smileys.KISSING),              //  5
115         Smileys.getSmileyResource(Smileys.YELLING),              //  6
116         Smileys.getSmileyResource(Smileys.COOL),                 //  7
117         Smileys.getSmileyResource(Smileys.MONEY_MOUTH),          //  8
118         Smileys.getSmileyResource(Smileys.FOOT_IN_MOUTH),        //  9
119         Smileys.getSmileyResource(Smileys.EMBARRASSED),          //  10
120         Smileys.getSmileyResource(Smileys.ANGEL),                //  11
121         Smileys.getSmileyResource(Smileys.UNDECIDED),            //  12
122         Smileys.getSmileyResource(Smileys.CRYING),               //  13
123         Smileys.getSmileyResource(Smileys.LIPS_ARE_SEALED),      //  14
124         Smileys.getSmileyResource(Smileys.LAUGHING),             //  15
125         Smileys.getSmileyResource(Smileys.WTF),                  //  16
126         Smileys.getSmileyResource(Smileys.MAD),                  //  17
127         Smileys.getSmileyResource(Smileys.HEART),                //  18
128         Smileys.getSmileyResource(Smileys.SMIRK),                //  19
129         Smileys.getSmileyResource(Smileys.POKERFACE),            //  20
130     };
131 
132     public static final int DEFAULT_SMILEY_TEXTS = R.array.default_smiley_texts;
133     public static final int DEFAULT_SMILEY_NAMES = R.array.default_smiley_names;
134 
135     /**
136      * Builds the hashtable we use for mapping the string version
137      * of a smiley (e.g. ":-)") to a resource ID for the icon version.
138      */
buildSmileyToRes()139     private HashMap<String, Integer> buildSmileyToRes() {
140         if (DEFAULT_SMILEY_RES_IDS.length != mSmileyTexts.length) {
141             // Throw an exception if someone updated DEFAULT_SMILEY_RES_IDS
142             // and failed to update arrays.xml
143             throw new IllegalStateException("Smiley resource ID/text mismatch");
144         }
145 
146         HashMap<String, Integer> smileyToRes =
147                             new HashMap<String, Integer>(mSmileyTexts.length);
148         for (int i = 0; i < mSmileyTexts.length; i++) {
149             smileyToRes.put(mSmileyTexts[i], DEFAULT_SMILEY_RES_IDS[i]);
150         }
151 
152         return smileyToRes;
153     }
154 
155     /**
156      * Builds the regular expression we use to find smileys in {@link #addSmileySpans}.
157      */
buildPattern()158     private Pattern buildPattern() {
159         // Set the StringBuilder capacity with the assumption that the average
160         // smiley is 3 characters long.
161         StringBuilder patternString = new StringBuilder(mSmileyTexts.length * 3);
162 
163         // Build a regex that looks like (:-)|:-(|...), but escaping the smilies
164         // properly so they will be interpreted literally by the regex matcher.
165         patternString.append('(');
166         for (String s : mSmileyTexts) {
167             patternString.append(Pattern.quote(s));
168             patternString.append('|');
169         }
170         // Replace the extra '|' with a ')'
171         patternString.replace(patternString.length() - 1, patternString.length(), ")");
172 
173         return Pattern.compile(patternString.toString());
174     }
175 
176 
177     /**
178      * Adds ImageSpans to a CharSequence that replace textual emoticons such
179      * as :-) with a graphical version.
180      *
181      * @param text A CharSequence possibly containing emoticons
182      * @return A CharSequence annotated with ImageSpans covering any
183      *         recognized emoticons.
184      */
addSmileySpans(CharSequence text)185     public CharSequence addSmileySpans(CharSequence text) {
186         SpannableStringBuilder builder = new SpannableStringBuilder(text);
187 
188         Matcher matcher = mPattern.matcher(text);
189         while (matcher.find()) {
190             int resId = mSmileyToRes.get(matcher.group());
191             builder.setSpan(new ImageSpan(mContext, resId),
192                             matcher.start(), matcher.end(),
193                             Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
194         }
195 
196         return builder;
197     }
198 }
199 
200 
201