Package danger.text.span

Danger Text System Overview This documents the design and intent of the Danger device text system as well as the specific classes in the danger.text.span package.

See:
          Description

Interface Summary
AlignmentSpan Implementations of AlignmentSpan change the alignment of the lines of text that they cover.
Anchored Classes should implement this interface if they can contain named anchors (see AnchorSpan) that the user can jump to.
AnchorSpan Implementations of AnchorSpan provide named anchors within the text.
AtomicSpan Spans that behave as a unit should implement this interface so EditText will not allow the insertion point or selection end to be positioned in the middle of the span and will delete its contents as a unit if backspaced over.
BaselineShiftSpan Implementations of BaselineShiftSpan cause the text baseline to be shifted upward or downward.
CharacterHeightAffectingSpan Implementations of CharacterHeightAffectingSpan affect the height of the characters they cover.
CharacterSpan All character-oriented text formatting spans implement CharacterSpan.
ClickableSpan This class represents a range of text that can be selected and clicked by the user.
ColorSpan This class changes the foreground or background color (or both) of a range of text.
DrawnSpan Implementations of DrawnSpan get their drawing and measuring functions called when text covered by them is drawn or measured.
FontSpan When a FontSpan is attached to text, it changes its font family or size
HaloSpan This class indicates to the CharacterSpan text-drawing routine that it should draw a halo in the text outline color around the text.
LeftMarginSpan Text covered by implementations of LeftMarginSpan has a left margin.
LineHeightSpan  
MarginHighlightSpan Implement this interface if you want your span to draw in the margins and not just over the characters it covers directly.
MetricAffectingSpan CharacterSpans and ParagraphSpans that affect the width or height of the text or its margins should implement this interface so EditText will know to rewrap when they are added or removed.
ModifierClickableSpan This class is an extension of ClickableSpan that also defines behavior when clicking with a modifier key.
MutableSpan Spans that can be altered after creation should implement this interface so they will be cloned when they are copied from one buffer to another.
OverlaySpan When text to which an OverlaySpan is attached is drawn, the overlay is given a chance to draw afterwards.
ParagraphOverlaySpan When a paragraph to which a ParagraphOverlaySpan is attached is drawn, the overlay is given a chance to draw after each line is drawn.
ParagraphSpan All paragraph-oriented text formatting spans implement ParagraphSpan.
RightMarginSpan Text covered by implementations of RightMarginSpan has a left margin.
Spannable Spannable is the interface for Spanneds that can have spans removed or added.
Spanned Spanned is the interface to sequences of characters to ranges of which objects may have been attached.
SpanWatcherSpan A SpanWatcherSpan is a span that receives notifications when spans overlapping it are added, removed, or moved.
StyleSpan When a StyleSpan is attached to text, it changes its font style.
TabAlignmentSpan Put this span over a tab character and you can choose the alignment of the text that follows the tab.
TabStopSpan Classes that implement TabStopSpan provide tab stops for text.
TextWatcherSpan A TextWatcherSpan is a span that receives notifications when the text underlying the span is changed.
 

Class Summary
AlignmentSpan.Standard Standard implementation of AlignmentSpan, which changes the alignment of the text that it covers.
AnchorSpan.Standard Standard implementation of AnchorSpan, which provides a named anchor within the text.
BaselineShiftSpan.Standard Standard implementation of BaselineShiftSpan to shift the baseline by a specified number of pixels.
BaselineShiftSpan.Subscript Standard implementation of BaselineShiftSpan to create subscript text.
BaselineShiftSpan.Superscript Standard implementation of BaselineShiftSpan to create superscript text.
BitmapSpan This implementation of DrawnSpan draws a Bitmap instead of text.
BulletSpan BulletSpan is a LeftMarginSpan that draws a bullet or a specified string of text in front of the first line it affects.
CharacterSpan.Series Utility functions for drawing and measuring text segments within which CharacterSpans can begin and end.
CharacterSpan.Set Utility functions for drawing and measuring text segments covered by a uniform array of CharacterSpans.
ClickSpan This class represents the range of text that will be activated when the user clicks the wheel button.
ColorSpan.Standard  
DropCapSpan DropCapSpan is a LeftMarginSpan that draws a specified bitmap in front of as much of the paragraph as the bitmap is tall, and then lets the margin width go back to 0.
FontSpan.Standard  
HaloSpan.Standard Standard implementation of HaloSpan.
HTML This utility class parses HTML source and converts as much as possible of the markup into span objects attached to the text.
HTML.Image Any inline images referenced in the HTML source are included in the output as objects of type Image.
LeftMarginSpan.Standard Standard left margin implementation.
MutableColorSpan This class changes the foreground or background color (or both) of a range of text and can be altered after creation.
ParagraphSpan.Set Utility functions for drawing and measuring lines of text covered by a uniform array of ParagraphSpans.
QuoteHackSpan QuoteHackSpan is a ParagraphSpan in which the left margin of each line but the first of each paragraph is made up of the greater-than signs (plus an optional trailing space) that appear at the beginning of the first line of the paragraph.
RightMarginSpan.Standard Standard right margin implementation.
SelectionSpan This class represents the text that has been selected (by shift-arrow movement) within the buffer.
SpannableString SpannableString is a wrapper around String to which spans can be attached.
SpannedString SpannedString is a wrapper around String which may have spans attached to it.
SpanUtils  
StandardSpannable This class implements the standard change notifications and editing fixups that Spannables and editable Spanneds need to do so they don't all have to implement them separately.
StripeSpan StripeSpan is a LeftMarginSpan that draws a blue stripe down the left margin, as is a common convention for quoted text in mail.
StyleSpan.Standard  
TabAlignmentSpan.Standard The standard implementation of TabAlignmentSpan.
TabStopSpan.Standard The standard implementation of TabStopSpan.
Undo This class implements the Undo feature of EditText.
URLSpan A URLSpan is a clickable span that attempts to go to a URL.
 

Package danger.text.span Description

Danger Text System Overview

This documents the design and intent of the Danger device text system as well as the specific classes in the danger.text.span package.

Types

CharSequence

All textual objects on the device implement the standard Java CharSequence interface. At any given moment a given CharSequence contains a particular number of characters (queried with CharSequence.length()) which can be individually retrieved with CharSequence.charAt(int), copied into a String with CharSequence.toString() or segmented with CharSequence.subSequence(int, int).

The best known implementations of CharSequence are the standard Java String and StringBuffer types.

String wrappers

Some CharSequences are just wrappers around String so their CharSequence.toString() method is guaranteed to be fast because it just returns the inner string. You can give some methods a hint that this is the case by making your CharSequence implementation also implement StringWrapper. The SpannedString and SpannableString types that will be described below are examples of StringWrappers.

Spanned

Often it is useful to be able to attach objects to ranges of text. In the Danger text system, CharSequences to which objects may have been attached are of type Spanned (named for the HTML "span" tag). These can be absolutely any objects at all. The text system only pays attention to certain types of attached objects (see below for details), but you may find it useful to attach other objects meaningful to your application.

You can get a list of all objects attached to a Spanned (or all objects of a specified type) with Spanned.getAllSpans(java.lang.Class). You can get a list of the attached objects overlapping a particular range of characters (optionally only those of a specified type) with Spanned.getSpansOverlapping(int, int, java.lang.Class). You can find the next offset where an given type of object begins or ends with Spanned.nextSpanTransition(int, int, java.lang.Class).

Or, to go the other way around, if you have a particular object you can find the character offset where it begins in the text with Spanned.getSpanStart(java.lang.Object) or where it ends with Spanned.getSpanEnd(java.lang.Object). When an object is placed in text, some flags can also be passed in to retain with it (see below); you can retrieve these with Spanned.getSpanFlags(java.lang.Object).

The most common implementation of Spanned is SpannedString, which combines a String with a particular set of objects. The list of objects associated with a SpannedString and their offsets and flags are guaranteed to be constant for the life of the object, as also is the case for the characters because they are a String.

It is worth noting that CharSequence.subSequence(int, int) is not guaranteed to be type-preserving. All standard Danger Spanneds will return another Spanned from subSequence() and you are encouraged to do the same if you define your own.

Spannable

Constant Spanneds are quite useful when you don't want them to change, but if you want a Spanned CharSequence where you can also change what objects are attached to it or where, you want one that implements Spanned.

You can add a new object or move an existing one with Spannable.setSpan(java.lang.Object, int, int, int). You can remove an object with Spannable.removeSpan(java.lang.Object).

All Spannables must be able to generate change notifications. If you attach a SpanWatcherSpan to a Spannable, it will have methods called whenever any object is added to or removed from the Spannable or has its offsets changed. (In modifiable text, however, no notifications will be generated when spans are added through insertion or when their offsets are changed by insertion or deletion, on the theory that these events are sufficiently well covered by the text change notifications that will be described below).

The most common implementation of Spannable is SpannableString, which combines a String with a particular set of objects that can be altered with setSpan() and removeSpan().

Modifiable Spannables

It is often useful to have a CharSequence where not only the span list but also the text can be changed. The standard Danger class that has this property is TextBuffer.

All Spannables in which the text can be changed must be able to generate text change notifications as well as span change notifications. If you attach a TextWatcherSpan to a TextBuffer, it will have its methods called when any text is added, removed, or changed. (As noted above, these insertions and deletions can sometimes cause quiet span changes as well. However, any cases where a span is affected beyond the bounds of the affected text (for example keeping the ends of a span pinned to the edges of a paragraph when a newline is deleted) will always generate explicit span change notifications.)

Most of the flags for Spannable.setSpan(java.lang.Object, int, int, int) are only really meaningful in modifiable text, although you are encouraged to set them sensibly in non-modifable text so they will behave properly if they are copied to a modifiable buffer. They specify what will happen if text is inserted right at the beginning or end of a span (whether it should grow to include the inserted text or not).

Drawing and Measuring CharSequences

You are probably already familiar with the methods Pen.drawText(int, int, java.lang.String) for drawing a sequence of characters in a particular font, Font.getAdvance(java.lang.CharSequence) for measuring the width of a sequence of characters in a particular font, and Font.getAscent() and Font.getDescent() for determining how much vertical space characters in a particular font can occupy.

Because Spanneds can change font in the middle of the sequence (see below for how) there are methods you can call instead that account for this. You can call CharacterSpan.Series.drawText(danger.ui.Pen, int, int, java.lang.CharSequence) to draw a possibly-spanned CharSequence, CharacterSpan.Series.getAdvance(danger.ui.Font, java.lang.CharSequence) to measure the width of a possibly-spanned CharSequence, and CharacterSpan.Series.getVerticalDimensions(danger.ui.Font, java.lang.CharSequence, int, int) to measure the vertical space occupied by a possibly-spanned CharSequence.

Span types that affect character drawing

The spans that affect how characters are drawn are all implementations of CharacterSpan, which has no methods of its own but is the parent of all the character-oriented span types.

You can change the foreground or background color of a range of text by attaching a ColorSpan.

You can change the font or size of a range of text by attaching a FontSpan.

You can change the style of a range of text by attaching a StyleSpan.

You can cause an outline to be drawn behind a range of text by attaching a HaloSpan. (This is just like the outline option to StyleSpan except that it doesn't change the font metrics or shift the baseline so it's easier to fit in with non-halo text).

You can move the baseline of a range of text up or down (for superscript or subscript) with an instance of BaselineShiftSpan.

You can replace a range of text with an image of your choice by attaching a BitmapSpan.

You can specify your own drawing function for a range of text by implementing and attaching some other DrawnSpan.

You can have a drawing function called after the normal text drawing has taken place by implementing and attaching an OverlaySpan.

Breaking text onto multiple lines

All the span types and drawing functions mentioned above are applicable to text that fits on a single line. Often a piece of text won't fit on a single line and has to be wrapped onto multiple lines.

You can have the system break a CharSequence up into multiple lines by using a LineBreaker. It knows about the various span types mentioned above and so will put fewer 12-point characters on a line than 7-point characters, etc.

Drawing text in paragraphs

After a range of text has been broken into multiple lines, there are of course methods to draw the lines. In practice most applications never call these directly; if they are dealing with multiline text they use the text box classes described below. But if you want to do your own drawing, you can certainly call ParagraphSpan.Set.drawText(danger.ui.Pen, int, int, int, int, int, java.lang.CharSequence, int, int, int, int, int, java.lang.Object[], int, int, int, int) to draw a line of text from a possibly-spanned CharSequence, ParagraphSpan.Set.getAdvance(danger.ui.Font, int, java.lang.CharSequence, int, int, int, int, int, int, java.lang.Object[], int, int, int, int) to measure the width of a subsequence of a line of text in a possibly-spanned CharSequence, and ParagraphSpan.Set.getVerticalDimensions(danger.ui.Font, java.lang.CharSequence, int, int, int, java.lang.Object[], int) to measure the vertical space occupied by a line of text in a possibly-spanned CharSequence.

Spans that affect paragraph drawing

The reason for these more complicated methods is that there are additional span types that give you greater control over text formatting in paragraphs. When you attach any of these to a Spannable, you should be careful to make the endpoints be at paragraph boundaries and, if the text is modifiable, to set the Spannable.SPAN_PARAGRAPH flag so its bounds will get moved around according to user expectation when newlines are deleted.

You can attach an AlignmentSpan to set left, right, or center alignment for a particular range of paragraphs.

You can attach a LeftMarginSpan or RightMarginSpan to change the left or right margins for a particular range of paragraphs.

You can attach a TabStopSpan to set tabs stops within a particular range of paragraphs.

You can attach a BulletSpan to put a bullet or other hanging character in the margin at the start of a range of text.

You can attach a DropCapSpan to put an image in the margin at the start of a range of text, with the indent going away after the bottom of the image.

You can attach a StripeSpan to get a blue stripe in the margin as is commonly used to indicate quoting in mail.

You can attach a QuoteHackSpan to get the weird property from mail where any greater-than signs at the start of a paragraph are carried forward onto other lines as well.

You can implement and attach a ParagraphOverlaySpan if you want to draw something on or around the text after it has been drawn.