📄 attributedstring.java
字号:
/* * @(#)AttributedString.java 1.33 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.text;import java.util.*;import java.text.AttributedCharacterIterator.Attribute;/*** An AttributedString holds text and related attribute information. It* may be used as the actual data storage in some cases where a text* reader wants to access attributed text through the AttributedCharacterIterator* interface.** @see AttributedCharacterIterator* @see Annotation* @since 1.2*/public class AttributedString { // since there are no vectors of int, we have to use arrays. // We allocate them in chunks of 10 elements so we don't have to allocate all the time. private static final int ARRAY_SIZE_INCREMENT = 10; // field holding the text String text; // fields holding run attribute information // run attributes are organized by run int runArraySize; // current size of the arrays int runCount; // actual number of runs, <= runArraySize int runStarts[]; // start index for each run Vector runAttributes[]; // vector of attribute keys for each run Vector runAttributeValues[]; // parallel vector of attribute values for each run /** * Constructs an AttributedString instance with the given * AttributedCharacterIterators. * * @param iterators AttributedCharacterIterators to construct * AttributedString from. * @throws NullPointerException if iterators is null */ AttributedString(AttributedCharacterIterator[] iterators) { if (iterators == null) { throw new NullPointerException("Iterators must not be null"); } if (iterators.length == 0) { text = ""; } else { // Build the String contents StringBuffer buffer = new StringBuffer(); for (int counter = 0; counter < iterators.length; counter++) { appendContents(buffer, iterators[counter]); } text = buffer.toString(); if (text.length() > 0) { // Determine the runs, creating a new run when the attributes // differ. int offset = 0; Map last = null; for (int counter = 0; counter < iterators.length; counter++) { AttributedCharacterIterator iterator = iterators[counter]; int start = iterator.getBeginIndex(); int end = iterator.getEndIndex(); int index = start; while (index < end) { iterator.setIndex(index); Map attrs = iterator.getAttributes(); if (mapsDiffer(last, attrs)) { setAttributes(attrs, index - start + offset); } last = attrs; index = iterator.getRunLimit(); } offset += (end - start); } } } } /** * Constructs an AttributedString instance with the given text. * @param text The text for this attributed string. */ public AttributedString(String text) { if (text == null) { throw new NullPointerException(); } this.text = text; } /** * Constructs an AttributedString instance with the given text and attributes. * @param text The text for this attributed string. * @param attributes The attributes that apply to the entire string. * @exception IllegalArgumentException if the text has length 0 * and the attributes parameter is not an empty Map (attributes * cannot be applied to a 0-length range). */ public AttributedString(String text, Map attributes) { if (text == null || attributes == null) { throw new NullPointerException(); } this.text = text; if (text.length() == 0) { if (attributes.isEmpty()) return; throw new IllegalArgumentException("Can't add attribute to 0-length text"); } int attributeCount = attributes.size(); if (attributeCount > 0) { createRunAttributeDataVectors(); Vector newRunAttributes = new Vector(attributeCount); Vector newRunAttributeValues = new Vector(attributeCount); runAttributes[0] = newRunAttributes; runAttributeValues[0] = newRunAttributeValues; Iterator iterator = attributes.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); newRunAttributes.addElement(entry.getKey()); newRunAttributeValues.addElement(entry.getValue()); } } } /** * Constructs an AttributedString instance with the given attributed * text represented by AttributedCharacterIterator. * @param text The text for this attributed string. */ public AttributedString(AttributedCharacterIterator text) { // If performance is critical, this constructor should be // implemented here rather than invoking the constructor for a // subrange. We can avoid some range checking in the loops. this(text, text.getBeginIndex(), text.getEndIndex(), null); } /** * Constructs an AttributedString instance with the subrange of * the given attributed text represented by * AttributedCharacterIterator. If the given range produces an * empty text, all attributes will be discarded. Note that any * attributes wrapped by an Annotation object are discarded for a * subrange of the original attribute range. * * @param text The text for this attributed string. * @param beginIndex Index of the first character of the range. * @param endIndex Index of the character following the last character * of the range. * @exception IllegalArgumentException if the subrange given by * beginIndex and endIndex is out of the text range. * @see java.text.Annotation */ public AttributedString(AttributedCharacterIterator text, int beginIndex, int endIndex) { this(text, beginIndex, endIndex, null); } /** * Constructs an AttributedString instance with the subrange of * the given attributed text represented by * AttributedCharacterIterator. Only attributes that match the * given attributes will be incorporated into the instance. If the * given range produces an empty text, all attributes will be * discarded. Note that any attributes wrapped by an Annotation * object are discarded for a subrange of the original attribute * range. * * @param text The text for this attributed string. * @param beginIndex Index of the first character of the range. * @param endIndex Index of the character following the last character * of the range. * @param attributes Specifies attributes to be extracted * from the text. If null is specified, all available attributes will * be used. * @exception IllegalArgumentException if the subrange given by * beginIndex and endIndex is out of the text range. * @see java.text.Annotation */ public AttributedString(AttributedCharacterIterator text, int beginIndex, int endIndex, Attribute[] attributes) { if (text == null) { throw new NullPointerException(); } // Validate the given subrange int textBeginIndex = text.getBeginIndex(); int textEndIndex = text.getEndIndex(); if (beginIndex < textBeginIndex || endIndex > textEndIndex || beginIndex > endIndex) throw new IllegalArgumentException("Invalid substring range"); // Copy the given string StringBuffer textBuffer = new StringBuffer(); text.setIndex(beginIndex); for (char c = text.current(); text.getIndex() < endIndex; c = text.next()) textBuffer.append(c); this.text = textBuffer.toString(); if (beginIndex == endIndex) return; // Select attribute keys to be taken care of HashSet keys = new HashSet(); if (attributes == null) { keys.addAll(text.getAllAttributeKeys()); } else { for (int i = 0; i < attributes.length; i++) keys.add(attributes[i]); keys.retainAll(text.getAllAttributeKeys()); } if (keys.isEmpty()) return; // Get and set attribute runs for each attribute name. Need to // scan from the top of the text so that we can discard any // Annotation that is no longer applied to a subset text segment. Iterator itr = keys.iterator(); while (itr.hasNext()) { Attribute attributeKey = (Attribute)itr.next(); text.setIndex(textBeginIndex); while (text.getIndex() < endIndex) { int start = text.getRunStart(attributeKey); int limit = text.getRunLimit(attributeKey); Object value = text.getAttribute(attributeKey); if (value != null) { if (value instanceof Annotation) { if (start >= beginIndex && limit <= endIndex) { addAttribute(attributeKey, value, start - beginIndex, limit - beginIndex); } else { if (limit > endIndex) break; } } else { // if the run is beyond the given (subset) range, we // don't need to process further. if (start >= endIndex) break; if (limit > beginIndex) { // attribute is applied to any subrange if (start < beginIndex) start = beginIndex; if (limit > endIndex) limit = endIndex; if (start != limit) { addAttribute(attributeKey, value, start - beginIndex, limit - beginIndex); } } } } text.setIndex(limit); } } } /** * Adds an attribute to the entire string. * @param attribute the attribute key * @param value the value of the attribute; may be 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); } /** * Adds an attribute to a subrange of the string. * @param attribute the attribute key * @param value The value of the attribute. May be null. * @param beginIndex Index of the first character of the range. * @param endIndex Index of the character following the last character of the range. * @exception IllegalArgumentException if beginIndex is less then 0, endIndex is * greater than the length of the string, or beginIndex and endIndex together don't * define a non-empty subrange of the string. */ public void addAttribute(Attribute attribute, Object value, int beginIndex, int endIndex) { if (attribute == null) { throw new NullPointerException(); } if (beginIndex < 0 || endIndex > length() || beginIndex >= endIndex) { throw new IllegalArgumentException("Invalid substring range"); } addAttributeImpl(attribute, value, beginIndex, endIndex); } /** * Adds a set of attributes to a subrange of the string. * @param attributes The attributes to be added to the string. * @param beginIndex Index of the first character of the range. * @param endIndex Index of the character following the last * character of the range. * @exception IllegalArgumentException if beginIndex is less then * 0, endIndex is greater than the length of the string, or * beginIndex and endIndex together don't define a non-empty * subrange of the string and the attributes parameter is not an * empty Map. */ public void addAttributes(Map attributes, int beginIndex, int endIndex) { if (attributes == null) { throw new NullPointerException(); } if (beginIndex < 0 || endIndex > length() || beginIndex > endIndex) { throw new IllegalArgumentException("Invalid substring range"); } if (beginIndex == endIndex) { if (attributes.isEmpty()) return; throw new IllegalArgumentException("Can't add attribute to 0-length text"); } // make sure we have run attribute data vectors if (runCount == 0) { createRunAttributeDataVectors(); } // break up runs if necessary int beginRunIndex = ensureRunBreak(beginIndex); int endRunIndex = ensureRunBreak(endIndex); Iterator iterator = attributes.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); addAttributeRunData((Attribute) entry.getKey(), entry.getValue(), beginRunIndex, endRunIndex); } } private synchronized void addAttributeImpl(Attribute attribute, Object value,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -