danger.text.span
Class SpannableString

java.lang.Object
  extended by danger.text.span.SpannableString
All Implemented Interfaces:
Spannable, Spanned, GetChars, StringWrapper, CharSequence


public class SpannableString
extends Object
implements CharSequence, Spanned, Spannable, StringWrapper

SpannableString is a wrapper around String to which spans can be attached. The text of SpannableString is immutable but the span list is not. See SpannedString if you want complete immutability.


Field Summary
 
Fields inherited from interface danger.text.span.Spannable
SPAN_DELETE_ON_EMPTY, SPAN_ENDS_AFTER, SPAN_ENDS_BEFORE, SPAN_EXCLUSIVE_AFTER, SPAN_EXCLUSIVE_BEFORE, SPAN_EXCLUSIVE_EXCLUSIVE, SPAN_EXCLUSIVE_INCLUSIVE, SPAN_GROW_FROM_ZERO, SPAN_INCLUSIVE_AFTER, SPAN_INCLUSIVE_BEFORE, SPAN_INCLUSIVE_EXCLUSIVE, SPAN_INCLUSIVE_INCLUSIVE, SPAN_MARKLIKE, SPAN_PARAGRAPH, SPAN_POINTLIKE, SPAN_STARTS_AFTER, SPAN_STARTS_BEFORE
 
Constructor Summary
SpannableString(CharSequence s)
          Create a new SpannableString based upon an existing sequence.
SpannableString(CharSequence s, int start, int end)
          Create a new SpannableString based upon a subsequence of an existing sequence.
 
Method Summary
 char charAt(int i)
          Return the character at the specified offset.
 Object[] getAllSpans(Class kind)
           
 void getChars(int start, int end, char[] dest, int destoff)
           
 int getSpanEnd(Object key)
          Return the ending offset of the specified span within the buffer, or -1 if there is no such span attached.
 int getSpanFlags(Object key)
          Return the flags that were specified when the specified span was attached to the buffer, or 0 if there is no such span attached.
 Object[] getSpansOverlapping(int start, int end, Class kind)
          Return an array of the keys of the spans of the specified kind (according to Class.isInstanceOf()) that overlap the specified range of buffer offsets, or null if no such spans are attached or overlap.
 int getSpanStart(Object key)
          Return the starting offset of the specified span within the buffer, or -1 if there is no such span attached.
 int length()
          Return the length of the underlying String.
 int nextSpanTransition(int offset, int limit, Class kind)
          Find the first offset in the buffer greater than the specified offset but less than or equal to the specified limit where a span of the specified kind (according to Class.isInstanceOf()) begins or ends.
 SpannableString prefixWith(String s)
          Return a new SpannableString containing the contents of this one preceded by the contents of a String.
 void removeSpan(Object key)
          Remove the span with the specified key from this buffer.
 void setSpan(Object key, int start, int end, int flags)
          Add a span with the specified key and flags to the specified range of buffer positions.
 CharSequence subSequence(int start, int end)
          Return a new SpannableString containing a copy of the specified range of this object.
 SpannableString suffixWith(String s)
          Return a new SpannableString containing the contents of this one followed by the contents of a String.
 String toString()
          Return the String underlying this object.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface danger.util.StringWrapper
toString
 

Constructor Detail

SpannableString

public SpannableString(CharSequence s)
Create a new SpannableString based upon an existing sequence. Spans attached to the original are copied unchanged unless they are of type MutableSpan, in which case they are cloned.


SpannableString

public SpannableString(CharSequence s,
                       int start,
                       int end)
Create a new SpannableString based upon a subsequence of an existing sequence. Spans attached to the relevant range of the original are copied unchanged unless they are of type MutableSpan, in which case they are cloned.

Method Detail

suffixWith

public SpannableString suffixWith(String s)
Return a new SpannableString containing the contents of this one followed by the contents of a String. Note that this is concatenation, not insertion; the spans at the end of this one do not grow to cover the new text.


prefixWith

public SpannableString prefixWith(String s)
Return a new SpannableString containing the contents of this one preceded by the contents of a String. Note that this is concatenation, not insertion; the spans at the start of this one do not grow to cover the new text.


setSpan

public void setSpan(Object key,
                    int start,
                    int end,
                    int flags)
Description copied from interface: Spannable
Add a span with the specified key and flags to the specified range of buffer positions. If this buffer already has a span with the same key, the new start, end, and flags replace the old.

The flags currently only matter in buffers whose contents can be changed, although all Spannables need to retain the flags so they can be returned by Spanned.getSpanFlags(java.lang.Object). If all you want to do is set fonts, you may find it easier to just use SpanUtils to do it and to ignore the section below.

The basic question is: when you insert text at the beginning or end of a span, does the insertion go inside or outside it? To provide an answer, spans do not really start exactly at the buffer position of their start and end. They really start and end just before or just after this position, which controls whether the insertion goes inside or outside.

If a Spannable.SPAN_STARTS_BEFORE its nominal start, new insertions go inside it. This is also called Spannable.SPAN_INCLUSIVE_BEFORE. If instead the Spannable.SPAN_STARTS_AFTER its nominal start, the insertions go outside it, also known as Spannable.SPAN_EXCLUSIVE_BEFORE.

Similarly, if a Spannable.SPAN_ENDS_AFTER its nominal end, new insertions at the end go inside it, making the Spannable.SPAN_INCLUSIVE_AFTER. If instead the Spannable.SPAN_ENDS_BEFORE its nominal end, insertions go outside it, and it is Spannable.SPAN_EXCLUSIVE_AFTER.

It is usually more convenient to specify the behavior on both ends with a single constant; hence Spannable.SPAN_INCLUSIVE_INCLUSIVE (inclusive on both ends), Spannable.SPAN_INCLUSIVE_EXCLUSIVE (inclusive before, exclusive after), Spannable.SPAN_EXCLUSIVE_INCLUSIVE (exclusive before, inclusive after}, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE (exclusive on both ends).

XEmacs extents use the term "open" for what I call exclusive and "closed" for what I call inclusive. This makes sense if you are a mathematically-minded person and are thinking of sets, but I avoided the terms because I keep thinking "open" means "can accept more" and "closed" means "is already complete," which is backwards.

You might think that if you have a zero-length span that is inclusive-after and that you make an insertion after it, the insertion would be included in the span. Similarly for inserting before an inclusive-before span. This is in fact what happens if the span is inclusive on both ends.

However, since inclusive-before is implemented in terms of starts-before and inclusive-after is implemented in terms of ends-before, when you have a zero-length inclusive-exclusive or exclusive-inclusive span, the start and end are both at the same position, either before or after the point, so the insertion happens outside the span, either before or after it. This may not be what you want to happen, but it is useful for setting marks within the text. Spannable.SPAN_MARKLIKE means starts-before and ends-before, and if you set a zero-length one of these, it stays where you put it when you insert near it. Spannable.SPAN_POINTLIKE, on the other hand, means starts-after and ends-after, so if you insert near one of these, you push it forward.

If it is in fact not what you want, you can use the Spannable.SPAN_GROW_FROM_ZERO flag, in which case a span that is zero-length and inclusive-after will grow to include a character inserted after it, and one that is zero-length and inclusive-before will grow to include a character inserted before it.

It is not possible to have a zero-length exclusive-exclusive span because that means it ends before it starts. If you try to create such a span in a TextBuffer it will throw an exception, and if through editing an exclusive-exclusive becomes zero-length, it disappears.

You can also use the Spannable.SPAN_DELETE_ON_EMPTY flag if you want an inclusive-inclusive, inclusive-exclusive, or exclusive-inclusive span to be removed when all of the text it covers is deleted, even though it could survive with a length of zero.

The final currently-defined flag is Spannable.SPAN_PARAGRAPH, details of which can be found in its own definition. Use this flag if your span needs to stay attached to paragraph boundaries, not merely character boundaries.

All of the above applies to inserting, not to concatenation. When you concatenate two Spanneds, the span bounds all stay where they were before you concatenated them. Inclusive-after spans at the end of the first Spanned do not grow to cover the second, nor do inclusive-before spans at the start of the second Spanned grow to cover the first.

Specified by:
setSpan in interface Spannable

removeSpan

public void removeSpan(Object key)
Description copied from interface: Spannable
Remove the span with the specified key from this buffer. If there was not already a span with this key, nothing happens.

Specified by:
removeSpan in interface Spannable

charAt

public char charAt(int i)
Return the character at the specified offset. This calls through to String.charAt() on the underlying string.

Specified by:
charAt in interface CharSequence

length

public int length()
Return the length of the underlying String.

Specified by:
length in interface CharSequence

subSequence

public CharSequence subSequence(int start,
                                int end)
Return a new SpannableString containing a copy of the specified range of this object.

Specified by:
subSequence in interface CharSequence

toString

public String toString()
Return the String underlying this object.

Specified by:
toString in interface CharSequence
Overrides:
toString in class Object

getChars

public void getChars(int start,
                     int end,
                     char[] dest,
                     int destoff)
Specified by:
getChars in interface GetChars

getSpanStart

public int getSpanStart(Object key)
Description copied from interface: Spanned
Return the starting offset of the specified span within the buffer, or -1 if there is no such span attached.

Specified by:
getSpanStart in interface Spanned

getSpanEnd

public int getSpanEnd(Object key)
Description copied from interface: Spanned
Return the ending offset of the specified span within the buffer, or -1 if there is no such span attached.

Specified by:
getSpanEnd in interface Spanned

getSpanFlags

public int getSpanFlags(Object key)
Description copied from interface: Spanned
Return the flags that were specified when the specified span was attached to the buffer, or 0 if there is no such span attached.

Specified by:
getSpanFlags in interface Spanned

nextSpanTransition

public int nextSpanTransition(int offset,
                              int limit,
                              Class kind)
Description copied from interface: Spanned
Find the first offset in the buffer greater than the specified offset but less than or equal to the specified limit where a span of the specified kind (according to Class.isInstanceOf()) begins or ends. You can specify a null kind if you want the next span transition of any type.

Specified by:
nextSpanTransition in interface Spanned

getSpansOverlapping

public Object[] getSpansOverlapping(int start,
                                    int end,
                                    Class kind)
Description copied from interface: Spanned
Return an array of the keys of the spans of the specified kind (according to Class.isInstanceOf()) that overlap the specified range of buffer offsets, or null if no such spans are attached or overlap. You can specify a null kind if you want the list of spans overlapping of any type.

Specified by:
getSpansOverlapping in interface Spanned

getAllSpans

public Object[] getAllSpans(Class kind)
Specified by:
getAllSpans in interface Spanned