下面列出了怎么用java.text.AttributedCharacterIterator.Attribute的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Extract a GraphicAttribute or Font from the given attributes.
* If attributes does not contain a GraphicAttribute, Font, or
* Font family entry this method returns null.
*/
private static Object getGraphicOrFont(
Map<? extends Attribute, ?> attributes) {
Object value = attributes.get(TextAttribute.CHAR_REPLACEMENT);
if (value != null) {
return value;
}
value = attributes.get(TextAttribute.FONT);
if (value != null) {
return value;
}
if (attributes.get(TextAttribute.FAMILY) != null) {
return Font.getFont(attributes);
}
else {
return null;
}
}
/**
* Tell the component to commit all of the characters in the string to the current
* text view. This effectively wipes out any text in progress.
*/
synchronized private void insertText(String aString) {
AttributedString attribString = new AttributedString(aString);
// Set locale information on the new string.
attribString.addAttribute(Attribute.LANGUAGE, getLocale(), 0, aString.length());
TextHitInfo theCaret = TextHitInfo.afterOffset(aString.length() - 1);
InputMethodEvent event = new InputMethodEvent(fAwtFocussedComponent,
InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
attribString.getIterator(),
aString.length(),
theCaret,
theCaret);
LWCToolkit.postEvent(LWCToolkit.targetToAppContext(fAwtFocussedComponent), event);
fCurrentText = null;
fCurrentTextAsString = null;
fCurrentTextLength = 0;
}
/**
* Extract a GraphicAttribute or Font from the given attributes.
* If attributes does not contain a GraphicAttribute, Font, or
* Font family entry this method returns null.
*/
private static Object getGraphicOrFont(
Map<? extends Attribute, ?> attributes) {
Object value = attributes.get(TextAttribute.CHAR_REPLACEMENT);
if (value != null) {
return value;
}
value = attributes.get(TextAttribute.FONT);
if (value != null) {
return value;
}
if (attributes.get(TextAttribute.FAMILY) != null) {
return Font.getFont(attributes);
}
else {
return null;
}
}
public int getRunStart(Set<? extends Attribute> attributes) {
if (currentRunStart == beginIndex || currentRunIndex == -1) {
return currentRunStart;
} else {
int runStart = currentRunStart;
int runIndex = currentRunIndex;
while (runStart > beginIndex &&
AttributedString.this.attributeValuesMatch(attributes, currentRunIndex, runIndex - 1)) {
runIndex--;
runStart = runStarts[runIndex];
}
if (runStart < beginIndex) {
runStart = beginIndex;
}
return runStart;
}
}
public int getRunLimit(Attribute attribute) {
if (currentRunLimit == endIndex || currentRunIndex == -1) {
return currentRunLimit;
} else {
Object value = getAttribute(attribute);
int runLimit = currentRunLimit;
int runIndex = currentRunIndex;
while (runLimit < endIndex &&
valuesMatch(value, AttributedString.this.getAttribute(attribute, runIndex + 1))) {
runIndex++;
runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex;
}
if (runLimit > endIndex) {
runLimit = endIndex;
}
return runLimit;
}
}
public Set<Map.Entry<Attribute, Object>> entrySet() {
HashSet<Map.Entry<Attribute, Object>> set = new HashSet<>();
synchronized (AttributedString.this) {
int size = runAttributes[runIndex].size();
for (int i = 0; i < size; i++) {
Attribute key = runAttributes[runIndex].get(i);
Object value = runAttributeValues[runIndex].get(i);
if (value instanceof Annotation) {
value = AttributedString.this.getAttributeCheckRange(key,
runIndex, beginIndex, endIndex);
if (value == null) {
continue;
}
}
Map.Entry<Attribute, Object> entry = new AttributeEntry(key, value);
set.add(entry);
}
}
return set;
}
public int getRunStart(Attribute attribute) {
if (currentRunStart == beginIndex || currentRunIndex == -1) {
return currentRunStart;
} else {
Object value = getAttribute(attribute);
int runStart = currentRunStart;
int runIndex = currentRunIndex;
while (runStart > beginIndex &&
valuesMatch(value, AttributedString.this.getAttribute(attribute, runIndex - 1))) {
runIndex--;
runStart = runStarts[runIndex];
}
if (runStart < beginIndex) {
runStart = beginIndex;
}
return runStart;
}
}
public AttributeValues merge(Map<? extends Attribute, ?>map,
int mask) {
if (map instanceof AttributeMap &&
((AttributeMap) map).getValues() != null) {
merge(((AttributeMap)map).getValues(), mask);
} else if (map != null && !map.isEmpty()) {
for (Map.Entry<? extends Attribute, ?> e: map.entrySet()) {
try {
EAttribute ea = EAttribute.forAttribute(e.getKey());
if (ea!= null && (mask & ea.mask) != 0) {
set(ea, e.getValue());
}
} catch (ClassCastException cce) {
// IGNORED
}
}
}
return this;
}
public int getRunStart(Set<? extends Attribute> attributes) {
if (currentRunStart == beginIndex || currentRunIndex == -1) {
return currentRunStart;
} else {
int runStart = currentRunStart;
int runIndex = currentRunIndex;
while (runStart > beginIndex &&
AttributedString.this.attributeValuesMatch(attributes, currentRunIndex, runIndex - 1)) {
runIndex--;
runStart = runStarts[runIndex];
}
if (runStart < beginIndex) {
runStart = beginIndex;
}
return runStart;
}
}
public int getRunLimit(Set<? extends Attribute> attributes) {
if (currentRunLimit == endIndex || currentRunIndex == -1) {
return currentRunLimit;
} else {
int runLimit = currentRunLimit;
int runIndex = currentRunIndex;
while (runLimit < endIndex &&
AttributedString.this.attributeValuesMatch(attributes, currentRunIndex, runIndex + 1)) {
runIndex++;
runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex;
}
if (runLimit > endIndex) {
runLimit = endIndex;
}
return runLimit;
}
}
/**
* Constructs a <code>TextLayout</code> from a <code>String</code>
* and an attribute set.
* <p>
* All the text is styled using the provided attributes.
* <p>
* <code>string</code> must specify a single paragraph of text because an
* entire paragraph is required for the bidirectional algorithm.
* @param string the text to display
* @param attributes the attributes used to style the text
* @param frc contains information about a graphics device which is needed
* to measure the text correctly.
* Text measurements can vary slightly depending on the
* device resolution, and attributes such as antialiasing. This
* parameter does not specify a translation between the
* <code>TextLayout</code> and user space.
*/
public TextLayout(String string, Map<? extends Attribute,?> attributes,
FontRenderContext frc)
{
if (string == null) {
throw new IllegalArgumentException("Null string passed to TextLayout constructor.");
}
if (attributes == null) {
throw new IllegalArgumentException("Null map passed to TextLayout constructor.");
}
if (string.length() == 0) {
throw new IllegalArgumentException("Zero length string passed to TextLayout constructor.");
}
char[] text = string.toCharArray();
Font font = singleFont(text, 0, text.length, attributes);
if (font != null) {
fastInit(text, font, attributes, frc);
} else {
AttributedString as = new AttributedString(string, attributes);
standardInit(as.getIterator(), text, frc);
}
}
public int getRunLimit(Set<? extends Attribute> attributes) {
if (currentRunLimit == endIndex || currentRunIndex == -1) {
return currentRunLimit;
} else {
int runLimit = currentRunLimit;
int runIndex = currentRunIndex;
while (runLimit < endIndex &&
AttributedString.this.attributeValuesMatch(attributes, currentRunIndex, runIndex + 1)) {
runIndex++;
runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex;
}
if (runLimit > endIndex) {
runLimit = endIndex;
}
return runLimit;
}
}
public Set<Map.Entry<Attribute, Object>> entrySet() {
HashSet<Map.Entry<Attribute, Object>> set = new HashSet<>();
synchronized (AttributedString.this) {
int size = runAttributes[runIndex].size();
for (int i = 0; i < size; i++) {
Attribute key = runAttributes[runIndex].get(i);
Object value = runAttributeValues[runIndex].get(i);
if (value instanceof Annotation) {
value = AttributedString.this.getAttributeCheckRange(key,
runIndex, beginIndex, endIndex);
if (value == null) {
continue;
}
}
Map.Entry<Attribute, Object> entry = new AttributeEntry(key, value);
set.add(entry);
}
}
return set;
}
/**
* Selects the passed in field, returning true if it is found,
* false otherwise.
*/
private boolean select(final JFormattedTextField ftf, final AttributedCharacterIterator iterator, final DateFormat.Field field) {
final int max = ftf.getDocument().getLength();
iterator.first();
do {
final Map<Attribute,Object> attrs = iterator.getAttributes();
if (attrs == null || !attrs.containsKey(field)) continue;
final int start = iterator.getRunStart(field);
final int end = iterator.getRunLimit(field);
if (start != -1 && end != -1 && start <= max && end <= max) {
ftf.select(start, end);
}
return true;
} while (iterator.next() != CharacterIterator.DONE);
return false;
}
/**
* Returns the <code>Format.Field</code> constants associated with
* the text at <code>offset</code>. If <code>offset</code> is not
* a valid location into the current text, this will return an
* empty array.
*
* @param offset offset into text to be examined
* @return Format.Field constants associated with the text at the
* given position.
*/
public Format.Field[] getFields(int offset) {
if (getAllowsInvalid()) {
// This will work if the currently edited value is valid.
updateMask();
}
Map<Attribute, Object> attrs = getAttributes(offset);
if (attrs != null && attrs.size() > 0) {
ArrayList<Attribute> al = new ArrayList<Attribute>();
al.addAll(attrs.keySet());
return al.toArray(EMPTY_FIELD_ARRAY);
}
return EMPTY_FIELD_ARRAY;
}
public int getRunLimit(Set<? extends Attribute> attributes) {
if (currentRunLimit == endIndex || currentRunIndex == -1) {
return currentRunLimit;
} else {
int runLimit = currentRunLimit;
int runIndex = currentRunIndex;
while (runLimit < endIndex &&
AttributedString.this.attributeValuesMatch(attributes, currentRunIndex, runIndex + 1)) {
runIndex++;
runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex;
}
if (runLimit > endIndex) {
runLimit = endIndex;
}
return runLimit;
}
}
/**
* Returns the number of occurrences of <code>f</code> before
* the location <code>start</code> in the current
* <code>AttributedCharacterIterator</code>.
*/
private int getFieldTypeCountTo(Object f, int start) {
AttributedCharacterIterator iterator = getIterator();
int count = 0;
if (iterator != null &&
(f instanceof AttributedCharacterIterator.Attribute)) {
AttributedCharacterIterator.Attribute field =
(AttributedCharacterIterator.Attribute)f;
iterator.first();
while (iterator.getIndex() < start) {
while (iterator.getAttribute(field) == null &&
iterator.next() != CharacterIterator.DONE);
if (iterator.current() != CharacterIterator.DONE) {
iterator.setIndex(iterator.getRunLimit(field));
iterator.next();
count++;
}
else {
break;
}
}
}
return count;
}
public int getRunStart(Attribute attribute) {
if (currentRunStart == beginIndex || currentRunIndex == -1) {
return currentRunStart;
} else {
Object value = getAttribute(attribute);
int runStart = currentRunStart;
int runIndex = currentRunIndex;
while (runStart > beginIndex &&
valuesMatch(value, AttributedString.this.getAttribute(attribute, runIndex - 1))) {
runIndex--;
runStart = runStarts[runIndex];
}
if (runStart < beginIndex) {
runStart = beginIndex;
}
return runStart;
}
}
/**
* Constructs a <code>TextLayout</code> from a <code>String</code>
* and an attribute set.
* <p>
* All the text is styled using the provided attributes.
* <p>
* <code>string</code> must specify a single paragraph of text because an
* entire paragraph is required for the bidirectional algorithm.
* @param string the text to display
* @param attributes the attributes used to style the text
* @param frc contains information about a graphics device which is needed
* to measure the text correctly.
* Text measurements can vary slightly depending on the
* device resolution, and attributes such as antialiasing. This
* parameter does not specify a translation between the
* <code>TextLayout</code> and user space.
*/
public TextLayout(String string, Map<? extends Attribute,?> attributes,
FontRenderContext frc)
{
if (string == null) {
throw new IllegalArgumentException("Null string passed to TextLayout constructor.");
}
if (attributes == null) {
throw new IllegalArgumentException("Null map passed to TextLayout constructor.");
}
if (string.length() == 0) {
throw new IllegalArgumentException("Zero length string passed to TextLayout constructor.");
}
char[] text = string.toCharArray();
Font font = singleFont(text, 0, text.length, attributes);
if (font != null) {
fastInit(text, font, attributes, frc);
} else {
AttributedString as = new AttributedString(string, attributes);
standardInit(as.getIterator(), text, frc);
}
}
/**
* Sets the attributes for the range from offset to the next run break
* (typically the end of the text) to the ones specified in attrs.
* This is only meant to be called from the constructor!
*/
private void setAttributes(Map<Attribute, Object> attrs, int offset) {
if (runCount == 0) {
createRunAttributeDataVectors();
}
int index = ensureRunBreak(offset, false);
int size;
if (attrs != null && (size = attrs.size()) > 0) {
Vector<Attribute> runAttrs = new Vector<>(size);
Vector<Object> runValues = new Vector<>(size);
Iterator<Map.Entry<Attribute, Object>> iterator = attrs.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Attribute, Object> entry = iterator.next();
runAttrs.add(entry.getKey());
runValues.add(entry.getValue());
}
runAttributes[index] = runAttrs;
runAttributeValues[index] = runValues;
}
}
private final void createRunAttributeDataVectors() {
// use temporary variables so things remain consistent in case of an exception
int newRunStarts[] = new int[ARRAY_SIZE_INCREMENT];
@SuppressWarnings("unchecked")
Vector<Attribute> newRunAttributes[] = (Vector<Attribute>[]) new Vector<?>[ARRAY_SIZE_INCREMENT];
@SuppressWarnings("unchecked")
Vector<Object> newRunAttributeValues[] = (Vector<Object>[]) new Vector<?>[ARRAY_SIZE_INCREMENT];
runStarts = newRunStarts;
runAttributes = newRunAttributes;
runAttributeValues = newRunAttributeValues;
runArraySize = ARRAY_SIZE_INCREMENT;
runCount = 1; // assume initial run starting at index 0
}
/**
* Constructs a <code>TextLayout</code> from a <code>String</code>
* and a {@link Font}. All the text is styled using the specified
* <code>Font</code>.
* <p>
* The <code>String</code> must specify a single paragraph of text,
* because an entire paragraph is required for the bidirectional
* algorithm.
* @param string the text to display
* @param font a <code>Font</code> used to style the text
* @param frc contains information about a graphics device which is needed
* to measure the text correctly.
* Text measurements can vary slightly depending on the
* device resolution, and attributes such as antialiasing. This
* parameter does not specify a translation between the
* <code>TextLayout</code> and user space.
*/
public TextLayout(String string, Font font, FontRenderContext frc) {
if (font == null) {
throw new IllegalArgumentException("Null font passed to TextLayout constructor.");
}
if (string == null) {
throw new IllegalArgumentException("Null string passed to TextLayout constructor.");
}
if (string.length() == 0) {
throw new IllegalArgumentException("Zero length string passed to TextLayout constructor.");
}
Map<? extends Attribute, ?> attributes = null;
if (font.hasLayoutAttributes()) {
attributes = font.getAttributes();
}
char[] text = string.toCharArray();
if (sameBaselineUpTo(font, text, 0, text.length) == text.length) {
fastInit(text, font, attributes, frc);
} else {
AttributedString as = attributes == null
? new AttributedString(string)
: new AttributedString(string, attributes);
as.addAttribute(TextAttribute.FONT, font);
standardInit(as.getIterator(), text, frc);
}
}
public AttributedCharacterIterator getCommittedText(int beginIndex,
int endIndex, Attribute[] attributes) {
int composedStartIndex = 0;
int composedEndIndex = 0;
if (composedTextExists()) {
composedStartIndex = composedTextStart.getOffset();
composedEndIndex = composedTextEnd.getOffset();
}
String committed;
try {
if (beginIndex < composedStartIndex) {
if (endIndex <= composedStartIndex) {
committed = getText(beginIndex, endIndex - beginIndex);
} else {
int firstPartLength = composedStartIndex - beginIndex;
committed = getText(beginIndex, firstPartLength) +
getText(composedEndIndex, endIndex - beginIndex - firstPartLength);
}
} else {
committed = getText(beginIndex + (composedEndIndex - composedStartIndex),
endIndex - beginIndex);
}
} catch (BadLocationException ble) {
throw new IllegalArgumentException("Invalid range");
}
return new AttributedString(committed).getIterator();
}
/**
* Constructs a <code>TextLayout</code> from an iterator over styled text.
* <p>
* The iterator must specify a single paragraph of text because an
* entire paragraph is required for the bidirectional
* algorithm.
* @param text the styled text to display
* @param frc contains information about a graphics device which is needed
* to measure the text correctly.
* Text measurements can vary slightly depending on the
* device resolution, and attributes such as antialiasing. This
* parameter does not specify a translation between the
* <code>TextLayout</code> and user space.
*/
public TextLayout(AttributedCharacterIterator text, FontRenderContext frc) {
if (text == null) {
throw new IllegalArgumentException("Null iterator passed to TextLayout constructor.");
}
int start = text.getBeginIndex();
int limit = text.getEndIndex();
if (start == limit) {
throw new IllegalArgumentException("Zero length iterator passed to TextLayout constructor.");
}
int len = limit - start;
text.first();
char[] chars = new char[len];
int n = 0;
for (char c = text.first();
c != CharacterIterator.DONE;
c = text.next())
{
chars[n++] = c;
}
text.first();
if (text.getRunLimit() == limit) {
Map<? extends Attribute, ?> attributes = text.getAttributes();
Font font = singleFont(chars, 0, len, attributes);
if (font != null) {
fastInit(chars, font, attributes, frc);
return;
}
}
standardInit(text, chars, frc);
}
/**
* Adds an attribute to the entire string.
* @param attribute the attribute key
* @param value the value of the attribute; may be null
* @exception NullPointerException if <code>attribute</code> is null.
* @exception IllegalArgumentException if the AttributedString has length 0
* (attributes cannot be applied to a 0-length range).
*/
public void addAttribute(Attribute attribute, Object value) {
if (attribute == null) {
throw new NullPointerException();
}
int len = length();
if (len == 0) {
throw new IllegalArgumentException("Can't add attribute to 0-length text");
}
addAttributeImpl(attribute, value, 0, len);
}
public Set<Attribute> getAllAttributeKeys() {
// ??? This should screen out attribute keys that aren't relevant to the client
if (runAttributes == null) {
// ??? would be nice to return null, but current spec doesn't allow it
// returning HashSet saves us from dealing with emptiness
return new HashSet<>();
}
synchronized (AttributedString.this) {
// ??? should try to create this only once, then update if necessary,
// and give callers read-only view
Set<Attribute> keys = new HashSet<>();
int i = 0;
while (i < runCount) {
if (runStarts[i] < endIndex && (i == runCount - 1 || runStarts[i + 1] > beginIndex)) {
Vector<Attribute> currentRunAttributes = runAttributes[i];
if (currentRunAttributes != null) {
int j = currentRunAttributes.size();
while (j-- > 0) {
keys.add(currentRunAttributes.get(j));
}
}
}
i++;
}
return keys;
}
}
static Attribute doSerializationCycle(Attribute attribute) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(attribute);
oos.flush();
byte[] data = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(bais);
Attribute result = (Attribute) ois.readObject();
return result;
}
private synchronized Object getAttribute(Attribute attribute, int runIndex) {
Vector<Attribute> currentRunAttributes = runAttributes[runIndex];
Vector<Object> currentRunAttributeValues = runAttributeValues[runIndex];
if (currentRunAttributes == null) {
return null;
}
int attributeIndex = currentRunAttributes.indexOf(attribute);
if (attributeIndex != -1) {
return currentRunAttributeValues.elementAt(attributeIndex);
}
else {
return null;
}
}
private boolean attributeValuesMatch(Set<? extends Attribute> attributes, int runIndex1, int runIndex2) {
Iterator<? extends Attribute> iterator = attributes.iterator();
while (iterator.hasNext()) {
Attribute key = iterator.next();
if (!valuesMatch(getAttribute(key, runIndex1), getAttribute(key, runIndex2))) {
return false;
}
}
return true;
}
public static AffineTransform getBaselineTransform(Map<?, ?> map) {
if (map != null) {
AttributeValues av = null;
if (map instanceof AttributeMap &&
((AttributeMap) map).getValues() != null) {
av = ((AttributeMap)map).getValues();
} else if (map.get(TextAttribute.TRANSFORM) != null) {
av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck
}
if (av != null) {
return av.baselineTransform;
}
}
return null;
}