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
17package android.text;
18
19import android.graphics.Typeface;
20import android.os.Parcel;
21import android.test.suitebuilder.annotation.SmallTest;
22import android.text.*;
23import android.text.style.*;
24import android.util.Log;
25
26import junit.framework.TestCase;
27
28/**
29 * SpannedTest tests some features of Spanned
30 */
31public class SpannedTest extends TestCase {
32    private int mExpect;
33
34    @SmallTest
35    public void testSpannableString() throws Exception {
36        checkPriority(new SpannableString("the quick brown fox"));
37    }
38
39    @SmallTest
40    public void testSpannableStringBuilder() throws Exception {
41        checkPriority2(new SpannableStringBuilder("the quick brown fox"));
42    }
43
44    @SmallTest
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
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
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
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
160        public Watcher(int sequence) {
161            mSequence = sequence;
162        }
163
164        public void onSpanChanged(Spannable b, Object o, int s, int e,
165                                  int st, int en) { }
166        public void onSpanRemoved(Spannable b, Object o, int s, int e) { }
167
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
175        public void beforeTextChanged(CharSequence s, int start, int count,
176                                      int after) { }
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
185        public void afterTextChanged(Editable s) { }
186    }
187}
188