by Archivist » Fri Mar 27, 2009 9:22 am
I made one more try, and seems that it is working ok. The code is not very nice, but maybe it can help:
public static class InsertCloseCurlyBraceAction extends RecordableTextAction {
private static final long serialVersionUID = 1L;
private Segment seg;
public InsertCloseCurlyBraceAction() {
super(rstaInsertCloseCurlyBraceAction);
seg = new Segment();
}
public void actionPerformedImpl(ActionEvent e, RTextArea textArea) {
RSyntaxTextArea rsta = (RSyntaxTextArea) textArea;
RSyntaxDocument doc = (RSyntaxDocument) rsta.getDocument();
boolean alignCurlyBraces = rsta.isAutoIndentEnabled() && doc.getCurlyBracesDenoteCodeBlocks();
if (alignCurlyBraces) {
textArea.beginAtomicEdit();
}
try {
int caretPosition = textArea.getCaretPosition();
int lineOfOffset = textArea.getLineOfOffset(caretPosition);
if (!(lineOfOffset - 2 >= 0)) return;
int prevLineEnd = textArea.getLineEndOffset(lineOfOffset - 2);
// int diff = curLineEnd - prevLineEnd;
int diff = caretPosition - prevLineEnd;
String selectedLineText = textArea.getText(prevLineEnd, diff);
if (!textArea.isEditable() || !textArea.isEnabled()) {
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
return;
}
RSyntaxTextArea sta = (RSyntaxTextArea) textArea;
boolean isNeedAdd = possibleNeedAddClosingBrace(selectedLineText);
// If we're in insert-mode and auto-indenting...
if (sta.getTextMode() == RTextArea.INSERT_MODE && sta.isAutoIndentEnabled() && sta.getSelectionStart() == sta.getSelectionEnd()) {
(new InsertBreakAction()).insertNewlineWithAutoIndent(sta);
}
// Otherwise, we're in overwrite-mode or not auto-indenting.
else {
textArea.replaceSelection("\n");
}
caretPosition = textArea.getCaretPosition();
lineOfOffset = textArea.getLineOfOffset(caretPosition);
if (isNeedAdd&&isNotEqualAmount(textArea.getText())) {
insertNewlineWithAutoIndent(sta);
textArea.insert("}", textArea.getCaretPosition());
textArea.setCaretPosition(caretPosition);
}
} catch (Exception exception) {
// do nothing
exception.printStackTrace();
} finally {
if (alignCurlyBraces) {
textArea.endAtomicEdit();
}
}
}
private void insertNewlineWithAutoIndent(RSyntaxTextArea sta) {
try {
int caretPosition = sta.getCaretPosition();
Document doc = sta.getDocument();
Element map = doc.getDefaultRootElement();
int lineNum = map.getElementIndex(caretPosition);
Element line = map.getElement(lineNum);
int start = line.getStartOffset();
int end = line.getEndOffset() - 1; // Why always "-1"?
int len = end - start;
String s = doc.getText(start, len);
// endWS is the end of the leading whitespace of the
// current line.
String leadingWS = RSyntaxUtilities.getLeadingWhitespace(s);
if (leadingWS.length() >= sta.getTabSize()) {
leadingWS = leadingWS.substring(0, leadingWS.length() - sta.getTabSize());
}
StringBuffer sb = new StringBuffer("\n");
sb.append(leadingWS);
// If there is only whitespace between the caret and
// the EOL, pressing Enter auto-indents the new line to
// the same place as the previous line.
int nonWhitespacePos = atEndOfLine(caretPosition - start, s, len);
if (nonWhitespacePos == -1) {
// If the line was nothing but whitespace...
if (leadingWS.length() == len && sta.isClearWhitespaceLinesEnabled()) {
sta.replaceRange(null, start, end);
}
sta.replaceSelection(sb.toString());
}
// If there is non-whitespace between the caret and the
// EOL, pressing Enter takes that text to the next line
// and auto-indents it to the same place as the last
// line.
else {
sb.append(s.substring(nonWhitespacePos));
sta.replaceRange(sb.toString(), caretPosition, end);
sta.setCaretPosition(caretPosition + leadingWS.length() + 1);
}
// Must do it after everything else, as the "smart indent"
// calculation depends on the previous line's state
// AFTER the Enter press (stuff may have been moved down).
if (sta.getShouldIndentNextLine(lineNum)) {
sta.replaceSelection("\t");
}
// if (sta.getCloseCurlyBraces()) {
// int dot = sta.getCaretPosition();
// String str = "\n" + leadingWS + "}";
// sta.replaceRange(str, dot, dot);
// sta.setCaretPosition(dot);
// }
} catch (BadLocationException ble) { // Never happens
sta.replaceSelection("\n");
ble.printStackTrace();
}
}
/**
* @return The first location in the string past <code>pos</code> that
* is NOT a whitespace char, or <code>-1</code> if only
* whitespace chars follow <code>pos</code> (or it is the end
* position in the string).
*/
private static final int atEndOfLine(int pos, String s, int sLen) {
for (int i = pos; i < sLen; i++) {
if (!RSyntaxUtilities.isWhitespace(s.charAt(i))) return i;
}
return -1;
}
public final String getMacroID() {
return rstaCloseCurlyBraceAction;
}
private boolean possibleNeedAddClosingBrace(String selectedLine) {
char a[] = selectedLine.toCharArray();
if (a.length > 0) {
for (int i = a.length - 1; i >= 0; i--) {
if (a[i] == 9 || a[i] == 32 || a[i] == 10 || a[i] == 13) continue;
if (a[i] == 123) return true;
else return false;
}
return false;
} else return false;
}
private boolean isNotEqualAmount(String selectedLine) {
char a[] = selectedLine.toCharArray();
int closeCurly = 0;
int openCurly = 0;
if (a.length > 0) {
for (int i = a.length - 1; i >= 0; i--) {
if (a[i] == 123) {
openCurly++;
} else if (a[i] == 125) {
closeCurly++;
}
}
}
if (openCurly > closeCurly) {
return true;
} else {
return false;
}
}
}
I made one more try, and seems that it is working ok. The code is not very nice, but maybe it can help:
public static class InsertCloseCurlyBraceAction extends RecordableTextAction {
private static final long serialVersionUID = 1L;
private Segment seg;
public InsertCloseCurlyBraceAction() {
super(rstaInsertCloseCurlyBraceAction);
seg = new Segment();
}
public void actionPerformedImpl(ActionEvent e, RTextArea textArea) {
RSyntaxTextArea rsta = (RSyntaxTextArea) textArea;
RSyntaxDocument doc = (RSyntaxDocument) rsta.getDocument();
boolean alignCurlyBraces = rsta.isAutoIndentEnabled() && doc.getCurlyBracesDenoteCodeBlocks();
if (alignCurlyBraces) {
textArea.beginAtomicEdit();
}
try {
int caretPosition = textArea.getCaretPosition();
int lineOfOffset = textArea.getLineOfOffset(caretPosition);
if (!(lineOfOffset - 2 >= 0)) return;
int prevLineEnd = textArea.getLineEndOffset(lineOfOffset - 2);
// int diff = curLineEnd - prevLineEnd;
int diff = caretPosition - prevLineEnd;
String selectedLineText = textArea.getText(prevLineEnd, diff);
if (!textArea.isEditable() || !textArea.isEnabled()) {
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
return;
}
RSyntaxTextArea sta = (RSyntaxTextArea) textArea;
boolean isNeedAdd = possibleNeedAddClosingBrace(selectedLineText);
// If we're in insert-mode and auto-indenting...
if (sta.getTextMode() == RTextArea.INSERT_MODE && sta.isAutoIndentEnabled() && sta.getSelectionStart() == sta.getSelectionEnd()) {
(new InsertBreakAction()).insertNewlineWithAutoIndent(sta);
}
// Otherwise, we're in overwrite-mode or not auto-indenting.
else {
textArea.replaceSelection("\n");
}
caretPosition = textArea.getCaretPosition();
lineOfOffset = textArea.getLineOfOffset(caretPosition);
if (isNeedAdd&&isNotEqualAmount(textArea.getText())) {
insertNewlineWithAutoIndent(sta);
textArea.insert("}", textArea.getCaretPosition());
textArea.setCaretPosition(caretPosition);
}
} catch (Exception exception) {
// do nothing
exception.printStackTrace();
} finally {
if (alignCurlyBraces) {
textArea.endAtomicEdit();
}
}
}
private void insertNewlineWithAutoIndent(RSyntaxTextArea sta) {
try {
int caretPosition = sta.getCaretPosition();
Document doc = sta.getDocument();
Element map = doc.getDefaultRootElement();
int lineNum = map.getElementIndex(caretPosition);
Element line = map.getElement(lineNum);
int start = line.getStartOffset();
int end = line.getEndOffset() - 1; // Why always "-1"?
int len = end - start;
String s = doc.getText(start, len);
// endWS is the end of the leading whitespace of the
// current line.
String leadingWS = RSyntaxUtilities.getLeadingWhitespace(s);
if (leadingWS.length() >= sta.getTabSize()) {
leadingWS = leadingWS.substring(0, leadingWS.length() - sta.getTabSize());
}
StringBuffer sb = new StringBuffer("\n");
sb.append(leadingWS);
// If there is only whitespace between the caret and
// the EOL, pressing Enter auto-indents the new line to
// the same place as the previous line.
int nonWhitespacePos = atEndOfLine(caretPosition - start, s, len);
if (nonWhitespacePos == -1) {
// If the line was nothing but whitespace...
if (leadingWS.length() == len && sta.isClearWhitespaceLinesEnabled()) {
sta.replaceRange(null, start, end);
}
sta.replaceSelection(sb.toString());
}
// If there is non-whitespace between the caret and the
// EOL, pressing Enter takes that text to the next line
// and auto-indents it to the same place as the last
// line.
else {
sb.append(s.substring(nonWhitespacePos));
sta.replaceRange(sb.toString(), caretPosition, end);
sta.setCaretPosition(caretPosition + leadingWS.length() + 1);
}
// Must do it after everything else, as the "smart indent"
// calculation depends on the previous line's state
// AFTER the Enter press (stuff may have been moved down).
if (sta.getShouldIndentNextLine(lineNum)) {
sta.replaceSelection("\t");
}
// if (sta.getCloseCurlyBraces()) {
// int dot = sta.getCaretPosition();
// String str = "\n" + leadingWS + "}";
// sta.replaceRange(str, dot, dot);
// sta.setCaretPosition(dot);
// }
} catch (BadLocationException ble) { // Never happens
sta.replaceSelection("\n");
ble.printStackTrace();
}
}
/**
* @return The first location in the string past <code>pos</code> that
* is NOT a whitespace char, or <code>-1</code> if only
* whitespace chars follow <code>pos</code> (or it is the end
* position in the string).
*/
private static final int atEndOfLine(int pos, String s, int sLen) {
for (int i = pos; i < sLen; i++) {
if (!RSyntaxUtilities.isWhitespace(s.charAt(i))) return i;
}
return -1;
}
public final String getMacroID() {
return rstaCloseCurlyBraceAction;
}
private boolean possibleNeedAddClosingBrace(String selectedLine) {
char a[] = selectedLine.toCharArray();
if (a.length > 0) {
for (int i = a.length - 1; i >= 0; i--) {
if (a[i] == 9 || a[i] == 32 || a[i] == 10 || a[i] == 13) continue;
if (a[i] == 123) return true;
else return false;
}
return false;
} else return false;
}
private boolean isNotEqualAmount(String selectedLine) {
char a[] = selectedLine.toCharArray();
int closeCurly = 0;
int openCurly = 0;
if (a.length > 0) {
for (int i = a.length - 1; i >= 0; i--) {
if (a[i] == 123) {
openCurly++;
} else if (a[i] == 125) {
closeCurly++;
}
}
}
if (openCurly > closeCurly) {
return true;
} else {
return false;
}
}
}