1 /*
2  * Copyright (C) 2008 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 android.text;
18 
19 import android.graphics.Typeface;
20 import android.os.Parcel;
21 import android.test.suitebuilder.annotation.SmallTest;
22 import android.text.*;
23 import android.text.style.*;
24 import android.util.Log;
25 
26 import junit.framework.TestCase;
27 
28 /**
29  * SpannedTest tests some features of Spanned
30  */
31 public class SpannedTest extends TestCase {
32     private int mExpect;
33 
34     @SmallTest
testSpannableString()35     public void testSpannableString() throws Exception {
36         checkPriority(new SpannableString("the quick brown fox"));
37     }
38 
39     @SmallTest
testSpannableStringBuilder()40     public void testSpannableStringBuilder() throws Exception {
41         checkPriority2(new SpannableStringBuilder("the quick brown fox"));
42     }
43 
44     @SmallTest
testAppend()45     public void testAppend() throws Exception {
46         Object o = new Object();
47         SpannableString ss = new SpannableString("Test");
48         ss.setSpan(o, 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
49 
50         SpannableStringBuilder ssb = new SpannableStringBuilder();
51         ssb.append(ss);
52         assertEquals(0, ssb.getSpanStart(o));
53         assertEquals(4, ssb.getSpanEnd(o));
54         assertEquals(1, ssb.getSpans(0, 4, Object.class).length);
55 
56         ssb.insert(0, ss);
57         assertEquals(4, ssb.getSpanStart(o));
58         assertEquals(8, ssb.getSpanEnd(o));
59         assertEquals(0, ssb.getSpans(0, 4, Object.class).length);
60         assertEquals(1, ssb.getSpans(4, 8, Object.class).length);
61     }
62 
63     @SmallTest
testWrapParcel()64     public void testWrapParcel() {
65         SpannableString s = new SpannableString("Hello there world");
66         CharacterStyle mark = new StyleSpan(Typeface.BOLD);
67         s.setSpan(mark, 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
68         s.setSpan(CharacterStyle.wrap(mark), 3, 7,
69                   Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
70         s.setSpan(new TextAppearanceSpan("mono", 0, -1, null, null), 7, 8,
71                   Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
72         s.setSpan(CharacterStyle.wrap(new TypefaceSpan("mono")), 8, 9,
73                   Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
74 
75         Parcel p = Parcel.obtain();
76         TextUtils.writeToParcel(s, p, 0);
77         p.setDataPosition(0);
78 
79         Spanned s2 = (Spanned) TextUtils.CHAR_SEQUENCE_CREATOR.
80                         createFromParcel(p);
81         StyleSpan[] style;
82 
83         style = s2.getSpans(1, 2, StyleSpan.class);
84         assertEquals(1, style.length);
85         assertEquals(1, s2.getSpanStart(style[0]));
86         assertEquals(2, s2.getSpanEnd(style[0]));
87 
88         style = s2.getSpans(3, 7, StyleSpan.class);
89         assertEquals(1, style.length);
90         assertEquals(3, s2.getSpanStart(style[0]));
91         assertEquals(7, s2.getSpanEnd(style[0]));
92 
93         TextAppearanceSpan[] appearance = s2.getSpans(7, 8,
94                                                 TextAppearanceSpan.class);
95         assertEquals(1, appearance.length);
96         assertEquals(7, s2.getSpanStart(appearance[0]));
97         assertEquals(8, s2.getSpanEnd(appearance[0]));
98 
99         TypefaceSpan[] tf = s2.getSpans(8, 9, TypefaceSpan.class);
100         assertEquals(1, tf.length);
101         assertEquals(8, s2.getSpanStart(tf[0]));
102         assertEquals(9, s2.getSpanEnd(tf[0]));
103     }
104 
checkPriority(Spannable s)105     private void checkPriority(Spannable s) {
106         s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
107                                       (5 << Spannable.SPAN_PRIORITY_SHIFT));
108         s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
109                                       (10 << Spannable.SPAN_PRIORITY_SHIFT));
110         s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
111                                       (0 << Spannable.SPAN_PRIORITY_SHIFT));
112         s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
113                                       (15 << Spannable.SPAN_PRIORITY_SHIFT));
114         s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
115                                       (3 << Spannable.SPAN_PRIORITY_SHIFT));
116         s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
117                                       (6 << Spannable.SPAN_PRIORITY_SHIFT));
118         s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
119                                       (0 << Spannable.SPAN_PRIORITY_SHIFT));
120 
121         Object[] spans = s.getSpans(0, s.length(), Object.class);
122 
123         for (int i = 0; i < spans.length - 1; i++) {
124             assertEquals((s.getSpanFlags(spans[i]) & Spanned.SPAN_PRIORITY) >=
125                          (s.getSpanFlags(spans[i + 1]) & Spanned.SPAN_PRIORITY),
126                          true);
127         }
128 
129         mExpect = 0;
130 
131         s.setSpan(new Watcher(2), 0, s.length(),
132                   Spannable.SPAN_INCLUSIVE_INCLUSIVE |
133                   (2 << Spannable.SPAN_PRIORITY_SHIFT));
134         s.setSpan(new Watcher(4), 0, s.length(),
135                   Spannable.SPAN_INCLUSIVE_INCLUSIVE |
136                   (4 << Spannable.SPAN_PRIORITY_SHIFT));
137         s.setSpan(new Watcher(1), 0, s.length(),
138                   Spannable.SPAN_INCLUSIVE_INCLUSIVE |
139                   (1 << Spannable.SPAN_PRIORITY_SHIFT));
140         s.setSpan(new Watcher(3), 0, s.length(),
141                   Spannable.SPAN_INCLUSIVE_INCLUSIVE |
142                   (3 << Spannable.SPAN_PRIORITY_SHIFT));
143 
144         mExpect = 4;
145         s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
146         assertEquals(mExpect, 0);
147     }
148 
checkPriority2(SpannableStringBuilder ssb)149     private void checkPriority2(SpannableStringBuilder ssb) {
150         checkPriority(ssb);
151 
152         mExpect = 4;
153         ssb.insert(3, "something");
154         assertEquals(mExpect, 0);
155     }
156 
157     private class Watcher implements SpanWatcher, TextWatcher {
158         private int mSequence;
159 
Watcher(int sequence)160         public Watcher(int sequence) {
161             mSequence = sequence;
162         }
163 
onSpanChanged(Spannable b, Object o, int s, int e, int st, int en)164         public void onSpanChanged(Spannable b, Object o, int s, int e,
165                                   int st, int en) { }
onSpanRemoved(Spannable b, Object o, int s, int e)166         public void onSpanRemoved(Spannable b, Object o, int s, int e) { }
167 
onSpanAdded(Spannable b, Object o, int s, int e)168         public void onSpanAdded(Spannable b, Object o, int s, int e) {
169             if (mExpect != 0) {
170                 assertEquals(mSequence, mExpect);
171                 mExpect = mSequence - 1;
172             }
173         }
174 
beforeTextChanged(CharSequence s, int start, int count, int after)175         public void beforeTextChanged(CharSequence s, int start, int count,
176                                       int after) { }
onTextChanged(CharSequence s, int start, int before, int count)177         public void onTextChanged(CharSequence s, int start, int before,
178                                       int count) {
179             if (mExpect != 0) {
180                 assertEquals(mSequence, mExpect);
181                 mExpect = mSequence - 1;
182             }
183         }
184 
afterTextChanged(Editable s)185         public void afterTextChanged(Editable s) { }
186     }
187 }
188