/**
* Copyright (c) 2001-2014 Mathew A. Nelson and Robocode contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://robocode.sourceforge.net/license/epl-v10.html
*/
package net.sf.robocode.ui.editor;
import java.awt.Color;
import java.awt.Rectangle;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import net.sf.robocode.ui.editor.theme.EditorThemeProperties;
import net.sf.robocode.ui.editor.theme.EditorThemePropertiesManager;
import net.sf.robocode.ui.editor.theme.EditorThemePropertyChangeAdapter;
/**
* A text area containing line numbers for the editor pane and editor panel.
*
* @author Flemming N. Larsen (original)
*/
@SuppressWarnings("serial")
public class LineNumberArea extends JTextArea {
private final DocumentListener documentListener = new TextDocumentListener();
public LineNumberArea(JTextComponent textComponent) {
super("1");
setEditable(false);
setLineWrap(false);
EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties();
setBackgroundColor(themeProps.getLineNumberBackgroundColor());
setTextColor(themeProps.getLineNumberTextColor());
textComponent.getDocument().addDocumentListener(documentListener);
EditorThemePropertiesManager.addListener(new EditorThemePropertyChangeAdapter() {
@Override
public void onLineNumberBackgroundColorChanged(Color newColor) {
setBackgroundColor(newColor);
}
@Override
public void onLineNumberTextColorChanged(Color newColor) {
setTextColor(newColor);
}
});
}
private class TextDocumentListener implements DocumentListener {
int lastNumLines = 1;
public void insertUpdate(DocumentEvent e) {
updateText(e.getDocument());
}
public void removeUpdate(DocumentEvent e) {
updateText(e.getDocument());
}
public void changedUpdate(DocumentEvent e) {
updateText(e.getDocument());
}
private void updateText(final Document doc) {
final int numLines = getNumLines(doc);
if (numLines == lastNumLines) {
return;
}
lastNumLines = numLines;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final Rectangle visibleRect = getVisibleRect();
setIgnoreRepaint(true); // avoid flickering
setText(generateLinesText(numLines));
// Must be done this way to keep aligned with scroll bar!
SwingUtilities.invokeLater(new Runnable() {
public void run() {
scrollRectToVisible(visibleRect);
setIgnoreRepaint(false); // avoid flickering
}
});
}
});
}
/**
* Returns a string containing text lines for all line numbers.
* Each line number is right-aligned and ended a space + a new-line character.
*
* @param numLines is the number of lines to create the line number text for.
* @return a string containing line numbers.
*/
private String generateLinesText(int numLines) {
String format = "%" + ("" + (numLines + 1)).length() + "s ";
StringBuilder lines = new StringBuilder();
int i = 1;
while (i <= numLines) {
String s = String.format(format, "" + i++);
lines.append(s).append('\n');
}
lines.append(String.format(format, "" + i));
return lines.toString();
}
private int getNumLines(Document doc) {
return doc.getDefaultRootElement().getElementIndex(doc.getLength());
}
}
private void setBackgroundColor(Color newBackgroundColor) {
setBackground(newBackgroundColor);
setSelectionColor(newBackgroundColor);
}
private void setTextColor(Color newTextColor) {
setForeground(newTextColor);
setSelectedTextColor(newTextColor);
}
}