下面列出了javax.swing.text.Element#getElementCount ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
Document doc = fb.getDocument();
Element root = doc.getDefaultRootElement();
int count = root.getElementCount();
int index = root.getElementIndex(offset);
Element cur = root.getElement(index);
int promptPosition = cur.getStartOffset() + PROMPT.length();
if (index == count - 1 && offset - promptPosition >= 0) {
String str = text;
if (LB.equals(str)) {
String line = doc.getText(promptPosition, offset - promptPosition);
// String[] args = line.split("\\s");
String[] args = Stream.of(line.split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.toArray(String[]::new);
String cmd = args[0];
if (cmd.isEmpty()) {
str = String.format("%n%s", PROMPT);
} else {
str = String.format("%n%s: command not found%n%s", cmd, PROMPT);
}
}
fb.replace(offset, length, str, attrs);
}
}
public void reindent() throws BadLocationException {
Document doc = context.document();
int startOffset = context.startOffset();
int endOffset = context.endOffset();
pushFormattingContextDocument(doc);
try {
// Original formatter does not have reindentation of multiple lines
// so reformat start line and continue for each line.
Element lineRootElem = lineRootElement(doc);
Position endPos = doc.createPosition(endOffset);
do {
startOffset = formatter.indentLine(doc, startOffset);
int startLineIndex = lineRootElem.getElementIndex(startOffset) + 1;
if (startLineIndex >= lineRootElem.getElementCount())
break;
Element lineElem = lineRootElem.getElement(startLineIndex);
startOffset = lineElem.getStartOffset(); // Move to next line
} while (startOffset < endPos.getOffset());
} finally {
popFormattingContextDocument(doc);
}
}
private static void removeTrailingWhitespace(Document doc) throws Exception {
Element lineRoot = DocumentUtilities.getParagraphRootElement(doc);
CharSequence docText = DocumentUtilities.getText(doc);
int lineCount = lineRoot.getElementCount();
for (int i = 0; i < lineCount; i++) {
Element lineElem = lineRoot.getElement(i);
int lineStartOffset = lineElem.getStartOffset();
int lineLastOffset = lineElem.getEndOffset() - 1;
int offset;
for (offset = lineLastOffset - 1; offset >= lineStartOffset; offset--) {
char c = docText.charAt(offset);
// Currently only remove ' ' and '\t' - may be revised
if (c != ' ' && c != '\t') {
break;
}
}
// Increase offset (either below lineStartOffset or on non-white char)
offset++;
if (offset < lineLastOffset) {
doc.remove(offset, lineLastOffset - offset);
}
}
}
public static int getRowStart(Document doc, int offset, int lineShift)
throws BadLocationException {
checkOffsetValid(doc, offset);
if (lineShift != 0) {
Element lineRoot = doc.getDefaultRootElement();
int line = lineRoot.getElementIndex(offset);
line += lineShift;
if (line < 0 || line >= lineRoot.getElementCount()) {
return -1; // invalid line shift
}
return lineRoot.getElement(line).getStartOffset();
} else { // no shift
return doc.getDefaultRootElement().getElement(
doc.getDefaultRootElement().getElementIndex(offset)).getStartOffset();
}
}
@Override
protected void loadChildren(ViewFactory f)
{
if (f == null) { return; }
Element e = getElement();
if (e.getElementCount() > 0)
{
View[] added = new View[1];
// load children (element) using ViewFactory (a new View)
// elements should contain only 1 LeafElement
added[0] = f.create(e.getElement(0));
replace(0, 1, added);
}
}
private static Element findFirstElement(Element e, String name) {
String elementName = e.getName();
if (elementName != null && elementName.equalsIgnoreCase(name)) {
return e;
}
for (int i = 0; i < e.getElementCount(); i++) {
Element result = findFirstElement(e.getElement(i), name);
if (result != null) {
return result;
}
}
return null;
}
public static VectorX<Element> findChild(Element e
, Attribute ab, String value){
VectorX<Element> vE= new VectorX<Element>(Element.class);
int count = e.getElementCount();
for (int i = 0; i < count; i++) {
Element c = e.getElement(i);
AttributeSet mAb = c.getAttributes();
if (mAb.containsAttribute(HTML.Attribute.ID, value))
vE.add(c);
}
return vE;
}
/**
* Load the children in the selected range of offsets.
* <br>
* Some implementations may reload all the present children if necessary.
*
* @param index index at which the views should be added/replaced.
* @param removeLength number of removed children views. It is useful
* when rebuilding children for a portion of the view.
* @param startOffset starting offset of the loading. It can be -1
* to indicate the loading from <code>View.getStartOffset()</code>.
* @param endOffset ending offset of the loading. It can be -1
* to indicate the loading till <code>View.getEndOffset()</code>.
*/
protected void reloadChildren(int index, int removeLength, int startOffset, int endOffset) {
if (useCustomReloadChildren()) {
if (startOffset == -1) {
startOffset = getStartOffset();
}
if (endOffset == -1) {
endOffset = getEndOffset();
}
customReloadChildren(index, removeLength, startOffset, endOffset);
} else { // element load of children
Element elem = getElement();
int startIndex;
if (startOffset == -1) {
startIndex = 0;
} else {
if (index == 0) {
if (startOffset != getStartOffset()) {
throw new IllegalArgumentException("Invalid startOffset=" + startOffset); // NOI18N
}
} else {
if (startOffset != getView(index - 1).getEndOffset()) {
throw new IllegalArgumentException("Invalid startOffset=" + startOffset); // NOI18N
}
}
startIndex = index;
}
int endIndex = (endOffset == -1)
? elem.getElementCount()
: elem.getElementIndex(endOffset - 1) + 1;
// TODO uncomment assert (startIndex == index);
elementReloadChildren(index, removeLength, endIndex - startIndex);
}
}
static void invalidateAllSyntaxStateInfos(BaseDocument doc) {
Element lineRoot = getLineRoot(doc);
int elemCount = lineRoot.getElementCount();
for (int i = elemCount - 1; i >= 0; i--) {
LineElement line = (LineElement) lineRoot.getElement(i);
line.legacySetAttributesObject(null);
}
}
private static Element findFirstElement(Element e, String name) {
String elementName = e.getName();
if (elementName != null && elementName.equalsIgnoreCase(name)) {
return e;
}
for (int i = 0; i < e.getElementCount(); i++) {
Element result = findFirstElement(e.getElement(i), name);
if (result != null) {
return result;
}
}
return null;
}
public static String lineInfosToString(Document doc) {
StringBuffer sb = new StringBuffer();
Element lineRoot = getLineRoot(doc);
int lineCount = lineRoot.getElementCount();
for (int i = 0; i < lineCount; i++) {
LineElement elem = (LineElement)lineRoot.getElement(i);
sb.append("[" + i + "]: lineStartOffset=" + elem.getStartOffset() // NOI18N
+ ", info: " + (Syntax.StateInfo) elem.legacyGetAttributesObject() + "\n"); // NOI18N
}
return sb.toString();
}
/**
* Removes the lines.
*
* @param e the e
*/
private void removeLines(DocumentEvent e) {
Document document = e.getDocument();
Element root = document.getDefaultRootElement();
while (root.getElementCount() > maximumLines) {
Element line = root.getElement(0);
int end = line.getEndOffset();
try {
document.remove(0, end);
} catch(BadLocationException ble) {
//System.out.println(ble);
}
}
}
/**
* Perform the goto operation.
*
* @return whether the dialog should be made invisible or not
*/
private boolean performGoto() {
JTextComponent c = getTargetComponent();
String text = (String) gotoCombo.getEditor().getItem();
if (c != null) {
try {
int lineNumber = Integer.parseInt(text);
if (lineNumber == 0) { // Works in vim to jump to begining
lineNumber = 1;
}
int lineIndex = lineNumber - 1;
Document doc = c.getDocument();
Element rootElem = doc.getDefaultRootElement();
int lineCount = rootElem.getElementCount();
if (lineIndex >= 0) {
if (lineIndex >= lineCount) {
lineIndex = lineCount - 1;
}
int offset = rootElem.getElement(lineIndex).getStartOffset();
c.setCaretPosition(offset);
return true;
} // else: lineIndex < 0 => beep and return false
} catch (NumberFormatException e) {
// Contains letters or other chars -> attempt bookmarks
BookmarkManager lockedBookmarkManager = BookmarkManager.getLocked();
try {
BookmarkInfo bookmark = lockedBookmarkManager.findBookmarkByNameOrKey(text, false);
if (bookmark != null) {
BookmarkUtils.postOpenEditor(bookmark);
return true;
} // else: unknown bookmark => beep
} finally {
lockedBookmarkManager.unlock();
}
}
}
c.getToolkit().beep();
return false;
}
private int getOffsetY(int rowStartOffset, FontMetrics fontMetrics)
throws BadLocationException
{
// Get the bounding rectangle of the row
Rectangle r = component.modelToView( rowStartOffset );
int lineHeight = fontMetrics.getHeight();
int y = r.y + r.height;
int descent = 0;
// The text needs to be positioned above the bottom of the bounding
// rectangle based on the descent of the font(s) contained on the row.
if (r.height == lineHeight) // default font is being used
{
descent = fontMetrics.getDescent();
}
else // We need to check all the attributes for font changes
{
if (fonts == null)
fonts = new HashMap<String, FontMetrics>();
Element root = component.getDocument().getDefaultRootElement();
int index = root.getElementIndex( rowStartOffset );
Element line = root.getElement( index );
for (int i = 0; i < line.getElementCount(); i++)
{
Element child = line.getElement(i);
AttributeSet as = child.getAttributes();
String fontFamily = (String)as.getAttribute(StyleConstants.FontFamily);
Integer fontSize = (Integer)as.getAttribute(StyleConstants.FontSize);
String key = fontFamily + fontSize;
FontMetrics fm = fonts.get( key );
if (fm == null)
{
Font font = new Font(fontFamily, Font.PLAIN, fontSize);
fm = component.getFontMetrics( font );
fonts.put(key, fm);
}
descent = Math.max(descent, fm.getDescent());
}
}
return y - descent;
}
/**
* 解析输入框中的输入数据
*
* @return
*/
private List<Object> parseEditorInput() {
List<Object> inputData = new ArrayList<>();
Document doc = messageEditorPanel.getEditor().getDocument();
int count = doc.getRootElements()[0].getElementCount();
// 是否是纯文本,如果发现有图片或附件,则不是纯文本
boolean pureText = true;
for (int i = 0; i < count; i++) {
Element root = doc.getRootElements()[0].getElement(i);
int elemCount = root.getElementCount();
for (int j = 0; j < elemCount; j++) {
try {
Element elem = root.getElement(j);
String elemName = elem.getName();
switch (elemName) {
case "content": {
int start = elem.getStartOffset();
int end = elem.getEndOffset();
String text = doc.getText(elem.getStartOffset(), end - start);
inputData.add(text);
break;
}
case "component": {
pureText = false;
Component component = StyleConstants.getComponent(elem.getAttributes());
inputData.add(component);
break;
}
case "icon": {
pureText = false;
ImageIcon icon = (ImageIcon) StyleConstants.getIcon(elem.getAttributes());
inputData.add(icon);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 如果是纯文本,直接返回整个文本,否则如果出消息中有换行符\n出现,那么每一行都会被解析成一句话,会造成一条消息被分散成多个消息发送
if (pureText) {
inputData.clear();
inputData.add(messageEditorPanel.getEditor().getText());
}
return inputData;
}
@Override
public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) {
// PENDING(prinz) properly calculate bias
bias[0] = Position.Bias.Forward;
Rectangle alloc = a.getBounds();
Document doc = getDocument();
int x = (int) fx;
int y = (int) fy;
if (y < alloc.y) {
// above the area covered by this icon, so the the position
// is assumed to be the start of the coverage for this view.
return getStartOffset();
} else if (y > alloc.y + alloc.height) {
// below the area covered by this icon, so the the position
// is assumed to be the end of the coverage for this view.
return getEndOffset() - 1;
} else {
// positioned within the coverage of this view vertically,
// so we figure out which line the point corresponds to.
// if the line is greater than the number of lines contained, then
// simply use the last line as it represents the last possible place
// we can position to.
Element map = doc.getDefaultRootElement();
int fontHeight = metrics.getHeight();
int lineIndex = (fontHeight > 0 ?
Math.abs((y - alloc.y) / fontHeight) :
map.getElementCount() - 1);
if (lineIndex >= map.getElementCount()) {
return getEndOffset() - 1;
}
Element line = map.getElement(lineIndex);
int dx = 0;
if (lineIndex == 0) {
//alloc.x += firstLineOffset;
// alloc.width -= firstLineOffset;
}
if (x < alloc.x) {
// point is to the left of the line
return line.getStartOffset();
} else if (x > alloc.x + alloc.width) {
// point is to the right of the line
return line.getEndOffset() - 1;
} else {
// Determine the offset into the text
try {
int p0 = line.getStartOffset();
int p1 = line.getEndOffset() - 1;
Segment s = new Segment();
doc.getText(p0, p1 - p0, s);
int tabBase = alloc.x;
int offs = p0 + UniTools.getTabbedTextOffset(s, metrics,
tabBase, x, this, p0);
//SegmentCache.releaseSharedSegment(s);
return offs;
} catch (BadLocationException e) {
// should not happen
return -1;
}
}
}
}
private void checkConsistency() {
try {
int docLength = masterDoc.getLength();
assertEquals(docLength, testDoc.getLength());
String masterText = masterDoc.getText(0, docLength);
String testText = testDoc.getText(0, docLength);
assertEquals(masterText, testText);
Element lineRoot = masterDoc.getDefaultRootElement();
Element testLineRoot = testDoc.getDefaultRootElement();
int lineCount = lineRoot.getElementCount();
if (lineCount != testLineRoot.getElementCount()) {
fail("Line count " + testLineRoot.getElementCount()
+ " != " + lineCount);
}
// Compare line boundaries
for (int i = 0; i < lineCount; i++) {
Element masterLine = lineRoot.getElement(i);
Element testLine = testLineRoot.getElement(i);
if (masterLine.getStartOffset() != testLine.getStartOffset()) {
fail("Start of line " + i + ": Offset " + testLine.getStartOffset()
+ " != " + masterLine.getStartOffset());
}
if (masterLine.getEndOffset() != testLine.getEndOffset()) {
fail("End of line " + i + ": Offset " + testLine.getEndOffset()
+ " != " + masterLine.getEndOffset());
}
}
int positionCount = masterPositions.size();
for (int i = 0; i < positionCount; i++) {
Position masterPos = (Position)masterPositions.get(i);
Position testPos = (Position)testPositions.get(i);
if (masterPos.getOffset() != testPos.getOffset()) {
fail("Tested position " + (i + 1) + " of " + positionCount
+ ": " + testPos.getOffset()
+ " != " + masterPos.getOffset());
}
}
} catch (BadLocationException e) {
throw new RuntimeException(e);
}
}
/**
* Return the number of lines in this document
*
* @return
*/
public int getLineCount() {
Element e = getDefaultRootElement();
int cnt = e.getElementCount();
return cnt;
}
/**
* Loads child views in a custom way.
*
* @param index index at which the views should be added/replaced.
* @param removeLength number of removed children views. It is useful
* when rebuilding children for a portion of the view.
* @param startOffset starting offset from which the loading starts.
* @param endOffset ending offset where the loading ends.
*/
protected void customReloadChildren(int index, int removeLength,
int startOffset, int endOffset) {
View[] added = null;
ViewFactory f = getViewFactory();
// Null view factory can mean that one of the grand parents is already disconnected
// from the view hierarchy. No added children for null factory.
if (f != null) {
Element elem = getElement();
int elementCount = elem.getElementCount();
int elementIndex = (elem != null) ? elem.getElementIndex(startOffset) : -1;
if (elementIndex >= elementCount) {
return; // Create no after last element
}
List childViews = new ArrayList();
int viewCount = getViewCount();
loop:
while (startOffset < endOffset) {
// Create custom child
View childView = createCustomView(f, startOffset, endOffset, elementIndex);
if (childView == null) {
throw new IllegalStateException("No view created for area (" // NOI18N
+ startOffset + ", " + endOffset + ")"); // NOI18N
}
// Assuming childView.getStartOffset() is at startOffset
childViews.add(childView);
// Update elementIndex
int childViewEndOffset = childView.getEndOffset();
while (childViewEndOffset > endOffset) {
/* throw new IllegalStateException(
"childViewEndOffset=" + childViewEndOffset // NOI18N
+ " > endOffset=" + endOffset // NOI18N
);
*/
/* The created child view interferes with a view
* that is still present and which is not planned
* to be removed.
* This can happen e.g. when a fold hierarchy change
* (caused by a document change) is fired
* prior to the document change gets fired
* to the view hierarchy.
* The fix for that situation is to continue to remove
* the present views until the end of the created view will match
* a beginning of a present view.
*/
if (index + removeLength >= viewCount) {
// Should not happen but can't remove past the last view
break;
}
endOffset = getView(index + removeLength).getEndOffset();
removeLength++;
if (LOG.isLoggable(Level.FINE)) {
LOG.fine(
"GapBoxView.customReloadChildren(): Increased removeLength to " // NOI18N
+ removeLength + ", eo=" + endOffset // NOI18N
);
}
}
Element childElem = elem.getElement(elementIndex);
while (childElem.getEndOffset() <= childViewEndOffset) {
elementIndex++;
if (elementIndex == elementCount) {
// #115034
break loop;
}
childElem = elem.getElement(elementIndex);
}
startOffset = childViewEndOffset;
}
added = new View[childViews.size()];
childViews.toArray(added);
}
replace(index, removeLength, added);
}
/**
* Return the number of lines in this document
* @return
*/
public int getLineCount() {
Element e = getDefaultRootElement();
int cnt = e.getElementCount();
return cnt;
}