// TODO: make this a method of SikuliDocument, no need to pass document as argument private void changeIndentation(DefaultStyledDocument doc, int linenum, int columns) throws BadLocationException { PreferencesUser pref = PreferencesUser.getInstance(); boolean expandTab = pref.getExpandTab(); int tabWidth = pref.getTabWidth(); if (linenum < 0) { throw new BadLocationException("Negative line", -1); } Element map = doc.getDefaultRootElement(); if (linenum >= map.getElementCount()) { throw new BadLocationException("No such line", doc.getLength() + 1); } if (columns == 0) { return; } Element lineElem = map.getElement(linenum); int lineStart = lineElem.getStartOffset(); int lineLength = lineElem.getEndOffset() - lineStart; String line = doc.getText(lineStart, lineLength); // determine current indentation and number of whitespace characters int wsChars; int indentation = 0; for (wsChars = 0; wsChars < line.length(); wsChars++) { char c = line.charAt(wsChars); if (c == ' ') { indentation++; } else if (c == '\t') { indentation += tabWidth; } else { break; } } int newIndentation = indentation + columns; if (newIndentation <= 0) { doc.remove(lineStart, wsChars); return; } // build whitespace string for new indentation StringBuilder newWs = new StringBuilder(newIndentation / tabWidth + tabWidth - 1); int ind = 0; if (!expandTab) { for (; ind + tabWidth <= newIndentation; ind += tabWidth) { newWs.append('\t'); } } for (; ind < newIndentation; ind++) { newWs.append(' '); } doc.replace(lineStart, wsChars, newWs.toString(), null); }
/** * Inserting text into the end of the document with the same attributes. * * <p>This test is equivalent to <code>doc.insertString(insertOffset, newLine, null)</code>, where * <code>insertOffset = doc.getLength()</code>. */ public void testInsertSameAttrsDocEnd() throws Exception { insertOffset = doc.getLength(); // doc.insertString(insertOffset, newLine, null); content.insertString(insertOffset, newLine); event = doc.new DefaultDocumentEvent(insertOffset, newLineLen, EventType.INSERT); ElementSpec[] specs = { new ElementSpec(null, ElementSpec.ContentType, newLineLen), new ElementSpec(null, ElementSpec.EndTagType), new ElementSpec(null, ElementSpec.StartTagType) }; specs[0].setDirection(ElementSpec.JoinPreviousDirection); specs[2].setDirection(ElementSpec.JoinFractureDirection); buf.insert(insertOffset, newLineLen, specs, event); List<?> edits = getEdits(event); assertEquals(2, edits.size()); assertChange(edits.get(0), new int[] {16, 22}, new int[] {16, 21}); assertChange(edits.get(1), new int[] {}, new int[] {21, 22}); assertChildren(root.getElement(1), new int[] {16, 21}, new AttributeSet[] {null}); assertChildren(root.getElement(2), new int[] {21, 22}, new AttributeSet[] {null}); assertEquals("text\n", getText(doc.getCharacterElement(insertOffset))); assertEquals("\n", getText(doc.getCharacterElement(insertOffset + newLineLen))); }
/** * Determine how many lines have been changed, then apply highlighting to each line. * * @param offset the offset of the changed lines * @param length the length of the change * @throws BadLocationException if offset is invalid */ public void processChangedLines(int offset, int length) throws BadLocationException { String content = m_Self.getText(0, m_Self.getLength()); // The lines affected by the latest document update int startLine = m_RootElement.getElementIndex(offset); int endLine = m_RootElement.getElementIndex(offset + length); // Make sure all comment lines prior to the start line are commented // and determine if the start line is still in a multi line comment if (getMultiLineComment()) setInsideMultiLineComment(commentLinesBefore(content, startLine)); // Do the actual highlighting for (int i = startLine; i <= endLine; i++) { applyHighlighting(content, i); } // Resolve highlighting to the next end multi line delimiter if (isMultiLineComment()) commentLinesAfter(content, endLine); else highlightLinesAfter(content, endLine); }